Reflection in RUST???
also implemented quarry
This commit is contained in:
parent
ebdc910a57
commit
551c472f53
3 changed files with 110 additions and 29 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::{Arc, atomic::{AtomicUsize, Ordering, AtomicI32}};
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use tokio::task::{JoinHandle, AbortHandle};
|
use tokio::task::{JoinHandle, AbortHandle};
|
||||||
|
@ -22,8 +24,17 @@ const VALUABLE: [&str; 1] = [
|
||||||
];
|
];
|
||||||
|
|
||||||
pub async fn mine(turtle: TurtleCommander, pos: Vec3, chunk: Vec3) -> Option<()> {
|
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 pos = pos;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
mine_chunk_and_sweep(turtle.clone(), pos, chunk).await?;
|
||||||
|
|
||||||
|
pos += Vec3::z() * chunk.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn mine_chunk_and_sweep(turtle: TurtleCommander, pos: Vec3, chunk: Vec3) -> Option<()> {
|
||||||
|
let volume = chunk.x * chunk.y * chunk.z;
|
||||||
let mut valuables = Vec::new();
|
let mut valuables = Vec::new();
|
||||||
|
|
||||||
async fn refuel_needed(turtle: &TurtleCommander, volume: i32) {
|
async fn refuel_needed(turtle: &TurtleCommander, volume: i32) {
|
||||||
|
@ -32,32 +43,30 @@ pub async fn mine(turtle: TurtleCommander, pos: Vec3, chunk: Vec3) -> Option<()>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
refuel_needed(&turtle, volume).await;
|
||||||
|
|
||||||
|
mine_chunk(turtle.clone(), pos, chunk).await?;
|
||||||
|
|
||||||
|
valuables.append(&mut near_valuables(&turtle, pos, chunk).await);
|
||||||
|
|
||||||
|
while let Some(block) = valuables.pop() {
|
||||||
|
if turtle.world().get(block).await.is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let near = turtle.goto_adjacent(block).await?;
|
||||||
|
turtle.execute(near.dig(block)?).await;
|
||||||
|
observe(turtle.clone(), block).await;
|
||||||
|
valuables.append(&mut near_valuables(&turtle, near.pos, Vec3::new(2,2,2)).await);
|
||||||
|
|
||||||
refuel_needed(&turtle, volume).await;
|
refuel_needed(&turtle, volume).await;
|
||||||
|
|
||||||
mine_chunk(turtle.clone(), pos, chunk).await?;
|
|
||||||
|
|
||||||
valuables.append(&mut near_valuables(&turtle, pos, chunk).await);
|
|
||||||
|
|
||||||
while let Some(block) = valuables.pop() {
|
|
||||||
if turtle.world().get(block).await.is_none() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let near = turtle.goto_adjacent(block).await?;
|
|
||||||
turtle.execute(near.dig(block)?).await;
|
|
||||||
observe(turtle.clone(), block).await;
|
|
||||||
valuables.append(&mut near_valuables(&turtle, near.pos, Vec3::new(2,2,2)).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.dock().await;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += Vec3::z() * chunk.z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dump_filter(turtle.clone(), |i| USELESS.iter().any(|u| **u == i.name)).await > 12 {
|
||||||
|
info!("storage rtb");
|
||||||
|
turtle.dock().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn near_valuables(turtle: &TurtleCommander, pos: Vec3, chunk: Vec3) -> Vec<Vec3> {
|
async fn near_valuables(turtle: &TurtleCommander, pos: Vec3, chunk: Vec3) -> Vec<Vec3> {
|
||||||
|
@ -204,3 +213,74 @@ impl Task for Mine {
|
||||||
TaskState::Waiting
|
TaskState::Waiting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize,Clone)]
|
||||||
|
pub struct Quarry {
|
||||||
|
pos: Vec3,
|
||||||
|
size: Vec3,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
miners: Arc<AtomicUsize>,
|
||||||
|
chunk: Arc<AtomicI32>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Quarry {
|
||||||
|
pub fn new(lower: Vec3, upper: Vec3) -> Self {
|
||||||
|
let size = upper - lower;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
pos: lower,
|
||||||
|
size,
|
||||||
|
miners: Arc::new(AtomicUsize::new(0)),
|
||||||
|
chunk: Arc::new(AtomicI32::new(0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chunk(pos: Vec3) -> Self {
|
||||||
|
let base = pos.map(|n| n%16);
|
||||||
|
Self {
|
||||||
|
pos: base,
|
||||||
|
size: Vec3::new(16,16,16),
|
||||||
|
miners: Arc::new(AtomicUsize::new(0)),
|
||||||
|
chunk: Arc::new(AtomicI32::new(0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde]
|
||||||
|
impl Task for Quarry {
|
||||||
|
fn run(&mut self,turtle:TurtleCommander) -> AbortHandle {
|
||||||
|
let chunk = self.chunk.fetch_add(1, Ordering::AcqRel);
|
||||||
|
// TODO: partial chunks on corners
|
||||||
|
let max_chunk = Vec3::new(4,4,4);
|
||||||
|
let e = self.size.component_div(&max_chunk);
|
||||||
|
|
||||||
|
let rel_pos = fill(e, chunk).component_mul(&max_chunk);
|
||||||
|
let abs_pos = rel_pos
|
||||||
|
+ self.pos;
|
||||||
|
|
||||||
|
let owned = self.miners.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
// TODO: handle failure
|
||||||
|
// another turtle should get the next chunk while this is in flight, but program
|
||||||
|
// termination or a None return should reschedule the chunk
|
||||||
|
mine_chunk_and_sweep(turtle, abs_pos, max_chunk).await.unwrap();
|
||||||
|
owned.fetch_sub(1, Ordering::AcqRel);
|
||||||
|
}).abort_handle()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll(&mut self) -> TaskState {
|
||||||
|
let only = self.miners.fetch_update(Ordering::AcqRel, Ordering::Acquire, |n| {
|
||||||
|
if n < 1 {
|
||||||
|
Some(n+1)
|
||||||
|
}else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).is_ok();
|
||||||
|
|
||||||
|
if only {
|
||||||
|
// This is approximate as we have to go to a depot anyway
|
||||||
|
return TaskState::Ready(Position::new(self.pos, Direction::North));
|
||||||
|
}
|
||||||
|
TaskState::Waiting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl Scheduler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_task(&mut self, task: Box<dyn Task>) {
|
pub fn add_task(&mut self, task: Box<dyn Task>) {
|
||||||
trace!("new task");
|
trace!("new {} task", task.typetag_name());
|
||||||
self.tasks.push(task);
|
self.tasks.push(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ impl Scheduler {
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!("scheduling task on #{}", closest_turtle.0.name().to_num());
|
trace!("scheduling {} on #{}", task.typetag_name(), closest_turtle.0.name().to_num());
|
||||||
closest_turtle.1 = Some(task.run(closest_turtle.0.clone()));
|
closest_turtle.1 = Some(task.run(closest_turtle.0.clone()));
|
||||||
}
|
}
|
||||||
if let TaskState::Complete = poll {
|
if let TaskState::Complete = poll {
|
||||||
|
|
|
@ -4,6 +4,7 @@ use blocks::Vec3;
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
use crate::fell::TreeFarm;
|
use crate::fell::TreeFarm;
|
||||||
use crate::mine::Mine;
|
use crate::mine::Mine;
|
||||||
|
use crate::mine::Quarry;
|
||||||
use crate::turtle::IDLE_TIME;
|
use crate::turtle::IDLE_TIME;
|
||||||
use crate::turtle::TurtleCommandResponse;
|
use crate::turtle::TurtleCommandResponse;
|
||||||
use crate::turtle::TurtleCommander;
|
use crate::turtle::TurtleCommander;
|
||||||
|
@ -112,8 +113,8 @@ pub(crate) async fn dig(
|
||||||
Json(req): Json<Vec3>,
|
Json(req): Json<Vec3>,
|
||||||
) -> &'static str {
|
) -> &'static str {
|
||||||
let schedule = &mut state.write().await.tasks;
|
let schedule = &mut state.write().await.tasks;
|
||||||
let chunk = Vec3::new(4,4,4);
|
let size = Vec3::new(16,16,16);
|
||||||
schedule.add_task(Box::new(Mine::new(req,chunk)));
|
schedule.add_task(Box::new(Quarry::new(req,req+size)));
|
||||||
|
|
||||||
"ACK"
|
"ACK"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue