diff options
Diffstat (limited to 'server/src/game.rs')
-rw-r--r-- | server/src/game.rs | 128 |
1 files changed, 65 insertions, 63 deletions
diff --git a/server/src/game.rs b/server/src/game.rs index 9a01e4a3..21bb5f33 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -25,8 +25,8 @@ use anyhow::{anyhow, bail, Result}; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, movement::MovementBase, - ClientGamedata, ItemIndex, ItemLocation, Message, PacketC, PacketS, PlayerID, RecipeIndex, - TileIndex, + ClientGamedata, ItemIndex, ItemLocation, Menu, Message, PacketC, PacketS, PlayerID, + RecipeIndex, Score, TileIndex, }; use log::{info, warn}; use std::{ @@ -72,15 +72,12 @@ 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, pub score_changed: bool, - pub points: i64, - pub demands_failed: usize, - pub demands_completed: usize, + pub score: Score, } impl Default for Game { @@ -94,30 +91,27 @@ impl Game { Self { lobby: false, data: Gamedata::default().into(), - packet_out: Default::default(), players: HashMap::new(), tiles: HashMap::new(), walkable: HashSet::new(), end: None, entities: Arc::new(RwLock::new(vec![])), players_spatial_index: SpatialIndex::default(), - points: 0, - demands_failed: 0, - demands_completed: 0, + score: Score::default(), score_changed: false, } } - 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], @@ -125,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() @@ -133,11 +132,11 @@ 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(); - self.points = 0; + self.score = Score::default(); self.end = timer.map(|dur| Instant::now() + dur); self.entities = Arc::new(RwLock::new(self.data.entities.clone())); @@ -184,11 +183,7 @@ impl Game { ); } - self.packet_out.extend(self.prime_client()); - } - - pub fn packet_out(&mut self) -> Option<PacketC> { - self.packet_out.pop_front() + packet_out.extend(self.prime_client()); } pub fn prime_client(&self) -> Vec<PacketC> { @@ -256,7 +251,7 @@ impl Game { }) } } - out.push(self.score()); + out.push(PacketC::Score(self.score.clone())); out.push(PacketC::SetIngame { state: true, lobby: self.lobby, @@ -264,22 +259,13 @@ impl Game { out } - pub fn score(&self) -> PacketC { - PacketC::Score { - time_remaining: self.end.map(|t| (t - Instant::now()).as_secs_f32()), - points: self.points, - demands_failed: self.demands_failed, - demands_completed: self.demands_completed, - } - } pub fn packet_in( &mut self, player: PlayerID, packet: PacketS, replies: &mut Vec<PacketC>, + packet_out: &mut VecDeque<PacketC>, ) -> Result<()> { - let points_before = self.points; - match packet { PacketS::Join { name, character } => { if self.players.contains_key(&player) { @@ -315,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, @@ -334,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), }); @@ -342,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, @@ -370,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; @@ -428,8 +412,8 @@ impl Game { &mut other.item, ItemLocation::Player(pid), None, - &mut self.packet_out, - &mut self.points, + packet_out, + &mut self.score, false, ) } else { @@ -446,8 +430,8 @@ impl Game { &mut player.item, ItemLocation::Player(pid), Some(tile.kind), - &mut self.packet_out, - &mut self.points, + packet_out, + &mut self.score, false, ) } @@ -459,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, @@ -474,31 +458,33 @@ impl Game { kind: i, active: None, }); - self.packet_out.push_back(PacketC::SetItem { + packet_out.push_back(PacketC::SetItem { location: ItemLocation::Player(player), item, }) } PacketS::ReplayTick { .. } => bail!("packet not supported in this session"), } - - if self.points != points_before { - self.packet_out.push_back(self.score()) - } Ok(()) } /// 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(self.score()); + packet_out.push_back(PacketC::Score(self.score.clone())); } for (&pos, tile) in &mut self.tiles { - if let Some(effect) = tick_slot(dt, &self.data, Some(tile.kind), &mut tile.item) { + if let Some(effect) = tick_slot( + dt, + &self.data, + Some(tile.kind), + &mut tile.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::Tile(pos), progress: tile @@ -510,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), }); @@ -537,16 +523,17 @@ 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, rot: player.movement.rotation, }); - if let Some(effect) = tick_slot(dt, &self.data, None, &mut player.item) { + 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 @@ -558,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), }); @@ -582,16 +569,31 @@ 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}") } } - self.end.map(|t| t < Instant::now()).unwrap_or_default() + if let Some(end) = self.end { + self.score.time_remaining = (end - Instant::now()).as_secs_f64(); + if end < Instant::now() { + packet_out.push_back(PacketC::Menu(Menu::Score(self.score.clone()))); + true + } else { + false + } + } else { + false + } } pub fn count_chefs(&self) -> usize { @@ -617,13 +619,13 @@ pub fn interact_effect( other_loc: ItemLocation, this_tile_kind: Option<TileIndex>, packet_out: &mut VecDeque<PacketC>, - points: &mut i64, + score: &mut Score, automated: bool, ) { let this_had_item = this.is_some(); let other_had_item = other.is_some(); - if let Some(effect) = interact(data, edge, this_tile_kind, this, other, points, automated) { + if let Some(effect) = interact(data, edge, this_tile_kind, this, other, score, automated) { match effect { InteractEffect::Put => { info!("put {this_loc} <- {other_loc}"); |