diff options
author | metamuffin <metamuffin@disroot.org> | 2024-07-20 19:43:14 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-07-20 19:43:14 +0200 |
commit | febbc005cfac682257af0b74be5b307d4f23f91c (patch) | |
tree | a9884a873bd995b75c74583121e4bdd27c3fa5c2 | |
parent | 1a45b0e0f5de785ddf268d7371f0cdaeafe9daa7 (diff) | |
download | hurrycurry-febbc005cfac682257af0b74be5b307d4f23f91c.tar hurrycurry-febbc005cfac682257af0b74be5b307d4f23f91c.tar.bz2 hurrycurry-febbc005cfac682257af0b74be5b307d4f23f91c.tar.zst |
send score menu on game end
-rw-r--r-- | server/protocol/src/lib.rs | 2 | ||||
-rw-r--r-- | server/src/entity/conveyor.rs | 12 | ||||
-rw-r--r-- | server/src/entity/customers/mod.rs | 6 | ||||
-rw-r--r-- | server/src/entity/mod.rs | 10 | ||||
-rw-r--r-- | server/src/entity/portal.rs | 13 | ||||
-rw-r--r-- | server/src/game.rs | 67 | ||||
-rw-r--r-- | server/src/state.rs | 51 |
7 files changed, 100 insertions, 61 deletions
diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 61efd74f..fcccb107 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -209,7 +209,7 @@ pub enum PacketC { } #[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(rename_all = "snake_case", tag = "type", content = "data")] +#[serde(rename_all = "snake_case", tag = "menu", content = "data")] pub enum Menu { Book, Score(Score), diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs index 38478db7..7f3d8688 100644 --- a/server/src/entity/conveyor.rs +++ b/server/src/entity/conveyor.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; + /* Hurry Curry! - a game about cooking Copyright 2024 metamuffin @@ -18,7 +20,7 @@ use super::EntityT; use crate::game::{interact_effect, Game}; use anyhow::{anyhow, Result}; -use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation}; +use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation, PacketC}; #[derive(Debug, Clone)] pub struct Conveyor { @@ -31,7 +33,7 @@ pub struct Conveyor { } impl EntityT for Conveyor { - fn tick(&mut self, game: &mut Game, dt: f32) -> Result<()> { + fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()> { let from = game .tiles .get(&self.from) @@ -44,7 +46,9 @@ impl EntityT for Conveyor { .get(t) .ok_or(anyhow!("conveyor filter missing"))?; filter_tile.item.as_ref().map(|e| e.kind) - } else { self.filter_item.as_ref().map(|i| *i) }; + } else { + self.filter_item.as_ref().map(|i| *i) + }; if let Some(filter) = filter { if from_item.kind != filter { @@ -71,7 +75,7 @@ impl EntityT for Conveyor { &mut from.item, ItemLocation::Tile(self.from), Some(to.kind), - &mut game.packet_out, + packet_out, &mut game.score, true, ); diff --git a/server/src/entity/customers/mod.rs b/server/src/entity/customers/mod.rs index e8679dc9..974ae686 100644 --- a/server/src/entity/customers/mod.rs +++ b/server/src/entity/customers/mod.rs @@ -22,7 +22,7 @@ use super::EntityT; use crate::{data::Demand, game::Game}; use anyhow::{anyhow, Result}; use fake::{faker, Fake}; -use hurrycurry_protocol::{glam::IVec2, DemandIndex, Message, PacketS, PlayerID}; +use hurrycurry_protocol::{glam::IVec2, DemandIndex, Message, PacketC, PacketS, PlayerID}; use log::{info, warn}; use pathfinding::{find_path, Path}; use rand::{random, thread_rng}; @@ -74,7 +74,7 @@ impl Customers { } impl EntityT for Customers { - fn tick(&mut self, game: &mut Game, dt: f32) -> Result<()> { + fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()> { self.spawn_cooldown -= dt; self.spawn_cooldown = self.spawn_cooldown.max(0.); if self.customers.len() < 5 && self.spawn_cooldown <= 0. { @@ -253,7 +253,7 @@ impl EntityT for Customers { self.customers.remove(&c).unwrap(); } for (player, packet) in self.cpackets.drain(..) { - if let Err(err) = game.packet_in(player, packet, &mut vec![]) { + if let Err(err) = game.packet_in(player, packet, &mut vec![], packet_out) { warn!("demand packet {err}"); } } diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs index c471a6d4..ec5ec744 100644 --- a/server/src/entity/mod.rs +++ b/server/src/entity/mod.rs @@ -18,18 +18,18 @@ pub mod conveyor; pub mod customers; pub mod portal; -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet, VecDeque}; use crate::{data::ItemTileRegistry, game::Game, interaction::Recipe}; use anyhow::{anyhow, Result}; use conveyor::Conveyor; use customers::{demands::generate_demands, Customers}; -use hurrycurry_protocol::{glam::IVec2, ItemIndex, TileIndex}; +use hurrycurry_protocol::{glam::IVec2, ItemIndex, PacketC, TileIndex}; use portal::Portal; use serde::{Deserialize, Serialize}; pub trait EntityT: Clone { - fn tick(&mut self, game: &mut Game, dt: f32) -> Result<()>; + fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()>; } macro_rules! entities { @@ -37,8 +37,8 @@ macro_rules! entities { #[derive(Debug, Clone)] pub enum Entity { $($e($e)),* } impl EntityT for Entity { - fn tick(&mut self, game: &mut Game, dt: f32) -> Result<()> { - match self { $(Entity::$e(x) => x.tick(game, dt)),*, } + fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()> { + match self { $(Entity::$e(x) => x.tick(game, packet_out, dt)),*, } } } }; diff --git a/server/src/entity/portal.rs b/server/src/entity/portal.rs index 2d4a762b..e0ec353f 100644 --- a/server/src/entity/portal.rs +++ b/server/src/entity/portal.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; + /* Hurry Curry! - a game about cooking Copyright 2024 metamuffin @@ -18,7 +20,7 @@ use super::EntityT; use crate::game::{interact_effect, Game}; use anyhow::{anyhow, Result}; -use hurrycurry_protocol::{glam::IVec2, ItemLocation}; +use hurrycurry_protocol::{glam::IVec2, ItemLocation, PacketC}; #[derive(Debug, Default, Clone)] pub struct Portal { @@ -27,7 +29,12 @@ pub struct Portal { } impl EntityT for Portal { - fn tick(&mut self, game: &mut Game, _dt: f32) -> Result<()> { + fn tick( + &mut self, + game: &mut Game, + packet_out: &mut VecDeque<PacketC>, + _dt: f32, + ) -> Result<()> { let [from, to] = game .tiles .get_many_mut([&self.from, &self.to]) @@ -42,7 +49,7 @@ impl EntityT for Portal { &mut from.item, ItemLocation::Tile(self.from), Some(to.kind), - &mut game.packet_out, + packet_out, &mut game.score, true, ); diff --git a/server/src/game.rs b/server/src/game.rs index 1f368b00..21bb5f33 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -72,7 +72,6 @@ pub struct Game { pub walkable: HashSet<IVec2>, pub players: HashMap<PlayerID, Player>, players_spatial_index: SpatialIndex<PlayerID>, - pub packet_out: VecDeque<PacketC>, entities: Arc<RwLock<Vec<Entity>>>, end: Option<Instant>, pub lobby: bool, @@ -92,7 +91,6 @@ impl Game { Self { lobby: false, data: Gamedata::default().into(), - packet_out: Default::default(), players: HashMap::new(), tiles: HashMap::new(), walkable: HashSet::new(), @@ -104,16 +102,16 @@ impl Game { } } - fn unload(&mut self) { - self.packet_out.push_back(PacketC::SetIngame { + fn unload(&mut self, packet_out: &mut VecDeque<PacketC>) { + packet_out.push_back(PacketC::SetIngame { state: false, lobby: false, }); for (id, _) in self.players.drain() { - self.packet_out.push_back(PacketC::RemovePlayer { id }) + packet_out.push_back(PacketC::RemovePlayer { id }) } for (pos, _) in self.tiles.drain() { - self.packet_out.push_back(PacketC::UpdateMap { + packet_out.push_back(PacketC::UpdateMap { tile: pos, kind: None, neighbors: [None, None, None, None], @@ -121,7 +119,12 @@ impl Game { } self.walkable.clear(); } - pub fn load(&mut self, gamedata: Gamedata, timer: Option<Duration>) { + pub fn load( + &mut self, + gamedata: Gamedata, + timer: Option<Duration>, + packet_out: &mut VecDeque<PacketC>, + ) { let players = self .players .iter() @@ -129,7 +132,7 @@ impl Game { .map(|(id, p)| (*id, (p.name.to_owned(), p.character))) .collect::<HashMap<_, _>>(); - self.unload(); + self.unload(packet_out); self.lobby = gamedata.map_name == "lobby"; self.data = gamedata.into(); @@ -180,7 +183,7 @@ impl Game { ); } - self.packet_out.extend(self.prime_client()); + packet_out.extend(self.prime_client()); } pub fn prime_client(&self) -> Vec<PacketC> { @@ -261,6 +264,7 @@ impl Game { player: PlayerID, packet: PacketS, replies: &mut Vec<PacketC>, + packet_out: &mut VecDeque<PacketC>, ) -> Result<()> { match packet { PacketS::Join { name, character } => { @@ -297,7 +301,7 @@ impl Game { name: name.clone(), }, ); - self.packet_out.push_back(PacketC::AddPlayer { + packet_out.push_back(PacketC::AddPlayer { id: player, name, position, @@ -316,7 +320,7 @@ impl Game { let pos = p.movement.position.floor().as_ivec2(); if let Some(tile) = self.tiles.get_mut(&pos) { if tile.item.is_none() { - self.packet_out.push_back(PacketC::SetItem { + packet_out.push_back(PacketC::SetItem { location: ItemLocation::Tile(pos), item: Some(item.kind), }); @@ -324,8 +328,7 @@ impl Game { } } } - self.packet_out - .push_back(PacketC::RemovePlayer { id: player }) + packet_out.push_back(PacketC::RemovePlayer { id: player }) } PacketS::Movement { pos, @@ -352,8 +355,7 @@ impl Game { } } PacketS::Collide { player, force } => { - self.packet_out - .push_back(PacketC::Collide { player, force }); + packet_out.push_back(PacketC::Collide { player, force }); } PacketS::Interact { pos } => { let pid = player; @@ -410,7 +412,7 @@ impl Game { &mut other.item, ItemLocation::Player(pid), None, - &mut self.packet_out, + packet_out, &mut self.score, false, ) @@ -428,7 +430,7 @@ impl Game { &mut player.item, ItemLocation::Player(pid), Some(tile.kind), - &mut self.packet_out, + packet_out, &mut self.score, false, ) @@ -441,7 +443,7 @@ impl Game { player.communicate_persist = message.clone() } } - self.packet_out.push_back(PacketC::Communicate { + packet_out.push_back(PacketC::Communicate { player, message, persist, @@ -456,7 +458,7 @@ impl Game { kind: i, active: None, }); - self.packet_out.push_back(PacketC::SetItem { + packet_out.push_back(PacketC::SetItem { location: ItemLocation::Player(player), item, }) @@ -467,11 +469,10 @@ impl Game { } /// Returns true if the game should end - pub fn tick(&mut self, dt: f32) -> bool { + pub fn tick(&mut self, dt: f32, packet_out: &mut VecDeque<PacketC>) -> bool { if self.score_changed { self.score_changed = false; - self.packet_out - .push_back(PacketC::Score(self.score.clone())); + packet_out.push_back(PacketC::Score(self.score.clone())); } for (&pos, tile) in &mut self.tiles { @@ -483,7 +484,7 @@ impl Game { &mut self.score, ) { match effect { - TickEffect::Progress(warn) => self.packet_out.push_back(PacketC::SetProgress { + TickEffect::Progress(warn) => packet_out.push_back(PacketC::SetProgress { warn, item: ItemLocation::Tile(pos), progress: tile @@ -495,7 +496,7 @@ impl Game { .map(|i| i.progress), }), TickEffect::Produce => { - self.packet_out.push_back(PacketC::SetItem { + packet_out.push_back(PacketC::SetItem { location: ItemLocation::Tile(pos), item: tile.item.as_ref().map(|i| i.kind), }); @@ -522,7 +523,7 @@ impl Game { }); for (&pid, player) in &mut self.players { - self.packet_out.push_back(PacketC::Position { + packet_out.push_back(PacketC::Position { player: pid, pos: player.movement.position, boosting: player.movement.boosting, @@ -532,7 +533,7 @@ impl Game { if let Some(effect) = tick_slot(dt, &self.data, None, &mut player.item, &mut self.score) { match effect { - TickEffect::Progress(warn) => self.packet_out.push_back(PacketC::SetProgress { + TickEffect::Progress(warn) => packet_out.push_back(PacketC::SetProgress { warn, item: ItemLocation::Player(pid), progress: player @@ -544,7 +545,7 @@ impl Game { .map(|i| i.progress), }), TickEffect::Produce => { - self.packet_out.push_back(PacketC::SetItem { + packet_out.push_back(PacketC::SetItem { location: ItemLocation::Player(pid), item: player.item.as_ref().map(|i| i.kind), }); @@ -568,11 +569,16 @@ impl Game { } } for pid in players_auto_release.drain(..) { - let _ = self.packet_in(pid, PacketS::Interact { pos: None }, &mut vec![]); + let _ = self.packet_in( + pid, + PacketS::Interact { pos: None }, + &mut vec![], + packet_out, + ); } for entity in self.entities.clone().write().unwrap().iter_mut() { - if let Err(e) = entity.tick(self, dt) { + if let Err(e) = entity.tick(self, packet_out, dt) { warn!("entity tick failed: {e}") } } @@ -580,8 +586,7 @@ impl Game { if let Some(end) = self.end { self.score.time_remaining = (end - Instant::now()).as_secs_f64(); if end < Instant::now() { - self.packet_out - .push_back(PacketC::Menu(Menu::Score(self.score.clone()))); + packet_out.push_back(PacketC::Menu(Menu::Score(self.score.clone()))); true } else { false diff --git a/server/src/state.rs b/server/src/state.rs index 3492e6e7..82540fd6 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -20,11 +20,12 @@ use anyhow::{anyhow, bail, Result}; use clap::{Parser, ValueEnum}; use hurrycurry_protocol::{Message, PacketC, PacketS, PlayerID}; use log::{debug, trace}; -use std::time::Duration; +use std::{collections::VecDeque, time::Duration}; use tokio::sync::broadcast::Sender; pub struct State { index: DataIndex, + packet_out: VecDeque<PacketC>, tx: Sender<PacketC>, pub game: Game, } @@ -74,24 +75,37 @@ impl State { let mut index = DataIndex::default(); index.reload()?; + let mut packet_out = VecDeque::new(); let mut game = Game::new(); - game.load(index.generate("lobby-none".to_string()).await?, None); + game.load( + index.generate("lobby-none".to_string()).await?, + None, + &mut packet_out, + ); - Ok(Self { game, index, tx }) + Ok(Self { + game, + index, + tx, + packet_out, + }) } pub async fn tick(&mut self, dt: f32) -> anyhow::Result<()> { - if self.game.tick(dt) { - self.game - .load(self.index.generate("lobby-none".to_string()).await?, None); + if self.game.tick(dt, &mut self.packet_out) { + self.game.load( + self.index.generate("lobby-none".to_string()).await?, + None, + &mut self.packet_out, + ); } - while let Some(p) = self.game.packet_out.pop_front() { + while let Some(p) = self.packet_out.pop_front() { if matches!(p, PacketC::UpdateMap { .. } | PacketC::Position { .. }) { trace!("-> {p:?}"); } else { debug!("-> {p:?}"); } - let _ = self.tx.send(p); + self.tx.send(p).unwrap(); } Ok(()) } @@ -113,15 +127,19 @@ impl State { } _ => (), } - self.game.packet_in(player, packet, &mut replies)?; + self.game + .packet_in(player, packet, &mut replies, &mut self.packet_out)?; if self.game.players.is_empty() && !self.game.lobby { self.tx .send(PacketC::ServerMessage { text: "Game was aborted automatically due to a lack of players".to_string(), }) .ok(); - self.game - .load(self.index.generate("lobby-none".to_string()).await?, None); + self.game.load( + self.index.generate("lobby-none".to_string()).await?, + None, + &mut self.packet_out, + ); } Ok(replies) } @@ -143,7 +161,8 @@ impl State { match command { Command::Start { spec, timer } => { let data = self.index.generate(spec).await?; - self.game.load(data, Some(Duration::from_secs(timer))); + self.game + .load(data, Some(Duration::from_secs(timer)), &mut self.packet_out); } Command::End => { self.tx @@ -158,8 +177,11 @@ impl State { ), }) .ok(); - self.game - .load(self.index.generate("lobby-none".to_string()).await?, None); + self.game.load( + self.index.generate("lobby-none".to_string()).await?, + None, + &mut self.packet_out, + ); } Command::Reload => { if self.game.count_chefs() > 1 { @@ -168,6 +190,7 @@ impl State { self.game.load( self.index.generate(self.game.data.spec.to_string()).await?, None, + &mut self.packet_out, ); } Command::ReloadIndex => { |