cargo fmt
This commit is contained in:
parent
93dc487750
commit
93f7befa7a
6 changed files with 182 additions and 99 deletions
|
@ -1,6 +1,6 @@
|
||||||
use rstar::{self, RTree, RTreeObject, AABB, PointDistance};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use pathfinding::prelude::astar;
|
use pathfinding::prelude::astar;
|
||||||
|
use rstar::{self, PointDistance, RTree, RTreeObject, AABB};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Vec3;
|
use crate::Vec3;
|
||||||
|
|
||||||
|
@ -12,9 +12,8 @@ pub struct Block {
|
||||||
pub pos: super::Vec3,
|
pub pos: super::Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl RTreeObject for Block {
|
impl RTreeObject for Block {
|
||||||
type Envelope = AABB<[i32;3]>;
|
type Envelope = AABB<[i32; 3]>;
|
||||||
|
|
||||||
fn envelope(&self) -> Self::Envelope {
|
fn envelope(&self) -> Self::Envelope {
|
||||||
AABB::from_point(self.pos.into())
|
AABB::from_point(self.pos.into())
|
||||||
|
@ -22,11 +21,7 @@ impl RTreeObject for Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointDistance for Block {
|
impl PointDistance for Block {
|
||||||
fn distance_2(
|
fn distance_2(&self, point: &[i32; 3]) -> i32 {
|
||||||
&self,
|
|
||||||
point: &[i32;3],
|
|
||||||
) -> i32 {
|
|
||||||
(self.pos - Vec3::from(*point)).abs().sum()
|
(self.pos - Vec3::from(*point)).abs().sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
use std::{env::args, sync::Arc, fs, io::ErrorKind, collections::VecDeque};
|
use std::{collections::VecDeque, env::args, fs, io::ErrorKind, sync::Arc};
|
||||||
|
|
||||||
|
use anyhow::{Context, Error, Ok};
|
||||||
use axum::{
|
use axum::{
|
||||||
|
extract::{Path, State},
|
||||||
|
http::request,
|
||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Router, extract::{State, Path}, Json, http::{request},
|
Json, Router,
|
||||||
};
|
};
|
||||||
use anyhow::{Error, Ok, Context};
|
|
||||||
use blocks::World;
|
use blocks::World;
|
||||||
use rstar::{self, AABB};
|
use rstar::{self, AABB};
|
||||||
|
|
||||||
mod names;
|
mod names;
|
||||||
use names::Name;
|
|
||||||
use tokio::{sync::{Mutex, RwLock, watch::{self}}};
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use const_format::formatcp;
|
use const_format::formatcp;
|
||||||
use hyper_util::rt::TokioIo;
|
|
||||||
use tower::Service;
|
|
||||||
use hyper::body::Incoming;
|
use hyper::body::Incoming;
|
||||||
|
use hyper_util::rt::TokioIo;
|
||||||
use nalgebra::Vector3;
|
use nalgebra::Vector3;
|
||||||
|
use names::Name;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tokio::sync::{
|
||||||
|
watch::{self},
|
||||||
|
Mutex, RwLock,
|
||||||
|
};
|
||||||
|
use tower::Service;
|
||||||
|
|
||||||
use crate::{blocks::Block, paths::route};
|
use crate::{blocks::Block, paths::route};
|
||||||
mod blocks;
|
mod blocks;
|
||||||
|
@ -42,7 +47,7 @@ impl Direction {
|
||||||
Direction::West => Direction::South,
|
Direction::West => Direction::South,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn right(self) -> Self {
|
fn right(self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Direction::North => Direction::East,
|
Direction::North => Direction::East,
|
||||||
|
@ -72,17 +77,19 @@ type SharedControl = Arc<RwLock<ControlState>>;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), Error> {
|
||||||
|
let state = match tokio::fs::OpenOptions::new()
|
||||||
let state = match tokio::fs::OpenOptions::new().read(true).open("state.json").await {
|
.read(true)
|
||||||
tokio::io::Result::Ok(file) => {
|
.open("state.json")
|
||||||
serde_json::from_reader(file.into_std().await)?
|
.await
|
||||||
},
|
{
|
||||||
|
tokio::io::Result::Ok(file) => serde_json::from_reader(file.into_std().await)?,
|
||||||
tokio::io::Result::Err(e) => match e.kind() {
|
tokio::io::Result::Err(e) => match e.kind() {
|
||||||
ErrorKind::NotFound => {
|
ErrorKind::NotFound => ControlState {
|
||||||
ControlState { turtles:Vec::new(), world: World::new() }
|
turtles: Vec::new(),
|
||||||
|
world: World::new(),
|
||||||
},
|
},
|
||||||
_ => panic!()
|
_ => panic!(),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = SharedControl::new(RwLock::new(state));
|
let state = SharedControl::new(RwLock::new(state));
|
||||||
|
@ -95,8 +102,7 @@ async fn main() -> Result<(), Error> {
|
||||||
.route("/turtle/:id/info", get(turtle_info))
|
.route("/turtle/:id/info", get(turtle_info))
|
||||||
.route("/turtle/updateAll", get(update_turtles))
|
.route("/turtle/updateAll", get(update_turtles))
|
||||||
.route("/flush", get(flush))
|
.route("/flush", get(flush))
|
||||||
.with_state(state.clone());
|
.with_state(state.clone());
|
||||||
|
|
||||||
|
|
||||||
let server = safe_kill::serve(server).await;
|
let server = safe_kill::serve(server).await;
|
||||||
|
|
||||||
|
@ -108,7 +114,7 @@ async fn main() -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
mod safe_kill;
|
mod safe_kill;
|
||||||
|
|
||||||
async fn write_to_disk(state: SharedControl) -> anyhow::Result<()> {
|
async fn write_to_disk(state: SharedControl) -> anyhow::Result<()> {
|
||||||
let json = serde_json::to_string_pretty(&(*state.read().await))?;
|
let json = serde_json::to_string_pretty(&(*state.read().await))?;
|
||||||
|
@ -125,42 +131,52 @@ async fn flush(State(state): State<SharedControl>) -> &'static str {
|
||||||
async fn create_turtle(
|
async fn create_turtle(
|
||||||
State(state): State<SharedControl>,
|
State(state): State<SharedControl>,
|
||||||
Json(req): Json<turtle::TurtleRegister>,
|
Json(req): Json<turtle::TurtleRegister>,
|
||||||
) -> Json<turtle::TurtleResponse> {
|
) -> Json<turtle::TurtleResponse> {
|
||||||
let turtles = &mut state.write().await.turtles;
|
let turtles = &mut state.write().await.turtles;
|
||||||
let id = turtles.len() as u32;
|
let id = turtles.len() as u32;
|
||||||
turtles.push(turtle::Turtle::new(id, req.position, req.facing, req.fuel));
|
turtles.push(turtle::Turtle::new(id, req.position, req.facing, req.fuel));
|
||||||
|
|
||||||
println!("turt {id}");
|
println!("turt {id}");
|
||||||
|
|
||||||
Json(turtle::TurtleResponse {name: Name::from_num(id).to_str(), id, command: turtle::TurtleCommand::Update})
|
Json(turtle::TurtleResponse {
|
||||||
|
name: Name::from_num(id).to_str(),
|
||||||
|
id,
|
||||||
|
command: turtle::TurtleCommand::Update,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_goal(
|
async fn set_goal(
|
||||||
Path(id): Path<u32>,
|
Path(id): Path<u32>,
|
||||||
State(state): State<SharedControl>,
|
State(state): State<SharedControl>,
|
||||||
Json(req): Json<Position>,
|
Json(req): Json<Position>,
|
||||||
) -> &'static str {
|
) -> &'static str {
|
||||||
state.write().await.turtles[id as usize].goal = Some(req);
|
state.write().await.turtles[id as usize].goal = Some(req);
|
||||||
|
|
||||||
"ACK"
|
"ACK"
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_turtles(
|
async fn update_turtles(State(state): State<SharedControl>) -> &'static str {
|
||||||
State(state): State<SharedControl>,
|
state
|
||||||
) -> &'static str {
|
.write()
|
||||||
state.write().await.turtles.iter_mut().for_each(|t| t.pending_update = true);
|
.await
|
||||||
|
.turtles
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|t| t.pending_update = true);
|
||||||
"ACK"
|
"ACK"
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn turtle_info(
|
async fn turtle_info(
|
||||||
Path(id): Path<u32>,
|
Path(id): Path<u32>,
|
||||||
State(state): State<SharedControl>,
|
State(state): State<SharedControl>,
|
||||||
) -> Json<turtle::Turtle> {
|
) -> Json<turtle::Turtle> {
|
||||||
let state = &mut state.read().await;
|
let state = &mut state.read().await;
|
||||||
let turtle = &state.turtles[id as usize];
|
let turtle = &state.turtles[id as usize];
|
||||||
|
|
||||||
let mut pseudomoves: VecDeque<turtle::TurtleCommand> = VecDeque::new();
|
let mut pseudomoves: VecDeque<turtle::TurtleCommand> = VecDeque::new();
|
||||||
turtle.moves.front().map(|m| pseudomoves.push_front(m.clone()));
|
turtle
|
||||||
|
.moves
|
||||||
|
.front()
|
||||||
|
.map(|m| pseudomoves.push_front(m.clone()));
|
||||||
|
|
||||||
let cloned = turtle::Turtle {
|
let cloned = turtle::Turtle {
|
||||||
name: turtle.name.clone(),
|
name: turtle.name.clone(),
|
||||||
|
@ -179,7 +195,7 @@ async fn command(
|
||||||
Path(id): Path<u32>,
|
Path(id): Path<u32>,
|
||||||
State(state): State<SharedControl>,
|
State(state): State<SharedControl>,
|
||||||
Json(req): Json<turtle::TurtleUpdate>,
|
Json(req): Json<turtle::TurtleUpdate>,
|
||||||
) -> Json<turtle::TurtleCommand> {
|
) -> Json<turtle::TurtleCommand> {
|
||||||
let mut state = &mut state.write().await;
|
let mut state = &mut state.write().await;
|
||||||
|
|
||||||
println!("{:?}", &req);
|
println!("{:?}", &req);
|
||||||
|
@ -219,7 +235,6 @@ fn difference(from: Position, to: Position) -> Option<turtle::TurtleCommand> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -227,7 +242,7 @@ fn difference(from: Position, to: Position) -> Option<turtle::TurtleCommand> {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct TurtleMineJobParams {
|
struct TurtleMineJobParams {
|
||||||
region: AABB<[i32;3]>,
|
region: AABB<[i32; 3]>,
|
||||||
to_mine: Vec<Vec3>,
|
to_mine: Vec<Vec3>,
|
||||||
method: TurtleMineMethod,
|
method: TurtleMineMethod,
|
||||||
refuel: Position,
|
refuel: Position,
|
||||||
|
@ -237,18 +252,21 @@ struct TurtleMineJobParams {
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct TurtleMineJob {
|
struct TurtleMineJob {
|
||||||
to_mine: VecDeque<Vec3>,
|
to_mine: VecDeque<Vec3>,
|
||||||
mined: AABB<[i32;3]>,
|
mined: AABB<[i32; 3]>,
|
||||||
params: TurtleMineJobParams,
|
params: TurtleMineJobParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum TurtleMineMethod {
|
enum TurtleMineMethod {
|
||||||
Clear,
|
Clear,
|
||||||
Strip,
|
Strip,
|
||||||
}
|
}
|
||||||
async fn client() -> &'static str {
|
async fn client() -> &'static str {
|
||||||
formatcp!("local ipaddr = {}\n{}", include_str!("../ipaddr.txt"), include_str!("../../client/client.lua"))
|
formatcp!(
|
||||||
|
"local ipaddr = {}\n{}",
|
||||||
|
include_str!("../ipaddr.txt"),
|
||||||
|
include_str!("../../client/client.lua")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
mod turtle;
|
mod turtle;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use bit_struct::*;
|
use bit_struct::*;
|
||||||
use feistel_rs::{feistel_encrypt, feistel_decrypt};
|
use feistel_rs::{feistel_decrypt, feistel_encrypt};
|
||||||
|
|
||||||
bit_struct! {
|
bit_struct! {
|
||||||
pub struct Name(u32) {
|
pub struct Name(u32) {
|
||||||
|
@ -24,48 +24,81 @@ impl Name {
|
||||||
pub fn from_str(name: &str) -> anyhow::Result<Self> {
|
pub fn from_str(name: &str) -> anyhow::Result<Self> {
|
||||||
let parts: Vec<&str> = name.splitn(4, ' ').collect();
|
let parts: Vec<&str> = name.splitn(4, ' ').collect();
|
||||||
let (first, last, order, mut pronouns) = (parts[0], parts[1], parts[2], parts[3]);
|
let (first, last, order, mut pronouns) = (parts[0], parts[1], parts[2], parts[3]);
|
||||||
pronouns = &pronouns[1..pronouns.len()-1];
|
pronouns = &pronouns[1..pronouns.len() - 1];
|
||||||
|
|
||||||
|
let first = FIRST_NAMES
|
||||||
let first = FIRST_NAMES.lines().position(|x| *x == *first).map(|n| u13::new(n as u16)).context("unknown first name")?;
|
.lines()
|
||||||
let last = LAST_NAMES.lines().position(|x| *x == *last).map(|n| u14::new(n as u16)).context("unknown last name")?;
|
.position(|x| *x == *first)
|
||||||
let order = ORDER.lines().position(|x| *x == *order).map(|n| u3::new(n as u8)).context("unknown title")?;
|
.map(|n| u13::new(n as u16))
|
||||||
let pronouns = PRONOUNS.lines().position(|x| *x == *pronouns).map(|n| u2::new(n as u8)).context("invalid gender")?;
|
.context("unknown first name")?;
|
||||||
|
let last = LAST_NAMES
|
||||||
|
.lines()
|
||||||
|
.position(|x| *x == *last)
|
||||||
|
.map(|n| u14::new(n as u16))
|
||||||
|
.context("unknown last name")?;
|
||||||
|
let order = ORDER
|
||||||
|
.lines()
|
||||||
|
.position(|x| *x == *order)
|
||||||
|
.map(|n| u3::new(n as u8))
|
||||||
|
.context("unknown title")?;
|
||||||
|
let pronouns = PRONOUNS
|
||||||
|
.lines()
|
||||||
|
.position(|x| *x == *pronouns)
|
||||||
|
.map(|n| u2::new(n as u8))
|
||||||
|
.context("invalid gender")?;
|
||||||
|
|
||||||
// first name 14 bits
|
// first name 14 bits
|
||||||
// last name 13 bits
|
// last name 13 bits
|
||||||
// order 3 bits
|
// order 3 bits
|
||||||
// pronouns 2 bits
|
// pronouns 2 bits
|
||||||
|
|
||||||
|
|
||||||
// TODO: trim tables to avoid "zach" crashes
|
// TODO: trim tables to avoid "zach" crashes
|
||||||
Ok(Name::new(first.unwrap(), last.unwrap(), order.unwrap(), pronouns.unwrap()))
|
Ok(Name::new(
|
||||||
|
first.unwrap(),
|
||||||
|
last.unwrap(),
|
||||||
|
order.unwrap(),
|
||||||
|
pronouns.unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_num(name: u32) -> Self {
|
pub fn from_num(name: u32) -> Self {
|
||||||
let encrypted = u32::from_le_bytes(
|
let encrypted = u32::from_le_bytes(
|
||||||
feistel_encrypt(&name.to_le_bytes(), &FEISTEL_KEY, FEISTEL_ROUNDS).try_into().unwrap()
|
feistel_encrypt(&name.to_le_bytes(), &FEISTEL_KEY, FEISTEL_ROUNDS)
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// This is ok because every possible value is valid (see tests)
|
// This is ok because every possible value is valid (see tests)
|
||||||
unsafe {
|
unsafe { Name(UnsafeStorage::new_unsafe(encrypted)) }
|
||||||
Name(UnsafeStorage::new_unsafe(encrypted))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_num(self) -> u32 {
|
pub fn to_num(self) -> u32 {
|
||||||
let num = self.raw();
|
let num = self.raw();
|
||||||
|
|
||||||
u32::from_le_bytes(
|
u32::from_le_bytes(
|
||||||
feistel_decrypt(&num.to_le_bytes(), &FEISTEL_KEY, FEISTEL_ROUNDS).try_into().unwrap()
|
feistel_decrypt(&num.to_le_bytes(), &FEISTEL_KEY, FEISTEL_ROUNDS)
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_str(&mut self) -> String {
|
pub fn to_str(&mut self) -> String {
|
||||||
let first = FIRST_NAMES.lines().nth(self.first().get().value() as usize).unwrap();
|
let first = FIRST_NAMES
|
||||||
let last = LAST_NAMES.lines().nth(self.last().get().value() as usize).unwrap();
|
.lines()
|
||||||
let order = ORDER.lines().nth(self.order().get().value() as usize).unwrap();
|
.nth(self.first().get().value() as usize)
|
||||||
let pronouns = PRONOUNS.lines().nth(self.pronouns().get().value() as usize).unwrap();
|
.unwrap();
|
||||||
|
let last = LAST_NAMES
|
||||||
|
.lines()
|
||||||
|
.nth(self.last().get().value() as usize)
|
||||||
|
.unwrap();
|
||||||
|
let order = ORDER
|
||||||
|
.lines()
|
||||||
|
.nth(self.order().get().value() as usize)
|
||||||
|
.unwrap();
|
||||||
|
let pronouns = PRONOUNS
|
||||||
|
.lines()
|
||||||
|
.nth(self.pronouns().get().value() as usize)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
format!("{first} {last} {order} ({pronouns})")
|
format!("{first} {last} {order} ({pronouns})")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,45 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
blocks::{Block, World},
|
||||||
|
Direction, Position,
|
||||||
|
};
|
||||||
use pathfinding::prelude::astar;
|
use pathfinding::prelude::astar;
|
||||||
use crate::{blocks::{World, Block}, Position, Direction};
|
|
||||||
|
|
||||||
use super::Vec3;
|
use super::Vec3;
|
||||||
|
|
||||||
pub fn route(from: Position, to: Position, world: &World) -> Option<Vec<Position>> {
|
pub fn route(from: Position, to: Position, world: &World) -> Option<Vec<Position>> {
|
||||||
// attempt at not crashing by looking infinitely into the abyss
|
// attempt at not crashing by looking infinitely into the abyss
|
||||||
if world.locate_at_point(&to.0.into())
|
if world
|
||||||
.is_some_and(|b| difficulty(&b.name).is_none()) {
|
.locate_at_point(&to.0.into())
|
||||||
|
.is_some_and(|b| difficulty(&b.name).is_none())
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
|
|
||||||
}
|
}
|
||||||
let route = astar(&from, move |p| {next(p, world)} , |p1| {(p1.0 - &to.0).abs().sum() as u32}, |p| {p == &to}).unwrap();
|
let route = astar(
|
||||||
|
&from,
|
||||||
|
move |p| next(p, world),
|
||||||
|
|p1| (p1.0 - &to.0).abs().sum() as u32,
|
||||||
|
|p| p == &to,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
Some(route.0)
|
Some(route.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(from: &Position, world: &World) -> Vec<(Position, u32)> {
|
fn next(from: &Position, world: &World) -> Vec<(Position, u32)> {
|
||||||
let mut vec: Vec<(Position, u32)> = Vec::new();
|
let mut vec: Vec<(Position, u32)> = Vec::new();
|
||||||
vec.push(((from.0, from.1.left()),1));
|
vec.push(((from.0, from.1.left()), 1));
|
||||||
vec.push(((from.0, from.1.right()),1));
|
vec.push(((from.0, from.1.right()), 1));
|
||||||
|
|
||||||
fn insert(vec: &mut Vec<(Position, u32)>, point: Vec3, orientation: Direction, world: &World, unknown: Option<u32>) {
|
fn insert(
|
||||||
world.locate_at_point(&point.into())
|
vec: &mut Vec<(Position, u32)>,
|
||||||
|
point: Vec3,
|
||||||
|
orientation: Direction,
|
||||||
|
world: &World,
|
||||||
|
unknown: Option<u32>,
|
||||||
|
) {
|
||||||
|
world
|
||||||
|
.locate_at_point(&point.into())
|
||||||
.map_or(unknown, |b| difficulty(&b.name))
|
.map_or(unknown, |b| difficulty(&b.name))
|
||||||
.map(|d| vec.push(((point, orientation), d)));
|
.map(|d| vec.push(((point, orientation), d)));
|
||||||
}
|
}
|
||||||
|
@ -32,12 +49,12 @@ fn next(from: &Position, world: &World) -> Vec<(Position, u32)> {
|
||||||
|
|
||||||
//let behind = from.0 - from.1.unit();
|
//let behind = from.0 - from.1.unit();
|
||||||
//insert(&mut vec, behind, from.1, world, None);
|
//insert(&mut vec, behind, from.1, world, None);
|
||||||
|
|
||||||
let above = from.0 + Vec3::y();
|
let above = from.0 + Vec3::y();
|
||||||
insert(&mut vec, above, from.1, world,UNKNOWN);
|
insert(&mut vec, above, from.1, world, UNKNOWN);
|
||||||
|
|
||||||
let below = from.0 - Vec3::y();
|
let below = from.0 - Vec3::y();
|
||||||
insert(&mut vec, below, from.1, world,UNKNOWN);
|
insert(&mut vec, below, from.1, world, UNKNOWN);
|
||||||
|
|
||||||
vec
|
vec
|
||||||
}
|
}
|
||||||
|
@ -56,7 +73,11 @@ const UNKNOWN: Option<u32> = Some(2);
|
||||||
|
|
||||||
// time to go somewhere
|
// time to go somewhere
|
||||||
fn difficulty(name: &str) -> Option<u32> {
|
fn difficulty(name: &str) -> Option<u32> {
|
||||||
if name == "minecraft:air" { return Some(1) };
|
if name == "minecraft:air" {
|
||||||
if GARBAGE.contains(&name) { return Some(2)};
|
return Some(1);
|
||||||
|
};
|
||||||
|
if GARBAGE.contains(&name) {
|
||||||
|
return Some(2);
|
||||||
|
};
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,9 @@ use tokio::sync::watch::Sender;
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
|
|
||||||
pub(crate) async fn serve(server: Router) -> Sender<()> {
|
pub(crate) async fn serve(server: Router) -> Sender<()> {
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:48228").await.unwrap();
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:48228")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let (close_tx, close_rx) = watch::channel(());
|
let (close_tx, close_rx) = watch::channel(());
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ pub(crate) async fn serve(server: Router) -> Sender<()> {
|
||||||
|
|
||||||
drop(close_rx);
|
drop(close_rx);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
drop(listener);
|
drop(listener);
|
||||||
|
|
||||||
|
@ -75,8 +77,7 @@ pub(crate) async fn serve(server: Router) -> Sender<()> {
|
||||||
|
|
||||||
pub(crate) async fn shutdown_signal() {
|
pub(crate) async fn shutdown_signal() {
|
||||||
let ctrl_c = async {
|
let ctrl_c = async {
|
||||||
signal::ctrl_c()
|
signal::ctrl_c().await.unwrap();
|
||||||
.await.unwrap();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ctrl_c.await
|
ctrl_c.await
|
||||||
|
|
|
@ -21,8 +21,8 @@ use super::Vec3;
|
||||||
|
|
||||||
use super::names::Name;
|
use super::names::Name;
|
||||||
|
|
||||||
use serde::Serialize;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
use super::paths::route;
|
use super::paths::route;
|
||||||
|
|
||||||
|
@ -40,8 +40,15 @@ pub(crate) struct Turtle {
|
||||||
|
|
||||||
impl Turtle {
|
impl Turtle {
|
||||||
pub(crate) fn new(id: u32, position: Vec3, facing: Direction, fuel: usize) -> Self {
|
pub(crate) fn new(id: u32, position: Vec3, facing: Direction, fuel: usize) -> Self {
|
||||||
Self { name: Name::from_num(id), fuel, queued_movement: Vec3::new(0, 0, 0), position: (position, facing), goal: None, pending_update: true, moves: VecDeque::new() }
|
Self {
|
||||||
|
name: Name::from_num(id),
|
||||||
|
fuel,
|
||||||
|
queued_movement: Vec3::new(0, 0, 0),
|
||||||
|
position: (position, facing),
|
||||||
|
goal: None,
|
||||||
|
pending_update: true,
|
||||||
|
moves: VecDeque::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +56,11 @@ pub(crate) fn process_turtle_update(
|
||||||
id: u32,
|
id: u32,
|
||||||
state: &mut ControlState,
|
state: &mut ControlState,
|
||||||
update: TurtleUpdate,
|
update: TurtleUpdate,
|
||||||
) -> anyhow::Result<TurtleCommand> {
|
) -> anyhow::Result<TurtleCommand> {
|
||||||
let turtle = state.turtles.get_mut(id as usize).context("nonexisting turtle")?;
|
let turtle = state
|
||||||
|
.turtles
|
||||||
|
.get_mut(id as usize)
|
||||||
|
.context("nonexisting turtle")?;
|
||||||
let world = &mut state.world;
|
let world = &mut state.world;
|
||||||
|
|
||||||
if turtle.pending_update {
|
if turtle.pending_update {
|
||||||
|
@ -58,7 +68,10 @@ pub(crate) fn process_turtle_update(
|
||||||
return Ok(TurtleCommand::Update);
|
return Ok(TurtleCommand::Update);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("above: {}, below: {}, ahead: {}", update.above, update.below, update.ahead);
|
println!(
|
||||||
|
"above: {}, below: {}, ahead: {}",
|
||||||
|
update.above, update.below, update.ahead
|
||||||
|
);
|
||||||
if turtle.fuel != update.fuel {
|
if turtle.fuel != update.fuel {
|
||||||
turtle.fuel = update.fuel;
|
turtle.fuel = update.fuel;
|
||||||
|
|
||||||
|
@ -96,20 +109,22 @@ pub(crate) fn process_turtle_update(
|
||||||
let route = route(turtle.position, goal, world).unwrap();
|
let route = route(turtle.position, goal, world).unwrap();
|
||||||
println!("route: {:?}", route);
|
println!("route: {:?}", route);
|
||||||
let mut next_move = difference(route[0], route[1]).unwrap();
|
let mut next_move = difference(route[0], route[1]).unwrap();
|
||||||
if world.locate_at_point(&route[1].0.into()).is_some_and(|b| b.name != "minecraft:air") {
|
if world
|
||||||
|
.locate_at_point(&route[1].0.into())
|
||||||
|
.is_some_and(|b| b.name != "minecraft:air")
|
||||||
|
{
|
||||||
next_move = match next_move {
|
next_move = match next_move {
|
||||||
TurtleCommand::Up(_) => TurtleCommand::DigUp,
|
TurtleCommand::Up(_) => TurtleCommand::DigUp,
|
||||||
TurtleCommand::Down(_) => TurtleCommand::DigDown,
|
TurtleCommand::Down(_) => TurtleCommand::DigDown,
|
||||||
TurtleCommand::Forward(_) => TurtleCommand::Dig,
|
TurtleCommand::Forward(_) => TurtleCommand::Dig,
|
||||||
_ => next_move,
|
_ => next_move,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
turtle.queued_movement = next_move.delta(turtle.position.1);
|
turtle.queued_movement = next_move.delta(turtle.position.1);
|
||||||
match next_move {
|
match next_move {
|
||||||
TurtleCommand::Left => turtle.position.1 = turtle.position.1.left(),
|
TurtleCommand::Left => turtle.position.1 = turtle.position.1.left(),
|
||||||
TurtleCommand::Right => turtle.position.1 = turtle.position.1.right(),
|
TurtleCommand::Right => turtle.position.1 = turtle.position.1.right(),
|
||||||
_ => {},
|
_ => {}
|
||||||
}
|
}
|
||||||
return Ok(next_move);
|
return Ok(next_move);
|
||||||
}
|
}
|
||||||
|
@ -165,16 +180,16 @@ pub(crate) enum TurtleCommandResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TurtleCommand {
|
impl TurtleCommand {
|
||||||
pub(crate) fn delta(&self, direction: Direction) -> Vec3 {
|
pub(crate) fn delta(&self, direction: Direction) -> Vec3 {
|
||||||
let dir = direction.unit();
|
let dir = direction.unit();
|
||||||
match self {
|
match self {
|
||||||
TurtleCommand::Forward(count) => dir * *count as i32,
|
TurtleCommand::Forward(count) => dir * *count as i32,
|
||||||
TurtleCommand::Backward(count) => -dir * *count as i32,
|
TurtleCommand::Backward(count) => -dir * *count as i32,
|
||||||
TurtleCommand::Up(count) => Vec3::y() * *count as i32,
|
TurtleCommand::Up(count) => Vec3::y() * *count as i32,
|
||||||
TurtleCommand::Down(count) => -Vec3::y() * *count as i32,
|
TurtleCommand::Down(count) => -Vec3::y() * *count as i32,
|
||||||
_ => Vec3::zeros(),
|
_ => Vec3::zeros(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
Loading…
Reference in a new issue