diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/src/game.rs | 89 | ||||
-rw-r--r-- | server/src/main.rs | 26 | ||||
-rw-r--r-- | server/src/protocol.rs | 71 |
3 files changed, 153 insertions, 33 deletions
diff --git a/server/src/game.rs b/server/src/game.rs index 458a796b..fbbab0a4 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -1,9 +1,10 @@ -use crate::protocol::{Item, PacketC, PacketS, ID}; +use crate::protocol::{Item, PacketC, PacketS, Tile, ID}; use anyhow::{anyhow, Result}; -use glam::UVec2; +use glam::IVec2; use std::collections::{HashMap, VecDeque}; struct TileData { + kind: Tile, items: Vec<ID>, active: bool, } @@ -16,7 +17,7 @@ struct Player { #[derive(Default)] pub struct Game { item_id_counter: ID, - tiles: HashMap<UVec2, TileData>, + tiles: HashMap<IVec2, TileData>, items: HashMap<ID, Item>, players: HashMap<ID, Player>, packet_out: VecDeque<PacketC>, @@ -24,13 +25,72 @@ pub struct Game { impl Game { pub fn new() -> Self { - Self::default() + let mut g = Self::default(); + for x in -5..5 { + for y in -5..5 { + g.tiles.insert(IVec2 { x, y }, Tile::Floor.into()); + } + } + for x in -5..5 { + g.tiles.insert(IVec2 { x, y: -5 }, Tile::Table.into()); + g.tiles.insert(IVec2 { x, y: 4 }, Tile::Table.into()); + } + for y in -5..5 { + g.tiles.insert(IVec2 { x: -5, y }, Tile::Table.into()); + g.tiles.insert(IVec2 { x: 4, y }, Tile::Table.into()); + } + + g.tiles.extend( + [ + ([-5, 1], Tile::Pan), + ([-5, 2], Tile::Pan), + ([4, 3], Tile::Pan), + ] + .map(|(k, v)| { + ( + IVec2::from_array(k), + TileData { + active: false, + items: vec![], + kind: v, + }, + ) + }), + ); + + g } pub fn packet_out(&mut self) -> Option<PacketC> { self.packet_out.pop_front() } + pub fn prime_client(&self, id: ID) -> Vec<PacketC> { + let mut out = Vec::new(); + for (&id, player) in &self.players { + out.push(PacketC::AddPlayer { + id, + name: player.name.clone(), + hand: player.hand.map(|i| (i, self.items[&i])), + }) + } + for (&pos, tdata) in &self.tiles { + out.push(PacketC::UpdateMap { + pos, + tile: tdata.kind, + }); + for &id in &tdata.items { + out.push(PacketC::ProduceItem { + id, + pos, + kind: self.items[&id], + }) + } + } + out.push(PacketC::Joined { id }); + out + } + pub fn packet_in(&mut self, player: ID, packet: PacketS) -> Result<()> { match packet { PacketS::Join { name } => { @@ -41,16 +101,19 @@ impl Game { name: name.clone(), }, ); - self.packet_out - .push_back(PacketC::AddPlayer { id: player, name }); + self.packet_out.push_back(PacketC::AddPlayer { + id: player, + name, + hand: None, + }); } PacketS::Leave => { let p = self .players .remove(&player) .ok_or(anyhow!("player does not exist"))?; - if let Some(_i) = p.hand { - // TODO what now? + if let Some(id) = p.hand { + self.items.remove(&id).expect("hand item lost"); } self.packet_out .push_back(PacketC::RemovePlayer { id: player }) @@ -84,3 +147,13 @@ impl Game { Ok(()) } } + +impl From<Tile> for TileData { + fn from(kind: Tile) -> Self { + Self { + kind, + active: false, + items: vec![], + } + } +} diff --git a/server/src/main.rs b/server/src/main.rs index 477595d0..7426e27e 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -53,11 +53,14 @@ async fn main() -> Result<()> { let game = game.clone(); let mut rx = rx.resubscribe(); info!("{addr} connected"); + let init = game.write().await.prime_client(id); spawn(async move { - write - .write_all(serde_json::to_string(&PacketC::Joined { id }).unwrap().as_bytes()) - .await?; - write.write_all(b"\n").await?; + for p in init { + write + .write_all(serde_json::to_string(&p).unwrap().as_bytes()) + .await?; + write.write_all(b"\n").await?; + } while let Ok(packet) = rx.recv().await { write .write_all(serde_json::to_string(&packet).unwrap().as_bytes()) @@ -78,6 +81,7 @@ async fn main() -> Result<()> { warn!("client error: {e}"); } } + let _ = game.write().await.packet_in(id, PacketS::Leave); }); } r = ws_listener.accept() => { @@ -87,12 +91,15 @@ async fn main() -> Result<()> { let game = game.clone(); let mut rx = rx.resubscribe(); info!("{addr} connected via ws"); + let init = game.write().await.prime_client(id); spawn(async move { - if let Err(e) = write.send(tokio_tungstenite::tungstenite::Message::Text( - serde_json::to_string(&PacketC::Joined { id }).unwrap(), - )).await { - warn!("ws error on init: {e}"); - return; + for p in init { + if let Err(e) = write.send(tokio_tungstenite::tungstenite::Message::Text( + serde_json::to_string(&p).unwrap(), + )).await { + warn!("ws error on init: {e}"); + return; + } } while let Ok(packet) = rx.recv().await { if let Err(e) = write.send(tokio_tungstenite::tungstenite::Message::Text( @@ -120,6 +127,7 @@ async fn main() -> Result<()> { _ => (), } } + let _ = game.write().await.packet_in(id, PacketS::Leave); }); } } diff --git a/server/src/protocol.rs b/server/src/protocol.rs index dc2af7d6..a8fd9979 100644 --- a/server/src/protocol.rs +++ b/server/src/protocol.rs @@ -1,13 +1,22 @@ -use glam::{UVec2, Vec2}; +use glam::{IVec2, Vec2}; use serde::{Deserialize, Serialize}; pub type ID = u32; -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum Item {} +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum Item { + Dough, + Pancake, +} -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum Tile {} +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum Tile { + Floor, + Table, + Pan, +} #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] @@ -15,20 +24,50 @@ pub enum PacketS { Join { name: String }, Leave, Position { pos: Vec2, rot: f32 }, - Interact { pos: UVec2 }, + Interact { pos: IVec2 }, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum PacketC { - Joined { id: ID }, - AddPlayer { id: ID, name: String }, - RemovePlayer { id: ID }, - Position { player: ID, pos: Vec2, rot: f32 }, - TakeItem { item: ID, player: ID }, - PutItem { item: ID, pos: UVec2 }, - ProduceItem { id: ID, pos: UVec2, kind: Item }, - ConsumeItem { id: ID, pos: UVec2 }, - SetActive { tile: UVec2 }, - UpdateMap { pos: UVec2, tile: Tile }, + Joined { + id: ID, + }, + AddPlayer { + id: ID, + name: String, + hand: Option<(ID, Item)>, + }, + RemovePlayer { + id: ID, + }, + Position { + player: ID, + pos: Vec2, + rot: f32, + }, + TakeItem { + item: ID, + player: ID, + }, + PutItem { + item: ID, + pos: IVec2, + }, + ProduceItem { + id: ID, + pos: IVec2, + kind: Item, + }, + ConsumeItem { + id: ID, + pos: IVec2, + }, + SetActive { + tile: IVec2, + }, + UpdateMap { + pos: IVec2, + tile: Tile, + }, } |