MudkipTheEpic

Turtle Stripmining with Ore Excavation

Dec 22nd, 2020 (edited)
1,593
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.72 KB | None | 0 0
  1. local dropTable = setmetatable({
  2.     ["minecraft:diamond_ore"] = "minecraft:diamond",
  3.     ["minecraft:coal_ore"] = "minecraft:coal",
  4.     ["minecraft:redstone_ore"] = "minecraft:redstone",
  5.     ["minecraft:lapis_ore"] = "minecraft:lapis_lazuli",
  6.     ["minecraft:emerald_ore"] = "minecraft:emerald",
  7.     ["minecraft:nether_quartz_ore"] = "minecraft:quartz",
  8.     ["minecraft:nether_gold_ore"] = "minecraft:gold_nugget",
  9.     ["minecraft:stone"] = "minecraft:cobblestone"
  10. }, {__index = function(tab, block) return block end})
  11.  
  12. local treasureTable = setmetatable({ --Descending priority order
  13.     ["minecraft:diamond"] = 9,
  14.     ["minecraft:emerald"] = 8,
  15.     ["minecraft:gold_ingot"] = 7,
  16.     ["minecraft:gold_ore"] = 6,
  17.     ["minecraft:lapis_lazuli"] = 5,
  18.     ["minecraft:iron_ore"] = 4,
  19.     ["minecraft:redstone"] = 3,
  20.     ["minecraft:coal"] = 2,
  21.     ["minecraft:gold_nugget"] = 1
  22. }, {__index = function() return 0 end})
  23.  
  24. local fuelRatio = 0.1
  25.  
  26. local function refuel()
  27.     if turtle.getFuelLevel() >= turtle.getFuelLimit() * fuelRatio then
  28.         return true
  29.     end
  30.     local slotDetail = turtle.getItemDetail(16)
  31.     if slotDetail == nil or slotDetail.name ~= "minecraft:coal" then
  32.         return false
  33.     end
  34.     turtle.select(16)
  35.     local neededCoal = math.ceil(((turtle.getFuelLimit() * fuelRatio) - turtle.getFuelLevel()) / 80)
  36.     if neededCoal > slotDetail.count - 1 then
  37.         turtle.refuel(slotDetail.count - 1)
  38.         return false
  39.     end
  40.     turtle.refuel(neededCoal)
  41.     return true
  42. end
  43.  
  44. local function isSpaceFor(item)
  45.     for slot=1, (item == "minecraft:coal" and 16 or 15) do
  46.         local slotDetail = turtle.getItemDetail(slot)
  47.         if slotDetail == nil or (slotDetail.name == item and turtle.getItemSpace(slot) > 0) then
  48.             return true
  49.         end
  50.     end
  51.     return false
  52. end
  53.  
  54. local function trashExtra()
  55.     local tSlotDetails = {}
  56.     for priority=0, 9 do
  57.         for slot=1, 15 do
  58.             tSlotDetails[slot] = tSlotDetails[slot] or turtle.getItemDetail(slot, false)
  59.             if tSlotDetails[slot] == nil then return slot end
  60.             if treasureTable[dropTable[tSlotDetails[slot].name]] <= priority then
  61.                 turtle.select(slot)
  62.                 turtle.drop()
  63.                 return slot
  64.             end
  65.         end
  66.     end
  67. end
  68.  
  69. local function dig(dir)
  70.  
  71.     local success, blockDetails
  72.  
  73.     if (dir == "up") then
  74.         if not turtle.detectUp() then return false end
  75.         success, blockDetails = turtle.inspectUp()
  76.     elseif (dir == "down") then
  77.         if not turtle.detectDown() then return false end
  78.         success, blockDetails = turtle.inspectDown()
  79.     else
  80.         if not turtle.detect() then return false end
  81.         success, blockDetails = turtle.inspect()
  82.     end
  83.  
  84.     local expectedItem = dropTable[blockDetails.name]
  85.  
  86.     if not isSpaceFor(expectedItem) and treasureTable[expectedItem] ~= 0 then
  87.         trashExtra()
  88.     end
  89.  
  90.     if expectedItem == "minecraft:coal" then
  91.         turtle.select(16)
  92.     else
  93.         turtle.select(1)
  94.     end
  95.     --sleep(0.25)
  96.  
  97.     if dir == "up" then
  98.         turtle.digUp()
  99.         if turtle.detectUp() then return dig("up") end
  100.         return true
  101.     elseif dir == "down" then
  102.         turtle.digDown()
  103.         if turtle.detectDown() then return dig("down") end
  104.         return true
  105.     else
  106.         turtle.dig()
  107.         if turtle.detect() then return dig() end
  108.         return true
  109.     end
  110.  
  111. end
  112.  
  113. function investigateVein()
  114.  
  115.     local oreMap = setmetatable({},
  116.     {
  117.         __index = function(tab, xVal)
  118.             if xVal == nil then
  119.                 error("Nil x value", 2)
  120.             end
  121.             tab[xVal] = setmetatable({},
  122.             {
  123.                 __index = function(tab_2, yVal)
  124.                     if yVal == nil then
  125.                         error("Nil y value", 2)
  126.                     end
  127.                     tab_2[yVal] = {}
  128.                     return tab_2[yVal]
  129.                 end
  130.             })
  131.             return tab[xVal]
  132.         end
  133.     })
  134.     local posX, posY, posZ = 0, 0, 0
  135.     local facing = 0
  136.  
  137.     local function getFacingCoords(dir)
  138.         if dir == 0 then
  139.             return posX + 1, posY, posZ
  140.         elseif dir == 1 then
  141.             return posX, posY, posZ + 1
  142.         elseif dir == 2 then
  143.             return posX - 1, posY, posZ
  144.         elseif dir == 3 then
  145.             return posX, posY, posZ - 1
  146.         end
  147.     end
  148.  
  149.     local function recordBlockInfo(block, x, y, z)
  150.         oreMap[x][y][z] = block
  151.         return block
  152.     end
  153.  
  154.     local function getBlockInfo(x, y, z)
  155.         if rawget(oreMap, x) == nil or rawget(oreMap[x], y) == nil then return nil end
  156.         return oreMap[x][y][z]
  157.     end
  158.  
  159.     local function populateBlockInfo(dir)
  160.         local x, y, z
  161.         local success, blockInfo
  162.         if dir == "up" or dir == "down" then
  163.             x = posX
  164.             y = posY + (dir == "up" and 1 or -1)
  165.             z = posZ
  166.             local currentInfo = getBlockInfo(x, y, z)
  167.             if currentInfo ~= nil then return currentInfo end
  168.             success, blockInfo = turtle[dir == "up" and "inspectUp" or "inspectDown"]()
  169.         else
  170.             x, y, z = getFacingCoords(facing)
  171.             local currentInfo = getBlockInfo(x, y, z)
  172.             if currentInfo ~= nil then return currentInfo end
  173.             success, blockInfo = turtle.inspect()
  174.         end
  175.         if not success then
  176.             blockInfo = {name = "minecraft:air"}
  177.         end
  178.         return recordBlockInfo(blockInfo, x, y, z)
  179.     end
  180.  
  181.     local function checkBlockForDig(dir)
  182.         local blockInfo = populateBlockInfo(dir)
  183.         if treasureTable[dropTable[blockInfo.name]] > 0 then
  184.             return dig(dir)
  185.         end
  186.         return false
  187.     end
  188.  
  189.     local function turnRight()
  190.         turtle.turnRight()
  191.         facing = (facing + 1) % 4
  192.     end
  193.  
  194.     local function turnLeft()
  195.         turtle.turnLeft()
  196.         facing = (facing - 1) % 4
  197.     end
  198.  
  199.     local function forward()
  200.         local result, err = turtle.forward()
  201.         if result then
  202.             if facing % 2 == 0 then
  203.                 posX = posX + (facing == 0 and 1 or -1)
  204.             else
  205.                 posZ = posZ + (facing == 1 and 1 or -1)
  206.             end
  207.             return true
  208.         else
  209.             return false, err
  210.         end
  211.     end
  212.  
  213.     local function back()
  214.         local result, err = turtle.back()
  215.         if result then
  216.             if facing % 2 == 0 then
  217.                 posX = posX - (facing == 0 and 1 or -1)
  218.             else
  219.                 posZ = posZ - (facing == 1 and 1 or -1)
  220.             end
  221.             return true
  222.         else
  223.             return false, err
  224.         end
  225.     end
  226.  
  227.     local function up()
  228.         local result, err = turtle.up()
  229.         if result then
  230.             posY = posY + 1
  231.             return true
  232.         else
  233.             return false, err
  234.         end
  235.     end
  236.    
  237.     local function down()
  238.         local result, err = turtle.down()
  239.         if result then
  240.             posY = posY - 1
  241.             return true
  242.         else
  243.             return false, err
  244.         end
  245.     end
  246.  
  247.     local function numUnknownNeighbors(x, y, z)
  248.         local count = 0
  249.  
  250.         count = count + (getBlockInfo(x+1, y, z) == nil and 1 or 0)
  251.         count = count + (getBlockInfo(x-1, y, z) == nil and 1 or 0)
  252.         count = count + (getBlockInfo(x, y+1, z) == nil and 1 or 0)
  253.         count = count + (getBlockInfo(x, y-1, z) == nil and 1 or 0)
  254.         count = count + (getBlockInfo(x, y, z+1) == nil and 1 or 0)
  255.         count = count + (getBlockInfo(x, y, z-1) == nil and 1 or 0)
  256.  
  257.         return count
  258.     end
  259.  
  260.     local function hasUnknownNeighbors(x, y, z)
  261.         return getBlockInfo(x+1, y, z) == nil or getBlockInfo(x-1, y, z) == nil or getBlockInfo(x, y+1, z) == nil or getBlockInfo(x, y-1, z) == nil or getBlockInfo(x, y, z+1) == nil or getBlockInfo(x, y, z-1) == nil
  262.     end
  263.  
  264.     local function turtleDist(x1, y1, z1, x2, y2, z2)
  265.         return math.abs(x1 - x2) + math.abs(y1 - y2) + math.abs(z1 - z2)
  266.     end
  267.  
  268.     local function getNextScanLocation()
  269.         local closestX, closestY, closestZ, closestDist = math.huge, math.huge, math.huge, math.huge
  270.         for x, xTab in pairs(oreMap) do
  271.             for y, yTab in pairs(xTab) do
  272.                 for z, blockInfo in pairs(yTab) do
  273.                     if treasureTable[dropTable[blockInfo.name]]~=0 and hasUnknownNeighbors(x, y, z) then
  274.                         local dist = turtleDist(x, y, z, posX, posY, posZ)
  275.                         if closestX == math.huge or dist < closestDist then
  276.                             closestX = x
  277.                             closestY = y
  278.                             closestZ = z
  279.                             closestDist = dist
  280.                             if dist == 1 then
  281.                                 return x, y, z
  282.                             end
  283.                         end
  284.                     end
  285.                 end
  286.             end
  287.         end
  288.         if closestX == math.huge then return nil end
  289.         return closestX, closestY, closestZ
  290.     end
  291.  
  292.     local function turnToDir(dir)
  293.         if dir == facing then return true end
  294.         if dir == (facing + 1) % 4 then turnRight() return true end
  295.         if dir == (facing - 1) % 4 then turnLeft() return true end
  296.         turnRight()
  297.         turnRight()
  298.         return true
  299.     end
  300.  
  301.     local function pathToPoint(x, y, z)
  302.         local xDelta = x - posX
  303.         local yDelta = y - posY
  304.         local zDelta = z - posZ
  305.         if xDelta ~= 0 or zDelta ~= 0 then
  306.             if (zDelta == 0) or (facing == 0 and xDelta > 0) or (facing == 2 and xDelta < 0) or (facing == 1 and zDelta < 0) or (facing == 3 and zDelta > 0) then
  307.                 turnToDir(xDelta < 0 and 2 or 0)
  308.                 for i=1, math.abs(xDelta) do
  309.                     dig()
  310.                     forward()
  311.                 end
  312.                 if (zDelta ~= 0) then
  313.                     turnToDir(zDelta < 0 and 3 or 1)
  314.                     for i=1, math.abs(zDelta) do
  315.                         dig()
  316.                         forward()
  317.                     end
  318.                 end
  319.             else
  320.                 turnToDir(zDelta < 0 and 3 or 1)
  321.                 for i=1, math.abs(zDelta) do
  322.                     dig()
  323.                     forward()
  324.                 end
  325.                 if (xDelta ~= 0) then
  326.                     turnToDir(xDelta < 0 and 2 or 0)
  327.                     for i=1, math.abs(xDelta) do
  328.                         dig()
  329.                         forward()
  330.                     end
  331.                 end
  332.             end
  333.         end
  334.         if yDelta > 0 then
  335.             for i=1, yDelta do
  336.                 dig("up")
  337.                 up()
  338.             end
  339.         elseif yDelta < 0 then
  340.             for i=1, -yDelta do
  341.                 dig("down")
  342.                 down()
  343.             end
  344.         end
  345.     end
  346.  
  347.     local function scan()
  348.         local originalFacing = facing
  349.         checkBlockForDig("up")
  350.         checkBlockForDig("down")
  351.         checkBlockForDig()
  352.         if getBlockInfo(unpack({getFacingCoords((originalFacing + 1) % 4)})) ~= nil and getBlockInfo(getFacingCoords((facing + 2) % 4)) ~= nil then
  353.             if getBlockInfo(unpack({getFacingCoords((originalFacing - 1) % 4)})) == nil then
  354.                 turnLeft()
  355.                 checkBlockForDig()
  356.             end
  357.             return
  358.         else
  359.             turnRight()
  360.             checkBlockForDig()
  361.             if getBlockInfo(unpack({getFacingCoords((originalFacing + 2) % 4)})) == nil or getBlockInfo(unpack({getFacingCoords((originalFacing + 3) % 4)})) == nil then
  362.                 turnRight()
  363.                 checkBlockForDig()
  364.             end
  365.             if getBlockInfo(unpack({getFacingCoords((originalFacing + 3) % 4)})) == nil then
  366.                 turnRight()
  367.                 checkBlockForDig()
  368.             end
  369.         end
  370.     end
  371.  
  372.     --Main loop
  373.     local nextX, nextY, nextZ = 0, 0, 0
  374.     repeat
  375.         refuel()
  376.         pathToPoint(nextX, nextY, nextZ)
  377.         scan()
  378.         nextX, nextY, nextZ = getNextScanLocation()
  379.     until nextX == nil
  380.     pathToPoint(0,0,0)
  381.     turnToDir(0)
  382. end
  383.  
  384. local function probe(dir, forceDig)
  385.     local success, blockDetails
  386.  
  387.     if dir=="up" then
  388.         success, blockDetails = turtle.inspectUp()
  389.     elseif dir=="down" then
  390.         success, blockDetails = turtle.inspectDown()
  391.     else
  392.         success, blockDetails = turtle.inspect()
  393.     end
  394.  
  395.     if success and treasureTable[dropTable[blockDetails.name]]~=0 then
  396.         print("Found a", dropTable[blockDetails.name], "vein.")
  397.         investigateVein()
  398.         print("Finished mining vein.")
  399.     elseif forceDig then
  400.         dig(dir)
  401.     end
  402. end
  403.  
  404. local maxRuns = tonumber(...)
  405.  
  406. for i=1, maxRuns do
  407.     refuel()
  408.     probe(nil, true)
  409.     turtle.forward()
  410.     probe("down")
  411.     probe("up", true)
  412.     turtle.turnLeft()
  413.     probe()
  414.     turtle.up()
  415.     probe()
  416.     probe("up")
  417.     turtle.turnRight()
  418.     turtle.turnRight()
  419.     probe()
  420.     turtle.down()
  421.     probe()
  422.     turtle.turnLeft()
  423. end
  424.  
  425. turtle.turnLeft()
  426. turtle.turnLeft()
  427. for i=1, maxRuns do
  428.     refuel()
  429.     while turtle.detect() do
  430.         turtle.dig()
  431.     end
  432.     turtle.forward()
  433. end
  434. turtle.turnRight()
  435. turtle.turnRight()
Add Comment
Please, Sign In to add comment