Myros27

VillageBot v1.0

May 24th, 2025 (edited)
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 69.61 KB | None | 0 0
  1. -- VillageBot v1.4
  2.  
  3. --#region STRICT TOP-LEVEL CONFIGURATION AND LOGGER GLOBALS
  4. local LOG_LEVELS = { DEBUG = 1, INFO = 2, WARN = 3, ERROR = 4, FATAL = 5 }
  5. local DEBUG_LOGGING_ENABLED = true
  6. local LOG_FILE_NAME_CONST = "villagebot.log"
  7.  
  8. local current_log_level_val
  9. if DEBUG_LOGGING_ENABLED then
  10.     current_log_level_val = (LOG_LEVELS and LOG_LEVELS.DEBUG) or 1
  11. else
  12.     current_log_level_val = (LOG_LEVELS and LOG_LEVELS.INFO) or 2
  13. end
  14.  
  15. local BOT_DATA_FILE = "villagebot_data.json"
  16. local ME_BRIDGE_NAME = "advancedperipherals:me_bridge"
  17. local REDSTONE_BLOCK_NAME = "minecraft:redstone_block"
  18.  
  19. local AUTOMATA_PERIPHERAL_NAME = "endAutomata"
  20. local ME_BRIDGE_PERIPHERAL_NAME = "meBridge"
  21. local COLONY_INTEGRATOR_PERIPHERAL_NAME = "colonyIntegrator"
  22.  
  23. local FUEL_SLOT = 16
  24. local COAL_BLOCK_NAME = "minecraft:coal_block"
  25. local REFUEL_BELOW_PERCENTAGE = 0.90
  26. local MAX_REDSTONE_BLOCK_RETRIES = 10
  27. local REDSTONE_BLOCK_RETRY_WAIT = 5
  28. local REFUEL_BARREL_ACCESS_POS = { x = -111, y = 65, z = 219, dir = 3 }
  29. --#endregion
  30.  
  31. --#region Global State
  32. local current_pos = { x = nil, y = nil, z = nil }; local current_dir = nil
  33. local roboSlot = nil; local home_pos = { x = nil, y = nil, z = nil, dir = nil }
  34. local pAutomata = nil; local pMeBridge = nil; local pColonyIntegrator = nil
  35. local DIR_VECTORS = { [0]={x=0,z=1},[1]={x=1,z=0},[2]={x=0,z=-1},[3]={x=-1,z=0} }
  36. local DIR_NAMES = {[0]="North",[1]="East",[2]="South",[3]="West"}
  37. local mounted_peripherals = {}; local undeliveredItemsBuffer = {}
  38. --#endregion
  39.  
  40. --#region Logger Function
  41. local function botLog(level, message)
  42.     local message_str = message
  43.     if type(message) ~= "string" and type(message) ~= "number" then
  44.         message_str = textutils.serialize(message, {compact=true})
  45.         if message == nil then message_str = "nil_message_passed_to_botLog" end
  46.     else message_str = tostring(message) end
  47.  
  48.     local level_display_name = "LVL?"
  49.     if LOG_LEVELS and type(LOG_LEVELS) == "table" then
  50.         for name_key, lVal_val in pairs(LOG_LEVELS) do if lVal_val == level then level_display_name = name_key; break end end
  51.     else print("Console: botLog - LOG_LEVELS is nil or not a table! Cannot determine level name.") end
  52.    
  53.     print(string.format("[%s] [%s] %s", os.date("%Y-%m-%d %H:%M:%S"), level_display_name, message_str))
  54.  
  55.     local can_write_to_file = false
  56.     if LOG_LEVELS and type(LOG_LEVELS) == "table" and current_log_level_val and LOG_FILE_NAME_CONST and type(LOG_FILE_NAME_CONST) == "string" then
  57.         if DEBUG_LOGGING_ENABLED or level >= (LOG_LEVELS.WARN or 3) then
  58.             if level >= current_log_level_val then
  59.                 can_write_to_file = true
  60.             end
  61.         end
  62.     end
  63.  
  64.     if can_write_to_file then
  65.         local levelNameInFile = "UNK_LVL"
  66.         if LOG_LEVELS then for name, lVal in pairs(LOG_LEVELS) do if lVal == level then levelNameInFile = name; break end end end
  67.         local logMessageToFile = string.format("[%s] [%s] %s", os.date("%Y-%m-%d %H:%M:%S"), levelNameInFile, message_str)
  68.         local f, err = fs.open(LOG_FILE_NAME_CONST, "a")
  69.         if f then
  70.             f.write(logMessageToFile .. "\n"); f.close()
  71.         else
  72.             print("CONSOLE: LOG FILE OPEN ERROR for '"..LOG_FILE_NAME_CONST.."' (in botLog): " .. tostring(err))
  73.         end
  74.     elseif DEBUG_LOGGING_ENABLED then
  75.         if not LOG_LEVELS or type(LOG_LEVELS) ~= "table" then print("Console: botLog - Cannot write to file, LOG_LEVELS invalid.") end
  76.         if not current_log_level_val then print("Console: botLog - Cannot write to file, current_log_level_val invalid.") end
  77.         if not LOG_FILE_NAME_CONST or type(LOG_FILE_NAME_CONST) ~= "string" then print("Console: botLog - Cannot write to file, LOG_FILE_NAME_CONST invalid.") end
  78.     end
  79. end
  80. --#endregion
  81.  
  82. --#region Peripheral Management
  83. function findPeripheral(name,type_arg,required)
  84.     if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"findPeripheral: Find "..name.." type '"..tostring(type_arg).."'")end
  85.     if type(type_arg) ~= "string" then
  86.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "findPeripheral: Invalid type argument passed. Expected string, got " .. type(type_arg)) end
  87.         return nil
  88.     end
  89.     local p=peripheral.find(type_arg)
  90.     if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"findPeripheral: peripheral.find Result for type '"..type_arg.."': "..tostring(p))end
  91.     if p then
  92.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"Found peripheral: "..name) end
  93.         mounted_peripherals[name]=p
  94.         return p
  95.     else
  96.         local m="Peripheral NOT FOUND: "..name.." (type: " .. type_arg .. ")"
  97.         if required then
  98.             if LOG_LEVELS then botLog(LOG_LEVELS.FATAL,m.." - REQUIRED!") end
  99.         else
  100.             if LOG_LEVELS then botLog(LOG_LEVELS.WARN,m) end
  101.         end
  102.         return nil
  103.     end
  104. end
  105.  
  106. function initCorePeripherals()
  107.     print("Console: CHKPT - Enter initCorePeripherals")
  108.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initCorePeripherals: Start") end
  109.     pAutomata=findPeripheral("Automata",AUTOMATA_PERIPHERAL_NAME,true)
  110.    
  111.     if not pAutomata then
  112.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"initCorePeripherals: Automata peripheral missing. Cannot proceed.") end
  113.         print("Console: CHKPT - initCorePeripherals FAIL (Automata missing)")
  114.         return false
  115.     end
  116.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initCorePeripherals: Core peripherals OK.") end
  117.     print("Console: CHKPT - initCorePeripherals OK")
  118.     return true
  119. end
  120.  
  121. function findHomeLocationPeripherals()
  122.     print("Console: CHKPT - Enter findHomeLocationPeripherals")
  123.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"findHomeLocationPeripherals: Start (should be at home and oriented)") end
  124.  
  125.     if not (home_pos and home_pos.x and current_pos and current_pos.x == home_pos.x and current_pos.y == home_pos.y and current_pos.z == home_pos.z) then
  126.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"findHomeLocationPeripherals: Called when not at stored home coordinates. This might fail.") end
  127.     end
  128.     if not (home_pos and home_pos.dir ~= nil and current_dir == home_pos.dir) then
  129.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"findHomeLocationPeripherals: Not facing home direction (".. (home_pos and DIR_NAMES[home_pos.dir] or "N/A").."). ME Bridge might not be in front.") end
  130.         if home_pos and home_pos.dir ~= nil then
  131.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "findHomeLocationPeripherals: Attempting re-orientation to home direction: " .. DIR_NAMES[home_pos.dir]) end
  132.             if not ml.turnToDir(home_pos.dir) then
  133.                 if LOG_LEVELS then botLog(LOG_LEVELS.WARN, "findHomeLocationPeripherals: Re-orientation failed.") end
  134.             end
  135.         else
  136.              if LOG_LEVELS then botLog(LOG_LEVELS.WARN, "findHomeLocationPeripherals: home_pos.dir is nil, cannot re-orient.") end
  137.         end
  138.     end
  139.  
  140.     if not pMeBridge then
  141.         pMeBridge=findPeripheral("ME Bridge",ME_BRIDGE_PERIPHERAL_NAME,true)
  142.     elseif LOG_LEVELS then
  143.         botLog(LOG_LEVELS.DEBUG, "findHomeLocationPeripherals: pMeBridge already attached.")
  144.     end
  145.  
  146.     if not pColonyIntegrator then
  147.         pColonyIntegrator=findPeripheral("Colony Integrator",COLONY_INTEGRATOR_PERIPHERAL_NAME,true)
  148.     elseif LOG_LEVELS then
  149.         botLog(LOG_LEVELS.DEBUG, "findHomeLocationPeripherals: pColonyIntegrator already attached.")
  150.     end
  151.  
  152.  
  153.     if not (pMeBridge and pColonyIntegrator)then
  154.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"findHomeLocationPeripherals: ME Bridge or Colony Integrator missing after checks.") end
  155.         print("Console: CHKPT - findHomeLocationPeripherals FAIL")
  156.         return false
  157.     end
  158.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"findHomeLocationPeripherals: Home location peripherals OK.") end
  159.     print("Console: CHKPT - findHomeLocationPeripherals OK")
  160.     return true
  161. end
  162. --#endregion
  163.  
  164. --#region JSON Data Handling
  165. function saveData() if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"saveData: Attempt")end; if roboSlot==nil or not home_pos or home_pos.x==nil or not current_pos or current_pos.x==nil or current_dir==nil then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"saveData: Skip, incomplete data (roboSlot, home_pos, current_pos, or current_dir is nil/incomplete).")end; return false end; local d={roboSlot=roboSlot,home_pos=home_pos,current_pos=current_pos,current_dir=current_dir}; if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"saveData: Data: "..textutils.serialize(d))end; local s,e=textutils.serialiseJSON(d); if not s then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"saveData: Serialize fail: "..tostring(e))end; return false end; local f,fe=fs.open(BOT_DATA_FILE,"w"); if not f then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"saveData: Open file fail: "..tostring(fe))end; return false end; f.write(s);f.close(); if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"Bot data saved.")end; return true end
  166. function loadData() print("Console: CHKPT - Enter loadData"); if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"loadData: Attempt from '"..BOT_DATA_FILE.."'")end; if not fs.exists(BOT_DATA_FILE)then if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"loadData: File not found.")end; print("Console: CHKPT - loadData: No file"); return false end; local f,fe=fs.open(BOT_DATA_FILE,"r"); if not f then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"loadData: Open file fail: "..tostring(fe))end; print("Console: CHKPT - loadData: Open fail"); return false end; local s=f.readAll();f.close(); if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"loadData: File content: "..s)end; local sc,d=pcall(textutils.unserialiseJSON,s); if not sc or type(d)~="table"then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"loadData: Parse fail. Success:"..tostring(sc)..", Err/Data:"..tostring(d))end; print("Console: CHKPT - loadData: Parse JSON fail"); return false end; if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"loadData: Parsed: "..textutils.serialize(d))end; if d.roboSlot and d.home_pos and d.home_pos.x~=nil and d.home_pos.y~=nil and d.home_pos.z~=nil and d.home_pos.dir~=nil and d.current_pos and d.current_pos.x~=nil and d.current_pos.y~=nil and d.current_pos.z~=nil and d.current_dir~=nil then roboSlot=d.roboSlot;home_pos=d.home_pos;current_pos=d.current_pos;current_dir=d.current_dir; if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"Bot data loaded.")end; print("Console: CHKPT - loadData: OK"); return true else if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"loadData: Incomplete/malformed data in JSON file.")end; print("Console: CHKPT - loadData: Malformed data"); return false end end
  167. --#endregion
  168.  
  169. --#region Movement Library (ml)
  170. ml = {}
  171. function ml.setPos(x,y,z,dirNum) current_pos={x=x,y=y,z=z}; current_dir=dirNum; if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, string.format("ml.setPos: X:%s Y:%s Z:%s Dir:%s (%s)",x,y,z,dirNum,DIR_NAMES[dirNum])) end; saveData() end
  172. function ml.inspect() if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "ml.inspect: Called") end; local s,d=turtle.inspect(); if s and d then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.inspect: Success, Block: "..d.name .. (d.state and " " .. textutils.serialize(d.state) or "")) end; return d elseif s and not d then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.inspect: Success, Empty space.")end; return nil else if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.inspect: Failed: " .. tostring(d))end; return nil end end
  173. function ml.inspectUp() if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "ml.inspectUp: Called") end; local s,d=turtle.inspectUp(); if s and d then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.inspectUp: Success, Block: "..d.name)end; return d else if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.inspectUp: Success, Empty/failed.")end; return nil end end
  174. function ml.inspectDown() if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "ml.inspectDown: Called") end; local s,d=turtle.inspectDown(); if s and d then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.inspectDown: Success, Block: "..d.name)end; return d else if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.inspectDown: Success, Empty/failed.")end; return nil end end
  175. local function genericMove(moveFunc,actionName,updatesPos,updatesDir) if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"genericMove: Action: '"..actionName.."' FuelStart:"..turtle.getFuelLevel())end; local s,e=pcall(moveFunc); if s then if LOG_LEVELS then botLog(LOG_LEVELS.INFO,actionName.." successful. FuelEnd:"..turtle.getFuelLevel())end; if updatesPos and current_pos and current_pos.x~=nil and current_dir~=nil then local oX,oY,oZ=current_pos.x,current_pos.y,current_pos.z; if actionName=="forward"then current_pos.x=current_pos.x+DIR_VECTORS[current_dir].x;current_pos.z=current_pos.z+DIR_VECTORS[current_dir].z elseif actionName=="back"then current_pos.x=current_pos.x-DIR_VECTORS[current_dir].x;current_pos.z=current_pos.z-DIR_VECTORS[current_dir].z elseif actionName=="up"then current_pos.y=current_pos.y+1 elseif actionName=="down"then current_pos.y=current_pos.y-1 end; if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"genericMove: Pos "..oX..","..oY..","..oZ.." -> "..current_pos.x..","..current_pos.y..","..current_pos.z)end; end; if updatesDir and current_dir~=nil then local oD=current_dir; if actionName=="turnLeft"then current_dir=(current_dir-1+4)%4 elseif actionName=="turnRight"then current_dir=(current_dir+1)%4 end; if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"genericMove: Dir "..(oD and DIR_NAMES[oD] or "nil").." -> "..(current_dir and DIR_NAMES[current_dir] or "nil"))end; end; if updatesPos or updatesDir then saveData() end; return true else if LOG_LEVELS then botLog(LOG_LEVELS.WARN,actionName.." failed: "..tostring(e))end; return false end end
  176. function ml.forward() return genericMove(turtle.forward,"forward",true,false) end
  177. function ml.back() return genericMove(turtle.back,"back",true,false) end
  178. function ml.up() return genericMove(turtle.up,"up",true,false) end
  179. function ml.down() return genericMove(turtle.down,"down",true,false) end
  180. function ml.turnLeft() return genericMove(turtle.turnLeft,"turnLeft",false,true) end
  181. function ml.turnRight() return genericMove(turtle.turnRight,"turnRight",false,true) end
  182. function ml.select(slot) if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.select: Slot "..slot) end; turtle.select(slot); return true end
  183. function ml.getItemCount(slot) local c=turtle.getItemCount(slot); if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.getItemCount: Slot "..slot.." has "..c)end; return c end
  184. function ml.getItemDetail(slot) local d=turtle.getItemDetail(slot); if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.getItemDetail: Slot "..slot.." detail: "..(d and textutils.serialize(d, {compact=true}) or "nil"))end; return d end
  185. function ml.getFuelLevel() local l=turtle.getFuelLevel(); if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.getFuelLevel: "..l)end; return l end
  186. function ml.getFuelLimit() local l=turtle.getFuelLimit(); if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.getFuelLimit: "..l)end; return l end
  187. function ml.drop(count) local sl=turtle.getSelectedSlot();local dt=ml.getItemDetail(sl);local iN=(dt and dt.name or "unk item");local aC=count or ml.getItemCount(sl);if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.drop: Attempt drop "..aC.." of "..iN.." from slot "..sl)end;if aC==0 then return true end;local sc;if count then sc=turtle.drop(count)else sc=turtle.drop()end;if sc then if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"ml.drop: Dropped from slot "..sl)end else if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.drop: Fail drop from slot "..sl)end end;return sc end
  188. function ml.suck(count) local sl=turtle.getSelectedSlot();local aC=count or 1;if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.suck: Attempt suck "..aC.." into slot "..sl)end;local sc;if count then sc=turtle.suck(count)else sc=turtle.suck()end;if sc then if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"ml.suck: Sucked items into slot "..sl .. " (requested: "..aC..")")end else if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.suck: Fail suck into slot "..sl)end end;return sc end
  189. function ml.refuel() ml.select(FUEL_SLOT);local it=ml.getItemDetail(FUEL_SLOT);if not it or it.name ~= COAL_BLOCK_NAME then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.refuel: Fail: No/wrong fuel. Expected '"..COAL_BLOCK_NAME.."', Item: "..(it and it.name or "nil"))end;return false end;if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.refuel: Attempt from slot "..FUEL_SLOT.." with "..it.name)end;local iF=ml.getFuelLevel();local s=turtle.refuel();if s then if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"ml.refuel: OK. Fuel: "..ml.getFuelLevel().." (was "..iF..")")end else if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.refuel: turtle.refuel() fail.")end end;return s end
  190. function ml.turnToDir(targetDirNum) if current_dir==nil then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"ml.turnToDir: current_dir is nil.")end; return false end;if targetDirNum<0 or targetDirNum>3 then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"ml.turnToDir: Invalid targetDir: "..targetDirNum)end; return false end;if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.turnToDir: From "..(current_dir and DIR_NAMES[current_dir] or "nil").." ("..current_dir..") to "..DIR_NAMES[targetDirNum].." ("..targetDirNum..")")end;if current_dir==targetDirNum then return true end;local df=(targetDirNum-current_dir+4)%4;if df==1 then return ml.turnRight()elseif df==2 then return ml.turnRight() and ml.turnRight()elseif df==3 then return ml.turnLeft()end;return false end
  191. function ml.moveTo(tx,ty,tz,tdir_opt) print(string.format("Console: ml.moveTo Start - Target X:%s Y:%s Z:%s Dir:%s", tx, ty, tz, (tdir_opt and DIR_NAMES[tdir_opt] or "any"))); if LOG_LEVELS then botLog(LOG_LEVELS.INFO, string.format("ml.moveTo: Attempt: Target X%sY%sZ%sD%s | Current X%sY%sZ%sD%s (%s)",tx,ty,tz,(tdir_opt and DIR_NAMES[tdir_opt] or "any"), current_pos.x,current_pos.y,current_pos.z,current_dir,(current_dir and DIR_NAMES[current_dir] or "nil")))end; local function att(aF,cnt,axisName)for i=1,cnt do if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo.att: "..axisName.." Step "..i.."/"..cnt)end;if not aF()then return false end;if ml.getFuelLevel()<5 and ml.getFuelLimit()>0 then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.moveTo: Low fuel ("..ml.getFuelLevel()..")!")end end;sleep(0.05)end;return true end; if current_pos.y~=ty then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo: Adjust Y "..current_pos.y.."->"..ty)end; while current_pos.y<ty do if not ml.up()then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.moveTo: Blocked UP at Y="..current_pos.y.." to Y="..ty)end;return false end end;while current_pos.y>ty do if not ml.down()then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.moveTo: Blocked DOWN at Y="..current_pos.y.." to Y="..ty)end;return false end end;if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo: Y OK at "..current_pos.y)end end; if current_pos.x~=tx then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo: Adjust X "..current_pos.x.."->"..tx)end; if current_pos.x<tx then if not ml.turnToDir(1)then return false end;if not att(ml.forward,tx-current_pos.x,"East")then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.moveTo: Blocked EAST at X="..current_pos.x.." to X="..tx)end;return false end elseif current_pos.x>tx then if not ml.turnToDir(3)then return false end;if not att(ml.forward,current_pos.x-tx,"West")then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.moveTo: Blocked WEST at X="..current_pos.x.." to X="..tx)end;return false end end;if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo: X OK at "..current_pos.x)end end; if current_pos.z~=tz then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo: Adjust Z "..current_pos.z.."->"..tz)end; if current_pos.z<tz then if not ml.turnToDir(0)then return false end;if not att(ml.forward,tz-current_pos.z,"North")then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.moveTo: Blocked NORTH at Z="..current_pos.z.." to Z="..tz)end;return false end elseif current_pos.z>tz then if not ml.turnToDir(2)then return false end;if not att(ml.forward,current_pos.z-tz,"South")then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"ml.moveTo: Blocked SOUTH at Z="..current_pos.z.." to Z="..tz)end;return false end end;if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo: Z OK at "..current_pos.z)end end; if tdir_opt~=nil and current_dir~=tdir_opt then if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"ml.moveTo: Adjust final dir to "..DIR_NAMES[tdir_opt].." ("..tdir_opt..")")end; if not ml.turnToDir(tdir_opt)then return false end end; if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"ml.moveTo: Target vicinity. Final Pos: X:"..current_pos.x.." Y:"..current_pos.y.." Z:"..current_pos.z.." Dir:"..current_dir.." ("..(current_dir and DIR_NAMES[current_dir] or "nil")..")")end; print(string.format("Console: ml.moveTo End - Current X:%s Y:%s Z:%s Dir:%s", current_pos.x, current_pos.y, current_pos.z, (current_dir and DIR_NAMES[current_dir] or "nil"))); return current_pos.x==tx and current_pos.y==ty and current_pos.z==tz and (tdir_opt == nil or current_dir == tdir_opt) end
  192. --#endregion
  193.  
  194. --#region Core Logic Functions
  195. function initializeBot()
  196.     print("Console: CHKPT - Enter initializeBot");
  197.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initializeBot: Start")end;
  198.     if not pAutomata then if LOG_LEVELS then botLog(LOG_LEVELS.FATAL,"initializeBot: pAutomata nil!")end; print("Console: initializeBot - pAutomata nil, FAIL"); return false end;
  199.    
  200.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"initializeBot: Warp 'home'")end;
  201.     local ws,we=pcall(function()return pAutomata.warpToPoint("home")end);
  202.     if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"initializeBot: Warp pcall: Success="..tostring(ws)..", Result="..tostring(we))end;
  203.     if not ws or not we then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"initializeBot: Warp fail: Success="..tostring(ws)..", Result="..tostring(we))end; print("Console: initializeBot - Warp FAIL"); return false end;
  204.    
  205.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initializeBot: Warp OK. Now at physical home.")end;
  206.     current_pos={x=nil,y=nil,z=nil};current_dir=nil;
  207.  
  208.     local me_bridge_peripheral_found = false
  209.     for i=1,4 do
  210.         if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "initializeBot: Attempt " .. i .. "/4 to find ME Bridge peripheral ("..ME_BRIDGE_PERIPHERAL_NAME..").") end
  211.         pMeBridge = peripheral.find(ME_BRIDGE_PERIPHERAL_NAME)
  212.         if pMeBridge then
  213.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "initializeBot: ME Bridge peripheral (type '"..ME_BRIDGE_PERIPHERAL_NAME.."') found on attempt " .. i .. ".") end
  214.             mounted_peripherals["ME Bridge"] = pMeBridge
  215.             me_bridge_peripheral_found = true
  216.             break
  217.         end
  218.         if i < 4 then
  219.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "initializeBot: ME Bridge peripheral not found in current direction. Turning right.") end
  220.             if not turtle.turnRight() then
  221.                 if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "initializeBot: turtle.turnRight() failed during ME Bridge peripheral search.") end
  222.                 return false
  223.             end
  224.             sleep(0.2)
  225.         end
  226.     end
  227.  
  228.     if not me_bridge_peripheral_found then
  229.         if LOG_LEVELS then botLog(LOG_LEVELS.FATAL, "initializeBot: ME Bridge peripheral (type '"..ME_BRIDGE_PERIPHERAL_NAME.."') NOT found after 4 attempts. This is required.") end
  230.         return false
  231.     end
  232.  
  233.     pColonyIntegrator = findPeripheral("Colony Integrator", COLONY_INTEGRATOR_PERIPHERAL_NAME, true)
  234.     if not pColonyIntegrator then
  235.         if LOG_LEVELS then botLog(LOG_LEVELS.FATAL, "initializeBot: Colony Integrator peripheral NOT found (it is required).") end
  236.         return false
  237.     end
  238.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initializeBot: Home location peripherals (ME Bridge, Colony Integrator) found and attached.") end
  239.  
  240.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "initializeBot: Confirming visual orientation to ME Bridge block ('"..ME_BRIDGE_NAME.."')...") end
  241.     local visually_oriented_to_me_block = false
  242.     for visual_orient_attempt = 1, 4 do
  243.         local success_inspect, block_in_front = turtle.inspect()
  244.         if success_inspect and block_in_front and block_in_front.name == ME_BRIDGE_NAME then
  245.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "initializeBot: Visually confirmed: ME_BRIDGE_NAME block is in front (attempt " .. visual_orient_attempt .. ").") end
  246.             visually_oriented_to_me_block = true
  247.             break
  248.         end
  249.         if visual_orient_attempt < 4 then
  250.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "initializeBot: Not visually facing ME_BRIDGE_NAME block. Turning right for visual confirmation.") end
  251.             if not turtle.turnRight() then
  252.                 if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "initializeBot: turtle.turnRight() failed during visual ME Bridge confirmation.") end
  253.                 return false
  254.             end
  255.             sleep(0.2)
  256.         end
  257.     end
  258.    
  259.     if not visually_oriented_to_me_block then
  260.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "initializeBot: Could not visually confirm ME_BRIDGE_NAME block in front after 4 attempts. This is needed for coordinate setup.") end
  261.         return false
  262.     end
  263.    
  264.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"initializeBot: Backing up from ME Bridge.")end;
  265.     if not turtle.back()then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"initializeBot: Raw turtle.back() failed after orienting to ME Bridge.")end; print("Console: initializeBot - Back ME FAIL"); return false end;
  266.    
  267.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"initializeBot: Turning right to face Redstone path.")end;
  268.     if not turtle.turnRight()then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"initializeBot: Raw turtle.turnRight() failed (to face Redstone path).")end; print("Console: initializeBot - TR after back FAIL"); return false end;
  269.    
  270.     local forward_count_to_redstone=0;
  271.     local redstone_retries=0;
  272.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"initializeBot: Searching for Redstone Block ("..REDSTONE_BLOCK_NAME..") along path...")end;
  273.     while true do
  274.         -- CORRECTED THE RETURN VALUE HANDLING FOR PCALL(TURTLE.INSPECT)
  275.         local pcall_success, inspect_success_val, block_data_val_or_errmsg = pcall(turtle.inspect);
  276.        
  277.         if pcall_success and inspect_success_val and block_data_val_or_errmsg and type(block_data_val_or_errmsg) == "table" and block_data_val_or_errmsg.name==REDSTONE_BLOCK_NAME then
  278.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initializeBot: Redstone Block found after " .. forward_count_to_redstone .. " forward moves.")end;
  279.             break
  280.         end;
  281.        
  282.         if DEBUG_LOGGING_ENABLED and LOG_LEVELS then
  283.             local block_ahead_log_str = "pcall_fail"
  284.             if pcall_success then
  285.                 if inspect_success_val then
  286.                     if block_data_val_or_errmsg and type(block_data_val_or_errmsg) == "table" then
  287.                         block_ahead_log_str = block_data_val_or_errmsg.name
  288.                     else
  289.                         block_ahead_log_str = "empty" -- inspect success, but no block table (air)
  290.                     end
  291.                 else
  292.                     block_ahead_log_str = "inspect_fail:" .. tostring(block_data_val_or_errmsg) -- inspect failed, block_data_val_or_errmsg is error
  293.                 end
  294.             else
  295.                  block_ahead_log_str = "pcall_fail:" .. tostring(inspect_success_val) -- pcall failed, inspect_success_val is pcall error
  296.             end
  297.             botLog(LOG_LEVELS.DEBUG,"initializeBot: Redstone not found in front, moving forward. Count:"..forward_count_to_redstone.." BlockAhead: " .. block_ahead_log_str)
  298.         end;
  299.        
  300.         if turtle.forward()then
  301.             forward_count_to_redstone=forward_count_to_redstone+1;
  302.             redstone_retries=0
  303.         else
  304.             if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"initializeBot: Path to Redstone obstructed. Retry "..(redstone_retries+1).."/"..MAX_REDSTONE_BLOCK_RETRIES)end;
  305.             redstone_retries=redstone_retries+1;
  306.             if redstone_retries>=MAX_REDSTONE_BLOCK_RETRIES then
  307.                 if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"initializeBot: Failed to reach Redstone Block after multiple retries.")end; print("Console: initializeBot - Redstone search FAIL (obstructed)"); return false
  308.             end;
  309.             sleep(REDSTONE_BLOCK_RETRY_WAIT)
  310.         end
  311.     end;
  312.    
  313.     roboSlot = forward_count_to_redstone + 1;
  314.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initializeBot: Determined roboSlot: "..roboSlot)end;
  315.    
  316.     local redstone_block_abs_x = -110
  317.     local redstone_block_abs_y = 65
  318.     local redstone_block_abs_z = 220
  319.     local redstone_block_abs_dir = 1
  320.    
  321.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, string.format("initializeBot: Setting current pos at Redstone (Slot %d's marker): X%d Y%d Z%d Dir%s(1)", roboSlot, redstone_block_abs_x, redstone_block_abs_y, redstone_block_abs_z, DIR_NAMES[redstone_block_abs_dir]))end;
  322.     ml.setPos(redstone_block_abs_x, redstone_block_abs_y, redstone_block_abs_z, redstone_block_abs_dir);
  323.    
  324.     home_pos.x = redstone_block_abs_x - (roboSlot - 1);
  325.     home_pos.y = redstone_block_abs_y;
  326.     home_pos.z = redstone_block_abs_z + 1;
  327.     home_pos.dir = 0;
  328.    
  329.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,string.format("initializeBot: Calculated home_pos: X%s Y%s Z%s Dir%s (%s)",home_pos.x,home_pos.y,home_pos.z,home_pos.dir, DIR_NAMES[home_pos.dir]))end;
  330.    
  331.     if not saveData()then if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"initializeBot: Save data failed post-initialization.")end end;
  332.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"initializeBot: Initialization complete.")end;
  333.     print("Console: CHKPT - initializeBot OK");
  334.     return true
  335. end
  336.  
  337. function maneuverToBarrelsFromHome()
  338.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"maneuverToBarrelsFromHome: Start")end;
  339.     if not(current_pos.x==home_pos.x and current_pos.y==home_pos.y and current_pos.z==home_pos.z and current_dir==home_pos.dir)then
  340.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"maneuverToBarrelsFromHome: Not at home! Current: X"..current_pos.x.." Y"..current_pos.y.." Z"..current_pos.z.." D"..current_dir..". Home: X"..home_pos.x.." Y"..home_pos.y.." Z"..home_pos.z.." D"..home_pos.dir..". Aborting.")end;
  341.         return false
  342.     end;
  343.     if not ml.moveTo(REFUEL_BARREL_ACCESS_POS.x,REFUEL_BARREL_ACCESS_POS.y,REFUEL_BARREL_ACCESS_POS.z,REFUEL_BARREL_ACCESS_POS.dir)then
  344.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"maneuverToBarrelsFromHome: Failed ml.moveTo barrel access point.")end;
  345.         return false
  346.     end;
  347.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"maneuverToBarrelsFromHome: OK, at barrel access point.")end;
  348.     return true
  349. end
  350.  
  351. function maneuverHomeFromBarrels()
  352.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"maneuverHomeFromBarrels: Start")end
  353.     if not(current_pos.x==REFUEL_BARREL_ACCESS_POS.x and current_pos.y==REFUEL_BARREL_ACCESS_POS.y and current_pos.z==REFUEL_BARREL_ACCESS_POS.z and current_dir==REFUEL_BARREL_ACCESS_POS.dir)then
  354.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"maneuverHomeFromBarrels: Not at barrel access point! Abort.")end; return false
  355.     end
  356.  
  357.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"maneuverHomeFromBarrels: Current pos at barrel access: X"..current_pos.x.." Y"..current_pos.y.." Z"..current_pos.z.." D"..DIR_NAMES[current_dir])end
  358.    
  359.     if not ml.turnRight() then return false end
  360.     if not ml.forward() then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"maneuverHomeFromBarrels: Failed forward (North) after turning from barrel access.")end; return false end
  361.  
  362.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"maneuverHomeFromBarrels: Intermediate pos: X"..current_pos.x.." Y"..current_pos.y.." Z"..current_pos.z.." D"..DIR_NAMES[current_dir])end
  363.  
  364.     local deltaX = home_pos.x - current_pos.x
  365.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"maneuverHomeFromBarrels: Calculated deltaX to home: " .. deltaX .. " (home_pos.x: "..home_pos.x..", current_pos.x: "..current_pos.x..")") end
  366.  
  367.     if deltaX > 0 then
  368.         if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"maneuverHomeFromBarrels: Moving East by "..deltaX)end
  369.         if not ml.turnToDir(1) then return false end
  370.         for _=1, deltaX do
  371.             if not ml.forward() then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"maneuverHomeFromBarrels: Failed move East step.")end; return false end
  372.         end
  373.     elseif deltaX < 0 then
  374.         if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"maneuverHomeFromBarrels: Moving West by "..math.abs(deltaX))end
  375.         if not ml.turnToDir(3) then return false end
  376.         for _=1, math.abs(deltaX) do
  377.             if not ml.forward() then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"maneuverHomeFromBarrels: Failed move West step.")end; return false end
  378.         end
  379.     end
  380.    
  381.     if not ml.turnToDir(home_pos.dir) then
  382.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"maneuverHomeFromBarrels: Failed to turn North for final approach.")end; return false
  383.     end
  384.  
  385.     if current_pos.z ~= home_pos.z then
  386.         local deltaZ = home_pos.z - current_pos.z
  387.         if deltaZ == 1 and current_dir == 0 then
  388.              if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"maneuverHomeFromBarrels: Moving final step North to Z:"..home_pos.z)end
  389.             if not ml.forward() then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"maneuverHomeFromBarrels: Failed final Northward move to home Z.")end; return false end
  390.         else
  391.             if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"maneuverHomeFromBarrels: Unexpected Z difference or direction for final move. deltaZ: "..deltaZ..", current_dir: "..current_dir)end; return false
  392.         end
  393.     end
  394.    
  395.     if current_pos.x==home_pos.x and current_pos.y==home_pos.y and current_pos.z==home_pos.z and current_dir==home_pos.dir then
  396.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"maneuverHomeFromBarrels: OK, successfully at home.")end; return true
  397.     else
  398.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,string.format("maneuverHomeFromBarrels: Homing FAILED. Position Mismatch. Expected X%sY%sZ%sD%s, Got X%sY%sZ%sD%s", home_pos.x,home_pos.y,home_pos.z,DIR_NAMES[home_pos.dir], current_pos.x,current_pos.y,current_pos.z,DIR_NAMES[current_dir]))end;
  399.         return false
  400.     end
  401. end
  402.  
  403. function goHomeProcedure()
  404.     print("Console: CHKPT - Enter goHomeProcedure");
  405.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"goHomeProcedure: Start")end;
  406.     if current_pos.x==home_pos.x and current_pos.y==home_pos.y and current_pos.z==home_pos.z and current_dir==home_pos.dir then
  407.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"goHomeProcedure: Already at home.")end; print("Console: goHomeProcedure - Already home");
  408.         return true
  409.     end;
  410.    
  411.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"goHomeProcedure: Navigating to nest entry point x-113 y100 z221...")end;
  412.     if not ml.moveTo(-113,100,221,nil)then
  413.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"goHomeProcedure: Failed to navigate to nest entry point.")end; print("Console: goHomeProcedure - moveTo nest entry FAIL");
  414.         return false
  415.     end;
  416.    
  417.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"goHomeProcedure: At nest entry. Descending to Y65.")end;
  418.     while current_pos.y > 65 do
  419.         if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"goHomeProcedure: Descending. Current Y:"..current_pos.y)end;
  420.         if not ml.down()then
  421.             if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"goHomeProcedure: Descend failed at Y:"..current_pos.y)end; print("Console: goHomeProcedure - descend FAIL");
  422.             return false
  423.         end
  424.     end;
  425.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"goHomeProcedure: Descended to Y65.")end;
  426.    
  427.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"goHomeProcedure: Moving to barrel access position defined by REFUEL_BARREL_ACCESS_POS")end;
  428.     if not ml.moveTo(REFUEL_BARREL_ACCESS_POS.x,REFUEL_BARREL_ACCESS_POS.y,REFUEL_BARREL_ACCESS_POS.z,REFUEL_BARREL_ACCESS_POS.dir)then
  429.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"goHomeProcedure: Failed to move to defined barrel access position.")end;
  430.         return false
  431.     end;
  432.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"goHomeProcedure: Positioned at refuel barrel access point.")end;
  433.    
  434.     if not maneuverHomeFromBarrels()then
  435.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"goHomeProcedure: maneuverHomeFromBarrels (called from goHomeProcedure) failed.")end;
  436.         return false
  437.     end;
  438.    
  439.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"goHomeProcedure: Successfully returned home.")end;
  440.     print("Console: CHKPT - goHomeProcedure OK");
  441.     return true
  442. end
  443.  
  444. function handleFuel()
  445.     print("Console: CHKPT - Enter handleFuel");
  446.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleFuel: Start")end;
  447.     if not(current_pos.x==REFUEL_BARREL_ACCESS_POS.x and current_pos.y==REFUEL_BARREL_ACCESS_POS.y and current_pos.z==REFUEL_BARREL_ACCESS_POS.z and current_dir==REFUEL_BARREL_ACCESS_POS.dir)then
  448.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"handleFuel: Not at barrel access point. Skipping fuel handling.")end;
  449.         return true
  450.     end;
  451.    
  452.     local fuel_level, fuel_limit = ml.getFuelLevel(), ml.getFuelLimit();
  453.     if fuel_limit == 0 then
  454.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleFuel: Infinite fuel detected.")end;
  455.         return true
  456.     end;
  457.    
  458.     local fuel_percentage = (fuel_level / fuel_limit);
  459.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,string.format("handleFuel: Fuel: %d/%d (%.2f%%)",fuel_level,fuel_limit,fuel_percentage*100))end;
  460.    
  461.     local needs_refuel = fuel_percentage < REFUEL_BELOW_PERCENTAGE;
  462.     local coal_detail = ml.getItemDetail(FUEL_SLOT);
  463.     local coal_count = ml.getItemCount(FUEL_SLOT);
  464.     local needs_restock = not coal_detail or coal_detail.name ~= COAL_BLOCK_NAME or coal_count < (coal_detail and coal_detail.maxCount or 64);
  465.  
  466.     if needs_refuel or needs_restock then
  467.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleFuel: Action required. Needs Refuel="..tostring(needs_refuel)..", Needs Restock="..tostring(needs_restock))end;
  468.        
  469.         if needs_restock then
  470.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleFuel: Restocking fuel slot "..FUEL_SLOT.." with "..COAL_BLOCK_NAME)end;
  471.             ml.select(FUEL_SLOT);
  472.             if coal_detail and coal_detail.name ~= COAL_BLOCK_NAME and coal_count > 0 then
  473.                 if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"handleFuel: Non-"..COAL_BLOCK_NAME.." item found in fuel slot! Cannot restock unless slot is cleared or contains correct item type.")end
  474.             else
  475.                 local amount_to_suck = (coal_detail and coal_detail.maxCount or 64) - coal_count;
  476.                 if amount_to_suck > 0 then
  477.                     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"handleFuel: Attempting to suck "..amount_to_suck.." "..COAL_BLOCK_NAME..".")end;
  478.                     if ml.suck(amount_to_suck)then
  479.                         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleFuel: Sucked "..COAL_BLOCK_NAME.." into fuel slot. New count: "..ml.getItemCount(FUEL_SLOT))end
  480.                     else
  481.                         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"handleFuel: Failed to suck "..COAL_BLOCK_NAME.." into fuel slot.")end
  482.                     end
  483.                 else
  484.                      if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"handleFuel: Fuel slot already full of "..COAL_BLOCK_NAME.." or needs 0 items.")end
  485.                 end
  486.             end
  487.         end;
  488.        
  489.         coal_detail = ml.getItemDetail(FUEL_SLOT)
  490.         if fuel_percentage < REFUEL_BELOW_PERCENTAGE and coal_detail and coal_detail.name == COAL_BLOCK_NAME then
  491.              if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleFuel: Refueling...")end;
  492.              if not ml.refuel()then
  493.                 if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"handleFuel: ml.refuel() attempt failed.")end
  494.              end
  495.         elseif fuel_percentage < REFUEL_BELOW_PERCENTAGE then
  496.             if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"handleFuel: Needs refuel, but fuel slot does not contain "..COAL_BLOCK_NAME)end
  497.         end
  498.     else
  499.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleFuel: Fuel level and stock OK.")end
  500.     end;
  501.     print("Console: CHKPT - Exit handleFuel");
  502.     return true
  503. end
  504.  
  505. function handleItemReturn()
  506.     print("Console: CHKPT - Enter handleItemReturn");
  507.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleItemReturn: Start")end;
  508.     if not(current_pos.x==REFUEL_BARREL_ACCESS_POS.x and current_pos.y==REFUEL_BARREL_ACCESS_POS.y and current_pos.z==REFUEL_BARREL_ACCESS_POS.z and current_dir==REFUEL_BARREL_ACCESS_POS.dir)then
  509.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"handleItemReturn: Not at barrel access point. Skipping item return.")end;
  510.         return true
  511.     end;
  512.    
  513.     local items_found_to_return=false;
  514.     for slot_idx=1,15 do
  515.         if ml.getItemCount(slot_idx)>0 then
  516.             items_found_to_return=true;
  517.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"handleItemReturn: Found items in slot "..slot_idx.." to return.")end;
  518.             break
  519.         end
  520.     end;
  521.    
  522.     if not items_found_to_return then
  523.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleItemReturn: No items in cargo slots 1-15 to return.")end; print("Console: handleItemReturn - No items");
  524.         return true
  525.     end;
  526.    
  527.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleItemReturn: Items found for return. Moving up to Return Barrel.")end;
  528.     if not ml.up()then
  529.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"handleItemReturn: Failed to move up to Return Barrel level.")end; print("Console: handleItemReturn - up FAIL");
  530.         return false
  531.     end;
  532.    
  533.     for slot_idx=1,15 do
  534.         ml.select(slot_idx);
  535.         local item_count_in_slot=ml.getItemCount(slot_idx);
  536.         if item_count_in_slot > 0 then
  537.             local item_detail=ml.getItemDetail(slot_idx);
  538.             local item_name = item_detail and item_detail.name or "Unknown Item";
  539.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"handleItemReturn: Attempting to return "..item_count_in_slot.."x "..item_name.." from slot "..slot_idx)end;
  540.             if not ml.drop()then
  541.                 if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"handleItemReturn: Failed to drop items from slot "..slot_idx)end
  542.             end
  543.         end
  544.     end;
  545.    
  546.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"handleItemReturn: Finished attempting returns. Moving down from Return Barrel level.")end;
  547.     if not ml.down()then
  548.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"handleItemReturn: Failed to move down from Return Barrel level.")end; print("Console: handleItemReturn - down FAIL");
  549.         return false
  550.     end;
  551.    
  552.     undeliveredItemsBuffer = {}
  553.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"handleItemReturn: Item return process complete.")end;
  554.     print("Console: CHKPT - Exit handleItemReturn");
  555.     return true
  556. end
  557.  
  558. function getItemsFromME(itemsToGetTable)
  559.     print("Console: CHKPT - Enter getItemsFromME")
  560.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "getItemsFromME: Start processing item requests.") end
  561.  
  562.     if not (current_pos.x == home_pos.x and current_pos.y == home_pos.y and current_pos.z == home_pos.z and current_dir == home_pos.dir) then
  563.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN, "getItemsFromME: Not at home position. Aborting.") end
  564.         return {}
  565.     end
  566.     if not pMeBridge then
  567.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "getItemsFromME: pMeBridge (ME Bridge peripheral) is nil. Aborting.") end
  568.         return {}
  569.     end
  570.  
  571.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "getItemsFromME: Moving up to access ME transfer chest.") end
  572.     if not ml.up() then
  573.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "getItemsFromME: Failed to move up to ME transfer chest level.") end
  574.         return {}
  575.     end
  576.  
  577.     local fetched_item_details = {}
  578.  
  579.     for _, requested_item_spec in ipairs(itemsToGetTable) do
  580.         if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "getItemsFromME: Requesting " .. requested_item_spec.count .. "x " .. requested_item_spec.name .. " from ME system.") end
  581.        
  582.         local export_success, export_result = pcall(function() return pMeBridge.exportItem({ name = requested_item_spec.name, count = requested_item_spec.count }, "up") end)
  583.        
  584.         if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "getItemsFromME: exportItem pcall Success=" .. tostring(export_success) .. ", Result=" .. textutils.serialize(export_result)) end
  585.  
  586.         if not export_success or type(export_result) ~= "number" or export_result == 0 then
  587.             if LOG_LEVELS then botLog(LOG_LEVELS.WARN, "getItemsFromME: ME export failed or exported 0 for " .. requested_item_spec.name .. ". Error/Msg: " .. tostring(export_result)) end
  588.             goto continue_me_item_request
  589.         end
  590.  
  591.         local actual_exported_count = export_result
  592.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "getItemsFromME: ME Bridge exported " .. actual_exported_count .. "x " .. requested_item_spec.name .. " to chest.") end
  593.        
  594.         local amount_remaining_to_suck_from_chest = actual_exported_count
  595.         while amount_remaining_to_suck_from_chest > 0 do
  596.             local target_slot = -1
  597.             for s = 1, 15 do
  598.                 local item_in_slot = ml.getItemDetail(s)
  599.                 if item_in_slot and item_in_slot.name == requested_item_spec.name and item_in_slot.count < item_in_slot.maxCount then
  600.                     target_slot = s
  601.                     break
  602.                 end
  603.             end
  604.             if target_slot == -1 then
  605.                 for s = 1, 15 do
  606.                     if not ml.getItemDetail(s) then
  607.                         target_slot = s
  608.                         break
  609.                     end
  610.                 end
  611.             end
  612.  
  613.             if target_slot == -1 then
  614.                 if LOG_LEVELS then botLog(LOG_LEVELS.WARN, "getItemsFromME: No inventory space for more '" .. requested_item_spec.name .. "' (needed " .. amount_remaining_to_suck_from_chest .. "). Items may remain in chest.") end
  615.                 break
  616.             end
  617.  
  618.             ml.select(target_slot)
  619.             local space_in_this_slot = turtle.getItemSpace(target_slot)
  620.             local attempt_suck_amount = math.min(amount_remaining_to_suck_from_chest, space_in_this_slot)
  621.  
  622.             if attempt_suck_amount == 0 then
  623.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "getItemsFromME: Slot " .. target_slot .. " is full or no more items needed for " .. requested_item_spec.name .. ". Skipping suck.") end
  624.                 break
  625.             end
  626.            
  627.             local count_in_slot_before_suck = ml.getItemCount(target_slot)
  628.             if ml.suck(attempt_suck_amount) then
  629.                 local count_in_slot_after_suck = ml.getItemCount(target_slot)
  630.                 local num_actually_sucked_this_op = count_in_slot_after_suck - count_in_slot_before_suck
  631.                
  632.                 if num_actually_sucked_this_op > 0 then
  633.                     amount_remaining_to_suck_from_chest = amount_remaining_to_suck_from_chest - num_actually_sucked_this_op
  634.                    
  635.                     local existing_entry_idx = -1
  636.                     for i, entry in ipairs(fetched_item_details) do
  637.                         if entry.slot == target_slot then
  638.                             existing_entry_idx = i; break
  639.                         end
  640.                     end
  641.                     if existing_entry_idx ~= -1 then
  642.                         fetched_item_details[existing_entry_idx].count = count_in_slot_after_suck
  643.                     else
  644.                         table.insert(fetched_item_details, { name = requested_item_spec.name, slot = target_slot, count = count_in_slot_after_suck })
  645.                     end
  646.                     if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "getItemsFromME: Sucked " .. num_actually_sucked_this_op .. "x " .. requested_item_spec.name .. " into slot " .. target_slot .. ". Total in slot: " .. count_in_slot_after_suck .. ". Remaining from chest: " .. amount_remaining_to_suck_from_chest) end
  647.                 else
  648.                     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "getItemsFromME: ml.suck() transferred 0 items for " .. requested_item_spec.name .. " into slot " .. target_slot .. ". Chest might be empty for this item now.") end
  649.                     break
  650.                 end
  651.             else
  652.                 if LOG_LEVELS then botLog(LOG_LEVELS.WARN, "getItemsFromME: ml.suck() failed for " .. requested_item_spec.name .. " into slot " .. target_slot .. ". Chest might be obstructed or empty.") end
  653.                 break
  654.             end
  655.         end
  656.         ::continue_me_item_request::
  657.     end
  658.  
  659.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "getItemsFromME: Finished processing all item requests. Moving down from ME chest level.") end
  660.     if not ml.down() then
  661.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "getItemsFromME: Failed to move down from ME transfer chest level.") end
  662.     end
  663.  
  664.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "getItemsFromME: Process complete. Fetched " .. #fetched_item_details .. " item stacks/details.") end
  665.     print("Console: CHKPT - Exit getItemsFromME")
  666.     return fetched_item_details
  667. end
  668.  
  669. function leaveNest()
  670.     print("Console: CHKPT - Enter leaveNest");
  671.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"leaveNest: Start")end;
  672.    
  673.     local start_exit_pos_x = home_pos.x
  674.     local start_exit_pos_y = home_pos.y
  675.     local start_exit_pos_z = home_pos.z - 1
  676.     local start_exit_dir = 1
  677.  
  678.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, string.format("leaveNest: Moving to its redstone block position (X%s Y%s Z%s Dir%s) to begin exit sequence.", start_exit_pos_x, start_exit_pos_y, start_exit_pos_z, DIR_NAMES[start_exit_dir]))end;
  679.     if not ml.moveTo(start_exit_pos_x, start_exit_pos_y, start_exit_pos_z, start_exit_dir)then
  680.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"leaveNest: Failed to move to its redstone block to start exit sequence.")end;
  681.         return false
  682.     end;
  683.    
  684.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"leaveNest: Turning South (TR from East).")end;
  685.     if not ml.turnRight()then return false end;
  686.    
  687.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"leaveNest: Moving Forward (South).")end;
  688.     if not ml.forward()then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"leaveNest: Obstructed moving South during exit.")end;return false end;
  689.    
  690.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"leaveNest: Turning West (TR from South).")end;
  691.     if not ml.turnRight()then return false end;
  692.    
  693.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"leaveNest: Moving Forward (West).")end;
  694.     if not ml.forward()then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"leaveNest: Obstructed moving West during exit.")end;return false end;
  695.    
  696.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"leaveNest: Ascending to Y=100...")end;
  697.     while current_pos.y < 100 do
  698.         if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"leaveNest: Ascending. Current Y:"..current_pos.y)end;
  699.         if not ml.up()then if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"leaveNest: Obstructed during ascent at Y:"..current_pos.y)end;return false end
  700.     end;
  701.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"leaveNest: Reached Y=100.")end;
  702.    
  703.     local target_exit_x = -111
  704.     local target_exit_y = 100
  705.     local target_exit_z = 221
  706.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, string.format("leaveNest: Moving to final exit point (X%s Y%s Z%s).",target_exit_x, target_exit_y, target_exit_z))end;
  707.     if not ml.moveTo(target_exit_x, target_exit_y, target_exit_z, nil)then
  708.         if LOG_LEVELS then botLog(LOG_LEVELS.WARN, string.format("leaveNest: Could not reach precise final exit point. Current Y:%s. Target was X%s Y%s Z%s.", current_pos.y, target_exit_x, target_exit_y, target_exit_z))end;
  709.         if current_pos.y ~= target_exit_y then
  710.             if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"leaveNest: Critical - Y coordinate incorrect after ascent and moveTo. Expected Y"..target_exit_y)end;
  711.             return false
  712.         end
  713.     end;
  714.    
  715.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,string.format("leaveNest: Successfully exited nest. Current Position: X:%s Y:%s Z:%s Dir:%s (%s)",current_pos.x,current_pos.y,current_pos.z,current_dir, DIR_NAMES[current_dir]))end;
  716.     print("Console: CHKPT - Exit leaveNest");
  717.     return true
  718. end
  719.  
  720. function deliverItems(target_pos,items_in_slots_details)
  721.     print("Console: CHKPT - Enter deliverItems");
  722.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,string.format("deliverItems: Target X:%s Y:%s Z:%s",target_pos.x,target_pos.y,target_pos.z))end;
  723.    
  724.     if not ml.moveTo(target_pos.x,target_pos.y,target_pos.z,nil)then
  725.         if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"deliverItems: Failed to move to delivery location.")end;
  726.         for _,item_detail_entry in ipairs(items_in_slots_details)do
  727.             table.insert(undeliveredItemsBuffer,{name=item_detail_entry.name,count=item_detail_entry.count,original_slot=item_detail_entry.slot})
  728.         end;
  729.         if DEBUG_LOGGING_ENABLED and LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"deliverItems: All items for this delivery moved to undeliveredItemsBuffer. Buffer size:"..#undeliveredItemsBuffer)end;
  730.         return false
  731.     end;
  732.    
  733.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"deliverItems: Arrived at delivery location. Attempting to drop items.")end;
  734.     for _,item_detail_entry in ipairs(items_in_slots_details)do
  735.         ml.select(item_detail_entry.slot);
  736.         local count_to_drop = ml.getItemCount(item_detail_entry.slot);
  737.        
  738.         if count_to_drop > 0 then
  739.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"deliverItems: Attempting to drop "..count_to_drop.."x "..item_detail_entry.name.." from slot "..item_detail_entry.slot)end;
  740.             if not ml.drop(count_to_drop)then
  741.                 if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"deliverItems: Failed to drop all items ("..item_detail_entry.name..") from slot "..item_detail_entry.slot)end;
  742.                 local remaining_count = ml.getItemCount(item_detail_entry.slot);
  743.                 if remaining_count > 0 then
  744.                     table.insert(undeliveredItemsBuffer,{name=item_detail_entry.name,count=remaining_count,original_slot=item_detail_entry.slot});
  745.                     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"deliverItems: "..remaining_count.."x "..item_detail_entry.name.." from slot "..item_detail_entry.slot.." added to undeliveredItemsBuffer.")end
  746.                 end
  747.             else
  748.                 if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"deliverItems: Successfully dropped "..count_to_drop.."x "..item_detail_entry.name.." from slot "..item_detail_entry.slot)end
  749.             end
  750.         end
  751.     end;
  752.    
  753.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"deliverItems: Delivery attempt complete.")end;
  754.     print("Console: CHKPT - Exit deliverItems");
  755.     return true
  756. end
  757. --#endregion
  758.  
  759. --#region Main Loop
  760. local function run()
  761.     print("Console: CHKPT - run() CALLED")
  762.     do
  763.         local fileNameToOpen = LOG_FILE_NAME_CONST
  764.         if type(fileNameToOpen) ~= "string" then
  765.             print("Console: CRITICAL - LOG_FILE_NAME_CONST is nil AT THE POINT OF OPENING. Forcing default for safety.")
  766.             fileNameToOpen = "villagebot_forced_CRITICAL.log"
  767.         end
  768.         local f,ferr=fs.open(fileNameToOpen,"w")
  769.         if f then
  770.             f.write(string.format("[%s] VillageBot Log Initialized.\n",os.date("%Y-%m-%d %H:%M:%S")))
  771.             f.close()
  772.             print("Console: Log file reset and initialized using: " .. fileNameToOpen)
  773.         else
  774.             print("Console: CRITICAL - Log init FAIL for '" .. tostring(fileNameToOpen) .. "': "..tostring(ferr))
  775.             if LOG_LEVELS and pcall then
  776.                  pcall(botLog,LOG_LEVELS.FATAL,"CRITICAL - Log init FAIL: "..tostring(ferr))
  777.             end
  778.             return
  779.         end
  780.     end
  781.  
  782.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"VillageBot v1.4 Starting...") else print("Console: VillageBot v1.4 Starting... (LOG_LEVELS nil)") end
  783.     sleep(0.1)
  784.     if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"RUN: Attempt init core peripherals...") end; sleep(0.1)
  785.     local corePOK=initCorePeripherals();
  786.     if not corePOK then if LOG_LEVELS then botLog(LOG_LEVELS.FATAL,"RUN: initCorePeripherals FAILED. Terminating script.")end; print("Console: Error - Core Peripheral init FAILED. Terminate from run()."); return end
  787.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"RUN: Core Peripherals OK.")end; sleep(0.1)
  788.    
  789.     local data_setup_successful=false
  790.     if loadData() and roboSlot~=nil and home_pos and home_pos.x~=nil and current_pos and current_pos.x~=nil and current_dir~=nil then
  791.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"RUN: Bot data loaded successfully. RoboSlot:"..roboSlot)end
  792.         data_setup_successful=true
  793.     else
  794.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"RUN: No valid data file found or data incomplete. Performing full initialization.")end
  795.         if fs.exists(BOT_DATA_FILE) then
  796.              if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"RUN: Existing data file was present but invalid. Deleting it.")end
  797.              pcall(fs.delete, BOT_DATA_FILE)
  798.         end
  799.         if initializeBot()then
  800.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"RUN: Bot full initialization successful.")end
  801.             data_setup_successful=true
  802.         else
  803.             if LOG_LEVELS then botLog(LOG_LEVELS.FATAL,"RUN: Bot full initialization FAILED. Terminating script.")end;print("Console: Error - Bot core initialization FAILED. Terminate.");return
  804.         end
  805.     end
  806.     if not data_setup_successful then if LOG_LEVELS then botLog(LOG_LEVELS.FATAL,"RUN: Failed to load or initialize bot data. Terminating script.")end;print("Console: FATAL - Data setup FAILED. Terminate.");return end
  807.    
  808.     if not pMeBridge or not pColonyIntegrator then
  809.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "RUN: Home location peripherals (ME Bridge, Colony Integrator) not yet confirmed/attached. Ensuring bot is home and then finding/attaching them.") end
  810.         if not (current_pos.x == home_pos.x and current_pos.y == home_pos.y and current_pos.z == home_pos.z and current_dir == home_pos.dir) then
  811.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "RUN: Bot is not at home. Running goHomeProcedure to reach home first.") end
  812.             if not goHomeProcedure() then
  813.                 if LOG_LEVELS then botLog(LOG_LEVELS.FATAL, "RUN: goHomeProcedure failed during setup phase. Cannot find home peripherals. Terminating.") end
  814.                 return
  815.             end
  816.         end
  817.         if not findHomeLocationPeripherals() then
  818.             if LOG_LEVELS then botLog(LOG_LEVELS.FATAL, "RUN: Failed to find/attach home location peripherals even after ensuring bot is at home. Terminating.") end
  819.             return
  820.         end
  821.     end
  822.  
  823.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"RUN: Data load/initialization phase complete. All required peripherals should now be found."); end; sleep(0.1)
  824.     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"RUN: Entering main operational loop...")end;
  825.    
  826.     while true do
  827.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "===== Starting New Cycle =====")end; sleep(0.1)
  828.        
  829.         local dummy_work_order, items_to_fetch, fetched_items_summary = nil,nil,nil
  830.         local needs_dedicated_barrel_trip_flag = false
  831.         local fuel_check_still_needed_flag = true
  832.         local item_return_check_still_needed_flag = true
  833.         local was_at_barrels_this_cycle_leg = false
  834.  
  835.         if not (current_pos.x == home_pos.x and current_pos.y == home_pos.y and current_pos.z == home_pos.z and current_dir == home_pos.dir) then
  836.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "LOOP: Not at home. Current: X"..current_pos.x.." Y"..current_pos.y.." Z"..current_pos.z.." D"..(current_dir and DIR_NAMES[current_dir] or "nil")..". Executing goHomeProcedure.")end
  837.             if not goHomeProcedure() then
  838.                 if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"LOOP: goHomeProcedure failed. Retrying cycle after a delay.")end
  839.                 sleep(60); goto continue_main_loop_cycle
  840.             end
  841.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: goHomeProcedure completed. Bot should now be at home (and passed barrels).")end
  842.             was_at_barrels_this_cycle_leg = true
  843.         else
  844.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Started cycle already at home position.")end
  845.         end
  846.  
  847.         if was_at_barrels_this_cycle_leg then
  848.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Bot was at barrels during goHomeProcedure transit. Performing necessary checks now.")end
  849.         else
  850.             local current_fuel_level = ml.getFuelLevel(); local current_fuel_limit = ml.getFuelLimit()
  851.             if current_fuel_limit == 0 or (current_fuel_limit > 0 and (current_fuel_level / current_fuel_limit >= REFUEL_BELOW_PERCENTAGE)) then
  852.                 fuel_check_still_needed_flag = false
  853.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Fuel OK or infinite type, no dedicated trip needed *just* for low fuel percentage.")end
  854.             else
  855.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Fuel is low. Dedicated trip for fuel may be needed.")end
  856.             end
  857.  
  858.             local items_in_cargo_slots = false
  859.             for slot_idx=1,15 do if ml.getItemCount(slot_idx) > 0 then items_in_cargo_slots = true; break; end end
  860.             if not items_in_cargo_slots then
  861.                 item_return_check_still_needed_flag = false
  862.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: No items in cargo slots, no dedicated trip needed *just* for item return.")end
  863.             else
  864.                  if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Items found in cargo slots. Dedicated trip for item return may be needed.")end
  865.             end
  866.            
  867.             local coal_detail_check = ml.getItemDetail(FUEL_SLOT)
  868.             local needs_fuel_slot_restock = not coal_detail_check or coal_detail_check.name ~= COAL_BLOCK_NAME or ml.getItemCount(FUEL_SLOT) < (coal_detail_check and coal_detail_check.maxCount or 64)
  869.             if needs_fuel_slot_restock then
  870.                  if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Fuel slot needs restocking. Dedicated trip for fuel may be needed.")end
  871.                  fuel_check_still_needed_flag = true
  872.             end
  873.  
  874.             needs_dedicated_barrel_trip_flag = fuel_check_still_needed_flag or item_return_check_still_needed_flag
  875.  
  876.             if needs_dedicated_barrel_trip_flag then
  877.                 if LOG_LEVELS then botLog(LOG_LEVELS.INFO, "LOOP: Bot is at home, but needs fuel/item return. Maneuvering to barrels. FuelNeeded="..tostring(fuel_check_still_needed_flag).." ItemReturnNeeded="..tostring(item_return_check_still_needed_flag))end
  878.                 if not maneuverToBarrelsFromHome() then
  879.                     if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "LOOP: Failed to maneuver to barrels from home. Retrying cycle after a delay.")end
  880.                     sleep(60); goto continue_main_loop_cycle
  881.                 end
  882.                 was_at_barrels_this_cycle_leg = true
  883.             else
  884.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Bot is at home, and no dedicated fuel/return operations are immediately required from here.")end
  885.             end
  886.         end
  887.  
  888.         if was_at_barrels_this_cycle_leg then
  889.             if item_return_check_still_needed_flag then
  890.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Performing item return at barrels.")end
  891.                 if not handleItemReturn() then
  892.                     if LOG_LEVELS then botLog(LOG_LEVELS.WARN, "LOOP: An issue occurred during item return at barrels. Continuing.")end
  893.                 end
  894.             end
  895.             if fuel_check_still_needed_flag then
  896.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Performing fuel handling at barrels.")end
  897.                 if not handleFuel() then
  898.                     if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "LOOP: Failed fuel handling at barrels. Retrying cycle after a delay.")end;
  899.                     sleep(60); goto continue_main_loop_cycle
  900.                 end
  901.             end
  902.            
  903.             if not (current_pos.x == home_pos.x and current_pos.y == home_pos.y and current_pos.z == home_pos.z and current_dir == home_pos.dir) then
  904.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG, "LOOP: Not at home after barrel operations. Maneuvering home from barrels.")end
  905.                 if not maneuverHomeFromBarrels() then
  906.                     if LOG_LEVELS then botLog(LOG_LEVELS.ERROR, "LOOP: Failed to maneuver home from barrels after operations. Retrying cycle after a delay.")end
  907.                     sleep(60); goto continue_main_loop_cycle
  908.                 end
  909.             end
  910.         end
  911.        
  912.         if not(current_pos.x==home_pos.x and current_pos.y==home_pos.y and current_pos.z==home_pos.z and current_dir==home_pos.dir) then
  913.              if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"LOOP: CRITICAL - NOT AT HOME before attempting to get work! Pos: X"..current_pos.x.." Y"..current_pos.y.." Z"..current_pos.z.." D"..(current_dir and DIR_NAMES[current_dir] or "nil")..". Forcing goHomeProcedure.")end
  914.              if not goHomeProcedure() then
  915.                  if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"LOOP: Critical Failure on forced goHomeProcedure. Retrying cycle after a delay.")end
  916.                  sleep(60); goto continue_main_loop_cycle
  917.              end
  918.         end
  919.         if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"LOOP: Position confirmed at home before starting work tasks.")end
  920.  
  921.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"LOOP: Fetching work order (V1.4 Placeholder)...")end
  922.         dummy_work_order={id="dummyWorkOrder123", resources={{name="minecraft:cobblestone",count=65},{name="minecraft:dirt",count=33}}, target_location={x=home_pos.x+10,y=home_pos.y,z=home_pos.z+5}}
  923.         if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,string.format("LOOP: Dummy Work Order: Deliver items to X:%s Y:%s Z:%s", dummy_work_order.target_location.x, dummy_work_order.target_location.y, dummy_work_order.target_location.z ))end
  924.        
  925.         if dummy_work_order and dummy_work_order.resources then
  926.             items_to_fetch = dummy_work_order.resources
  927.             fetched_items_summary = getItemsFromME(items_to_fetch)
  928.            
  929.             if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"LOOP: getItemsFromME returned "..#fetched_items_summary.." item slot details.")end
  930.            
  931.             local has_items_to_deliver = false
  932.             if fetched_items_summary and #fetched_items_summary > 0 then
  933.                 for _, item_entry in ipairs(fetched_items_summary) do
  934.                     if item_entry.count > 0 then has_items_to_deliver = true; break; end
  935.                 end
  936.             end
  937.  
  938.             if has_items_to_deliver then
  939.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"LOOP: Items fetched. Attempting to leave nest.")end
  940.                 if not leaveNest()then
  941.                     if LOG_LEVELS then botLog(LOG_LEVELS.ERROR,"LOOP: Failed to leave nest. Items will be returned next cycle if still in inventory. Retrying cycle after delay.")end
  942.                     sleep(30);goto continue_main_loop_cycle
  943.                 end
  944.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"LOOP: leaveNest successful.")end
  945.                
  946.                 if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"LOOP: Attempting to deliver items.")end
  947.                 if not deliverItems(dummy_work_order.target_location, fetched_items_summary)then
  948.                     if LOG_LEVELS then botLog(LOG_LEVELS.WARN,"LOOP: Delivery issues encountered. Any undelivered items were buffered (and will be handled by handleItemReturn next cycle).")end
  949.                 else
  950.                     if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"LOOP: deliverItems process completed (check logs for specifics).")end
  951.                 end
  952.             else
  953.                 if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"LOOP: No items were actually fetched from ME system for the current work order, or fetched items had 0 count.")end
  954.             end
  955.         else
  956.             if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"LOOP: No work orders found or work order invalid.")end
  957.         end
  958.  
  959.         if LOG_LEVELS then botLog(LOG_LEVELS.INFO,"===== Cycle Ended Successfully =====")end
  960.         ::continue_main_loop_cycle::
  961.         if LOG_LEVELS then botLog(LOG_LEVELS.DEBUG,"LOOP: Sleeping for 30 seconds before next cycle.")end
  962.         print("Console: LOOP - Cycle End. Sleeping 30s.")
  963.         sleep(30)
  964.     end
  965.     if LOG_LEVELS then botLog(LOG_LEVELS.FATAL,"RUN: Main operational loop EXITED UNEXPECTEDLY!")end; print("Console: FATAL - Main loop EXITED!")
  966. end
  967. --#endregion
  968.  
  969. -- Start the bot
  970. print("Console: DEBUG - Script execution starting. About to call run().")
  971. run()
  972. print("Console: DEBUG - Script execution finished. run() function has completed/exited.")
  973. if LOG_LEVELS and LOG_FILE_NAME_CONST and type(LOG_FILE_NAME_CONST) == "string" then
  974.     pcall(botLog,LOG_LEVELS.FATAL, "SCRIPT ENDED ABNORMALLY: Reached end of file after run() call, indicating run() exited.")
  975. else
  976.     print("Console: SCRIPT ENDED ABNORMALLY (LOG_LEVELS or LOG_FILE_NAME_CONST was nil/invalid, cannot use botLog for final message).")
  977. end
Add Comment
Please, Sign In to add comment