Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local args = { ... }
- local width, height, depth = tonumber(args[1]), tonumber(args[2]), tonumber(args[3])
- local trashlist = {
- "minecraft:stone",
- "minecraft:granite",
- "minecraft:andesite",
- "minecraft:diorite",
- "minecraft:cobblestone",
- "minecraft:dirt",
- "minecraft:grass",
- "minecraft:gravel",
- "extcaves:lavastone",
- "extcaves:sedimentstone",
- "extcaves:pebble_stone",
- "create:weathered_limestone",
- }
- local blacklist = {
- "tetra"
- }
- local function dig()
- local _, item = turtle.inspect()
- if item.name ~= nil then
- for _, v in ipairs(blacklist) do
- if v == nil then
- error("Blacklist is empty")
- return
- else
- if string.find(item.name, v) then
- print("Found blacklisted item "..item.name)
- return
- end
- end
- end
- turtle.dig()
- end
- end
- local function digUp()
- local _, item = turtle.inspectUp()
- if item.name ~= nil then
- for _, v in ipairs(blacklist) do
- if v == nil then
- error("Blacklist is empty")
- return
- else
- if string.find(item.name, v) then
- print("Found blacklisted item "..item.name)
- return
- end
- end
- end
- turtle.digUp()
- end
- end
- local function digDown()
- local _, item = turtle.inspectDown()
- if item.name ~= nil then
- for _, v in ipairs(blacklist) do
- if v == nil then
- error("Blacklist is empty")
- return
- else
- if string.find(item.name, v) then
- print("Found blacklisted item "..item.name)
- return
- end
- end
- end
- turtle.digDown()
- end
- end
- local function getCurrentPos()
- local gps_x, gps_y, gps_z = gps.locate()
- local gps_pos = vector.new(gps_x, gps_y, gps_z)
- if gps_x == nil then
- print("Couldn't determine position please help: x y z")
- local x, y, z = io.read("*number", "*number", "*number")
- local vec = vector.new(x, y, z)
- return vec
- end
- return gps_pos
- end
- local function getGoalPos(start_pos)
- print(width .. "w " .. height .. "h " .. depth .. "d")
- return vector.new(start_pos.x + width, start_pos.y + height, start_pos.z + depth)
- end
- local mine_start_pos = getCurrentPos() --vector.new(0, 0, 0)
- local mine_end_pos = getGoalPos(mine_start_pos) --vector.new(10, 4, 30)
- -- Returns the number of blocks that the turtle has to travel back along.
- -- If the turtle starts in the lower left and the width is divisible by 2 then
- -- the turtle will have to travel height + width blocks.
- -- If the width is not divisible by 2 then the turtle will also have to travel along the depth
- local function diffStartEndPosition(depth, width, height)
- local result = height + width
- if width % 2 ~= 0 then
- result = result + depth
- end
- return result
- end
- -- Returns the amount of blocks the turtle requires fuel for (plus a little extra).
- -- 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
- -- It also adds a little extra fuel, to be safe
- local function necessaryFuel()
- return math.ceil((depth * width * height) + 2 * vector.distance(mine_end_pos, mine_start_pos) + diffStartEndPosition(depth, width, height) + 5)
- end
- -- Returns the Manhattan distance based on vector subtraction
- function vector.distance(v1, v2)
- local res_v = v2 - v1
- return (math.abs(res_v.x) + math.abs(res_v.y) + math.abs(res_v.z))
- end
- local function left(orientation)
- turtle.turnLeft()
- orientation = orientation - 1
- orientation = orientation % 4
- return orientation
- end
- local function right(orientation)
- turtle.turnRight()
- orientation = orientation + 1
- orientation = orientation % 4
- return orientation
- end
- local function forward()
- while turtle.detect() do
- dig()
- if turtle.detect() then sleep(0.8) end -- wait for the falling animation to finish (if gravel)
- end
- while not turtle.forward() do
- turtle.attack()
- end
- end
- local function face(current_orientation, goal_orientation)
- local needed_right_turns = (goal_orientation - current_orientation) % 4
- if needed_right_turns == 0 then
- return goal_orientation
- elseif needed_right_turns > 2 then
- left(current_orientation)
- elseif needed_right_turns == 2 then
- right(current_orientation)
- right(current_orientation + 1 % 4)
- else
- right(current_orientation)
- end
- return goal_orientation
- end
- local function determineMineEndOrientation(orientation, start_pos, end_pos)
- local facing_forward = orientation
- local dx, dy, dz = 1, 1, 1 -- face in the positive (1) or negative (-1) x-direction
- -- Edge cases
- -- width == 1
- if start_pos.x == end_pos.x then
- if start_pos.z < end_pos.z then
- return 2, 2, 2, 2 --dx, dy, dz
- else
- return 0, 0, 0, 0--dx, dy, dz
- end
- end
- -- depth == 1
- if start_pos.z == end_pos.z then
- if start_pos.x < end_pos.x then
- return 1, 1, 1, 1
- else
- return 3, 3, 3, 3
- end
- end
- -- Regular behavior
- if start_pos.z < end_pos.z then
- dz = 1
- else
- dz = -1
- end
- if start_pos.x < end_pos.x then
- dx = 1
- else
- dx = -1
- end
- if start_pos.y < end_pos.y then
- dy = 1
- else
- dy = -1
- end
- local facing_even_turn, facing_backward, facing_odd_turn = facing_forward + dx % 4, facing_forward + 2 % 4, facing_forward + 3 * dx % 4
- -- Special case z
- if orientation == 2 or orientation == 3 then
- facing_even_turn, facing_odd_turn = facing_forward + dz % 4, facing_forward + 3 * dz % 4
- end
- return facing_forward, facing_even_turn, facing_backward, facing_odd_turn, dx, dy, dz
- end
- local function listContains(list, value)
- for _, v in ipairs(list) do
- if v == value then
- return true
- end
- end
- return false
- end
- local function clearInventory(trashlist)
- for slot = 1, 16, 1 do
- local details = turtle.getItemDetail(slot)
- if details ~= nil then
- if listContains(trashlist, details.name) then
- turtle.select(slot)
- turtle.drop()
- end
- end
- end
- end
- local function up()
- digUp()
- turtle.up()
- end
- local function down()
- digDown()
- turtle.down()
- end
- local function mineDy(dy)
- if dy > 0 then
- up()
- elseif dy < 0 then
- down()
- end
- end
- local function turn(orientation, dx)
- if dx > 0 then
- return right(orientation)
- elseif dx < 0 then
- return left(orientation)
- end
- end
- local function mineColumn(length)
- for x = 1, length, 1 do
- forward()
- digUp()
- digDown()
- end
- end
- --[[ local function mineColumn(length)
- for x = 1, length, 1 do
- forward()
- end
- end ]]
- local function mine(orientation, mine_start_pos)
- local width, height, depth = width, height, depth
- local mine_end_pos = getGoalPos(mine_start_pos)
- local facing_forward, facing_even_turn, facing_backward, facing_odd_turn, dx, dy, dz = determineMineEndOrientation(orientation, mine_start_pos, mine_end_pos)
- local facing_end = facing_forward
- local current_pos = mine_start_pos + vector.new(0, dy, 0)
- local next_pos = mine_start_pos
- local num_height_changes = math.abs((mine_start_pos - mine_end_pos).y) / 3
- local next_num_height_steps = 0
- local turn_direction = dx
- mineDy(dy) -- Mine up/down one, to start off at the midele of a 3 high
- digUp()
- while num_height_changes >= 0 do
- if num_height_changes > 1 then
- next_num_height_steps = 3 * dy -- is this dz?
- num_height_changes = num_height_changes - 1
- elseif num_height_changes > 0 then
- next_num_height_steps = 0 * dy
- num_height_changes = 0
- end
- next_pos = current_pos + vector.new(width, next_num_height_steps, depth)
- while depth > 0 do
- mineColumn(width - 1)
- if depth > 1 then
- orientation = turn(orientation, turn_direction)
- mineColumn(1)
- orientation = turn(orientation, turn_direction)
- turn_direction = -turn_direction
- end
- depth = depth - 1
- clearInventory(trashlist)
- end
- while next_num_height_steps > 0 do
- mineDy(dy)
- next_num_height_steps = next_num_height_steps - 1
- end
- end
- local mine_end_pos = mine_start_pos + vector.new((width - 1) * dx, (height - 1) * dy, (depth - 1) * dz)
- print(mine_end_pos.."me "..orientation.."o")
- return orientation, mine_end_pos
- end
- --[[ local function mine(orientation, mine_start_pos, mine_end_pos)
- local facing_forward, facing_even_turn, facing_backward, facing_odd_turn, dx, dy, dz = determineMineEndOrientation(orientation, mine_start_pos, mine_end_pos)
- local facing_end = facing_forward
- local s = mine_end_pos - mine_start_pos
- local mine_width, mine_depth, mine_height = s.x, s.z, s.y
- print(mine_height)
- if mine_width % 2 == 0 then
- facing_end = facing_backward
- else
- facing_end = facing_forward
- end
- for y = 0, mine_height, dy do
- -- when the mine_width is odd, it doesn't matter if we start with
- -- 0, or mine_width as
- if (mine_width + dx) % 2 ~= 0 then
- for x = 0, mine_width, dx do
- mineColumn(mine_depth)
- clearInventory(blacklist)
- if x ~= mine_width then
- if y % 2 == 0 then
- orientation = face(orientation, facing_even_turn)
- else
- orientation = face(orientation, facing_odd_turn)
- end
- forward()
- end
- if x % 2 == 0 then
- if y % 2 == 0 then
- orientation = face(orientation, facing_backward)
- elseif x - 1 == mine_width then
- orientation = face(orientation, facing_backward)
- else
- orientation = face(orientation, facing_forward)
- end
- else
- if y % 2 == 0 then
- orientation = face(orientation, facing_forward)
- else
- orientation = face(orientation, facing_backward)
- end
- end
- end
- else
- for x = 0, mine_width, 2 * dx do
- mineColumn(mine_depth)
- clearInventory(blacklist)
- orientation = face(orientation, facing_even_turn)
- forward()
- orientation = face(orientation, facing_backward)
- mineColumn(mine_depth)
- clearInventory(blacklist)
- orientation = face(orientation, facing_odd_turn)
- forward()
- orientation = face(orientation, facing_forward)
- end
- end
- if y ~= mine_height then
- turtle.digDown()
- turtle.down()
- end
- end
- if mine_height % 2 ~= 0 then
- mine_end_pos.x = mine_start_pos.x
- mine_end_pos.z = mine_start_pos.z
- end
- return orientation, mine_end_pos
- end ]]
- local function moveToGoal(orientation, current_pos, goal_pos)
- local res_v = goal_pos - current_pos
- local distance_x, distance_y, distance_z = res_v.x, res_v.y, res_v.z
- if distance_y > 0 then
- for step = 1, math.abs(distance_y), 1 do
- digUp()
- turtle.up()
- end
- elseif distance_y < 0 then
- for step = 1, math.abs(distance_y), 1 do
- digDown()
- turtle.down()
- end
- end
- if distance_x < 0 then orientation = face(orientation, 3) elseif distance_x > 0 then orientation = face(orientation, 1) end
- for step = 1, math.abs(distance_x), 1 do
- forward()
- end
- if distance_z < 0 then orientation = face(orientation, 0) elseif distance_z > 0 then orientation = face(orientation, 2) end
- for step = 1, math.abs(distance_z), 1 do
- forward()
- end
- return orientation
- end
- local function determineStartingOrientation()
- dig()
- turtle.forward()
- local new_x, new_y, new_z = gps.locate()
- if new_x == nil then
- print("Couldn't determine orientation, please help: 0 (north) | 1 (east) | 2 (south) | 3 (west)")
- error("GPS error")
- return io.read("*number")
- end
- local new_location = vector.new(new_x, new_y, new_z)
- local pos_diff = new_location - mine_start_pos
- if pos_diff == nil then
- print("Couldn't determine orientation, please help: 0 (north) | 1 (east) | 2 (south) | 3 (west)")
- error("pos diff error")
- return io.read("*number")
- end
- if pos_diff.x > 0 then
- return 1
- elseif pos_diff.x < 0 then
- return 3
- end
- if pos_diff.y > 0 then
- return 2
- elseif pos_diff.y < 0 then
- return 0
- end
- return 0 -- if the diff is in the z direction, just face north
- end
- local function deploy()
- local orientation = determineStartingOrientation() -- facing south
- --modem message to server "ready for next bot"
- --local mine_start_pos, mine_end_pos = recv modem message from server "mine area start pos, mine area end pos"
- --orientation = moveToGoal(orientation, mine_start_pos, mine_end_pos)
- orientation, mine_end_pos = mine(orientation, mine_start_pos) --errors if x (depth) is even
- print("reached end of mining")
- orientation = moveToGoal(orientation, mine_end_pos, mine_start_pos)
- end
- -- Returns the slot an item with a given name is in.
- -- If it can't be found, returns nil
- local function getInventoryId(name)
- for slot = 1, 16, 1 do
- turtle.select(slot)
- local details = turtle.getItemDetail()
- if details ~= nil then
- if details.name == name then
- return slot
- end
- end
- end
- end
- local function enumerateCoal()
- local coal = getInventoryId("minecraft:coal")
- local coal_value = 80
- local total_fuel_units = 0
- if coal ~= nil then
- local details = turtle.getItemDetail(coal)
- total_fuel_units = total_fuel_units + details.count * coal_value
- end
- return total_fuel_units
- end
- local function determineFuelMethod()
- local chest_id = getInventoryId("enderstorage:ender_storage")
- if chest_id == nil then
- return "coal"
- else
- return "lava"
- end
- end
- -- Performs a refueling cycle.
- -- It gets a lava bucket from
- local function refuel(fuel, necessary_fuel, method)
- if method == "lava" then
- turtle.select(getInventoryId("enderstorage:ender_storage"))
- digUp()
- turtle.placeUp()
- while fuel < necessary_fuel do
- turtle.suckUp()
- local bucket_id = getInventoryId("minecraft:lava_bucket")
- while bucket_id == nil do
- turtle.dropUp()
- sleep(1)
- turtle.suckUp()
- bucket_id = getInventoryId("minecraft:lava_bucket")
- end
- turtle.select(bucket_id)
- turtle.refuel()
- turtle.dropUp()
- fuel = turtle.getFuelLevel()
- end
- local empty_bucket_id = getInventoryId("minecraft:bucket")
- while empty_bucket_id ~= nil do
- turtle.select(empty_bucket_id)
- turtle.dropUp()
- empty_bucket_id = getInventoryId("minecraft:bucket")
- end
- digUp()
- elseif method == "coal" then
- local coal_fuel = enumerateCoal()
- if fuel + coal_fuel < necessary_fuel then
- error("Not enough coal to proceed.\nNeed at least ".. (necessary_fuel - fuel) / 80 .. " more pieces.")
- end
- while fuel < necessary_fuel do
- local coal = getInventoryId("minecraft:coal")
- if coal ~= nil then
- turtle.select(coal)
- end
- turtle.refuel()
- fuel = turtle.getFuelLevel()
- end
- end
- return fuel
- end
- -- Checks if there is enough fuel and if not performs a refueling cycle
- local function checkFuel(method)
- local fuel = turtle.getFuelLevel()
- local necessary_fuel = necessaryFuel()
- local method = determineFuelMethod()
- if fuel < necessary_fuel then
- fuel = refuel(fuel, necessary_fuel, method)
- end
- end
- local function main()
- checkFuel()
- deploy()
- end
- main()
Add Comment
Please, Sign In to add comment