TechManDylan

TMDExcavate

Jul 19th, 2026 (edited)
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.99 KB | None | 0 0
  1. local tArgs = { ... }
  2. if #tArgs ~= 1 then
  3.     print("Usage: excavate <diameter>")
  4.     return
  5. end
  6.  
  7. local size = tonumber(tArgs[1])
  8. if not size or size < 1 or size % 1 ~= 0 then
  9.     print("Excavate diameter must be a positive whole number")
  10.     return
  11. end
  12.  
  13. local ENDER_CHEST_ID = "enderstorage:ender_chest"
  14. local STORAGE_RECHECK_SECONDS = 15
  15.  
  16. local depth = 0
  17. local unloaded = 0
  18. local collected = 0
  19.  
  20. local xPos, zPos = 0, 0
  21. local xDir, zDir = 0, 1
  22.  
  23. local storageMode = nil
  24. local goTo
  25. local returnSupplies
  26.  
  27. local function findEnderChestSlot()
  28.     for i = 1, 16 do
  29.         local detail = turtle.getItemDetail(i)
  30.         if detail and detail.name == ENDER_CHEST_ID then
  31.             return i
  32.         end
  33.     end
  34.     return nil
  35. end
  36.  
  37. local function isInventory(side)
  38.     if peripheral.hasType and peripheral.hasType(side, "inventory") then
  39.         return true
  40.     end
  41.  
  42.     local wrapped = peripheral.wrap(side)
  43.     return wrapped ~= nil and type(wrapped.list) == "function"
  44. end
  45.  
  46. local function waitForRearStorage()
  47.     while not isInventory("back") do
  48.         print("ERROR: No valid storage found.")
  49.         print("Place a chest, barrel, or other inventory behind the turtle's initial starting location.")
  50.         print("Checking again in " .. STORAGE_RECHECK_SECONDS .. " seconds...")
  51.         sleep(STORAGE_RECHECK_SECONDS)
  52.     end
  53. end
  54.  
  55. local function chooseStorageMode()
  56.     if findEnderChestSlot() then
  57.         storageMode = "ender"
  58.         print("EnderStorage chest found. Using portable unloading.")
  59.         return
  60.     end
  61.  
  62.     storageMode = "rear"
  63.     waitForRearStorage()
  64.     print("Storage found behind starting location.")
  65. end
  66.  
  67. local function inventoryTotal()
  68.     local total = 0
  69.     for i = 1, 16 do
  70.         total = total + turtle.getItemCount(i)
  71.     end
  72.     return total
  73. end
  74.  
  75. local function hasEmptySlot()
  76.     for i = 1, 16 do
  77.         if turtle.getItemCount(i) == 0 then
  78.             return true
  79.         end
  80.     end
  81.     return false
  82. end
  83.  
  84. local function fuelLevel()
  85.     return turtle.getFuelLevel()
  86. end
  87.  
  88. local function distanceFromStart()
  89.     return math.abs(xPos) + math.abs(zPos) + depth
  90. end
  91.  
  92. local function refuelTo(requiredLevel)
  93.     local level = fuelLevel()
  94.     if level == "unlimited" then
  95.         return true
  96.     end
  97.  
  98.     if level >= requiredLevel then
  99.         return true
  100.     end
  101.  
  102.     for i = 1, 16 do
  103.         if turtle.getItemCount(i) > 0 then
  104.             turtle.select(i)
  105.             if turtle.refuel(0) then
  106.                 turtle.refuel(turtle.getItemCount(i))
  107.                 level = fuelLevel()
  108.                 if level == "unlimited" or level >= requiredLevel then
  109.                     turtle.select(1)
  110.                     return true
  111.                 end
  112.             end
  113.         end
  114.     end
  115.  
  116.     turtle.select(1)
  117.     level = fuelLevel()
  118.     return level == "unlimited" or level >= requiredLevel
  119. end
  120.  
  121. local function burnFuelToFreeSlot()
  122.     if hasEmptySlot() then
  123.         return true
  124.     end
  125.  
  126.     for i = 1, 16 do
  127.         local before = turtle.getItemCount(i)
  128.         if before > 0 then
  129.             turtle.select(i)
  130.             if turtle.refuel(0) then
  131.                 turtle.refuel(before)
  132.                 local after = turtle.getItemCount(i)
  133.                 if after < before then
  134.                     print("Inventory full: used " .. (before - after) .. " collected fuel item(s).")
  135.                 end
  136.                 if after == 0 then
  137.                     turtle.select(1)
  138.                     return true
  139.                 end
  140.             end
  141.         end
  142.     end
  143.  
  144.     turtle.select(1)
  145.     return hasEmptySlot()
  146. end
  147.  
  148. local function collect()
  149.     local total = inventoryTotal()
  150.  
  151.     if total > collected then
  152.         collected = total
  153.         if math.fmod(collected + unloaded, 50) == 0 then
  154.             print("Mined " .. (collected + unloaded) .. " items.")
  155.         end
  156.     end
  157.  
  158.     return hasEmptySlot()
  159. end
  160.  
  161. local function waitForFuel(requiredLevel)
  162.     while not refuelTo(requiredLevel) do
  163.         print("Not enough fuel to continue safely.")
  164.         print("Add burnable fuel directly to the turtle. Checking again in 15 seconds...")
  165.         sleep(15)
  166.     end
  167. end
  168.  
  169. local function turnLeft()
  170.     turtle.turnLeft()
  171.     xDir, zDir = -zDir, xDir
  172. end
  173.  
  174. local function turnRight()
  175.     turtle.turnRight()
  176.     xDir, zDir = zDir, -xDir
  177. end
  178.  
  179. local function unloadToEnderChest()
  180.     local chestSlot = findEnderChestSlot()
  181.     if not chestSlot then
  182.         return false
  183.     end
  184.  
  185.     print("Unloading items to EnderStorage chest...")
  186.  
  187.     while turtle.detectUp() do
  188.         if not turtle.digUp() then
  189.             print("Unable to clear space above to place EnderStorage chest.")
  190.             return false
  191.         end
  192.     end
  193.  
  194.     turtle.select(chestSlot)
  195.     if not turtle.placeUp() then
  196.         print("Failed to place EnderStorage chest above.")
  197.         return false
  198.     end
  199.  
  200.     for i = 1, 16 do
  201.         if i ~= chestSlot then
  202.             local before = turtle.getItemCount(i)
  203.             if before > 0 then
  204.                 turtle.select(i)
  205.                 turtle.dropUp()
  206.                 local moved = before - turtle.getItemCount(i)
  207.                 unloaded = unloaded + moved
  208.             end
  209.         end
  210.     end
  211.  
  212.     turtle.select(chestSlot)
  213.     if not turtle.digUp() then
  214.         print("Warning: Failed to retrieve EnderStorage chest.")
  215.     end
  216.  
  217.     turtle.select(1)
  218.     collected = inventoryTotal()
  219.     return true
  220. end
  221.  
  222. local function unloadToRearStorage()
  223.     waitForRearStorage()
  224.  
  225.     turnLeft()
  226.     turnLeft()
  227.  
  228.     while true do
  229.         if not isInventory("front") then
  230.             turnLeft()
  231.             turnLeft()
  232.             waitForRearStorage()
  233.             turnLeft()
  234.             turnLeft()
  235.         end
  236.  
  237.         local remaining = false
  238.  
  239.         for i = 1, 16 do
  240.             local before = turtle.getItemCount(i)
  241.             if before > 0 then
  242.                 turtle.select(i)
  243.                 turtle.drop()
  244.                 local after = turtle.getItemCount(i)
  245.                 local moved = before - after
  246.                 unloaded = unloaded + moved
  247.  
  248.                 if after > 0 then
  249.                     remaining = true
  250.                 end
  251.             end
  252.         end
  253.  
  254.         if not remaining then
  255.             break
  256.         end
  257.  
  258.         print("Storage is full or rejected an item.")
  259.         print("Make room in the storage behind the starting location.")
  260.         print("Trying again in " .. STORAGE_RECHECK_SECONDS .. " seconds...")
  261.         sleep(STORAGE_RECHECK_SECONDS)
  262.     end
  263.  
  264.     turtle.select(1)
  265.     turnLeft()
  266.     turnLeft()
  267.     collected = inventoryTotal()
  268. end
  269.  
  270. local function ensureInventorySpace()
  271.     if hasEmptySlot() then
  272.         return true
  273.     end
  274.  
  275.     if burnFuelToFreeSlot() then
  276.         return true
  277.     end
  278.  
  279.     print("Inventory is full and no burnable items can free a slot.")
  280.     returnSupplies()
  281.     return hasEmptySlot()
  282. end
  283.  
  284. local function ensureFuelForMove()
  285.     local required = distanceFromStart() + 2
  286.     if refuelTo(required) then
  287.         return true
  288.     end
  289.  
  290.     print("Fuel reserve is too low. Returning for supplies...")
  291.     returnSupplies()
  292.     return refuelTo(distanceFromStart() + 2)
  293. end
  294.  
  295. function goTo(x, y, z, xd, zd)
  296.     while depth > y do
  297.         if turtle.up() then
  298.             depth = depth - 1
  299.         elseif turtle.digUp() or turtle.attackUp() then
  300.             collect()
  301.         else
  302.             sleep(0.5)
  303.         end
  304.     end
  305.  
  306.     if xPos > x then
  307.         while xDir ~= -1 do turnLeft() end
  308.         while xPos > x do
  309.             if turtle.forward() then
  310.                 xPos = xPos - 1
  311.             elseif turtle.dig() or turtle.attack() then
  312.                 collect()
  313.             else
  314.                 sleep(0.5)
  315.             end
  316.         end
  317.     elseif xPos < x then
  318.         while xDir ~= 1 do turnLeft() end
  319.         while xPos < x do
  320.             if turtle.forward() then
  321.                 xPos = xPos + 1
  322.             elseif turtle.dig() or turtle.attack() then
  323.                 collect()
  324.             else
  325.                 sleep(0.5)
  326.             end
  327.         end
  328.     end
  329.  
  330.     if zPos > z then
  331.         while zDir ~= -1 do turnLeft() end
  332.         while zPos > z do
  333.             if turtle.forward() then
  334.                 zPos = zPos - 1
  335.             elseif turtle.dig() or turtle.attack() then
  336.                 collect()
  337.             else
  338.                 sleep(0.5)
  339.             end
  340.         end
  341.     elseif zPos < z then
  342.         while zDir ~= 1 do turnLeft() end
  343.         while zPos < z do
  344.             if turtle.forward() then
  345.                 zPos = zPos + 1
  346.             elseif turtle.dig() or turtle.attack() then
  347.                 collect()
  348.             else
  349.                 sleep(0.5)
  350.             end
  351.         end
  352.     end
  353.  
  354.     while depth < y do
  355.         if turtle.down() then
  356.             depth = depth + 1
  357.         elseif turtle.digDown() or turtle.attackDown() then
  358.             collect()
  359.         else
  360.             sleep(0.5)
  361.         end
  362.     end
  363.  
  364.     while zDir ~= zd or xDir ~= xd do
  365.         turnLeft()
  366.     end
  367. end
  368.  
  369. function returnSupplies()
  370.     local x, y, z, xd, zd = xPos, depth, zPos, xDir, zDir
  371.     local travelDistance = math.abs(x) + math.abs(z) + y
  372.  
  373.     print("Handling inventory and fuel...")
  374.  
  375.     if findEnderChestSlot() then
  376.         storageMode = "ender"
  377.         refuelTo(travelDistance + 2)
  378.  
  379.         if unloadToEnderChest() then
  380.             waitForFuel(travelDistance + 2)
  381.             print("Resuming mining...")
  382.             return true
  383.         end
  384.     end
  385.  
  386.     storageMode = "rear"
  387.  
  388.     if not refuelTo(travelDistance) then
  389.         print("The turtle does not have enough fuel to reach the starting location.")
  390.         waitForFuel(travelDistance)
  391.     end
  392.  
  393.     print("Returning to starting storage...")
  394.     goTo(0, 0, 0, 0, 1)
  395.  
  396.     -- Burn collected fuel before depositing. This keeps enough internal fuel
  397.     -- to return to the saved mining position whenever possible.
  398.     refuelTo(travelDistance + 2)
  399.  
  400.     unloadToRearStorage()
  401.  
  402.     if not refuelTo(travelDistance + 2) then
  403.         waitForFuel(travelDistance + 2)
  404.     end
  405.  
  406.     print("Resuming mining...")
  407.     goTo(x, y, z, xd, zd)
  408.     return true
  409. end
  410.  
  411. local function tryForwards()
  412.     if not ensureFuelForMove() then
  413.         return false
  414.     end
  415.  
  416.     while not turtle.forward() do
  417.         if turtle.detect() then
  418.             if not ensureInventorySpace() then
  419.                 return false
  420.             end
  421.  
  422.             if turtle.dig() then
  423.                 collect()
  424.             else
  425.                 return false
  426.             end
  427.         elseif turtle.attack() then
  428.             collect()
  429.         else
  430.             sleep(0.5)
  431.         end
  432.     end
  433.  
  434.     xPos = xPos + xDir
  435.     zPos = zPos + zDir
  436.  
  437.     if turtle.detectUp() then
  438.         if not ensureInventorySpace() then
  439.             return false
  440.         end
  441.         if turtle.digUp() then
  442.             collect()
  443.         end
  444.     end
  445.  
  446.     if turtle.detectDown() then
  447.         if not ensureInventorySpace() then
  448.             return false
  449.         end
  450.         if turtle.digDown() then
  451.             collect()
  452.         end
  453.     end
  454.  
  455.     return true
  456. end
  457.  
  458. local function tryDown()
  459.     for i = 1, 3 do
  460.         if not ensureFuelForMove() then
  461.             return false
  462.         end
  463.  
  464.         while not turtle.down() do
  465.             if turtle.detectDown() then
  466.                 if not ensureInventorySpace() then
  467.                     return false
  468.                 end
  469.  
  470.                 if turtle.digDown() then
  471.                     collect()
  472.                 else
  473.                     return false
  474.                 end
  475.             elseif turtle.attackDown() then
  476.                 collect()
  477.             else
  478.                 sleep(0.5)
  479.             end
  480.         end
  481.  
  482.         depth = depth + 1
  483.  
  484.         if turtle.detectUp() then
  485.             if not ensureInventorySpace() then
  486.                 return false
  487.             end
  488.             if turtle.digUp() then
  489.                 collect()
  490.             end
  491.         end
  492.  
  493.         if turtle.detectDown() then
  494.             if not ensureInventorySpace() then
  495.                 return false
  496.             end
  497.             if turtle.digDown() then
  498.                 collect()
  499.             end
  500.         end
  501.     end
  502.  
  503.     if math.fmod(depth, 10) == 0 then
  504.         print("Descended " .. depth .. " metres.")
  505.     end
  506.  
  507.     return true
  508. end
  509.  
  510. chooseStorageMode()
  511.  
  512. if not refuelTo(2) then
  513.     print("Out of fuel. Add burnable fuel to the turtle.")
  514.     return
  515. end
  516.  
  517. print("Excavating...")
  518.  
  519. local alternate = 0
  520. local done = false
  521.  
  522. while not done do
  523.     for n = 1, size do
  524.         for m = 1, size - 1 do
  525.             if not tryForwards() then
  526.                 done = true
  527.                 break
  528.             end
  529.         end
  530.  
  531.         if done then
  532.             break
  533.         end
  534.  
  535.         if n < size then
  536.             if math.fmod(n + alternate, 2) == 0 then
  537.                 turnLeft()
  538.                 if not tryForwards() then
  539.                     done = true
  540.                     break
  541.                 end
  542.                 turnLeft()
  543.             else
  544.                 turnRight()
  545.                 if not tryForwards() then
  546.                     done = true
  547.                     break
  548.                 end
  549.                 turnRight()
  550.             end
  551.         end
  552.     end
  553.  
  554.     if done then
  555.         break
  556.     end
  557.  
  558.     if size > 1 then
  559.         if math.fmod(size, 2) == 0 then
  560.             turnRight()
  561.         else
  562.             if alternate == 0 then
  563.                 turnLeft()
  564.             else
  565.                 turnRight()
  566.             end
  567.             alternate = 1 - alternate
  568.         end
  569.     end
  570.  
  571.     if not tryDown() then
  572.         done = true
  573.         break
  574.     end
  575. end
  576.  
  577. print("Returning to surface...")
  578.  
  579. local finalDistance = distanceFromStart()
  580. if not refuelTo(finalDistance) then
  581.     waitForFuel(finalDistance)
  582. end
  583.  
  584. goTo(0, 0, 0, 0, 1)
  585.  
  586. if findEnderChestSlot() then
  587.     unloadToEnderChest()
  588. else
  589.     storageMode = "rear"
  590.     unloadToRearStorage()
  591. end
  592.  
  593. goTo(0, 0, 0, 0, 1)
  594.  
  595. print("Mined " .. (collected + unloaded) .. " items total.")
Advertisement
Add Comment
Please, Sign In to add comment