summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-20 19:29:41 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-20 19:29:41 +0200
commit1a45b0e0f5de785ddf268d7371f0cdaeafe9daa7 (patch)
tree5712d2d0784da660733e41d1b69636127b71c3b3 /server
parent89ba8a6b62b90ac72547e2ca9ea5eeae7bbc6500 (diff)
downloadhurrycurry-1a45b0e0f5de785ddf268d7371f0cdaeafe9daa7.tar
hurrycurry-1a45b0e0f5de785ddf268d7371f0cdaeafe9daa7.tar.bz2
hurrycurry-1a45b0e0f5de785ddf268d7371f0cdaeafe9daa7.tar.zst
refactor score code (and break things)
Diffstat (limited to 'server')
-rw-r--r--server/protocol/src/lib.rs28
-rw-r--r--server/src/entity/conveyor.rs2
-rw-r--r--server/src/entity/customers/mod.rs8
-rw-r--r--server/src/entity/portal.rs2
-rw-r--r--server/src/game.rs69
-rw-r--r--server/src/interaction.rs10
-rw-r--r--server/src/state.rs7
7 files changed, 69 insertions, 57 deletions
diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs
index cf422761..61efd74f 100644
--- a/server/protocol/src/lib.rs
+++ b/server/protocol/src/lib.rs
@@ -193,12 +193,7 @@ pub enum PacketC {
ServerMessage {
text: String,
},
- Score {
- points: i64,
- demands_failed: usize,
- demands_completed: usize,
- time_remaining: Option<f32>,
- },
+ Score(Score),
SetIngame {
state: bool,
lobby: bool,
@@ -206,12 +201,33 @@ pub enum PacketC {
Error {
message: String,
},
+ Menu(Menu),
MovementSync,
/// For use in replay sessions only
ReplayStart,
}
+#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
+#[serde(rename_all = "snake_case", tag = "type", content = "data")]
+pub enum Menu {
+ Book,
+ Score(Score),
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Default)]
+pub struct Score {
+ pub time_remaining: f64,
+ pub stars: u8,
+ pub points: i64,
+ pub demands_failed: usize,
+ pub demands_completed: usize,
+ pub players: usize,
+ pub active_recipes: usize,
+ pub passive_recipes: usize,
+ pub instant_recipes: usize,
+}
+
#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Copy, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ItemLocation {
diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs
index 6067c679..38478db7 100644
--- a/server/src/entity/conveyor.rs
+++ b/server/src/entity/conveyor.rs
@@ -72,7 +72,7 @@ impl EntityT for Conveyor {
ItemLocation::Tile(self.from),
Some(to.kind),
&mut game.packet_out,
- &mut game.points,
+ &mut game.score,
true,
);
}
diff --git a/server/src/entity/customers/mod.rs b/server/src/entity/customers/mod.rs
index 7a8280bc..e8679dc9 100644
--- a/server/src/entity/customers/mod.rs
+++ b/server/src/entity/customers/mod.rs
@@ -151,8 +151,8 @@ impl EntityT for Customers {
)
.expect("no path to exit");
*self.chairs.get_mut(chair).unwrap() = true;
- game.demands_failed += 1;
- game.points -= 1;
+ game.score.demands_failed += 1;
+ game.score.points -= 1;
game.score_changed = true;
info!("{id:?} -> exiting");
*state = CustomerState::Exiting { path }
@@ -232,8 +232,8 @@ impl EntityT for Customers {
)
.ok_or(anyhow!("no path to exit"))?;
*self.chairs.get_mut(chair).unwrap() = true;
- game.demands_completed += 1;
- game.points += demand.points;
+ game.score.demands_completed += 1;
+ game.score.points += demand.points;
game.score_changed = true;
info!("{id:?} -> exiting");
*state = CustomerState::Exiting { path }
diff --git a/server/src/entity/portal.rs b/server/src/entity/portal.rs
index 3aed35ac..2d4a762b 100644
--- a/server/src/entity/portal.rs
+++ b/server/src/entity/portal.rs
@@ -43,7 +43,7 @@ impl EntityT for Portal {
ItemLocation::Tile(self.from),
Some(to.kind),
&mut game.packet_out,
- &mut game.points,
+ &mut game.score,
true,
);
}
diff --git a/server/src/game.rs b/server/src/game.rs
index 9a01e4a3..1f368b00 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::{
@@ -78,9 +78,7 @@ pub struct Game {
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 {
@@ -101,9 +99,7 @@ impl Game {
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,
}
}
@@ -137,7 +133,7 @@ impl Game {
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()));
@@ -187,10 +183,6 @@ impl Game {
self.packet_out.extend(self.prime_client());
}
- pub fn packet_out(&mut self) -> Option<PacketC> {
- self.packet_out.pop_front()
- }
-
pub fn prime_client(&self) -> Vec<PacketC> {
let mut out = Vec::new();
out.push(PacketC::Data {
@@ -256,7 +248,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 +256,12 @@ 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>,
) -> Result<()> {
- let points_before = self.points;
-
match packet {
PacketS::Join { name, character } => {
if self.players.contains_key(&player) {
@@ -429,7 +411,7 @@ impl Game {
ItemLocation::Player(pid),
None,
&mut self.packet_out,
- &mut self.points,
+ &mut self.score,
false,
)
} else {
@@ -447,7 +429,7 @@ impl Game {
ItemLocation::Player(pid),
Some(tile.kind),
&mut self.packet_out,
- &mut self.points,
+ &mut self.score,
false,
)
}
@@ -481,10 +463,6 @@ impl Game {
}
PacketS::ReplayTick { .. } => bail!("packet not supported in this session"),
}
-
- if self.points != points_before {
- self.packet_out.push_back(self.score())
- }
Ok(())
}
@@ -492,11 +470,18 @@ impl Game {
pub fn tick(&mut self, dt: f32) -> bool {
if self.score_changed {
self.score_changed = false;
- self.packet_out.push_back(self.score());
+ self.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 {
warn,
@@ -544,7 +529,8 @@ impl Game {
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 {
warn,
@@ -591,7 +577,18 @@ impl Game {
}
}
- 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() {
+ self.packet_out
+ .push_back(PacketC::Menu(Menu::Score(self.score.clone())));
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ }
}
pub fn count_chefs(&self) -> usize {
@@ -617,13 +614,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}");
diff --git a/server/src/interaction.rs b/server/src/interaction.rs
index 2f6c940a..71125ac4 100644
--- a/server/src/interaction.rs
+++ b/server/src/interaction.rs
@@ -19,7 +19,7 @@ use crate::{
data::Gamedata,
game::{Involvement, Item},
};
-use hurrycurry_protocol::{ItemIndex, TileIndex};
+use hurrycurry_protocol::{ItemIndex, Score, TileIndex};
use log::info;
use serde::{Deserialize, Serialize};
@@ -115,7 +115,7 @@ pub fn interact(
tile: Option<TileIndex>,
this: &mut Option<Item>,
other: &mut Option<Item>,
- points: &mut i64,
+ score: &mut Score,
automated: bool,
) -> Option<InteractEffect> {
let interactable = automated
@@ -180,6 +180,7 @@ pub fn interact(
});
}
*this = Some(item);
+ score.active_recipes += 1;
return Some(InteractEffect::Put);
}
}
@@ -200,7 +201,8 @@ pub fn interact(
let ok_rev = ok_rev as usize;
*other = outputs[1 - ok_rev].map(|kind| Item { kind, active: None });
*this = outputs[ok_rev].map(|kind| Item { kind, active: None });
- *points += pd;
+ score.points += pd;
+ score.instant_recipes += 1;
return Some(InteractEffect::Produce);
}
}
@@ -234,6 +236,7 @@ pub fn tick_slot(
data: &Gamedata,
tile: Option<TileIndex>,
slot: &mut Option<Item>,
+ score: &mut Score,
) -> Option<TickEffect> {
if let Some(item) = slot {
if let Some(a) = &mut item.active {
@@ -246,6 +249,7 @@ pub fn tick_slot(
if a.progress >= 1. {
if let Recipe::Passive { output, .. } = &data.recipe(a.recipe) {
*slot = output.map(|kind| Item { kind, active: None });
+ score.passive_recipes += 1;
return Some(TickEffect::Produce);
};
a.progress = 1.;
diff --git a/server/src/state.rs b/server/src/state.rs
index 61795da4..3492e6e7 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -82,15 +82,10 @@ impl State {
pub async fn tick(&mut self, dt: f32) -> anyhow::Result<()> {
if self.game.tick(dt) {
- self.tx
- .send(PacketC::ServerMessage {
- text: format!("Game finished. You reached {} points.", self.game.points),
- })
- .ok();
self.game
.load(self.index.generate("lobby-none".to_string()).await?, None);
}
- while let Some(p) = self.game.packet_out() {
+ while let Some(p) = self.game.packet_out.pop_front() {
if matches!(p, PacketC::UpdateMap { .. } | PacketC::Position { .. }) {
trace!("-> {p:?}");
} else {