summaryrefslogtreecommitdiff
path: root/server/editor/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/editor/src/main.rs')
-rw-r--r--server/editor/src/main.rs108
1 files changed, 94 insertions, 14 deletions
diff --git a/server/editor/src/main.rs b/server/editor/src/main.rs
index 1ae4c81e..c5b6f61d 100644
--- a/server/editor/src/main.rs
+++ b/server/editor/src/main.rs
@@ -1,16 +1,23 @@
+pub mod save;
+
use anyhow::{Result, anyhow};
use clap::Parser;
use futures_util::{SinkExt, StreamExt};
+use hurrycurry_client_lib::network::sync::Network;
use hurrycurry_protocol::{
Gamedata, Hand, Message, PacketC, PacketS, PlayerClass, PlayerID, TileIndex, VERSION,
glam::{IVec2, Vec2, ivec2},
movement::MovementBase,
};
use log::{debug, info, warn};
+use save::export_state;
use std::{
collections::{HashMap, HashSet},
+ fs::File,
+ io::Write,
net::SocketAddr,
- time::Instant,
+ thread::{sleep, spawn},
+ time::{Duration, Instant},
};
use tokio::net::{TcpListener, TcpStream};
@@ -24,8 +31,9 @@ struct Args {
#[derive(Parser)]
#[clap(multicall = true)]
-enum Command {
+pub enum Command {
Play,
+ Save,
}
#[tokio::main]
@@ -41,15 +49,17 @@ async fn main() -> Result<()> {
}
}
-const TILES: &[&str] = &[
- "grass",
- "floor",
- "counter",
- "oven",
- "stove",
- "cuttingboard",
- "chair",
- "table",
+const TILES: &[(&str, char, u8)] = &[
+ ("grass", 'a', 1),
+ ("floor", 'b', 1),
+ ("counter", 'c', 0),
+ ("oven", 'd', 0),
+ ("stove", 'e', 0),
+ ("cuttingboard", 'f', 0),
+ ("chair", 'g', 1),
+ ("table", 'h', 0),
+ ("wall", 'h', 2),
+ ("counter-window", 'h', 0),
];
#[allow(unused_assignments)]
@@ -65,6 +75,8 @@ async fn handle_conn(sock: TcpStream, addr: SocketAddr) -> Result<()> {
movement: MovementBase::new(Vec2::ZERO),
last_movement: Instant::now(),
tile: TileIndex(0),
+ chef_spawn: ivec2(0, 0),
+ customer_spawn: ivec2(0, 0),
};
state.out.push(PacketC::Version {
@@ -76,7 +88,7 @@ async fn handle_conn(sock: TcpStream, addr: SocketAddr) -> Result<()> {
data: Gamedata {
tile_collide: TILES.iter().map(|_| false).collect(),
tile_interact: TILES.iter().map(|_| true).collect(),
- tile_names: TILES.iter().map(|s| s.to_string()).collect(),
+ tile_names: TILES.iter().map(|(name, _, _)| name.to_string()).collect(),
current_map: "editor".to_owned(),
..Default::default()
},
@@ -128,7 +140,7 @@ async fn handle_conn(sock: TcpStream, addr: SocketAddr) -> Result<()> {
Ok(())
}
-struct State {
+pub struct State {
tiles: HashMap<IVec2, TileIndex>,
walkable: HashSet<IVec2>,
out: Vec<PacketC>,
@@ -136,6 +148,9 @@ struct State {
movement: MovementBase,
last_movement: Instant,
tile: TileIndex,
+
+ customer_spawn: IVec2,
+ chef_spawn: IVec2,
}
impl State {
@@ -222,6 +237,7 @@ impl State {
message: Some(Message::Text(t)),
..
} => {
+ let t = t.strip_prefix("/").unwrap_or(&t);
self.handle_command(
Command::try_parse_from(
shlex::split(&t)
@@ -239,7 +255,7 @@ impl State {
self.tile.0 += 1;
self.tile.0 %= TILES.len();
self.out.push(PacketC::ServerMessage {
- message: Message::Text(format!("tile brush: {}", TILES[self.tile.0])),
+ message: Message::Text(format!("tile brush: {}", TILES[self.tile.0].0)),
error: false,
});
}
@@ -262,14 +278,78 @@ impl State {
Ok(())
}
+ pub fn save(&mut self) -> Result<()> {
+ let e = export_state(&self);
+ File::create("data/maps/editor.yaml")?.write_all(e.as_bytes())?;
+ self.out.push(PacketC::ServerMessage {
+ message: Message::Text(format!("Map saved.")),
+ error: false,
+ });
+ Ok(())
+ }
+
pub fn handle_command(&mut self, command: Command) -> Result<()> {
match command {
Command::Play => {
+ self.save()?;
+ spawn(move || {
+ if let Err(e) = start_map_bot("ws://127.0.0.1:27032", "editor") {
+ warn!("editor bot: {e}")
+ }
+ });
self.out.push(PacketC::Redirect {
uri: vec!["ws://127.0.0.1:27032".to_string()],
});
}
+ Command::Save => {
+ self.save()?;
+ }
}
Ok(())
}
}
+
+fn start_map_bot(address: &str, mapname: &str) -> Result<()> {
+ let mut network = Network::connect(address)?;
+
+ network.queue_out.push_back(PacketS::Join {
+ name: "editor-bot".to_owned(),
+ character: 0,
+ class: PlayerClass::Bot,
+ id: None,
+ });
+
+ let mut timer = 10.;
+ loop {
+ let dt = 1. / 50.;
+
+ network.poll()?;
+
+ while let Some(packet) = network.queue_in.pop_front() {
+ match &packet {
+ PacketC::Joined { id } => {
+ network.queue_out.push_back(PacketS::Communicate {
+ player: *id,
+ message: Some(Message::Text(format!("/start {mapname}"))),
+ timeout: None,
+ pin: None,
+ });
+ }
+ PacketC::ServerMessage {
+ message,
+ error: true,
+ } => {
+ warn!("server error message: {message:?}");
+ }
+ _ => (),
+ }
+ }
+
+ timer -= dt;
+ if timer < 0. {
+ break;
+ }
+ sleep(Duration::from_secs_f32(dt));
+ }
+ Ok(())
+}