Merge netherite/excavation controllers, overhaul movement logic with verticality support
This commit is contained in:
324
controller/excavation_controller.lua
Normal file
324
controller/excavation_controller.lua
Normal file
@ -0,0 +1,324 @@
|
||||
local Direction = require("lib.direction")
|
||||
local TurtleController = require("controller.turtle_controller")
|
||||
|
||||
---@alias ExcavationControllerConfig {slice_length: number, slice_height: number, center_slice_width: number, slice_width: number, slice_padding: number, slices_left: number, slices_right: number}
|
||||
|
||||
---@class ExcavationController
|
||||
---@field controller TurtleController
|
||||
---@field config ExcavationControllerConfig
|
||||
local ExcavationController = {}
|
||||
ExcavationController.__index = ExcavationController
|
||||
|
||||
|
||||
---@return ExcavationController
|
||||
function ExcavationController:Create()
|
||||
local t = {}
|
||||
setmetatable(t, ExcavationController)
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Fields
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
t.controller = TurtleController:Create()
|
||||
t.config = {
|
||||
slice_length = 0,
|
||||
slice_height = 0,
|
||||
center_slice_width = 0,
|
||||
slice_width = 0,
|
||||
slice_padding = 0,
|
||||
slices_left = 0,
|
||||
slices_right = 0,
|
||||
}
|
||||
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Behavior Methods
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
---Excavates a single 1x1/1x2 tunnel of configured length.
|
||||
---Will leave the turtle wherever it ends up.
|
||||
---Only unstocks/refuels if required.
|
||||
---@param mine_above boolean
|
||||
---@param mine_below boolean
|
||||
function ExcavationController:Excavate_1x1or2or3xL(mine_above, mine_below)
|
||||
self.controller:EnableMiningForward()
|
||||
if mine_above then
|
||||
self.controller:EnableMiningAbove()
|
||||
end
|
||||
if mine_below then
|
||||
self.controller:EnableMiningBelow()
|
||||
end
|
||||
|
||||
self.controller:MoveForward(self.config.slice_length)
|
||||
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:DisableMiningBelow()
|
||||
end
|
||||
|
||||
|
||||
---Excavates a single 1xH partial slice of configured length.
|
||||
---Will leave the turtle in its starting position.
|
||||
---Only unstocks/refuels if required.
|
||||
function ExcavationController:Excavate_1xHxL()
|
||||
self.controller:StorePosition()
|
||||
|
||||
-- We can mine 2 blocks heigh in a single go
|
||||
local number_of_1x3xL = math.floor(self.config.slice_height / 3)
|
||||
|
||||
-- Prepare for mining the blocks below the turtle
|
||||
if number_of_1x3xL > 0 then
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveVertical(1)
|
||||
self.controller:DisableMiningAbove()
|
||||
end
|
||||
|
||||
-- Mine 1x3xL
|
||||
for i = 1,number_of_1x3xL do
|
||||
self:Excavate_1x1or2or3xL(true, true)
|
||||
|
||||
self.controller:TurnRelative(2)
|
||||
|
||||
-- Don't move upwards in the last iteration so we can decide
|
||||
-- how much to move depending on how much we still have to excavate
|
||||
if i == number_of_1x3xL then
|
||||
break
|
||||
end
|
||||
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveVertical(4)
|
||||
self.controller:MoveVertical(-1)
|
||||
self.controller:DisableMiningAbove()
|
||||
end
|
||||
|
||||
-- Mine remaining 1x2xL or 1x1xL
|
||||
if self.config.slice_height % 3 == 2 then
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveVertical(3)
|
||||
self.controller:MoveVertical(-1)
|
||||
self.controller:DisableMiningAbove()
|
||||
|
||||
self:Excavate_1x1or2or3xL(true, false)
|
||||
elseif self.config.slice_height % 3 == 1 then
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveVertical(3)
|
||||
self.controller:MoveVertical(-1)
|
||||
self.controller:DisableMiningAbove()
|
||||
|
||||
self:Excavate_1x1or2or3xL(false, false)
|
||||
end
|
||||
|
||||
self.controller:EnableMiningBelow()
|
||||
self.controller:MoveBack()
|
||||
self.controller:DisableMiningBelow()
|
||||
end
|
||||
|
||||
|
||||
---Excavates a single WxH slice of configured length (EAST to WEST).
|
||||
---Will leave the turtle in its starting position.
|
||||
---Only unstocks/refuels if required.
|
||||
---@param center_slice boolean | nil
|
||||
function ExcavationController:Excavate_WxHxL(center_slice)
|
||||
self.controller:StorePosition()
|
||||
|
||||
center_slice = center_slice or false
|
||||
local width = center_slice and self.config.center_slice_width or self.config.slice_width
|
||||
|
||||
for i = 1,width do
|
||||
self:Excavate_1xHxL()
|
||||
|
||||
if i == width then
|
||||
break
|
||||
end
|
||||
|
||||
self.controller:TurnToDirection(Direction.WEST)
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(1)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
end
|
||||
|
||||
self.controller:MoveBack()
|
||||
end
|
||||
|
||||
|
||||
---Excavates all slices.
|
||||
---Will leave the turtle refueled and unstocked in its 0x0x0 position.
|
||||
function ExcavationController:Excavate()
|
||||
-- Enter excavation area
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(1)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
|
||||
-- Excavate center slice (start from right/back/bottom)
|
||||
-- Uneven center widths will be centered, even center widths will have a block more on the right
|
||||
print("Excavating center slice...")
|
||||
local center_width_right = math.floor(self.config.center_slice_width / 2)
|
||||
self.controller:StorePosition()
|
||||
self.controller:TurnToDirection(Direction.EAST)
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(center_width_right)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
self:Excavate_WxHxL(true)
|
||||
self.controller:MoveBack() -- (0, 0, 1)
|
||||
|
||||
-- Move to right slices starting location
|
||||
local padded_width_right = self.config.slices_right * (self.config.slice_width + self.config.slice_padding)
|
||||
self.controller:StorePosition()
|
||||
self.controller:TurnToDirection(Direction.EAST)
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(center_width_right + padded_width_right)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
|
||||
-- Excavate right slices
|
||||
print("Excavating right slices")
|
||||
for i = 1,self.config.slices_right do
|
||||
self:Excavate_WxHxL()
|
||||
|
||||
if i == self.config.slices_right then
|
||||
break
|
||||
end
|
||||
|
||||
-- Move to the next slice
|
||||
self.controller:TurnToDirection(Direction.WEST)
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(self.config.slice_width + self.config.slice_padding)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
end
|
||||
self.controller:MoveBack() -- (0, 0, 1)
|
||||
|
||||
-- Move to left slices starting location
|
||||
local center_width_left = self.config.center_slice_width - center_width_right
|
||||
self.controller:StorePosition()
|
||||
self.controller:TurnToDirection(Direction.WEST)
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(center_width_left)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
|
||||
-- Excavate left slices
|
||||
print("Excavate left slices")
|
||||
for i = 1,self.config.slices_left do
|
||||
-- Move to the next slice
|
||||
self.controller:TurnToDirection(Direction.WEST)
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(self.config.slice_padding)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
|
||||
self:Excavate_WxHxL()
|
||||
|
||||
if i == self.config.slices_left then
|
||||
break
|
||||
end
|
||||
|
||||
self.controller:TurnToDirection(Direction.WEST)
|
||||
self.controller:EnableMiningForward()
|
||||
self.controller:EnableMiningAbove()
|
||||
self.controller:MoveForward(self.config.slice_width)
|
||||
self.controller:DisableMiningForward()
|
||||
self.controller:DisableMiningAbove()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
end
|
||||
self.controller:MoveBack() -- (0, 0, 1)
|
||||
|
||||
-- Finish up
|
||||
self.controller:MoveToPosition(0, 0, 0, self.controller.config.storage_direction)
|
||||
self.controller:DropInventory()
|
||||
self.controller:TurnToDirection(Direction.NORTH)
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Management Methods
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function ExcavationController:Configure()
|
||||
local config_complete = false
|
||||
|
||||
while not config_complete do
|
||||
print("How long should each slice be?")
|
||||
self.config.slice_length = tonumber(io.read()) or 3
|
||||
|
||||
print("How high should each slice be?")
|
||||
self.config.slice_height = tonumber(io.read()) or 3
|
||||
|
||||
print("How wide should the center slice be?")
|
||||
self.config.center_slice_width = tonumber(io.read()) or 1
|
||||
|
||||
print("How wide should the other slices be?")
|
||||
self.config.slice_width = tonumber(io.read()) or 1
|
||||
|
||||
print("How many blocks should remain between each slice?")
|
||||
self.config.slice_padding = tonumber(io.read()) or 0
|
||||
|
||||
print("How many slices should the turtle mine to its right?")
|
||||
self.config.slices_right = tonumber(io.read()) or 1
|
||||
|
||||
print("How many slices should the turtle mine to its left?")
|
||||
self.config.slices_left = tonumber(io.read()) or 1
|
||||
|
||||
local padded_width_left = self.config.slices_left * (self.config.slice_width + self.config.slice_padding)
|
||||
local padded_width_right = self.config.slices_right * (self.config.slice_width + self.config.slice_padding)
|
||||
local padded_width = padded_width_left + padded_width_right + self.config.center_slice_width
|
||||
local mined_width_left = self.config.slices_left * self.config.slice_width
|
||||
local mined_width_right = self.config.slices_right * self.config.slice_width
|
||||
local mined_width = mined_width_left + mined_width_right + self.config.center_slice_width
|
||||
|
||||
print("Configuration complete!")
|
||||
print(("Mining area spans %d x %d x %d (width x height x forward), totalling %d blocks."):format(
|
||||
padded_width, self.config.slice_height, self.config.slice_length, padded_width * self.config.slice_height * self.config.slice_length
|
||||
))
|
||||
print(("Turtle will mine %d block wide slices (%d wide in the center) with %d blocks of padding, totalling %d mined blocks."):format(
|
||||
self.config.slice_width, self.config.center_slice_width, self.config.slice_padding, mined_width * self.config.slice_height * self.config.slice_length
|
||||
))
|
||||
print("Do you want to accept the configuration (enter 1, otherwise 0)?")
|
||||
config_complete = tonumber(io.read()) == 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Main Method
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function ExcavationController:Run()
|
||||
self.controller:Configure()
|
||||
self:Configure()
|
||||
|
||||
-- Consume our starting fuel and refuel to the full amount
|
||||
turtle.select(1)
|
||||
turtle.refuel()
|
||||
self.controller:RefuelIfEmpty()
|
||||
|
||||
self:Excavate()
|
||||
end
|
||||
|
||||
|
||||
return ExcavationController
|
||||
Reference in New Issue
Block a user