aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-03-10 23:59:25 +0100
committermetamuffin <metamuffin@disroot.org>2026-03-10 23:59:25 +0100
commit1383cf5dac9d1471034ec491e122dfef6cf9999c (patch)
treec96f9f554b7752c7c31c8e72e32459b3282ec3b7 /server
parentc49f0a8afd405e5fe8f0ed79c034f9a9b80674cf (diff)
downloadhurrycurry-1383cf5dac9d1471034ec491e122dfef6cf9999c.tar
hurrycurry-1383cf5dac9d1471034ec491e122dfef6cf9999c.tar.bz2
hurrycurry-1383cf5dac9d1471034ec491e122dfef6cf9999c.tar.zst
clean up server code, move some code to game behaviour crate
Diffstat (limited to 'server')
-rw-r--r--server/game-core/src/lib.rs134
-rw-r--r--server/src/server.rs166
-rw-r--r--server/src/state.rs2
3 files changed, 144 insertions, 158 deletions
diff --git a/server/game-core/src/lib.rs b/server/game-core/src/lib.rs
index faecb9d1..21315a07 100644
--- a/server/game-core/src/lib.rs
+++ b/server/game-core/src/lib.rs
@@ -316,4 +316,138 @@ impl Game {
self.player_id_counter += 1;
PlayerID(self.player_id_counter)
}
+
+ pub fn prime_client(&self) -> Vec<PacketC> {
+ let mut out = Vec::new();
+ out.push(PacketC::GameData({
+ let mut k = self.data.as_ref().to_owned();
+ k.recipes.clear();
+ k.demands.clear();
+ k
+ }));
+ out.push(PacketC::Environment {
+ effects: self.environment_effects.clone(),
+ });
+ for (&id, player) in &self.players {
+ out.push(PacketC::AddPlayer {
+ id,
+ class: player.class,
+ position: player.movement.position,
+ character: player.character,
+ name: player.name.clone(),
+ });
+ for (i, item) in player.items.iter().enumerate() {
+ if let Some(item) = &item {
+ out.push(PacketC::SetItem {
+ location: ItemLocation::Player(id, Hand(i)),
+ item: Some(item.kind),
+ });
+ if let Some(Involvement {
+ players: player,
+ position,
+ speed,
+ warn,
+ ..
+ }) = item.active.clone()
+ {
+ out.push(PacketC::SetProgress {
+ players: player,
+ item: ItemLocation::Player(id, Hand(i)),
+ position,
+ speed,
+ warn,
+ });
+ }
+ }
+ }
+ if let Some((message, timeout)) = &player.communicate_persist {
+ out.push(PacketC::Communicate {
+ player: id,
+ message: Some(message.to_owned()),
+ timeout: Some(*timeout),
+ })
+ }
+ }
+ out.push(PacketC::UpdateMap {
+ changes: self
+ .tiles
+ .iter()
+ .map(|(pos, tile)| (*pos, tile.parts.clone()))
+ .collect(),
+ });
+ for (&tile, tdata) in &self.tiles {
+ if let Some(item) = &tdata.item {
+ out.push(PacketC::SetItem {
+ location: ItemLocation::Tile(tile),
+ item: Some(item.kind),
+ });
+ if let Some(Involvement {
+ players,
+ position,
+ speed,
+ warn,
+ ..
+ }) = item.active.clone()
+ {
+ out.push(PacketC::SetProgress {
+ players: players.to_owned(),
+ item: ItemLocation::Tile(tile),
+ position,
+ speed,
+ warn,
+ });
+ }
+ }
+ }
+ out.push(PacketC::Score(self.score.clone()));
+ out.push(PacketC::SetIngame {
+ state: true,
+ lobby: self.lobby,
+ });
+ out
+ }
+
+ pub 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.players_spatial_index.remove_entry(id);
+ packet_out.push_back(PacketC::RemovePlayer { id })
+ }
+ packet_out.push_back(PacketC::UpdateMap {
+ changes: self.tiles.keys().map(|&p| (p, Vec::new())).collect(),
+ });
+ self.tiles.clear();
+ self.score = Score::default();
+ self.environment_effects.clear();
+ self.walkable.clear();
+ self.tile_index.clear();
+ self.item_locations_index.clear();
+ }
+
+ pub fn remove_player(&mut self, id: PlayerID) -> bool {
+ let Some(p) = self.players.remove(&id) else {
+ return false;
+ };
+ for (hand, item) in p.items.into_iter().enumerate() {
+ if let Some(item) = item {
+ self.item_locations_index
+ .remove(&ItemLocation::Player(id, Hand(hand)));
+ let pos = p.movement.position.floor().as_ivec2();
+ if let Some(tile) = self.tiles.get_mut(&pos)
+ && tile.item.is_none()
+ {
+ self.events.push_back(PacketC::SetItem {
+ location: ItemLocation::Tile(pos),
+ item: Some(item.kind),
+ });
+ tile.item = Some(item);
+ }
+ }
+ }
+ self.events.push_back(PacketC::RemovePlayer { id });
+ true
+ }
}
diff --git a/server/src/server.rs b/server/src/server.rs
index 27ad86a7..efa3fba3 100644
--- a/server/src/server.rs
+++ b/server/src/server.rs
@@ -22,7 +22,7 @@ use crate::{
};
use anyhow::{Context, Result, anyhow};
use hurrycurry_data::{PrivateGamedata, build_gamedata, map_list};
-use hurrycurry_game_core::{Game, Involvement, Item, Player, Tile};
+use hurrycurry_game_core::{Game, Item, Player};
use hurrycurry_locale::{
GLOBAL_LOCALE, TrError,
message::{COLORED, MessageDisplayExt},
@@ -129,7 +129,6 @@ impl Default for ServerConfig {
}
pub trait GameServerExt {
- fn unload(&mut self, packet_out: &mut VecDeque<PacketC>);
fn load(
&mut self,
gamedata: Gamedata,
@@ -149,28 +148,8 @@ pub trait GameServerExt {
custom_position: Option<Vec2>,
packet_out: Option<&mut VecDeque<PacketC>>,
);
- fn prime_client(&self) -> Vec<PacketC>;
}
impl GameServerExt for Game {
- 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.players_spatial_index.remove_entry(id);
- packet_out.push_back(PacketC::RemovePlayer { id })
- }
- packet_out.push_back(PacketC::UpdateMap {
- changes: self.tiles.keys().map(|&p| (p, Vec::new())).collect(),
- });
- self.tiles.clear();
- self.score = Score::default();
- self.environment_effects.clear();
- self.walkable.clear();
- self.tile_index.clear();
- self.item_locations_index.clear();
- }
fn load(
&mut self,
gamedata: Gamedata,
@@ -196,25 +175,10 @@ impl GameServerExt for Game {
..Default::default()
};
- for (&p, (tiles, item)) in &serverdata.initial_map {
- self.tiles.insert(
- p,
- Tile {
- parts: tiles.to_vec(),
- item: item.map(|i| Item {
- kind: i,
- active: None,
- }),
- },
- );
- if !self.data.walkable(tiles) {
- self.walkable.insert(p);
- }
- for tile in tiles {
- self.tile_index.entry(*tile).or_default().insert(p);
- }
+ for (&pos, (parts, item)) in &serverdata.initial_map {
+ self.set_tile(pos, parts.to_vec());
if item.is_some() {
- self.item_locations_index.insert(ItemLocation::Tile(p));
+ self.set_item(pos, *item);
}
}
for (id, (name, character, class)) in players {
@@ -224,96 +188,6 @@ impl GameServerExt for Game {
packet_out.extend(self.prime_client());
}
- fn prime_client(&self) -> Vec<PacketC> {
- let mut out = Vec::new();
- out.push(PacketC::GameData({
- let mut k = self.data.as_ref().to_owned();
- k.recipes.clear();
- k.demands.clear();
- k
- }));
- out.push(PacketC::Environment {
- effects: self.environment_effects.clone(),
- });
- for (&id, player) in &self.players {
- out.push(PacketC::AddPlayer {
- id,
- class: player.class,
- position: player.movement.position,
- character: player.character,
- name: player.name.clone(),
- });
- for (i, item) in player.items.iter().enumerate() {
- if let Some(item) = &item {
- out.push(PacketC::SetItem {
- location: ItemLocation::Player(id, Hand(i)),
- item: Some(item.kind),
- });
- if let Some(Involvement {
- players: player,
- position,
- speed,
- warn,
- ..
- }) = item.active.clone()
- {
- out.push(PacketC::SetProgress {
- players: player,
- item: ItemLocation::Player(id, Hand(i)),
- position,
- speed,
- warn,
- });
- }
- }
- }
- if let Some((message, timeout)) = &player.communicate_persist {
- out.push(PacketC::Communicate {
- player: id,
- message: Some(message.to_owned()),
- timeout: Some(*timeout),
- })
- }
- }
- out.push(PacketC::UpdateMap {
- changes: self
- .tiles
- .iter()
- .map(|(pos, tile)| (*pos, tile.parts.clone()))
- .collect(),
- });
- for (&tile, tdata) in &self.tiles {
- if let Some(item) = &tdata.item {
- out.push(PacketC::SetItem {
- location: ItemLocation::Tile(tile),
- item: Some(item.kind),
- });
- if let Some(Involvement {
- players,
- position,
- speed,
- warn,
- ..
- }) = item.active.clone()
- {
- out.push(PacketC::SetProgress {
- players: players.to_owned(),
- item: ItemLocation::Tile(tile),
- position,
- speed,
- warn,
- });
- }
- }
- }
- out.push(PacketC::Score(self.score.clone()));
- out.push(PacketC::SetIngame {
- state: true,
- lobby: self.lobby,
- });
- out
- }
-
fn join_player(
&mut self,
id: PlayerID,
@@ -473,34 +347,12 @@ impl Server {
} else {
info!("Server removes {player}");
}
- let p = self
- .game
- .players
- .remove(&player)
- .ok_or(tre!("s.error.no_player"))?;
-
- self.game.players_spatial_index.remove_entry(player);
-
- // ! if holding two, one is destroyed
- for (hand, item) in p.items.into_iter().enumerate() {
- if let Some(item) = item {
- self.game
- .item_locations_index
- .remove(&ItemLocation::Player(player, Hand(hand)));
- let pos = p.movement.position.floor().as_ivec2();
- if let Some(tile) = self.game.tiles.get_mut(&pos)
- && tile.item.is_none()
- {
- self.packet_out.push_back(PacketC::SetItem {
- location: ItemLocation::Tile(pos),
- item: Some(item.kind),
- });
- tile.item = Some(item);
- }
- }
+ if !self.game.remove_player(player) {
+ return Err(tre!("s.error.no_player"));
}
- self.packet_out
- .push_back(PacketC::RemovePlayer { id: player })
+ self.game.players_spatial_index.remove_entry(player);
+ self.player_inactivity_timers.remove(&player);
+ self.last_movement_update.remove(&player);
}
PacketS::Effect { player, name } => {
self.packet_out.push_back(PacketC::Effect2 {
diff --git a/server/src/state.rs b/server/src/state.rs
index 83d04d16..04458aea 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -17,7 +17,7 @@
*/
use crate::{
ConnectionID,
- server::{AnnounceState, ConnectionData, GameServerExt, Server},
+ server::{AnnounceState, ConnectionData, Server},
};
use anyhow::Result;
use hurrycurry_data::build_gamedata;