diff --git a/client/client.lua b/client/client.lua index a25c19d..b6634e9 100644 --- a/client/client.lua +++ b/client/client.lua @@ -43,6 +43,16 @@ local function iteminfo(slot) return { ["Item"] = turtle.getItemDetail(slot) } end +local function restartfront() + front = peripheral.wrap("front") + if not front.shutdown then + return false + end + front.shutdown() + front.turnOn() + return front.isOn() +end + local function inventoryinfo() return { ["Inventory"] = peripheral.wrap("front").list() } end @@ -115,6 +125,7 @@ local commands = { ["Place"] = turtle.place, ["PlaceDown"] = turtle.placeDown, ["Update"] = update, + ["CycleFront"] = restartfront, ["Poweroff"] = os.shutdown, ["GetFuelLimit"] = turtle.getFuelLimit, }; diff --git a/server/src/depot.rs b/server/src/depot.rs index 50cf614..e75a5bf 100644 --- a/server/src/depot.rs +++ b/server/src/depot.rs @@ -25,9 +25,9 @@ pub struct DepotGuard { } impl DepotGuard { - pub fn new(mutex: OwnedMutexGuard, semaphore: OwnedSemaphorePermit) -> Self { Self { mutex, semaphore } } + fn new(mutex: OwnedMutexGuard, semaphore: OwnedSemaphorePermit) -> Self { Self { mutex, semaphore } } - fn position(&self) -> &Position { + pub fn position(&self) -> &Position { &self.mutex } diff --git a/server/src/mine.rs b/server/src/mine.rs index 4ef3357..73ff8a7 100644 --- a/server/src/mine.rs +++ b/server/src/mine.rs @@ -49,6 +49,8 @@ pub async fn mine_chunk_and_sweep(turtle: TurtleCommander, pos: Vec3, chunk: Vec turtle.dock().await; } + devore(&turtle).await; + refuel_needed(&turtle, volume).await; mine_chunk(turtle.clone(), pos, chunk).await?; @@ -70,6 +72,42 @@ pub async fn mine_chunk_and_sweep(turtle: TurtleCommander, pos: Vec3, chunk: Vec Some(()) } +/// Send mined turtles to the nearest depot +async fn devore(turtle: &TurtleCommander) { + let turtles: Vec = turtle.inventory().await.into_iter().enumerate() + .filter(|(_,b)| b.as_ref().is_some_and(|b| b.name.contains("turtle"))) + .map(|(i,_)| i as u32).collect(); + + if turtles.is_empty() { + return; + } + + let depot = turtle.get_depot().await; + + for i in turtles { + let position = depot.position(); + + let staging = position.pos - position.dir.unit(); + + turtle.goto(Position::new(staging, position.dir)).await; + turtle.execute(Select(i as u32)).await; + turtle.execute(Place).await; + turtle.execute(CycleFront).await; + loop { + let ret = turtle.execute(Wait(3)).await; + // this won't do well with dead (energy-lacking) turtles, perhaps obtaining + // a new depot (lock) for every turtle is more consistent + // + // alternatively, figure out label parsing (names with spaces) + // and issue a command to the child turtle + if !ret.ahead.contains("turtle") { + break; + } + warn!("devored turtle still inactive"); + } + } +} + async fn near_valuables(turtle: &TurtleCommander, pos: Vec3, chunk: Vec3) -> Vec { let scan = (0..(chunk*2).product()).map(|n| fill(chunk * 2, n) - chunk/2); @@ -227,7 +265,7 @@ pub struct Quarry { size: Vec3, #[serde(skip_deserializing)] miners: Arc, - pub progress: ChunkedTask, + progress: ChunkedTask, } impl Quarry { diff --git a/server/src/turtle.rs b/server/src/turtle.rs index 5ef1053..016b975 100644 --- a/server/src/turtle.rs +++ b/server/src/turtle.rs @@ -3,6 +3,7 @@ use crate::blocks::Direction; use crate::blocks::Position; use crate::blocks::Vec3; use crate::blocks::SharedWorld; +use crate::depot::DepotGuard; use crate::depot::Depots; use crate::paths::route_facing; @@ -293,6 +294,10 @@ impl TurtleCommander { self.depots.dock(self.clone()).await } + pub async fn get_depot(&self) -> DepotGuard { + self.depots.nearest(self.pos().await).await + } + #[tracing::instrument(skip(self))] pub async fn goto(&self, pos: Position) -> Option<()> { let mut recent = self.pos().await; @@ -512,6 +517,7 @@ pub enum TurtleCommand { Update, Poweroff, Refuel, + CycleFront, } #[derive(Serialize, Deserialize, Clone, Debug)]