331 lines
11 KiB
Lua
331 lines
11 KiB
Lua
local Direction = require("lib.direction")
|
|
local TurtleController = require("controller.turtle_controller")
|
|
local AudioController = require("controller.audio_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 audio AudioController
|
|
---@field config ExcavationControllerConfig
|
|
local ExcavationController = {}
|
|
ExcavationController.__index = ExcavationController
|
|
|
|
---@return ExcavationController
|
|
function ExcavationController:Create()
|
|
local t = {}
|
|
setmetatable(t, ExcavationController)
|
|
|
|
-----------------------------------------------------------------------------------------------
|
|
-- Fields
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
t.controller = TurtleController:Create()
|
|
t.audio = AudioController: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)
|
|
|
|
if self.config.slices_right > 0 then
|
|
-- 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)
|
|
end
|
|
|
|
if self.config.slices_left > 0 then
|
|
-- 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)
|
|
end
|
|
|
|
-- Finish up
|
|
self.controller:MoveToPosition(0, 0, 0, self.controller.config.storage_direction)
|
|
self.controller:DropInventoryIntoChest()
|
|
self.controller:TurnToDirection(Direction.NORTH)
|
|
self.audio:StopPlaying()
|
|
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()
|
|
|
|
parallel.waitForAll(function()
|
|
self:Excavate()
|
|
end, self.audio:PlayAudioFactory("bangarang"))
|
|
end
|
|
|
|
return ExcavationController
|