1

Compare commits

...

3 Commits

5 changed files with 214 additions and 37 deletions

View File

@ -0,0 +1,82 @@
local TurtleController = require("controller.turtle_controller")
local AudioController = require("controller.audio_controller")
---@class AudioTestingController
---@field controller TurtleController
---@field audio AudioController
local AudioTestingController = {}
AudioTestingController.__index = AudioTestingController
---@return AudioTestingController
function AudioTestingController:Create()
local t = {}
setmetatable(t, AudioTestingController)
-----------------------------------------------------------------------------------------------
-- Fields
-----------------------------------------------------------------------------------------------
t.controller = TurtleController:Create()
t.audio = AudioController:Create()
return t
end
-----------------------------------------------------------------------------------------------
-- Behavior Methods
-----------------------------------------------------------------------------------------------
function AudioTestingController:TestAudioWithoutMovement()
local function dancing()
for _ = 1, 256 do
self.controller:TurnRelative(1)
end
self.audio:StopPlaying()
end
parallel.waitForAll(dancing, self.audio:PlayAudioFactory("bangarang"))
end
function AudioTestingController:TestAudioWithMovement()
local function movement()
for _ = 1, 10 do
self.controller:MoveForward(10)
self.controller:MoveVertical(3)
self.controller:TurnRelative(2)
self.controller:MoveForward(10)
self.controller:MoveVertical(-3)
self.controller:TurnRelative(2)
end
self.audio:StopPlaying()
end
parallel.waitForAll(movement, self.audio:PlayAudioFactory("bangarang"))
end
-----------------------------------------------------------------------------------------------
-- Main Method
-----------------------------------------------------------------------------------------------
function AudioTestingController:Run()
self.controller:Configure()
self.controller:DisableMiningForward()
self.controller:DisableMiningAbove()
self.controller:DisableMiningBelow()
print("There are multiple tests available:")
print("1: Audio without movement")
print("2: Audio with movement")
local choice = 0
while choice < 1 or choice > 2 do
print("Choose a test by entering its number:")
choice = tonumber(io.read()) or 0
end
if choice == 1 then
self:TestAudioWithoutMovement()
elseif choice == 2 then
self:TestAudioWithMovement()
end
end
return AudioTestingController

View File

@ -246,7 +246,7 @@ function ExcavationController:Excavate()
-- Finish up -- Finish up
self.controller:MoveToPosition(0, 0, 0, self.controller.config.storage_direction) self.controller:MoveToPosition(0, 0, 0, self.controller.config.storage_direction)
self.controller:DropInventory() self.controller:DropInventoryIntoChest()
self.controller:TurnToDirection(Direction.NORTH) self.controller:TurnToDirection(Direction.NORTH)
self.audio:StopPlaying() self.audio:StopPlaying()
end end

View File

@ -102,15 +102,24 @@ function TurtleController:MoveForward(number_of_blocks, skip_unstocking, skip_re
-- Mine/Move -- Mine/Move
if self.mine_forward then if self.mine_forward then
while not turtle.forward() do while not turtle.forward() do
if self:TestForBlock("minecraft:chest") then
error("Won't mine because a chest is in the way!")
end
turtle.dig() turtle.dig()
end end
elseif not turtle.forward() then elseif not turtle.forward() then
error("Turtle failed to move forward!") error("Turtle failed to move forward!")
end end
if self.mine_above then if self.mine_above then
if self:TestForBlock("minecraft:chest", true, false) then
error("Won't mine because a chest is in the way!")
end
turtle.digUp() turtle.digUp()
end end
if self.mine_below then if self.mine_below then
if self:TestForBlock("minecraft:chest", false, true) then
error("Won't mine because a chest is in the way!")
end
turtle.digDown() turtle.digDown()
end end
@ -152,13 +161,15 @@ function TurtleController:MoveVertical(number_of_blocks, skip_unstocking, skip_r
self:UnstockIfFull() self:UnstockIfFull()
end end
-- Mine -- Mine/Move
if mine_enabled then if mine_enabled then
mine_function() while not move_function() do
end if self:TestForBlock("minecraft:chest", number_of_blocks > 0, number_of_blocks < 0) then
error("Won't mine because a chest is in the way!")
-- Move end
if not move_function() then mine_function()
end
elseif not move_function() then
error("Turtle failed to move vertically!") error("Turtle failed to move vertically!")
end end
@ -189,7 +200,15 @@ function TurtleController:MoveToPosition(x, y, z, dir, skip_unstocking, skip_ref
-- Store the current position on the stack, so we can return using TurtleController:MoveBack() -- Store the current position on the stack, so we can return using TurtleController:MoveBack()
self.last_positions:Push(Position:Copy(self.position)) self.last_positions:Push(Position:Copy(self.position))
-- Store mining config so we can restore it later
local mine_forward = self.mine_forward
local mine_above = self.mine_above
local mine_below = self.mine_below
-- EAST/WEST axis (do first to not interfere with chests) -- EAST/WEST axis (do first to not interfere with chests)
self:EnableMiningForward()
self:DisableMiningAbove()
self:DisableMiningBelow()
if self.position.x > x then if self.position.x > x then
self:TurnToDirection(Direction.WEST) self:TurnToDirection(Direction.WEST)
elseif self.position.x < x then elseif self.position.x < x then
@ -206,11 +225,34 @@ function TurtleController:MoveToPosition(x, y, z, dir, skip_unstocking, skip_ref
self:MoveForward(math.abs(z - self.position.z), skip_unstocking, skip_refueling) self:MoveForward(math.abs(z - self.position.z), skip_unstocking, skip_refueling)
-- UP/DOWN axis -- UP/DOWN axis
self:DisableMiningForward()
if y < self.position.y then
self:EnableMiningBelow()
elseif y > self.position.y then
self:EnableMiningAbove()
end
self:MoveVertical(y - self.position.y, skip_unstocking, skip_refueling) self:MoveVertical(y - self.position.y, skip_unstocking, skip_refueling)
-- Direction -- Direction
self:TurnToDirection(dir or Direction.NORTH) self:TurnToDirection(dir or Direction.NORTH)
-- Restore mining config
if mine_forward then
self:EnableMiningForward()
else
self:DisableMiningForward()
end
if mine_above then
self:EnableMiningAbove()
else
self:DisableMiningAbove()
end
if mine_below then
self:EnableMiningBelow()
else
self:DisableMiningBelow()
end
-- Sanity check -- Sanity check
if not (self.position.x == x and self.position.y == y and self.position.z == z and self.position.dir == dir) then if not (self.position.x == x and self.position.y == y and self.position.z == z and self.position.dir == dir) then
error("TurtleController:MoveToPosition failed to move to target position!") error("TurtleController:MoveToPosition failed to move to target position!")
@ -258,6 +300,37 @@ function TurtleController:MoveBack(skip_unstocking, skip_refueling)
end end
end end
-----------------------------------------------------------------------------------------------
-- Testing Methods
-----------------------------------------------------------------------------------------------
---@param block_name string
---@param above boolean | nil
---@param below boolean | nil
---@return boolean
function TurtleController:TestForBlock(block_name, above, below)
above = above or false
below = below or false
if above and below then
error("Can only test for blocks in one direction!")
end
local inspect_function = turtle.inspect
if above then
inspect_function = turtle.inspectUp
elseif below then
inspect_function = turtle.inspectDown
end
local has_block, block_data = inspect_function()
if not has_block then
return false
end
return block_data.name == block_name
end
----------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------
-- Inventory Methods -- Inventory Methods
----------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------
@ -284,7 +357,11 @@ end
---@param slot number ---@param slot number
---@param count number ---@param count number
---@return boolean ---@return boolean
function TurtleController:SuckItem(slot, count) function TurtleController:SuckItemFromChest(slot, count)
if not self:TestForBlock("minecraft:chest") then
error("Can't suck item: no chest!")
end
local previous_slot = turtle.getSelectedSlot() local previous_slot = turtle.getSelectedSlot()
turtle.select(slot or 1) turtle.select(slot or 1)
@ -298,7 +375,11 @@ end
---@param slot number ---@param slot number
---@param count number ---@param count number
---@return boolean ---@return boolean
function TurtleController:DropItem(slot, count) function TurtleController:DropItemIntoChest(slot, count)
if not self:TestForBlock("minecraft:chest") then
error("Can't drop item: no chest!")
end
local previous_slot = turtle.getSelectedSlot() local previous_slot = turtle.getSelectedSlot()
turtle.select(slot or 1) turtle.select(slot or 1)
@ -309,7 +390,11 @@ function TurtleController:DropItem(slot, count)
return dropped return dropped
end end
function TurtleController:DropInventory() function TurtleController:DropInventoryIntoChest()
if not self:TestForBlock("minecraft:chest") then
error("Can't drop item: no chest!")
end
print("Dropping inventory into chest...") print("Dropping inventory into chest...")
for slot = 1, 16 do for slot = 1, 16 do
@ -333,9 +418,11 @@ function TurtleController:UnstockIfFull(skip_inventory_check)
print("Turtle is unstocking...") print("Turtle is unstocking...")
self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true) self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true)
self:DropInventory() self:DropInventoryIntoChest()
self:RefuelIfEmpty() self:RefuelIfEmpty()
self:TurnToDirection(Direction.NORTH)
self:MoveForward(1)
self:MoveBack(true, true) self:MoveBack(true, true)
end end
@ -353,7 +440,7 @@ function TurtleController:RefuelIfEmpty(skip_fuel_check)
-- Clear our inventory into the storage chest -- Clear our inventory into the storage chest
self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true) self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true)
self:DropInventory() self:DropInventoryIntoChest()
-- Prepare refueling -- Prepare refueling
self:TurnToDirection(self.config.fuel_direction) self:TurnToDirection(self.config.fuel_direction)
@ -372,13 +459,15 @@ function TurtleController:RefuelIfEmpty(skip_fuel_check)
-- Refuel until we hit the refuel_amount -- Refuel until we hit the refuel_amount
local before_level = turtle.getFuelLevel() local before_level = turtle.getFuelLevel()
repeat repeat
if not self:SuckItem(1, 1) then if not self:SuckItemFromChest(1, 1) then
error("Failed to suck fuel out of fuel chest!") error("Failed to suck fuel out of fuel chest!")
end end
turtle.refuel() turtle.refuel()
until turtle.getFuelLevel() >= target_fuel_level until turtle.getFuelLevel() >= target_fuel_level
local after_level = turtle.getFuelLevel() local after_level = turtle.getFuelLevel()
self:TurnToDirection(Direction.NORTH)
self:MoveForward(1)
self:MoveBack(true, true) self:MoveBack(true, true)
print( print(

View File

@ -1,15 +1,15 @@
local Direction = require("lib.direction") local Direction = require("lib.direction")
local TurtleController = require("controller.turtle_controller") local TurtleController = require("controller.turtle_controller")
---@class TestingController ---@class TurtleTestingController
---@field controller TurtleController ---@field controller TurtleController
local TestingController = {} local TurtleTestingController = {}
TestingController.__index = TestingController TurtleTestingController.__index = TurtleTestingController
---@return TestingController ---@return TurtleTestingController
function TestingController:Create() function TurtleTestingController:Create()
local t = {} local t = {}
setmetatable(t, TestingController) setmetatable(t, TurtleTestingController)
t.controller = TurtleController:Create() t.controller = TurtleController:Create()
@ -20,7 +20,7 @@ end
-- Behavior Methods -- Behavior Methods
----------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------
function TestingController:TestRelativeMovementWithRelativeRotation() function TurtleTestingController:TestRelativeMovementWithRelativeRotation()
print("Testing relative movement with relative rotation...") print("Testing relative movement with relative rotation...")
-- N: BackCenter (Center) -- N: BackCenter (Center)
@ -50,7 +50,7 @@ function TestingController:TestRelativeMovementWithRelativeRotation()
_ = io.read() _ = io.read()
end end
function TestingController:TestRelativeMovementWithAbsoluteRotation() function TurtleTestingController:TestRelativeMovementWithAbsoluteRotation()
print("Testing relative movement with absolute rotation...") print("Testing relative movement with absolute rotation...")
-- N: BackCenter (Center) -- N: BackCenter (Center)
@ -80,7 +80,7 @@ function TestingController:TestRelativeMovementWithAbsoluteRotation()
_ = io.read() _ = io.read()
end end
function TestingController:TestAbsoluteMovementWithoutStack() function TurtleTestingController:TestAbsoluteMovementWithoutStack()
print("Testing absolute movement without stack...") print("Testing absolute movement without stack...")
-- N: BackCenter (Center) -- N: BackCenter (Center)
@ -104,7 +104,7 @@ function TestingController:TestAbsoluteMovementWithoutStack()
_ = io.read() _ = io.read()
end end
function TestingController:TestAbsoluteMovementWithStack() function TurtleTestingController:TestAbsoluteMovementWithStack()
print("Testing absolute movement with stack...") print("Testing absolute movement with stack...")
-- N: BotCenter (Center) -- N: BotCenter (Center)
@ -126,7 +126,7 @@ function TestingController:TestAbsoluteMovementWithStack()
_ = io.read() _ = io.read()
end end
function TestingController:TestUnstocking() function TurtleTestingController:TestUnstocking()
print("Testing inventory unloading...") print("Testing inventory unloading...")
self.controller:MoveToPosition(3, 0, 3, Direction.WEST) self.controller:MoveToPosition(3, 0, 3, Direction.WEST)
@ -143,7 +143,7 @@ function TestingController:TestUnstocking()
_ = io.read() _ = io.read()
end end
function TestingController:TestRefueling() function TurtleTestingController:TestRefueling()
print("Testing refueling...") print("Testing refueling...")
self.controller:MoveToPosition(3, 0, 3, Direction.WEST) self.controller:MoveToPosition(3, 0, 3, Direction.WEST)
@ -164,7 +164,7 @@ end
-- Main Method -- Main Method
----------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------
function TestingController:Run() function TurtleTestingController:Run()
self.controller:Configure() self.controller:Configure()
self.controller:DisableMiningForward() self.controller:DisableMiningForward()
self.controller:DisableMiningAbove() self.controller:DisableMiningAbove()
@ -217,4 +217,4 @@ function TestingController:Run()
end end
end end
return TestingController return TurtleTestingController

View File

@ -1,17 +1,20 @@
local TestingController = require("controller.testing_controller") local TurtleTestingController = require("controller.turtle_testing_controller")
local AudioTestingController = require("controller.audio_testing_controller")
local ExcavationController = require("controller.excavation_controller") local ExcavationController = require("controller.excavation_controller")
local AudioController = require("controller.audio_controller") local AudioController = require("controller.audio_controller")
local controllers = { local controllers = {
TestingController:Create(), TurtleTestingController:Create(),
AudioTestingController:Create(),
ExcavationController:Create(), ExcavationController:Create(),
AudioController:Create(), AudioController:Create(),
} }
print("Multiple controllers are available:") print("Multiple controllers are available:")
print("1: Testing Mode") print("1: Turtle Testing Mode")
print("2: Volume Excavation") print("2: Audio Testing Mode")
print("3: Play Bangarang") print("3: Volume Excavation")
print("4: Play Bangarang")
local choice = 0 local choice = 0
while choice < 1 or choice > #controllers do while choice < 1 or choice > #controllers do
@ -21,10 +24,13 @@ end
controllers[choice]:Run() controllers[choice]:Run()
-- TODO: StackOverflow once the inventory is full, unstocking doesn't work... -- TODO: When refueling but chest is missing, wait there until the user puts a chest with fuel
-- Is the InventoryFull check wrong? -- TODO: Improve error handling: Don't abort the program in all cases,
-- TODO: Test if there's a chest when dropping/sucking/mining (don't mine chests!) -- but wait until the user fixes the issue (e.g. places a chest)
-- TODO: Add shortcuts for the volume excavation:
-- - Tunnel forward 3x2 or 3x3 with specified length
-- - Excavate downwards (quarry) in a square, specify side length
-- TODO: Add controller to build rooms with walls of a specified material -- TODO: Add controller to build rooms with walls of a specified material
-- TODO: Support specifying the mining height -- TODO: Add a stair building mode (specify side length, min 2x2)
-- TODO: Add configurable trash_list with items that won't be picked up -- TODO: Add configurable trash_list with items that won't be picked up
-- TODO: Add a speaker to the turtle (listen to music while mining)