summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/game.rs89
-rw-r--r--server/src/main.rs26
-rw-r--r--server/src/protocol.rs71
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,
+ },
}