1
Fork 0

cargo fmt

This commit is contained in:
Andy Killorin 2023-12-17 15:46:42 -06:00
parent 93dc487750
commit 93f7befa7a
Signed by: ank
GPG key ID: B6241CA3B552BCA4
6 changed files with 182 additions and 99 deletions

View file

@ -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()
} }
} }

View file

@ -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;

View file

@ -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})")
} }

View file

@ -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
} }

View file

@ -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

View file

@ -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)]