1
Fork 0

exec api (global state in limbo)

This commit is contained in:
Andy Killorin 2023-12-19 07:43:10 -06:00
parent fef8f7bce3
commit 715520801d
Signed by: ank
GPG key ID: B6241CA3B552BCA4
3 changed files with 61 additions and 26 deletions

View file

@ -12,10 +12,12 @@ bit-struct = "0.3.2"
const_format = "0.2.32"
erased-serde = "0.4.1"
feistel_rs = "0.1.0"
future-parking_lot = "0.3.3"
hilbert_index = "0.2.0"
hyper = "1.0.1"
hyper-util = "0.1.1"
nalgebra = { version = "0.32.3", features = ["serde-serialize"] }
parking_lot = { version = "0.11", features = ["serde"] }
pathfinding = "4.6.0"
rstar = { version = "0.11.0", features = ["serde"] }
rustmatica = "0.1.1"

View file

@ -1,3 +1,5 @@
#![feature(iter_map_windows)]
use std::{collections::VecDeque, io::ErrorKind, sync::Arc};
use anyhow::{Context, Error, Ok};
@ -21,7 +23,7 @@ use tokio::sync::{
Mutex, RwLock, mpsc
};
use tower::Service;
use turtle::{TurtleTask, Iota, Receiver, Sender, Turtle, TurtleUpdate};
use turtle::{TurtleTask, Iota, Receiver, Sender, Turtle, TurtleUpdate, TurtleInfo};
use crate::{blocks::Block, paths::route};
@ -127,11 +129,11 @@ async fn create_turtle(
async fn place_up(
Path(id): Path<u32>,
State(state): State<SharedControl>,
) -> Json<TurtleUpdate> {
) -> Json<TurtleInfo> {
let turtle = state.write().await.saved.turtles.get(id as usize).unwrap()
.cmd();
Json(turtle.execute(Iota::Execute(turtle::TurtleCommand::PlaceUp)).await)
Json(turtle.execute(turtle::TurtleCommand::PlaceUp).await)
}
async fn set_goal(
@ -139,9 +141,10 @@ async fn set_goal(
State(state): State<SharedControl>,
Json(req): Json<Position>,
) -> &'static str {
state.write().await.saved.tasks[id as usize].push_back(
TurtleMineJob::chunk(req.0)
);
state.read().await.saved.turtles[id as usize].cmd().goto(req).await;
//state.write().await.saved.tasks[id as usize].push_back(
// TurtleMineJob::chunk(req.0)
//);
"ACK"
}

View file

@ -38,15 +38,34 @@ pub(crate) struct Turtle {
pub(crate) goal: Option<Iota>,
pub(crate) pending_update: bool,
#[serde(skip)]
callback: Option<oneshot::Sender<TurtleUpdate>>,
callback: Option<oneshot::Sender<TurtleInfo>>,
#[serde(skip)]
sender: Option<Arc<Sender>>,
#[serde(skip)]
receiver: Option<Receiver>,
}
pub type Sender = mpsc::Sender<(Iota, oneshot::Sender<TurtleUpdate>)>;
pub type Receiver = mpsc::Receiver<(Iota, oneshot::Sender<TurtleUpdate>)>;
#[derive(Debug)]
pub struct TurtleInfo {
pub name: Name,
pub pos: Position,
pub fuel: usize,
/// Block name
pub ahead: String,
pub above: String,
pub below: String,
pub ret: TurtleCommandResponse,
}
impl TurtleInfo {
fn from_update(update: TurtleUpdate, name: Name, pos: Position) -> Self {
Self { name, pos,
fuel: update.fuel, ahead: update.ahead, above: update.above, below: update.below, ret: update.ret }
}
}
pub type Sender = mpsc::Sender<(TurtleCommand, oneshot::Sender<TurtleInfo>)>;
pub type Receiver = mpsc::Receiver<(TurtleCommand, oneshot::Sender<TurtleInfo>)>;
impl Default for Turtle {
fn default() -> Self {
@ -102,25 +121,40 @@ pub struct TurtleCommander {
}
impl TurtleCommander {
pub async fn execute(&self, command: Iota) -> TurtleUpdate {
let (send, recv) = oneshot::channel::<TurtleUpdate>();
pub async fn execute(&self, command: TurtleCommand) -> TurtleInfo {
let (send, recv) = oneshot::channel::<TurtleInfo>();
self.sender.to_owned().send((command,send)).await.unwrap();
recv.await.unwrap()
}
}
pub async fn command(&self, command: TurtleCommand) -> TurtleUpdate {
self.execute(Iota::Execute(command)).await
}
async fn goto(cmd: &TurtleCommander, recent: TurtleInfo, pos: Position, world: &rstar::RTree<Block>) -> Option<()> {
let mut recent = recent.pos;
loop {
if recent == pos {
break;
}
pub async fn goto(&self, pos: Position) -> TurtleUpdate {
self.execute(Iota::Goto(pos)).await
}
let route = route(recent, pos, world)?;
pub async fn mine(&self, pos: Vec3) -> TurtleUpdate {
self.execute(Iota::Mine(pos)).await
let steps: Vec<TurtleCommand> = route.iter().map_windows(|[from,to]| difference(**from,**to).unwrap()).collect();
'route: for (next_position, command) in route.into_iter().skip(1).zip(steps) {
// reroute if the goal point is not empty before moving
// valid routes will explicitly tell you to break ground
if world.locate_at_point(&next_position.0.into()).unwrap().name != "minecraft:air" {
break 'route;
}
let state = cmd.execute(command).await;
recent = state.pos;
}
}
Some(())
}
pub(crate) async fn process_turtle_update(
@ -171,21 +205,17 @@ pub(crate) async fn process_turtle_update(
world.remove_at_point(&below.pos.into());
world.insert(below.clone());
if let Some(task) = tasks.front_mut() {
task.handle_block(above);
task.handle_block(below);
task.handle_block(ahead);
}
let info = TurtleInfo::from_update(update, turtle.name.clone(), turtle.position.clone());
if let Some(send) = turtle.callback.take() {
send.send(update).unwrap();
send.send(info).unwrap();
}
if let Some(recv) = turtle.receiver.as_mut() {
if let Some((cmd, ret)) = recv.try_recv().ok() {
turtle.callback = Some(ret);
turtle.goal = Some(cmd);
return Ok(cmd);
}
}