minecraft-cc-tools/miner.lua
2024-05-08 22:29:52 +02:00

242 lines
5.8 KiB
Lua

local robotApi = require('robot')
local turtleUtils = require('turtle-utils')
local config = {
startY = 122,
targetY = 109,
height = 1,
size = 4
}
local TARGET_Y = config.targetY - config.startY
local TARGET_Z = config.size - 1
local TARGET_X = config.size - 1
local MAX_X = TARGET_X
local MAX_Y = TARGET_Y + (config.height - 1)
local MAX_Z = TARGET_Z
local LOWER_LIMIT = 2;
local HIGHER_LIMIT = 128;
local robot = robotApi.create()
local MAX_INVENTORY_BLOCKS = 16 * 64
local ADDITIONAL_FUEL_NEEDED = 128
local MIN_FUEL_NEEDED = (config.size * 2) + TARGET_Y + MAX_INVENTORY_BLOCKS + ADDITIONAL_FUEL_NEEDED
local miner = {
robot = robot,
mission = 'unload', -- "unload" | "refuel" | "mine" | "return-home" | "return-mine" | nil
finished = false,
lastPositionState = nil -- { x, y, z, dir }
}
local function isOdd(x)
return (x % 2) == 1
end
local function checkConfig()
if config.targetY >= config.startY then
error('targetY should be lower than startY')
end
if config.height < 1 then
error('height cannot be lower than 1')
end
if config.size < LOWER_LIMIT then
error('size cannot be lower than ' .. LOWER_LIMIT)
end
if config.size > HIGHER_LIMIT then
error('size is too large (higher limit is ' .. HIGHER_LIMIT .. ')')
end
if isOdd(config.size) then
error('configured size should be even')
end
end
local function prepareTurtle()
turtle.select(1)
end
local function isProgramFinished()
if miner.mission ~= nil then
return false
end
local robotState = miner.robot.getSate()
return robotState.x == 0 and robotState.y == 0 and robotState.z == 0
end
local function unloadProcedure()
print('> Starting unload procedure...')
turtleUtils.waitForInventory('front')
for i=1, 16, 1 do
turtle.select(i)
turtle.refuel()
turtleUtils.tryDrop()
end
miner.mission = 'refuel'
end
local function refuelProcedure()
print('> Starting refuel procedure (' .. turtleUtils.getFuelPercentage() .. '%)')
turtleUtils.waitForInventory('top')
turtle.select(1)
while turtle.getFuelLevel() < MIN_FUEL_NEEDED do
turtleUtils.trySuckUp()
local ok = turtle.refuel()
if not ok then
turtleUtils.tryDrop()
end
end
print('> Refuel done.')
miner.mission = 'return-mine'
end
local function returnMineProcedure()
if miner.finished then
miner.mission = nil -- it will stop the loop
return
end
if robot.lastPositionState then
local robotState = miner.robot.getState()
if robotState.y > miner.lastPositionState.y then
miner.robot.down()
elseif robotState.z < miner.lastPositionState.z then
miner.robot.forward()
else
miner.robot.turnRight()
for i=1, miner.lastPositionState.x, 1 do
miner.robot.forward()
end
while miner.robot.getState().dir ~= miner.lastPositionState.dir do
miner.robot.turnRight()
end
miner.mission = 'mine'
print('> Starting mining procedure...')
end
else
miner.mission = 'mine'
print('> Starting mining procedure...')
end
end
local function mineProcedure()
local robotState = miner.robot.getState()
local targetY = TARGET_Y
local targetZ = TARGET_Z
-- 1. Move
if robotState.y > targetY then
turtle.digDown()
miner.robot.down()
elseif robotState.dir == 'FORWARD' and robotState.z < targetZ then
turtleUtils.digAll()
miner.robot.forward()
elseif robotState.dir == 'FORWARD' and robotState.z == targetZ then
miner.robot.turnRight()
turtleUtils.digAll()
miner.robot.forward()
miner.robot.turnRight()
elseif robotState.dir == 'BACKWARD' and robotState.z > 0 then
turtleUtils.digAll()
miner.robot.forward()
elseif robotState.dir == 'BACKWARD' and robotState.z == 0 then
miner.robot.turnLeft()
turtleUtils.digAll()
miner.robot.forward()
miner.robot.turnLeft()
end
-- 2. Check
if robotState.x == MAX_X and robotState.y == MAX_Y and robotState.z == MAX_Z then
miner.finished = true
miner.mission = 'return-home'
miner.lastPositionState = miner.robot.getState()
print('> Starting return home procedure because mining session is finished...')
elseif robotState.x == MAX_X and robotState.z == MAX_Z then
-- this part assume that the size of the mine is even
miner.robot.turnRight()
for i=1, config.size - 1, 1 do
miner.robot.forward()
end
miner.robot.turnRight()
miner.robot.up()
end
if turtleUtils.countFreeSlots() < 1 then
print('> Starting return home procedure because inventory is almost full...')
miner.mission = 'return-home'
miner.lastPositionState = miner.robot.getState()
end
end
local function returnHomeProcedure()
local robotState = miner.robot.getState()
if robotState.x == 0 and robotState.y == 0 and robotState.z == 0 then
miner.mission = 'unload'
elseif robotState.x == 0 and robotState.z == 0 then
miner.robot.up()
elseif robotState.x > 0 then
if robotState.dir == 'FORWARD' then
miner.robot.turnLeft()
elseif robotState.dir == 'BACKWARD' then
miner.robot.turnRight()
end
for i=1, robotState.x, 1 do
miner.robot.forward()
end
miner.robot.turnLeft()
elseif robotState.z > 0 then
for i=1, robotState.z, 1 do
miner.robot.forward()
end
miner.robot.turnLeft()
miner.robot.turnLeft()
end
end
checkConfig()
prepareTurtle()
print("> Miner program started, minimum fuel needed: " .. MIN_FUEL_NEEDED)
while not isProgramFinished() do
if miner.mission == 'unload' then
unloadProcedure()
elseif miner.mission == 'refuel' then
refuelProcedure()
elseif miner.mission == 'mine' then
mineProcedure()
elseif miner.mission == 'return-home' then
returnHomeProcedure()
elseif miner.mission == 'return-mine' then
returnMineProcedure()
end
end
print("> Miner program finished!")