77wisher77

stripMine Persistent

Jun 8th, 2021 (edited)
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.42 KB | None | 0 0
  1. local PROGRAM_VERSION = "1.0"
  2. -- TODO: add more args to configure
  3. --    preffered fuel?, height Layers?, height tier up/down
  4. -- TODO: remove dependency downloads and checks, should be handled by startup, reduces issues with different modpacks needing different files
  5. -- TODO: logic for wireless command activation
  6. -- TODO: vertical strip logic/cycles
  7. -- TODO: autostart in startup, wait for wireless input if no active file/=true, and inform user to CTRL+T and relaunch with args to enter manually
  8. -- TODO: enderchest stuff
  9. -- TODO: if out of fuel turtle doesnt know and keeps looping, need to stop and pause, need checks for fuel levels, new fuel logic will probs handle it
  10.  
  11. local PROGRAM_NAME = "STRIP_MINE_PERSISTENT"
  12.  
  13.  
  14. --make a dependencies table with pastebin download links
  15. local DEPENDENCIES = {
  16.   [1] = {
  17.     ["name"] = "wLibMining",
  18.     ["link"] = "rJjmGPwk",
  19.     ["path"] = "wisher/"
  20.   },
  21.   [2] = {
  22.     ["name"] = "wLibVariables",
  23.     ["link"] = "P1xXXYKC",
  24.     ["path"] = "wisher/"
  25.   },
  26.   [3] = {
  27.     ["name"] = "wLibFs",
  28.     ["link"] = "", --TODO: add link
  29.     ["path"] = "wisher/"
  30.   }
  31. }
  32.  
  33. -- Ensures all Libraries/Apis are downloaded
  34. function checkDependencies()
  35.   local libList = {} -- for libs physically located on the robot
  36.   local apiExist = false
  37.   for i, v in ipairs(DEPENDENCIES) do
  38.     local libName = DEPENDENCIES[i]["path"]..DEPENDENCIES[i]["name"]
  39.     libList[i] = shell.resolveProgram(libName) -- attempts to add the filename of dependency[i] to libList to prove it exists
  40.     if(libList[i]==libName) then --if the lib exists then set true so file is not downloaded
  41.       print("Found file: "..DEPENDENCIES[i]["name"])
  42.       apiExist = true
  43.       --sleep(0.15) -- for readability
  44.     end
  45.     if(apiExist==false) then -- if the lib doesnt exist, restart to have startup grab it or cancel out manually
  46.       --local libLink = DEPENDENCIES[i]["link"]
  47.       print("Dependencies not found")
  48.       print("press'CTRL+T' to exit and manually fix, restarting automatically")
  49.       sleep(2)
  50.       os.reboot() -- TODO: launch startup with the command to force download files (if still using pastebin or if gitlab doesnt like tonnes of downloads)
  51.     end -- at this point the file should be downloaded and we SHOULD be able to continue the for loop normally?
  52.     apiExist = false
  53.   end
  54. end
  55. checkDependencies()
  56. -- Dynamically initializes DEPENDENCIES globally, only if one with the same name doesnt already exist
  57. for keyLibIndex, valueLibName in ipairs(DEPENDENCIES) do
  58.   local libraryName = DEPENDENCIES[keyLibIndex]["name"]
  59.   local libraryPath = DEPENDENCIES[keyLibIndex]["path"]..DEPENDENCIES[keyLibIndex]["name"]
  60.   if(_G[libraryName]) then
  61.     print("Already Loaded: "..libraryName)
  62.   end
  63.   if(not _G[libraryName]) then
  64.     _G[libraryName] = require(libraryPath)
  65.     print("Loaded: "..libraryName)
  66.   end
  67. end
  68. sleep(2) -- for readability
  69.  
  70.  
  71. -- expected args
  72. local cycles = 1
  73. local mineDistance = 96
  74. local refuelCount = 3
  75. local argCount = 3 -- #of expected args
  76.  
  77. -- persistence variables
  78. local isActive -- was running before current boot
  79. local r_mineDistance -- mineDistance left on current cycle
  80. local strips -- total strips left --TODO: possibly dont need this
  81. local r_turnReturnStrip --total return strips left
  82. local r_turnReturnStripStatus -- if and how the turtle is positioned in a turn
  83. local r_turnNewStrip -- total new strips left
  84. local r_turnNewStripStatus -- if and how the turtle is positioned in a turn
  85. local r_exportInvStatus -- If and where the turtle is at with exporting inventory
  86.  
  87. -- persistence files
  88. local stateDir = "wisher/_states/stripMine/"
  89. local completeFile = stateDir.."isComplete"
  90. local activeFile = stateDir.."isActive"
  91. local conf_mineDistance = stateDir.."_mineDistance"
  92. local pers_mineDistance = stateDir.."mineDistance"
  93. local pers_strips = stateDir.."stripsRemaining" --cycles x2 at start, number of strips left to do
  94. local pers_turnReturn = stateDir.."turnReturn" -- number of remaining return strips
  95. local pers_turnReturnStatus = stateDir.."turnReturnStatus" -- 0 if not turning, 1 if turned, 2 if moved forward, (then 0 if finished turning?)
  96. local pers_turnNewStrip = stateDir.."turnNewStrip" --number of new strips remaining
  97. local pers_turnNewStripStatus = stateDir.."turnNewStripStatus" -- 0 if not turning, 1 if turned, 2 if moved forward, (then 0 if finished turning?)
  98. local pers_inventoryExportStatus = stateDir.."invExpStatus" -- 0 if not exporting, 1 placed inventory, 2 can deposite & exported, 3 ERROR can't deposit (no chest? or access problem), 4 ERROR still too many full slots in turtle (chest full?)
  99.  
  100. local pers_files = {
  101.   [1] = activeFile,
  102.   [2] = conf_mineDistance,
  103.   [3] = pers_mineDistance,
  104.   [4] = pers_strips,
  105.   [5] = pers_turnReturn,
  106.   [6] = pers_turnReturnStatus,
  107.   [7] = pers_turnNewStrip,
  108.   [8] = pers_turnNewStripStatus
  109. }
  110.  
  111. if (#arg > 0) then
  112.   isActive = false
  113. elseif (wLibFs.exists(activeFile)) then
  114.   isActive = wLibFs.read(nil, activeFile, 2, nil, true)
  115.   if (isActive == "") then
  116.     isActive = false
  117.   elseif (isActive == "true") then
  118.     isActive = true
  119.   elseif (isActive == "false") then
  120.     isActive = false
  121.   end
  122. else
  123.   isActive = false
  124. end
  125.  
  126.  
  127. -- To stop program from auto-contiuing when turtle should remain still
  128. if wLibFs.exists(completeFile) then
  129.   print("Strip mine previously completed")
  130.   print("press key to clear configs and continue")
  131.   os.pullEvent("key_up")
  132.   fs.delete(completeFile)
  133.   print("Cleared Configs!")
  134.   sleep(2)
  135.   shell.run("clear")
  136. end
  137.  
  138. if not (isActive) then
  139.   if wLibFs.exists(stateDir.."_errorLog") then
  140.     fs.delete(stateDir.."_errorLog") -- if not currently meant to be running then delete error log, error log shouldnt exist if the entire config was deleted
  141.   end
  142.  
  143.   --TODO: print out a message telling user to cancel program and launch manually with args or to enter args wirelessly
  144.  
  145.   for argIndex=1,#arg,1 do
  146.     if(argIndex>argCount) then
  147.       print("Incorrect number of args")
  148.       print("Defaulting to:")
  149.       break
  150.     end
  151.     if(argIndex==1) then cycles = tonumber(arg[argIndex]) end
  152.     if(argIndex==2) then mineDistance = tonumber(arg[argIndex]) end
  153.     if(argIndex==3) then refuelCount = tonumber(arg[argIndex]) end
  154.     if(argIndex==#arg) then print("Args received:") end
  155.     --if(argIndex>argCount) then print("Discarding unknown arg "..arg[argIndex]) -- could be used but will leave disabled, safer to just use defaults
  156.   end
  157.   if(#arg==0) then
  158.     print("No args")
  159.     print("Defaulting to:")
  160.   end
  161.   print("Cycles= "..cycles..", Mine Distance= "..mineDistance.." blocks"..", fuelConsume#= "..refuelCount)
  162.   print("waiting a few seconds so you can verify the args")
  163.   sleep(1)
  164.  
  165.   print("saving settings, please wait")
  166.   wLibFs.write(nil, conf_mineDistance, tostring(mineDistance), 2, true)
  167.   wLibFs.write(nil, pers_mineDistance, tostring(mineDistance), 2, true)
  168.   r_mineDistance = mineDistance
  169.   wLibFs.write(nil, pers_strips, tostring(cycles * 2), 2, true)
  170.   strips = (cycles * 2)
  171.   wLibFs.write(nil, pers_turnReturn, tostring(cycles), 2, true)
  172.   r_turnReturnStrip = cycles
  173.   wLibFs.write(nil, pers_turnReturnStatus, tostring(0), 2, true)
  174.   r_turnReturnStripStatus = 0
  175.   wLibFs.write(nil, pers_turnNewStrip, tostring(cycles - 1), 2, true)
  176.   r_turnNewStrip = (cycles - 1)
  177.   wLibFs.write(nil, pers_turnNewStripStatus, tostring(0), 2, true)
  178.   r_turnNewStripStatus = 0
  179.   wLibFs.write(nil, pers_inventoryExportStatus, tostring(0), 2, true)
  180.   r_exportInvStatus = 0
  181.   wLibFs.write(nil, activeFile, tostring(true), 2, true)
  182.   sleep(1) -- give files some time
  183.   print("Saved!")
  184.  
  185. elseif isActive then
  186.  
  187.   local isFullyConfigured = true
  188.   for i, file in ipairs(pers_files) do
  189.     if not (wLibFs.exists(file)) then
  190.       isFullyConfigured = false
  191.     end
  192.     if (wLibFs.read(nil, file, 2, nil, true) == "") then
  193.       isFullyConfigured = false
  194.     end
  195.   end
  196.   if (isFullyConfigured) then
  197.     mineDistance = tonumber(wLibFs.read(nil, conf_mineDistance, 2, nil, true))
  198.     r_mineDistance = tonumber(wLibFs.read(nil, pers_mineDistance, 2, nil, true))
  199.     strips = tonumber(wLibFs.read(nil, pers_strips, 2, nil, true))
  200.     r_turnReturnStrip = tonumber(wLibFs.read(nil, pers_turnReturn, 2, nil, true))
  201.     r_turnReturnStripStatus = tonumber(wLibFs.read(nil, pers_turnReturnStatus, 2, nil, true))
  202.     r_turnNewStrip = tonumber(wLibFs.read(nil, pers_turnNewStrip, 2, nil, true))
  203.     r_turnNewStripStatus = tonumber(wLibFs.read(nil, pers_turnNewStripStatus, 2, nil, true))
  204.     r_exportInvStatus = tonumber(wLibFs.read(nil, pers_inventoryExportStatus, 2, nil, true))
  205.     cycles = math.ceil(strips / 2)
  206.  
  207.   elseif not isFullyConfigured then
  208.     local handle = wLibFs.write(nil, stateDir.."_errorLog", os.date(), 2, false)
  209.     wLibFs.write(handle, nil, "Config Corrupted, unable to safely continue", 2, true)
  210.     print("Config corrupted, unable to continue safely")
  211.     print("please press CTRL+T and refer to the log")
  212.     os.pullEvent("key_up") -- stops program from contiuing, turtle may get lost
  213.   end
  214.  
  215. end
  216.  
  217.  
  218. -- if adjusting r_mineDistance here will need to check its not 0, leave at 0 until end of turn then reset to full for forward() to deplete
  219. -- add optional parameter for turning manuevers, e.g. isOverride = isOverride or false so we can use the function to move forward while r_mineDistance == 0
  220. -- to move forward and dig, iterate this in a for loop to move needed number of times
  221. -- when coding is more advanced we will use this better
  222. function forward(isOverride, isReduceMineDistance)
  223.   isOverride = isOverride or false
  224.   isReduceMineDistance = isReduceMineDistance or true
  225.   -- check/ensure atleast 3 slots free to store mined items, stripmine may mine up to 3 blocks per movement
  226.   if (not wLibMining.emptySlots(3)) then
  227.     wLibMining.dropItems()
  228.   end
  229.   if ((isOverride) or (r_mineDistance > 0)) then
  230.     wLibMining.detectAndDigStrip()
  231.     turtle.forward()
  232.     if isReduceMineDistance then
  233.       wLibFs.write(nil, pers_mineDistance, tostring(r_mineDistance - 1), 2, true)
  234.       r_mineDistance = r_mineDistance - 1
  235.     end
  236.   elseif ((r_mineDistance == 0) and (not (isOverride))) then
  237.     local handle = wLibFs.write(nil, stateDir.."_errorLog", os.date(), 2, false)
  238.     wLibFs.write(handle, nil, "Tried to move forward while mineDistance = 0", 2, true)
  239.     print("mineDistance forward() error")
  240.     print("please press CTRL+T and refer to the log")
  241.     os.pullEvent("key_up")
  242.   end
  243. end
  244.  
  245. -- reduces return strip count and updates turnStripStatus at each interval. Once finished should reset mineDistance to full
  246. --    and set turnStripStatus to the starting value
  247. --to return from far end of a strip
  248. function turnReturnStrip(isOverride, isResetMineDistance)
  249.   isOverride = isOverride or false
  250.   isResetMineDistance = isResetMineDistance or true
  251.   if ((isOverride) or ((r_mineDistance == 0) and (r_turnReturnStrip > 0))) then
  252.     if (r_turnReturnStripStatus == 0) then
  253.       turtle.turnRight()
  254.       wLibFs.write(nil, pers_turnReturnStatus, tostring(1), 2, true)
  255.       r_turnReturnStripStatus = 1
  256.     end
  257.     if (r_turnReturnStripStatus == 1) then
  258.       forward(true, false)
  259.       wLibFs.write(nil, pers_turnReturnStatus, tostring(2), 2, true)
  260.       r_turnReturnStripStatus = 2
  261.     end
  262.     if (r_turnReturnStripStatus == 2) then
  263.       turtle.turnRight()
  264.       wLibFs.write(nil, pers_turnReturnStatus, tostring(0), 2, true)
  265.       r_turnReturnStripStatus = 0
  266.       if (not isOverride) then
  267.         wLibFs.write(nil, pers_turnReturn, tostring(r_turnReturnStrip - 1), 2, true)
  268.         r_turnReturnStrip = r_turnReturnStrip - 1
  269.       end
  270.       if isResetMineDistance then
  271.         wLibFs.write(nil, pers_mineDistance, (tostring(tonumber(wLibFs.read(nil, conf_mineDistance, 2, nil, true)))), 2, true)
  272.         r_mineDistance = mineDistance
  273.       end
  274.     end
  275.   elseif ((r_turnReturnStrip == 0) and (not isOverride)) then
  276.     local handle = wLibFs.write(nil, stateDir.."_errorLog", os.date(), 2, false)
  277.     wLibFs.write(handle, nil, "Tried to turnReturnStrip() when turnReturn = 0", 2, true)
  278.     print("Return Strip# turnReturnStrip() error")
  279.     print("please press CTRL+T and refer to the log")
  280.     os.pullEvent("key_up")
  281.   elseif ((r_mineDistance > 0) and (not isOverride)) then
  282.     local handle = wLibFs.write(nil, stateDir.."_errorLog", os.date(), 2, false)
  283.     wLibFs.write(handle, nil, "Tried to turnReturnStrip() when mineDistance > 0", 2, true)
  284.     print("mineDistance turnReturnStrip() error")
  285.     print("please press CTRL+T and refer to the log")
  286.     os.pullEvent("key_up")
  287.   end
  288. end
  289.  
  290. -- persistence should work the same as turnReturnStrip
  291. --to begin a new strip, use if there is more than 1 cycle
  292. function turnNewStrip(isOverride, isResetMineDistance)
  293.   isOverride = isOverride or false
  294.   isResetMineDistance = isResetMineDistance or true
  295.   if ((isOverride) or ((r_mineDistance == 0) and (r_turnNewStrip > 0))) then
  296.     if (r_turnNewStripStatus == 0) then
  297.       turtle.turnLeft()
  298.       wLibFs.write(nil, pers_turnNewStripStatus, tostring(1), 2, true)
  299.       r_turnNewStripStatus = 1
  300.     end
  301.     if (r_turnNewStripStatus == 1) then
  302.       forward(true, false)
  303.       wLibFs.write(nil, pers_turnNewStripStatus, tostring(2), 2, true)
  304.       r_turnNewStripStatus = 2
  305.     end
  306.     if (r_turnNewStripStatus == 2) then
  307.       turtle.turnLeft()
  308.       wLibFs.write(nil, pers_turnNewStripStatus, tostring(0), 2, true)
  309.       r_turnNewStripStatus = 0
  310.       if (not isOverride) then
  311.         wLibFs.write(nil, pers_turnNewStrip, tostring(r_turnNewStrip - 1), 2, true)
  312.         r_turnNewStrip = r_turnNewStrip - 1
  313.       end
  314.       if isResetMineDistance then
  315.         wLibFs.write(nil, pers_mineDistance, (tostring(tonumber(wLibFs.read(nil, conf_mineDistance, 2, nil, true)))), 2, true)
  316.         r_mineDistance = mineDistance
  317.       end
  318.     end
  319.   elseif ((r_turnNewStrip == 0) and (not isOverride)) then
  320.     local handle = wLibFs.write(nil, stateDir.."_errorLog", os.date(), 2, false)
  321.     wLibFs.write(handle, nil, "Tried to turnNewStrip() when turnNew = 0", 2, true)
  322.     print("NewStrip# turnNewStrip() error")
  323.     print("please press CTRL+T and refer to the log")
  324.     os.pullEvent("key_up")
  325.   elseif ((r_mineDistance > 0) and (not isOverride)) then
  326.     local handle = wLibFs.write(nil, stateDir.."_errorLog", os.date(), 2, false)
  327.     wLibFs.write(handle, nil, "Tried to turnNewStrip() when mineDistance > 0", 2, true)
  328.     print("MineDistance turnNewStrip() error")
  329.     print("please press CTRL+T and refer to the log")
  330.     os.pullEvent("key_up")
  331.   end
  332. end
  333.  
  334.  
  335. function exportInventory(isOverride)
  336.   isOverride = isOverride or false
  337.   local handle = wLibFs.open(stateDir.."_errorLog", "w")
  338.   if ((isOverride) or ((r_mineDistance == 0) and ((r_turnReturnStrip == r_turnNewStrip) and (r_turnNewStrip > 0)) )) then
  339.     if (r_exportInvStatus == 0) then
  340.       wLibMining.placeInventoryLocal()
  341.       wLibFs.write(nil, pers_inventoryExportStatus, tostring(1), 2, true)
  342.       r_exportInvStatus = 1
  343.     end
  344.     if (r_exportInvStatus == 1) then
  345.       if(wLibMining.depositInventory()) then
  346.         wLibMining.exportInventoryMining()
  347.         wLibFs.write(nil, pers_inventoryExportStatus, tostring(2), 2, true)
  348.         r_exportInvStatus = 2
  349.       end
  350.       if(not wLibMining.depositInventory()) then
  351.         wLibFs.write(nil, pers_strips, tostring(1))
  352.         wLibFs.write(nil, pers_inventoryExportStatus, tostring(3), 2, true)
  353.         strips = 1
  354.         r_exportInvStatus = 3
  355.         wLibFs.write(handle, nil, os.date(), 2, false)
  356.         wLibFs.write(handle, nil, "DepositInventory() returned false, did chest get placed?", 2, false)
  357.         print("Unable deposit inventory, did the chest get placed?")
  358.       end
  359.     end
  360.     if ((r_exportInvStatus == 2) or (r_exportInvStatus == 3)) then
  361.       if(not wLibMining.emptySlots(3)) then -- if unable to clear inventory into export too acceptable level then stop
  362.         wLibFs.write(nil, pers_strips, tostring(1))
  363.         wLibFs.write(nil, pers_inventoryExportStatus, tostring(4), 2, true)
  364.         strips = 1
  365.         r_exportInvStatus = 4
  366.         wLibFs.write(handle, nil, os.date(), 2, false)
  367.         wLibFs.write(handle, nil, "emptySlots() failed, is the chest full?", 2, false)
  368.         print("Unable export inventory, is the chest full?")
  369.       end
  370.     end
  371.     if ((r_exportInvStatus == 3) or (r_exportInvStatus == 4)) then
  372.       handle.close()
  373.       print("please press CTRL+T and check logs")
  374.       os.pullEvent("key_up")
  375.     end
  376.     if (r_exportInvStatus == 2) then
  377.       handle.close()
  378.       fs.delete(stateDir.."_errorLog")
  379.       wLibFs.write(nil, pers_inventoryExportStatus, tostring(0), 2, true)
  380.       r_exportInvStatus = 0
  381.     end
  382.  
  383.   end
  384. end
  385.  
  386.  
  387. -- add logic to check whats happening in persistence files, should read the status of turns first
  388. -- need a startup bool that can be used to set the current minedistance
  389. -- Main Function
  390. function start()
  391.   -- split into halves so robot finished beside where it started for strip mines
  392.   -- bear in mind if more than 1 cycle is present the turtle needs an inventory to deploy
  393.   -- TODO: adjust checkFuel, dropItems to calculate when to do that based on mineDistance
  394.  
  395.   -- ensure the first run after booting mines the correct distance, then set so all other runs do the expected distance
  396.   local firstRun = true -- first run after reboot, should be used to set mineDistance to r_mineDistance
  397.  
  398.   local fuelThreshold = 80 * refuelCount - 70 -- assumes the smallest fuel source, larger ones shouldnt be problematic
  399.   print("Initiating: " ..PROGRAM_NAME.." "..PROGRAM_VERSION)
  400.   wLibMining.checkFuel(refuelCount, fuelThreshold)
  401.   repeat
  402.  
  403.   if (firstRun) then
  404.  
  405.     if (r_exportInvStatus > 0) then
  406.       exportInventory()
  407.     end
  408.  
  409.     if (r_turnReturnStripStatus > 0) then
  410.       turnReturnStrip()
  411.       print("2nd half of STRIP MINE Cycle"..cycles)
  412.     end
  413.     if (r_turnNewStripStatus > 0) then
  414.       turnNewStrip()
  415.       print("1st half of Cycle "..cycles)
  416.     end
  417.  
  418.     if ((r_mineDistance ~= mineDistance) and (not (r_mineDistance == 0))) then
  419.       mineDistance = r_mineDistance
  420.     end
  421.  
  422.   end
  423.  
  424.   for i=1,mineDistance,1 do
  425.     if((turtle.getFuelLevel()) / (fuelThreshold - 1) == 1) then wLibMining.checkFuel(refuelCount, fuelThreshold) end
  426.     --if(i%47==0) then wLibMining.checkFuel(refuelCount, fuelThreshold) end
  427.     -- if(i%10==0) then wLibMining.dropItems() end -- not needed now as checked on each forward()
  428.     forward()
  429.   end
  430.   print("Turning!")
  431.  
  432.   if ((firstRun) and (mineDistance ~= ( tonumber(wLibFs.read(nil, conf_mineDistance, 2, nil, true)) ) )) then
  433.     mineDistance = tonumber(wLibFs.read(nil, conf_mineDistance, 2, nil, true))
  434.   end
  435.   if firstRun then
  436.     firstRun = false
  437.   end
  438.  
  439.   if(strips>1) then
  440.  
  441.     --TODO: persistence breaks here, need persistence for exporting inv
  442.     exportInventory()
  443.  
  444.     if (strips > 1) then
  445.  
  446.       if((turtle.getFuelLevel()) / (fuelThreshold - 1) == 1) then wLibMining.checkFuel(refuelCount, fuelThreshold) end
  447.  
  448.       if (r_turnReturnStrip > r_turnNewStrip) then
  449.         turnReturnStrip()
  450.         print("Finished Turning!")
  451.         print("1st half of Cycle "..cycles)
  452.       elseif (r_turnReturnStrip == r_turnNewStrip) then
  453.         turnNewStrip()
  454.         print("Finished Turning!")
  455.         print("2nd half of STRIP MINE Cycle"..cycles)
  456.       end
  457.     end
  458.  
  459.   end
  460.   wLibFs.write(nil, pers_strips, tostring(strips - 1), 2, true)
  461.   strips = strips-1
  462.  
  463.   until strips==0
  464.  
  465.   fs.delete(stateDir)
  466.   wLibFs.newFileBlank(completeFile, true)
  467.   print("Completed STRIP MINE")
  468.   print("press key to clear configs and reboot")
  469.   os.pullEvent("key_up")
  470.   fs.delete(completeFile)
  471.   os.reboot()
  472.  
  473. end
  474. start()
Add Comment
Please, Sign In to add comment