emily99

CC Turtle: miner/excgps

Jun 23rd, 2023 (edited)
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.80 KB | None | 0 0
  1. if not turtle then
  2.     printError("Requires a Turtle")
  3.     return
  4. end
  5.  
  6. if 0 ~= tonumber(settings.get("miner.done",0)) then
  7.     printError("Current area marked as done! Change settings or run 'miner/sethome.lua' to allow another excavation.")
  8.     error()
  9. end
  10.  
  11. -- Mine in a quarry pattern until we hit something we can't dig
  12. local size = tonumber(settings.get("miner.exc_rad",20))
  13. if size < 1 then
  14.     printError("Excavate diameter must be positive")
  15.     error()
  16. end
  17.  
  18. -- Some forward-declarations
  19. local goTo, refuel
  20. local _await, _awaitRefuel
  21.  
  22. local xPos, zPos, depth, lowDepth
  23. local xDir, zDir
  24. local tohomeFuel
  25.  
  26. -- gps.locate() that does not return until it succeeds
  27. local function locate()
  28.     local printed = false
  29.     local x,y,z
  30.     repeat
  31.         x,y,z = gps.locate()
  32.         if x == nil then
  33.             if not printed then
  34.                 print("GPS Error! Please fix!")
  35.                 rednet.broadcast({"gpserr"},"excgps")
  36.                 printed = true
  37.             end
  38.             _await(5, true)
  39.         end
  40.     until x ~= nil
  41.     return x,y,z
  42. end
  43.  
  44. -- Save settings to disk
  45. local function save()
  46.     settings.save(".settings")
  47. end
  48.  
  49. -- Setup network
  50. local sides = {"up","down","left","right","forward","back"}
  51. local function openNet()
  52.     if rednet.isOpen() then
  53.         return true
  54.     else
  55.         for i = 1,#sides do
  56.             if peripheral.getType(sides[i]) == "modem" then
  57.                 if rednet.open(sides[i]) then
  58.                     return true
  59.                 end
  60.             end
  61.         end
  62.     end
  63.     return false
  64. end
  65. local function sendPos()
  66.     if not rednet.isOpen() then return end
  67.     local x,y,z = locate()
  68.     rednet.broadcast({"coord",x,y,z},"excgps")
  69. end
  70. if not openNet() then
  71.     printError("Failed to open rednet connection; modem required")
  72.     error()
  73. end
  74.  
  75. -- Mine straight down this far first
  76. local startDepth = tonumber(settings.get("miner.sdepth",10))
  77. -- Max distance to mine down before stopping, even if no bedrock reached
  78. local maxDepth = tonumber(settings.get("miner.mdepth",999))
  79. -- Extra distance to travel forwards before starting mining
  80. local wanderDist = tonumber(settings.get("miner.wander",0))
  81.  
  82. --The home location to return supplies to, absolute coordinates
  83. local homex = tonumber(settings.get("miner.homex",nil))
  84. local homey = tonumber(settings.get("miner.homey",nil))
  85. local homez = tonumber(settings.get("miner.homez",nil))
  86. local hxDir = tonumber(settings.get("miner.homexd",nil))
  87. local hzDir = tonumber(settings.get("miner.homezd",nil))
  88.  
  89. local function refuel(ammount)
  90.     local fuelLevel = turtle.getFuelLevel()
  91.     if fuelLevel == "unlimited" then
  92.         return true
  93.     end
  94.  
  95.     local needed = ammount or xPos + zPos + depth + tohomeFuel + 64
  96.     if turtle.getFuelLevel() < needed then
  97.         for n = 1, 16 do
  98.             if turtle.getItemCount(n) > 0 then
  99.                 turtle.select(n)
  100.                 if turtle.refuel(1) then
  101.                     while turtle.getItemCount(n) > 0 and turtle.getFuelLevel() < needed do
  102.                         turtle.refuel(1)
  103.                     end
  104.                     if turtle.getFuelLevel() >= needed then
  105.                         turtle.select(1)
  106.                         return true
  107.                     end
  108.                 end
  109.             end
  110.         end
  111.         turtle.select(1)
  112.         return false
  113.     end
  114.  
  115.     return true
  116. end
  117. local function fuelCheck()
  118.     refuel(16)
  119.     _await(0)
  120. end
  121. function _await(s, nopos)
  122.     if not nopos then sendPos() end
  123.     sleep(s or 0.05)
  124. end
  125. function _awaitRefuel(fuelNeeded)
  126.     repeat
  127.         turtle.suckUp(64)
  128.     until refuel(fuelNeeded)
  129. end
  130.  
  131. -- Use two separate locates to determine facing direction
  132. local function getDirs(bMine)
  133.     local invert = false
  134.     local x1,_1,z1 = locate()
  135.     fuelCheck()
  136.     if not turtle.forward() then
  137.         if turtle.back() then
  138.             invert = true
  139.         end
  140.         if not invert then
  141.             while not turtle.forward() do
  142.                 if bMine then turtle.dig() end
  143.                 fuelCheck()
  144.                 _await()
  145.             end
  146.         end
  147.     end
  148.     local x2,_2,z2 = locate()
  149.     local xd,zd = x2-x1,z2-z1
  150.     if invert then
  151.         xd,zd = -xd,-zd
  152.         while not turtle.forward() do
  153.             fuelCheck()
  154.             _await()
  155.         end
  156.     else
  157.         while not turtle.back() do
  158.             fuelCheck()
  159.             _await()
  160.         end
  161.     end
  162.     if xd > 1 then xd = 1 end
  163.     if xd < -1 then xd = -1 end
  164.     if zd > 1 then zd = 1 end
  165.     if zd < -1 then zd = -1 end
  166.     return xd,zd
  167. end
  168.  
  169. -- Save current position as the home position if none saved
  170. if homex == nil or homey == nil or homez == nil then
  171.     homex, homey, homez = locate()
  172.     settings.set("miner.homex",homex)
  173.     settings.set("miner.homey",homey)
  174.     settings.set("miner.homez",homez)
  175.     save()
  176. end
  177. xDir, zDir = getDirs(hxDir ~= nil and hzDir ~= nil)
  178. if hxDir == nil or hzDir == nil then
  179.     hxDir,hzDir = xDir,zDir
  180.     settings.set("miner.homexd",hxDir)
  181.     settings.set("miner.homezd",hzDir)
  182.     save()
  183. end
  184.  
  185. local function turnLeft()
  186.     turtle.turnLeft()
  187.     xDir, zDir = zDir, -xDir
  188. end
  189.  
  190. local function turnRight()
  191.     turtle.turnRight()
  192.     xDir, zDir = -zDir, xDir
  193. end
  194.  
  195. -- The position to start this tunnel from
  196. local tx,ty,tz = homex + hxDir*wanderDist, homey-startDepth, homez + hzDir*wanderDist
  197. -- The home position, relative to the tunnel start, y is inverted
  198. local hx,hy,hz = homex-tx,ty-homey,homez-tz
  199. -- The launch position
  200. local sx,sy,sz = locate()
  201.  
  202. local athome = sx==homex and sy==homey and sz==homez
  203. local exc = tonumber(settings.get("miner.is_exc",0))
  204. local resume = 0 ~= exc
  205. local resume_deposit = 2 == exc
  206.  
  207. -- Relative coordinates to the tunnel start position
  208. depth = ty-sy --inverted!
  209. xPos, zPos = sx-tx, sz-tz
  210.  
  211. -- The fuel required from tx,ty,tz to homex,homey,homez and a little extra
  212. tohomeFuel = math.abs(tx-homex) + math.abs(ty-homey) + math.abs(tz-homez) + 16
  213.  
  214. local function unload(bKeepFuel)
  215.     print("Unloading items...")
  216.     --Never hold fuel stack if fuel is infinite
  217.     if turtle.getFuelLevel() == "unlimited" then
  218.         bKeepFuel = false
  219.     end
  220.     for n = 1, 16 do
  221.         local nCount = turtle.getItemCount(n)
  222.         if nCount > 0 then
  223.             turtle.select(n)
  224.             local bDrop = true
  225.             if bKeepFuel and turtle.refuel(0) then
  226.                 bDrop = false
  227.                 bKeepFuel = false
  228.             end
  229.             if bDrop then
  230.                 --First drop into any container above
  231.                 if turtle.detectUp() then
  232.                     turtle.dropUp()
  233.                 end
  234.                 if turtle.getItemCount(n) > 0 then
  235.                     --Then to each side, if there's any left
  236.                     for _ = 1,4 do
  237.                         if turtle.detect() and turtle.getItemCount(n) > 0 then
  238.                             turtle.drop()
  239.                            
  240.                         end
  241.                         turnLeft()
  242.                     end
  243.                 end
  244.                 --finally, if anything remains, just drop it on the ground
  245.                 if turtle.getItemCount(n) > 0 then
  246.                     turtle.drop()
  247.                 end
  248.             end
  249.         end
  250.     end
  251.     turtle.select(1)
  252. end
  253.  
  254. local function returnSupplies()
  255.     local x, y, z, xd, zd = xPos, depth, zPos, xDir, zDir
  256.     print("Returning to surface...")
  257.     goTo(0, 0, 0) --returns to the relative start
  258.     goTo(hx, hy, hz, hxDir, -hzDir) --returns to home
  259.  
  260.     local fuelNeeded = 3 * (x + y + z) + 128 + tohomeFuel
  261.     if not refuel(fuelNeeded) then
  262.         unload(true)
  263.         print("Waiting for fuel")
  264.         --redstone.setOutput("top", true)
  265.         _awaitRefuel(fuelNeeded)
  266.         --redstone.setOutput("top", false)
  267.         unload(true) --prevent >1 stack of fuel from being stored
  268.     else
  269.         unload(true)
  270.     end
  271.  
  272.     print("Resuming mining...")
  273.     goTo(0, 0, 0)
  274.     goTo(x, y, z, xd, zd)
  275. end
  276.  
  277. local function collect()
  278.     local bFull = true
  279.     local nTotalItems = 0
  280.     for n = 1, 16 do
  281.         local nCount = turtle.getItemCount(n)
  282.         if nCount == 0 then
  283.             bFull = false
  284.         end
  285.         nTotalItems = nTotalItems + nCount
  286.     end
  287.  
  288.     if bFull then
  289.         print("No empty slots left.")
  290.         return false
  291.     end
  292.     return true
  293. end
  294.  
  295. local function countSlots()
  296.     local slotcount = 0
  297.     for n = 1, 16 do
  298.         if turtle.getItemCount(n) == 0 then
  299.             slotcount = slotcount + 1
  300.         end
  301.     end
  302.     return slotcount
  303. end
  304.  
  305. local function tryForwards()
  306.     if not refuel() then
  307.         print("Not enough Fuel")
  308.         returnSupplies()
  309.     end
  310.    
  311.     while not turtle.forward() do
  312.         if turtle.detect() then
  313.             if turtle.dig() then
  314.                 if not collect() then
  315.                     returnSupplies()
  316.                 end
  317.             else
  318.                 return false
  319.             end
  320.         elseif turtle.attack() then
  321.             if not collect() then
  322.                 returnSupplies()
  323.             end
  324.         else
  325.             _await()
  326.         end
  327.         fuelCheck()
  328.     end
  329.  
  330.     xPos = xPos + xDir
  331.     zPos = zPos + zDir
  332.     return true
  333. end
  334.  
  335. local function tryDown()
  336.     if not refuel() then
  337.         print("Not enough Fuel")
  338.         returnSupplies()
  339.     end
  340.  
  341.     if depth + 1 > maxDepth then
  342.         return false
  343.     end
  344.    
  345.     while not turtle.down() do
  346.         if turtle.detectDown() then
  347.             if turtle.digDown() then
  348.                 if not collect() then
  349.                     returnSupplies()
  350.                 end
  351.             else
  352.                 return false
  353.             end
  354.         elseif turtle.attackDown() then
  355.             if not collect() then
  356.                 returnSupplies()
  357.             end
  358.         else
  359.             _await()
  360.         end
  361.         fuelCheck()
  362.     end
  363.  
  364.     depth = depth + 1
  365.     if math.fmod(depth, 10) == 0 then
  366.         print("Descended " .. depth .. " metres.")
  367.     end
  368.     if lowDepth < depth then
  369.         lowDepth = depth
  370.         settings.set("miner.lastDepth",lowDepth)
  371.         save()
  372.     end
  373.     return true
  374. end
  375.  
  376. local function goY(y)
  377.     if y == nil then return end
  378.     while depth > y do
  379.         if turtle.up() then
  380.             depth = depth - 1
  381.         elseif turtle.digUp() or turtle.attackUp() then
  382.             collect()
  383.         else
  384.             _await()
  385.         end
  386.         fuelCheck()
  387.     end
  388.    
  389.     while depth < y do
  390.         if turtle.down() then
  391.             depth = depth + 1
  392.         elseif turtle.digDown() or turtle.attackDown() then
  393.             collect()
  394.         else
  395.             _await()
  396.         end
  397.         fuelCheck()
  398.     end
  399. end
  400.  
  401. local function goX(x)
  402.     if x == nil then return end
  403.     if xPos > x then
  404.         while xDir ~= -1 do
  405.             turnLeft()
  406.         end
  407.         while xPos > x do
  408.             if turtle.forward() then
  409.                 xPos = xPos - 1
  410.             elseif turtle.dig() or turtle.attack() then
  411.                 collect()
  412.             else
  413.                 _await()
  414.             end
  415.             fuelCheck()
  416.         end
  417.     elseif xPos < x then
  418.         while xDir ~= 1 do
  419.             turnLeft()
  420.         end
  421.         while xPos < x do
  422.             if turtle.forward() then
  423.                 xPos = xPos + 1
  424.             elseif turtle.dig() or turtle.attack() then
  425.                 collect()
  426.             else
  427.                 _await()
  428.             end
  429.             fuelCheck()
  430.         end
  431.     end
  432. end
  433.  
  434. local function goZ(z)
  435.     if z == nil then return end
  436.     if zPos > z then
  437.         while zDir ~= -1 do
  438.             turnLeft()
  439.         end
  440.         while zPos > z do
  441.             if turtle.forward() then
  442.                 zPos = zPos - 1
  443.             elseif turtle.dig() or turtle.attack() then
  444.                 collect()
  445.             else
  446.                 _await()
  447.             end
  448.             fuelCheck()
  449.         end
  450.     elseif zPos < z then
  451.         while zDir ~= 1 do
  452.             turnLeft()
  453.         end
  454.         while zPos < z do
  455.             if turtle.forward() then
  456.                 zPos = zPos + 1
  457.             elseif turtle.dig() or turtle.attack() then
  458.                 collect()
  459.             else
  460.                 _await()
  461.             end
  462.             fuelCheck()
  463.         end
  464.     end
  465. end
  466.  
  467. local function goXZ(x,z)
  468.     if hzDir ~= 0 then
  469.         goZ(z)
  470.         goX(x)
  471.     else
  472.         goX(x)
  473.         goZ(z)
  474.     end
  475. end
  476.  
  477. function goTo(x, y, z, xd, zd)
  478.     if depth < 0 and ((x ~= nil and x ~= xPos) or (z ~= nil and z ~= zPos)) then
  479.         goY(0)
  480.     end
  481.     goXZ(x,z)
  482.     goY(y)
  483.    
  484.     while (zd ~= nil and zDir ~= zd) or (xd ~= nil and xDir ~= xd) do
  485.         turnLeft()
  486.     end
  487. end
  488.  
  489. if athome then
  490.     if not refuel(256) then
  491.         print("Waiting for fuel...")
  492.         --redstone.setOutput("top", true)
  493.         _awaitRefuel(256)
  494.         --redstone.setOutput("top", false)
  495.     end
  496.  
  497.     if countSlots() < 15 then
  498.         print("Depositing down to 1 stack of fuel...")
  499.         unload(true)
  500.     end
  501.     if not resume_deposit then
  502.         print("Excavating...")
  503.         goTo(0,0,0,hxDir,hzDir)
  504.     end
  505. end
  506. if resume then
  507.     if (depth < 0 and (sy > homey or sx ~= homex or sz ~= homez)) or math.abs(xPos) > size or math.abs(zPos) > size then
  508.         printError("Cannot resume from current position; might mine through important things.")
  509.         printError("Please reposition me back to my home, or underground near where I was mining!")
  510.         error()
  511.     end
  512.     print("Resuming...")
  513. end
  514.  
  515. turtle.select(1)
  516.  
  517. local alternate = 0
  518. local done = false
  519.  
  520. --Store some values which will be used to resume from a terminated state
  521. local rxp,rzp = xPos,zPos
  522. lowDepth = tonumber(settings.get("miner.lastDepth",0))
  523. if resume and not resume_deposit then
  524.     goTo(0,lowDepth,0,hxDir,hzDir)
  525. end
  526. --
  527.  
  528. if not resume_deposit then
  529.     exc = 1
  530.     settings.set("miner.is_exc",exc)
  531.     save()
  532.  
  533.     while not done do
  534.         for n = 1, size do
  535.             for _ = 1, size - 1 do
  536.                 if not tryForwards() then
  537.                     done = true
  538.                     break
  539.                 end
  540.             end
  541.             if done then
  542.                 break
  543.             end
  544.             if n < size then
  545.                 if math.fmod(n + alternate, 2) == 0 then
  546.                     turnLeft()
  547.                     if not tryForwards() then
  548.                         done = true
  549.                         break
  550.                     end
  551.                     turnLeft()
  552.                 else
  553.                     turnRight()
  554.                     if not tryForwards() then
  555.                         done = true
  556.                         break
  557.                     end
  558.                     turnRight()
  559.                 end
  560.             end
  561.         end
  562.         if done then
  563.             break
  564.         end
  565.  
  566.         if size > 1 then
  567.             if math.fmod(size, 2) == 0 then
  568.                 turnRight()
  569.             else
  570.                 if alternate == 0 then
  571.                     turnLeft()
  572.                 else
  573.                     turnRight()
  574.                 end
  575.                 alternate = 1 - alternate
  576.             end
  577.         end
  578.         if not tryDown() then
  579.             done = true
  580.             break
  581.         end
  582.     end
  583.  
  584.     exc = 2
  585.     settings.set("miner.is_exc",exc)
  586.     settings.set("miner.lastDepth",0)
  587.     save()
  588. end
  589.  
  590. print("Returning to surface...")
  591.  
  592. goY(0) --return to relative start y, important to avoid bedrock
  593. goTo(0, 0, 0) --returns to the relative start
  594. goTo(hx, hy, hz, hxDir, -hzDir) --returns to home
  595. unload(false)
  596. goTo(nil,nil,nil,hxDir,hzDir)
  597.  
  598. print("Excavate complete.")
  599. settings.set("miner.is_exc",0)
  600. if 0 ~= tonumber(settings.get("miner.autoinc",1)) then
  601.     settings.set("miner.wander",wanderDist+size)
  602.     save()
  603.     print("Ready to excavate again!")
  604. else
  605.     settings.set("miner.done",1)
  606.     save()
  607. end
  608.  
  609.  
Add Comment
Please, Sign In to add comment