local _VERSION = '0.1.0'; local args = table.pack(...); local command = args[1]; local GOO_BLOCK_PREFIX = 'justdirethings:gooblock_tier'; local WAIT_SECONDS = 2; local PROCESS_ITEMS = { ['minecraft:iron_block'] = { tier = 1, label = 'iron' }, ['minecraft:coal_block'] = { tier = 1, label = 'coal' }, ['mekanism:block_charcoal'] = { tier = 1, label = 'charcoal' }, ['minecraft:gold_block'] = { tier = 2, label = 'gold' }, ['minecraft:diamond_block'] = { tier = 3, label = 'diamond' }, ['minecraft:netherite_block'] = { tier = 4, label = 'netherite' }, }; local FEEDING_ITEMS_BY_TIER = { [1] = { 'minecraft:sugar', 'minecraft:rotten_flesh' }, [2] = { 'minecraft:nether_wart' }, [3] = { 'minecraft:chorus_fruit' }, [4] = { 'minecraft:sculk' }, }; local loggedBlockedItems = {}; local function isFlag(name) return function(arg) return arg == '-' .. name or arg == '--' .. name; end end local isHelpFlag = isFlag('help'); local isVersionFlag = isFlag('version'); local function printUsage() print('goo usage:'); print(); print('\t\t\tgoo start'); print('\t\t\tgoo version'); print('\t\t\tgoo help'); end if command == 'version' or isVersionFlag(command) then print('goo v' .. _VERSION); return; end if command == nil or command == '' or command == 'help' or isHelpFlag(command) then printUsage(); return; end if command ~= 'start' then printUsage(); return; end if not turtle then error('goo must be run on a turtle'); end local function turnAround() turtle.turnRight(); turtle.turnRight(); end local function parseGooTier(blockName) local tier = string.match(blockName or '', '^' .. GOO_BLOCK_PREFIX .. '(%d+)$'); return tonumber(tier); end local function isGooBlock(blockName) return parseGooTier(blockName) ~= nil; end local function isProcessBlock(blockName) return PROCESS_ITEMS[blockName] ~= nil; end local function inspectGoo() local ok, inspected = turtle.inspectUp(); if not ok then error('expected a Just Dire Things goo block above the turtle'); end local tier = parseGooTier(inspected.name); if not tier then error('expected a Just Dire Things goo block above the turtle, got ' .. tostring(inspected.name)); end return tier, inspected; end local function findItemSlot(itemName) for slot = 1, 16 do local item = turtle.getItemDetail(slot); if item and item.name == itemName then return slot, item; end end return nil; end local function findFeedingSlot(gooTier) local feedingItems = FEEDING_ITEMS_BY_TIER[gooTier] or {}; for i = 1, #feedingItems do local slot, item = findItemSlot(feedingItems[i]); if slot then return slot, item; end end return nil; end local function findEligibleProcessSlot(gooTier) for slot = 1, 16 do local item = turtle.getItemDetail(slot); local processItem = item and PROCESS_ITEMS[item.name]; if processItem then if processItem.tier <= gooTier then return slot, item, processItem; end local logKey = item.name .. ':' .. tostring(gooTier); if not loggedBlockedItems[logKey] then print(item.name .. ' requires goo tier ' .. tostring(processItem.tier) .. ', current tier is ' .. tostring(gooTier)); loggedBlockedItems[logKey] = true; end end end return nil; end local function ensureGooAlive() while true do local gooTier, inspected = inspectGoo(); if inspected.state and inspected.state.alive == true then return gooTier; end local slot, item = findFeedingSlot(gooTier); if not slot then print('Goo tier ' .. tostring(gooTier) .. ' is not alive. Waiting for feeding item...'); os.sleep(WAIT_SECONDS); else turtle.select(slot); print('Goo tier ' .. tostring(gooTier) .. ' is not alive. Feeding with ' .. item.name .. '...'); if not turtle.placeUp() then print('Could not feed the goo. Waiting before retry...'); os.sleep(WAIT_SECONDS); else os.sleep(1); end end end end local function selectProcessItem(gooTier) local slot, item, processItem = findEligibleProcessSlot(gooTier); if not slot then return nil; end turtle.select(slot); return item, processItem; end local function workTarget(inspectFn, digFn, placeFn, gooTier, targetName) local ok, inspected = inspectFn(); if ok then if isGooBlock(inspected.name) then return false; end if isProcessBlock(inspected.name) then return false; end print('Mining processed ' .. targetName .. ' block: ' .. tostring(inspected.name)); return digFn(); end local item = selectProcessItem(gooTier); if not item then return false; end print('Placing ' .. item.name .. ' on goo ' .. targetName); return placeFn(); end local function workHorizontalSide(gooTier, sideIndex) if not turtle.forward() then print('Cannot move to horizontal side ' .. tostring(sideIndex) .. '. Waiting...'); return false; end local changed = workTarget(turtle.inspectUp, turtle.digUp, turtle.placeUp, gooTier, 'side'); if not turtle.back() then error('could not return below the goo'); end return changed; end local function workHorizontalSides(gooTier) local changed = false; for sideIndex = 1, 4 do changed = workHorizontalSide(gooTier, sideIndex) or changed; turtle.turnRight(); end return changed; end local function workTopFromCurrentSide(gooTier) if not turtle.forward() then return false; end local sideOccupied = turtle.inspectUp(); local changed = false; if not sideOccupied then if turtle.up() then if turtle.up() then turnAround(); changed = workTarget(turtle.inspect, turtle.dig, turtle.place, gooTier, 'top'); turnAround(); if not turtle.down() then error('could not descend from top placement position'); end else print('Cannot climb high enough to work on the top side.'); end if not turtle.down() then error('could not return to side floor position'); end else print('Cannot climb to work on the top side.'); end end if not turtle.back() then error('could not return below the goo after top side check'); end return changed; end local function workTop(gooTier) local changed = false; for _ = 1, 4 do if not changed then changed = workTopFromCurrentSide(gooTier); end turtle.turnRight(); end return changed; end local function turnLeft(times) for _ = 1, times do turtle.turnLeft(); end end local function moveToSideFacingCenter() for turns = 0, 3 do if turtle.forward() then turnAround(); return turns; end turtle.turnRight(); end return nil; end local function returnFromBottomSide(turns) if not turtle.forward() then return false; end turnAround(); turnLeft(turns); return true; end local function workBottom() local gooTier = ensureGooAlive(); local turns = moveToSideFacingCenter(); if not turns then print('Cannot move to a side position for bottom placement. Waiting...'); return false; end local changed = false; while true do local ok, inspected = turtle.inspect(); if not ok then if changed then if returnFromBottomSide(turns) then return changed; end print('Center position is clear, but the turtle could not return. Waiting...'); os.sleep(WAIT_SECONDS); else local item = selectProcessItem(gooTier); if item then print('Placing ' .. item.name .. ' on goo bottom'); if turtle.place() then changed = true; else print('Could not place bottom block.'); end elseif returnFromBottomSide(turns) then return changed; else print('Center position is blocked. Waiting...'); os.sleep(WAIT_SECONDS); end end elseif isProcessBlock(inspected.name) then print('Bottom block is still processing. Waiting outside...'); os.sleep(WAIT_SECONDS); elseif isGooBlock(inspected.name) then error('unexpected goo block in the turtle center position'); else print('Mining processed bottom block: ' .. tostring(inspected.name)); if turtle.dig() then changed = true; else print('Could not mine bottom block. Waiting...'); os.sleep(WAIT_SECONDS); end end end end print('goo started. Place the turtle directly below the goo block.'); while true do local gooTier = ensureGooAlive(); local hasEligibleBlocks = findEligibleProcessSlot(gooTier) ~= nil; local changed = false; changed = workTop(gooTier) or changed; changed = workHorizontalSides(gooTier) or changed; changed = workBottom() or changed; if not changed then if hasEligibleBlocks then print('No free goo side found. Waiting for processing...'); else print('No eligible process block found. Waiting for inventory...'); end os.sleep(WAIT_SECONDS); end end