diff --git a/server/src/fell.rs b/server/src/fell.rs index a55c43e..72fd938 100644 --- a/server/src/fell.rs +++ b/server/src/fell.rs @@ -102,7 +102,6 @@ impl TreeFarm { 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(()) @@ -110,12 +109,22 @@ impl TreeFarm { pub async fn build(&self, turtle: TurtleCommander) -> Option<()> { let trees = self.size.x * self.size.y * self.size.z; - turtle.dock().await; + let mut soil_to_lay = Vec::new(); for tree in 0..trees { let index = fill(self.size, tree); let offset = index.component_mul(&Vec3::new(2, 32, 2)); let tree = self.position + offset; + let soil = tree - Vec3::y(); + if turtle.world().get(soil).await.map_or_else(|| true, |b| b.name.contains("dirt")) { + soil_to_lay.push(soil); + } + } + + for block in soil_to_lay { + let near = turtle.goto_adjacent(block).await?; // TODO: item management + //turtle.execute(TurtleCommand::Select(soil)).await; + turtle.execute(near.place(block)?).await; } Some(()) diff --git a/server/src/mine.rs b/server/src/mine.rs index 45bd40f..ee6ca8e 100644 --- a/server/src/mine.rs +++ b/server/src/mine.rs @@ -1,6 +1,9 @@ use log::{info, warn}; +use serde::{Serialize, Deserialize}; +use tokio::task::JoinHandle; +use typetag::serde; -use crate::{blocks::{Position, Vec3}, turtle::{TurtleCommand, TurtleCommander, TurtleCommandResponse, InventorySlot}, paths::TRANSPARENT}; +use crate::{blocks::{Position, Vec3, Direction}, turtle::{TurtleCommand, TurtleCommander, TurtleCommandResponse, InventorySlot}, paths::TRANSPARENT, tasks::{Task, TaskState}}; use TurtleCommand::*; /// Things to leave in the field (not worth fuel) @@ -18,24 +21,19 @@ const VALUABLE: [&str; 1] = [ "ore", ]; -pub async fn mine(turtle: TurtleCommander, pos: Vec3, fuel: Position, storage: Position) -> Option<()> { - let chunk = Vec3::new(4,4,4); +pub async fn mine(turtle: TurtleCommander, pos: Vec3, chunk: Vec3) -> Option<()> { let volume = chunk.x * chunk.y * chunk.z; let mut pos = pos; let mut valuables = Vec::new(); - async fn refuel_needed(turtle: &TurtleCommander, volume: i32, fuel: Position) -> Option<()> { - Some(if (turtle.fuel() as f64) < (2 * volume + (fuel.pos-turtle.pos().await.pos).abs().sum()) as f64 * 1.8 { - let name = turtle.name().to_str(); - info!("{name}: refueling"); - turtle.goto(fuel).await?; - info!("{name}: docked"); - refuel(turtle.clone()).await; - }) + async fn refuel_needed(turtle: &TurtleCommander, volume: i32) { + if (turtle.fuel() as i32) < 2 * volume + 4000 { + turtle.dock().await; + } } loop { - refuel_needed(&turtle, volume, fuel).await?; + refuel_needed(&turtle, volume).await; mine_chunk(turtle.clone(), pos, chunk).await?; @@ -50,16 +48,12 @@ pub async fn mine(turtle: TurtleCommander, pos: Vec3, fuel: Position, storage: P observe(turtle.clone(), block).await; valuables.append(&mut near_valuables(&turtle, near.pos, Vec3::new(2,2,2)).await); - refuel_needed(&turtle, volume, fuel).await?; + refuel_needed(&turtle, volume).await; } if dump_filter(turtle.clone(), |i| USELESS.iter().any(|u| **u == i.name)).await > 12 { info!("storage rtb"); - turtle.goto(storage).await?; - dump(turtle.clone()).await; - // while we're here - turtle.goto(fuel).await?; - refuel(turtle.clone()).await; + turtle.dock().await; } pos += Vec3::z() * chunk.z; @@ -179,3 +173,34 @@ async fn observe(turtle: TurtleCommander, pos: Vec3) -> Option<()> { Some(()) } + +#[derive(Serialize, Deserialize,Clone)] +pub struct Mine { + pos: Vec3, + chunk: Vec3, + #[serde(skip_deserializing)] + miners: usize, // Default is false +} + +impl Mine { + pub fn new(pos: Vec3, chunk: Vec3) -> Self { Self { pos, chunk, miners: 0 } } +} + +#[serde] +impl Task for Mine { + fn run(&mut self,turtle:TurtleCommander) -> JoinHandle<()> { + self.miners += 1; + let frozen = self.clone(); + tokio::spawn(async move { + mine(turtle,frozen.pos, frozen.chunk).await.unwrap(); + }) + // TODO: mutability after spawn + } + + fn poll(&mut self) -> TaskState { + if self.miners < 1 { + return TaskState::Ready(Position::new(self.pos, Direction::North)); + } + TaskState::Waiting + } +} diff --git a/server/src/turtle_api.rs b/server/src/turtle_api.rs index 176a32a..bb0d16e 100644 --- a/server/src/turtle_api.rs +++ b/server/src/turtle_api.rs @@ -2,6 +2,7 @@ use log::trace; use tokio; use blocks::Vec3; use crate::fell::TreeFarm; +use crate::mine::Mine; use crate::turtle::TurtleCommandResponse; use crate::turtle::TurtleCommander; use crate::turtle::TurtleInfo; @@ -34,12 +35,12 @@ pub fn turtle_api() -> Router { .route("/:id/update", post(command)) .route("/client.lua", get(client)) .route("/:id/setGoal", post(set_goal)) - .route("/:id/dig", post(dig)) .route("/:id/cancelTask", post(cancel)) .route("/:id/manual", post(run_command)) .route("/:id/dock", post(dock)) .route("/:id/info", get(turtle_info)) .route("/createTreeFarm", post(fell)) + .route("/createMine", post(dig)) .route("/registerDepot", post(new_depot)) .route("/pollScheduler", get(poll)) .route("/updateAll", get(update_turtles)) @@ -101,19 +102,12 @@ pub(crate) async fn run_command( } pub(crate) async fn dig( - Path(id): Path, State(state): State, - Json(req): Json<(Vec3, Position, Position)>, + Json(req): Json, ) -> &'static str { - let turtle = state.read().await.get_turtle(id).await.unwrap(); - let (req, fuel, inventory) = req; - //let fuel = Position::new(Vec3::new(-19, 93, 73), blocks::Direction::East); - //let inventory = Position::new(Vec3::new(-19, 92, 73), blocks::Direction::East); - tokio::spawn( - async move { - mine::mine(turtle.clone(), req, fuel, inventory).await - } - ); + let schedule = &mut state.write().await.tasks; + let chunk = Vec3::new(4,4,4); + schedule.add_task(Box::new(Mine::new(req,chunk))); "ACK" }