From 2378e9a8461ee277b5dda551445e4f9ea6a5a9d3 Mon Sep 17 00:00:00 2001 From: Andy Killorin <37423245+Speedy6451@users.noreply.github.com> Date: Fri, 22 Dec 2023 22:31:16 -0600 Subject: [PATCH] automatic arbor --- server/src/blocks.rs | 11 ++++++++ server/src/depot.rs | 5 ++-- server/src/fell.rs | 66 +++++++++++++++++++++++++++++++++++++++++--- server/src/paths.rs | 5 ++-- 4 files changed, 79 insertions(+), 8 deletions(-) diff --git a/server/src/blocks.rs b/server/src/blocks.rs index aa444e4..b41e3b8 100644 --- a/server/src/blocks.rs +++ b/server/src/blocks.rs @@ -105,6 +105,17 @@ impl Position { } } + /// Command to place + /// Assumes that "to" can be reached from your position + pub fn place(&self, to: Vec3) -> Option { + Some(match self.dig(to)? { + TurtleCommand::Dig => TurtleCommand::Place, + TurtleCommand::DigDown => TurtleCommand::PlaceDown, + TurtleCommand::DigUp => TurtleCommand::PlaceUp, + _ => None? + }) + } + /// Command to dig /// Assumes that "to" can be dug from your position pub fn dig(&self, to: Vec3) -> Option { diff --git a/server/src/depot.rs b/server/src/depot.rs index bd50fed..01eb9a1 100644 --- a/server/src/depot.rs +++ b/server/src/depot.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use log::{warn, info}; +use log::{warn, info, trace}; use tokio::sync::{Mutex, OwnedMutexGuard}; use crate::{blocks::Position, turtle::TurtleCommander}; @@ -28,6 +28,7 @@ impl Depots { pub async fn dock(&self, turtle: TurtleCommander) -> Option { let depot = self.clone().nearest(turtle.pos().await).await?; + trace!("depot at {depot:?}"); turtle.goto(*depot).await?; // dump inventory @@ -39,7 +40,7 @@ impl Depots { // refuel turtle.execute(Select(1)).await; let limit = turtle.fuel_limit(); - while turtle.fuel() < limit { + while turtle.fuel() + 1000 < limit { turtle.execute(SuckFront(64)).await; let re = turtle.execute(Refuel).await; turtle.execute(DropDown(64)).await; diff --git a/server/src/fell.rs b/server/src/fell.rs index c173e0e..a55c43e 100644 --- a/server/src/fell.rs +++ b/server/src/fell.rs @@ -1,9 +1,12 @@ +use std::ops::Mul; + +use log::{trace, warn, info}; use serde::{Serialize, Deserialize}; use time::OffsetDateTime; use tokio::task::JoinHandle; use typetag::serde; -use crate::{blocks::{Vec3, Position, Direction}, turtle::TurtleCommander, tasks::{Task, TaskState}, depot::Depots, mine::fill}; +use crate::{blocks::{Vec3, Position, Direction}, turtle::{TurtleCommander, TurtleCommand, TurtleCommandResponse, InventorySlot}, tasks::{Task, TaskState}, depot::Depots, mine::fill}; pub async fn fell_tree(turtle: TurtleCommander, bottom: Vec3) -> Option<()> { let mut log = bottom; @@ -38,15 +41,70 @@ impl TreeFarm { } pub async fn sweep(&self, turtle: TurtleCommander) -> Option<()> { - let trees = self.size.x * self.size.y * self.size.z; - //turtle.dock().await; + let trees = self.size.product(); + let spacing = Vec3::new(2, 32, 2); + turtle.dock().await; for tree in 0..trees { let index = fill(self.size, tree); - let offset = index.component_mul(&Vec3::new(2, 32, 2)); + let offset = index.component_mul(&spacing); + trace!("tree {tree}; {offset:?}"); let tree = self.position + offset; fell_tree(turtle.clone(), tree).await?; } + // sweep across floor (not upper levels) to get saplings + // this goes one block past the far corner and to the near corner + let area = self.size.xz().component_mul(&spacing.xz()).product(); + for tile in 0..area { + let offset = fill(self.size.component_mul(&Vec3::new(spacing.x, 1, spacing.z)), tile); + let tile = self.position + offset; + turtle.goto_adjacent(tile-Vec3::y()).await; + turtle.execute(TurtleCommand::SuckFront(64)).await; + } + + // scan inventory for saplings + let mut saplings = Vec::new(); + let mut needed = trees; + for slot in 1..=16 { + if let TurtleCommandResponse::Item(i) = turtle.execute(TurtleCommand::ItemInfo(slot)).await.ret { + if i.name.contains("sapling") { + needed -= i.count as i32; + saplings.push((slot,i)); + } + if needed <= 0 { break; } + } + } + + if needed > 0 { + warn!("incomplete wood harvest, {needed} saplings short"); + } + + fn pop_item(vec: &mut Vec<(u32, InventorySlot)>) -> Option { + let mut slot = vec.pop()?; + let index = slot.0; + slot.1.count -= 1; + if slot.1.count > 0 { + vec.push(slot); + } + Some(index) + } + + // plant saplings + for tree in 0..trees { + let sapling = match pop_item(&mut saplings) { + Some(slot) => slot, + None => break, + }; + + let index = fill(self.size, tree); + let offset = index.component_mul(&spacing); + let tree = self.position + offset; + let near = turtle.goto_adjacent(tree).await?; + turtle.execute(TurtleCommand::Select(sapling)).await; + turtle.execute(near.place(tree)?).await; + fell_tree(turtle.clone(), tree).await?; + } + Some(()) } diff --git a/server/src/paths.rs b/server/src/paths.rs index 6538db5..26cf7f5 100644 --- a/server/src/paths.rs +++ b/server/src/paths.rs @@ -1,10 +1,10 @@ use crate::{ blocks::{World, Position, Direction, Vec3, WorldReadLock}, }; -use log::trace; +use log::{trace, error}; use pathfinding::prelude::astar; -const LOOKUP_LIMIT: usize = 1_000_000; +const LOOKUP_LIMIT: usize = 10_000_000; pub async fn route_facing(from: Position, to: Vec3, world: &World) -> Option> { let facing = |p: &Position| { @@ -51,6 +51,7 @@ where D: FnMut(&Position) -> bool { if limit != 0 { Some(route.0) } else { + error!("pathfinding timed out"); None } }