LaniusFNV

CC Miner

Nov 17th, 2020 (edited)
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.65 KB | None | 0 0
  1. local args = { ... }
  2. local width, height, depth = tonumber(args[1]), tonumber(args[2]), tonumber(args[3])
  3.  
  4. local trashlist = {
  5.     "minecraft:stone",
  6.     "minecraft:granite",
  7.     "minecraft:andesite",
  8.     "minecraft:diorite",
  9.     "minecraft:cobblestone",
  10.     "minecraft:dirt",
  11.     "minecraft:grass",
  12.     "minecraft:gravel",
  13.     "extcaves:lavastone",
  14.     "extcaves:sedimentstone",
  15.     "extcaves:pebble_stone",
  16.     "create:weathered_limestone",
  17. }
  18.  
  19. local blacklist = {
  20.     "tetra"
  21. }
  22.  
  23. local function dig()
  24.     local _, item = turtle.inspect()
  25.  
  26.     if item.name ~= nil then
  27.         for _, v in ipairs(blacklist) do
  28.             if v == nil then
  29.                 error("Blacklist is empty")
  30.                 return
  31.             else
  32.                 if string.find(item.name, v) then
  33.                     print("Found blacklisted item "..item.name)
  34.                     return
  35.                 end
  36.             end
  37.         end
  38.         turtle.dig()
  39.     end
  40. end
  41.  
  42. local function digUp()
  43.     local _, item = turtle.inspectUp()
  44.  
  45.     if item.name ~= nil then
  46.         for _, v in ipairs(blacklist) do
  47.             if v == nil then
  48.                 error("Blacklist is empty")
  49.                 return
  50.             else
  51.                 if string.find(item.name, v) then
  52.                     print("Found blacklisted item "..item.name)
  53.                     return
  54.                 end
  55.             end
  56.         end
  57.         turtle.digUp()
  58.     end
  59. end
  60.  
  61. local function digDown()
  62.     local _, item = turtle.inspectDown()
  63.  
  64.     if item.name ~= nil then
  65.         for _, v in ipairs(blacklist) do
  66.             if v == nil then
  67.                 error("Blacklist is empty")
  68.                 return
  69.             else
  70.                 if string.find(item.name, v) then
  71.                     print("Found blacklisted item "..item.name)
  72.                     return
  73.                 end
  74.             end
  75.         end
  76.         turtle.digDown()
  77.     end
  78. end
  79.  
  80. local function getCurrentPos()
  81.     local gps_x, gps_y, gps_z = gps.locate()
  82.     local gps_pos = vector.new(gps_x, gps_y, gps_z)
  83.  
  84.     if gps_x == nil then
  85.         print("Couldn't determine position please help: x y z")
  86.         local x, y, z = io.read("*number", "*number", "*number")
  87.  
  88.         local vec = vector.new(x, y, z)
  89.  
  90.         return vec
  91.     end
  92.  
  93.     return gps_pos
  94. end
  95.  
  96. local function getGoalPos(start_pos)
  97.     print(width .. "w " .. height .. "h " .. depth .. "d")
  98.  
  99.     return vector.new(start_pos.x + width, start_pos.y + height, start_pos.z + depth)
  100. end
  101.  
  102. local mine_start_pos = getCurrentPos() --vector.new(0, 0, 0)
  103. local mine_end_pos = getGoalPos(mine_start_pos) --vector.new(10, 4, 30)
  104.  
  105. -- Returns the number of blocks that the turtle has to travel back along.
  106. -- If the turtle starts in the lower left and the width is divisible by 2 then
  107. -- the turtle will have to travel height + width blocks.
  108. -- If the width is not divisible by 2 then the turtle will also have to travel along the depth
  109. local function diffStartEndPosition(depth, width, height)
  110.     local result = height + width
  111.  
  112.     if width % 2 ~= 0 then
  113.         result = result + depth
  114.     end
  115.  
  116.     return result
  117. end
  118.  
  119. -- Returns the amount of blocks the turtle requires fuel for (plus a little extra).
  120. -- It sums the area (this can be optimized TODO), the way to and from the dig site and the amount of blocks the turtle traveled away from home in the mine
  121. -- It also adds a little extra fuel, to be safe
  122. local function necessaryFuel()
  123.     return math.ceil((depth * width * height) + 2 * vector.distance(mine_end_pos, mine_start_pos) + diffStartEndPosition(depth, width, height) + 5)
  124. end
  125.  
  126. -- Returns the Manhattan distance based on vector subtraction
  127. function vector.distance(v1, v2)
  128.     local res_v = v2 - v1
  129.  
  130.     return (math.abs(res_v.x) + math.abs(res_v.y) + math.abs(res_v.z))
  131. end
  132.  
  133. local function left(orientation)
  134.     turtle.turnLeft()
  135.     orientation = orientation - 1
  136.     orientation = orientation % 4
  137.  
  138.     return orientation
  139. end
  140.  
  141. local function right(orientation)
  142.     turtle.turnRight()
  143.     orientation = orientation + 1
  144.     orientation = orientation % 4
  145.  
  146.     return orientation
  147. end
  148.  
  149. local function forward()
  150.     while turtle.detect() do
  151.         dig()
  152.         if turtle.detect() then sleep(0.8) end -- wait for the falling animation to finish (if gravel)
  153.     end
  154.     while not turtle.forward() do
  155.         turtle.attack()
  156.     end
  157. end
  158.  
  159. local function face(current_orientation, goal_orientation)
  160.     local needed_right_turns = (goal_orientation - current_orientation) % 4
  161.  
  162.     if needed_right_turns == 0 then
  163.         return goal_orientation
  164.     elseif needed_right_turns > 2 then
  165.         left(current_orientation)
  166.     elseif needed_right_turns == 2 then
  167.         right(current_orientation)
  168.         right(current_orientation + 1 % 4)
  169.     else
  170.         right(current_orientation)
  171.     end
  172.  
  173.     return goal_orientation
  174. end
  175.  
  176. local function determineMineEndOrientation(orientation, start_pos, end_pos)
  177.     local facing_forward = orientation
  178.     local dx, dy, dz = 1, 1, 1 -- face in the positive (1) or negative (-1) x-direction
  179.  
  180.     -- Edge cases
  181.     -- width == 1
  182.     if start_pos.x == end_pos.x then
  183.         if start_pos.z < end_pos.z then
  184.             return 2, 2, 2, 2 --dx, dy, dz
  185.         else
  186.             return 0, 0, 0, 0--dx, dy, dz
  187.         end
  188.     end
  189.     -- depth == 1
  190.     if start_pos.z == end_pos.z then
  191.         if start_pos.x < end_pos.x then
  192.             return 1, 1, 1, 1
  193.         else
  194.             return 3, 3, 3, 3
  195.         end
  196.     end
  197.     -- Regular behavior
  198.     if start_pos.z < end_pos.z then
  199.         dz = 1
  200.     else
  201.         dz = -1
  202.     end
  203.  
  204.     if start_pos.x < end_pos.x then
  205.         dx = 1
  206.     else
  207.         dx = -1
  208.     end
  209.  
  210.     if start_pos.y < end_pos.y then
  211.         dy = 1
  212.     else
  213.         dy = -1
  214.     end
  215.        
  216.  
  217.     local facing_even_turn, facing_backward, facing_odd_turn = facing_forward + dx % 4, facing_forward + 2 % 4, facing_forward + 3 * dx % 4
  218.  
  219.     -- Special case z
  220.     if orientation == 2 or orientation == 3 then
  221.         facing_even_turn, facing_odd_turn = facing_forward + dz % 4, facing_forward + 3 * dz % 4
  222.     end
  223.  
  224.     return facing_forward, facing_even_turn, facing_backward, facing_odd_turn, dx, dy, dz
  225. end
  226.  
  227. local function listContains(list, value)
  228.     for _, v in ipairs(list) do
  229.         if v == value then
  230.             return true
  231.         end
  232.     end
  233.     return false
  234. end
  235.  
  236. local function clearInventory(trashlist)
  237.     for slot = 1, 16, 1 do
  238.         local details = turtle.getItemDetail(slot)
  239.  
  240.         if details ~= nil then
  241.             if listContains(trashlist, details.name) then
  242.                 turtle.select(slot)
  243.                 turtle.drop()
  244.             end
  245.         end
  246.     end
  247. end
  248.  
  249.  
  250.  
  251. local function up()
  252.     digUp()
  253.     turtle.up()
  254. end
  255.  
  256. local function down()
  257.     digDown()
  258.     turtle.down()
  259. end
  260.  
  261. local function mineDy(dy)
  262.     if dy > 0 then
  263.         up()
  264.     elseif dy < 0 then
  265.         down()
  266.     end
  267. end
  268.  
  269. local function turn(orientation, dx)
  270.     if dx > 0 then
  271.         return right(orientation)
  272.     elseif dx < 0 then
  273.         return left(orientation)
  274.     end
  275. end
  276.  
  277. local function mineColumn(length)
  278.     for x = 1, length, 1 do
  279.         forward()
  280.         digUp()
  281.         digDown()
  282.     end
  283. end
  284.  
  285. --[[ local function mineColumn(length)
  286.     for x = 1, length, 1 do
  287.         forward()
  288.     end
  289. end ]]
  290.  
  291. local function mine(orientation, mine_start_pos)
  292.     local width, height, depth = width, height, depth
  293.  
  294.     local mine_end_pos = getGoalPos(mine_start_pos)
  295.     local facing_forward, facing_even_turn, facing_backward, facing_odd_turn, dx, dy, dz = determineMineEndOrientation(orientation, mine_start_pos, mine_end_pos)
  296.     local facing_end = facing_forward
  297.  
  298.     local current_pos = mine_start_pos + vector.new(0, dy, 0)
  299.     local next_pos = mine_start_pos
  300.  
  301.     local num_height_changes = math.abs((mine_start_pos - mine_end_pos).y) / 3
  302.  
  303.     local next_num_height_steps = 0
  304.     local turn_direction = dx
  305.  
  306.     mineDy(dy) -- Mine up/down one, to start off at the midele of a 3 high
  307.     digUp()
  308.  
  309.     while num_height_changes >= 0 do
  310.         if num_height_changes > 1 then
  311.             next_num_height_steps = 3 * dy -- is this dz?
  312.             num_height_changes = num_height_changes - 1
  313.         elseif num_height_changes > 0 then
  314.             next_num_height_steps = 0 * dy
  315.             num_height_changes = 0
  316.         end
  317.  
  318.         next_pos = current_pos + vector.new(width, next_num_height_steps, depth)
  319.  
  320.         while depth > 0 do
  321.             mineColumn(width - 1)
  322.             if depth > 1 then
  323.                 orientation = turn(orientation, turn_direction)
  324.                 mineColumn(1)
  325.                 orientation = turn(orientation, turn_direction)
  326.  
  327.                 turn_direction = -turn_direction
  328.             end
  329.  
  330.             depth = depth - 1
  331.  
  332.             clearInventory(trashlist)
  333.         end
  334.  
  335.         while next_num_height_steps > 0 do
  336.             mineDy(dy)
  337.             next_num_height_steps = next_num_height_steps - 1
  338.         end
  339.     end
  340.  
  341.     local mine_end_pos = mine_start_pos + vector.new((width - 1) * dx, (height - 1) * dy, (depth - 1) * dz)
  342.     print(mine_end_pos.."me "..orientation.."o")
  343.     return orientation, mine_end_pos
  344. end
  345.  
  346. --[[ local function mine(orientation, mine_start_pos, mine_end_pos)
  347.     local facing_forward, facing_even_turn, facing_backward, facing_odd_turn, dx, dy, dz = determineMineEndOrientation(orientation, mine_start_pos, mine_end_pos)
  348.     local facing_end = facing_forward
  349.  
  350.     local s = mine_end_pos - mine_start_pos
  351.     local mine_width, mine_depth, mine_height = s.x, s.z, s.y
  352.  
  353.     print(mine_height)
  354.  
  355.     if mine_width % 2 == 0 then
  356.         facing_end = facing_backward
  357.     else
  358.         facing_end = facing_forward
  359.     end
  360.  
  361.     for y = 0, mine_height, dy do
  362.         -- when the mine_width is odd, it doesn't matter if we start with
  363.         -- 0, or mine_width as
  364.         if (mine_width + dx) % 2 ~= 0 then
  365.             for x = 0, mine_width, dx do
  366.                 mineColumn(mine_depth)
  367.                 clearInventory(blacklist)
  368.  
  369.                 if x ~= mine_width then
  370.                     if y % 2 == 0 then
  371.                         orientation = face(orientation, facing_even_turn)
  372.                     else
  373.                         orientation = face(orientation, facing_odd_turn)
  374.                     end
  375.                     forward()
  376.                 end
  377.  
  378.                 if x % 2 == 0 then
  379.                     if y % 2 == 0 then
  380.                         orientation = face(orientation, facing_backward)
  381.                     elseif x - 1 == mine_width then
  382.                         orientation = face(orientation, facing_backward)
  383.                     else
  384.                         orientation = face(orientation, facing_forward)
  385.                     end
  386.                 else
  387.                     if y % 2 == 0 then
  388.                         orientation = face(orientation, facing_forward)
  389.                     else
  390.                         orientation = face(orientation, facing_backward)
  391.                     end
  392.                 end
  393.             end
  394.         else
  395.             for x = 0, mine_width, 2 * dx do
  396.                 mineColumn(mine_depth)
  397.                 clearInventory(blacklist)
  398.  
  399.                 orientation = face(orientation, facing_even_turn)
  400.                 forward()
  401.                 orientation = face(orientation, facing_backward)
  402.  
  403.                 mineColumn(mine_depth)
  404.                 clearInventory(blacklist)
  405.  
  406.                 orientation = face(orientation, facing_odd_turn)
  407.                 forward()
  408.                 orientation = face(orientation, facing_forward)
  409.             end
  410.         end
  411.         if y ~= mine_height then
  412.             turtle.digDown()
  413.             turtle.down()
  414.         end
  415.     end
  416.  
  417.     if mine_height % 2 ~= 0 then
  418.         mine_end_pos.x = mine_start_pos.x
  419.         mine_end_pos.z = mine_start_pos.z
  420.     end
  421.    
  422.     return orientation, mine_end_pos
  423. end ]]
  424.  
  425. local function moveToGoal(orientation, current_pos, goal_pos)
  426.     local res_v = goal_pos - current_pos
  427.  
  428.     local distance_x, distance_y, distance_z = res_v.x, res_v.y, res_v.z
  429.  
  430.     if distance_y > 0 then
  431.         for step = 1, math.abs(distance_y), 1 do
  432.             digUp()
  433.             turtle.up()
  434.         end
  435.     elseif distance_y < 0 then
  436.         for step = 1, math.abs(distance_y), 1 do
  437.             digDown()
  438.             turtle.down()
  439.         end
  440.     end
  441.  
  442.     if distance_x < 0 then orientation = face(orientation, 3) elseif distance_x > 0 then orientation = face(orientation, 1) end
  443.  
  444.     for step = 1, math.abs(distance_x), 1 do
  445.         forward()
  446.     end
  447.  
  448.     if distance_z < 0 then orientation = face(orientation, 0) elseif distance_z > 0 then orientation = face(orientation, 2) end
  449.  
  450.     for step = 1, math.abs(distance_z), 1 do
  451.         forward()
  452.     end
  453.  
  454.     return orientation
  455. end
  456.  
  457. local function determineStartingOrientation()
  458.     dig()
  459.     turtle.forward()
  460.  
  461.     local new_x, new_y, new_z = gps.locate()
  462.  
  463.     if new_x == nil then
  464.         print("Couldn't determine orientation, please help: 0 (north) | 1 (east) | 2 (south) | 3 (west)")
  465.         error("GPS error")
  466.         return io.read("*number")
  467.     end
  468.  
  469.     local new_location = vector.new(new_x, new_y, new_z)
  470.  
  471.     local pos_diff = new_location - mine_start_pos
  472.  
  473.     if pos_diff == nil then
  474.         print("Couldn't determine orientation, please help: 0 (north) | 1 (east) | 2 (south) | 3 (west)")
  475.         error("pos diff error")
  476.         return io.read("*number")
  477.     end
  478.  
  479.     if pos_diff.x > 0 then
  480.         return 1
  481.     elseif pos_diff.x < 0 then
  482.         return 3
  483.     end
  484.  
  485.     if pos_diff.y > 0 then
  486.         return 2
  487.     elseif pos_diff.y < 0 then
  488.         return 0
  489.     end
  490.  
  491.     return 0 -- if the diff is in the z direction, just face north
  492. end
  493.  
  494. local function deploy()
  495.     local orientation = determineStartingOrientation() -- facing south
  496.  
  497.     --modem message to server "ready for next bot"
  498.     --local mine_start_pos, mine_end_pos = recv modem message from server "mine area start pos, mine area end pos"
  499.    
  500.     --orientation = moveToGoal(orientation, mine_start_pos, mine_end_pos)
  501.    
  502.     orientation, mine_end_pos = mine(orientation, mine_start_pos) --errors if x (depth) is even
  503.  
  504.     print("reached end of mining")
  505.     orientation = moveToGoal(orientation, mine_end_pos, mine_start_pos)
  506. end
  507.  
  508. -- Returns the slot an item with a given name is in.
  509. -- If it can't be found, returns nil
  510. local function getInventoryId(name)
  511.     for slot = 1, 16, 1 do
  512.         turtle.select(slot)
  513.         local details = turtle.getItemDetail()
  514.         if details ~= nil then
  515.             if details.name == name then
  516.                 return slot
  517.             end
  518.         end
  519.     end
  520. end
  521.  
  522. local function enumerateCoal()
  523.     local coal = getInventoryId("minecraft:coal")
  524.  
  525.     local coal_value = 80
  526.  
  527.     local total_fuel_units = 0
  528.  
  529.     if coal ~= nil then
  530.         local details = turtle.getItemDetail(coal)
  531.  
  532.         total_fuel_units = total_fuel_units + details.count * coal_value
  533.     end
  534.  
  535.     return total_fuel_units
  536. end
  537.  
  538. local function determineFuelMethod()
  539.     local chest_id = getInventoryId("enderstorage:ender_storage")
  540.  
  541.     if chest_id == nil then
  542.         return "coal"
  543.     else
  544.         return "lava"
  545.     end
  546. end
  547.  
  548. -- Performs a refueling cycle.
  549. -- It gets a lava bucket from
  550. local function refuel(fuel, necessary_fuel, method)
  551.     if method == "lava" then
  552.         turtle.select(getInventoryId("enderstorage:ender_storage"))
  553.         digUp()
  554.         turtle.placeUp()
  555.  
  556.         while fuel < necessary_fuel do
  557.             turtle.suckUp()
  558.        
  559.             local bucket_id = getInventoryId("minecraft:lava_bucket")
  560.             while bucket_id == nil do
  561.                 turtle.dropUp()
  562.                 sleep(1)
  563.                 turtle.suckUp()
  564.                 bucket_id = getInventoryId("minecraft:lava_bucket")
  565.             end
  566.        
  567.             turtle.select(bucket_id)
  568.             turtle.refuel()
  569.             turtle.dropUp()
  570.  
  571.             fuel = turtle.getFuelLevel()
  572.         end
  573.  
  574.         local empty_bucket_id = getInventoryId("minecraft:bucket")
  575.         while empty_bucket_id ~= nil do
  576.             turtle.select(empty_bucket_id)
  577.             turtle.dropUp()
  578.  
  579.             empty_bucket_id = getInventoryId("minecraft:bucket")
  580.         end
  581.  
  582.         digUp()
  583.     elseif method == "coal" then
  584.         local coal_fuel = enumerateCoal()
  585.         if fuel + coal_fuel < necessary_fuel then
  586.             error("Not enough coal to proceed.\nNeed at least ".. (necessary_fuel - fuel) / 80 .. " more pieces.")
  587.         end
  588.  
  589.         while fuel < necessary_fuel do
  590.             local coal = getInventoryId("minecraft:coal")
  591.  
  592.             if coal ~= nil then
  593.                 turtle.select(coal)
  594.             end
  595.             turtle.refuel()
  596.  
  597.             fuel = turtle.getFuelLevel()
  598.         end
  599.     end
  600.     return fuel
  601. end
  602.  
  603. -- Checks if there is enough fuel and if not performs a refueling cycle
  604. local function checkFuel(method)
  605.     local fuel = turtle.getFuelLevel()
  606.     local necessary_fuel = necessaryFuel()
  607.     local method = determineFuelMethod()
  608.  
  609.     if fuel < necessary_fuel then
  610.         fuel = refuel(fuel, necessary_fuel, method)
  611.     end
  612. end
  613.  
  614.  
  615. local function main()
  616.     checkFuel()
  617.     deploy()
  618. end
  619.  
  620. main()
  621.  
Add Comment
Please, Sign In to add comment