aboutsummaryrefslogtreecommitdiff
path: root/server/src/entity
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-10-06 23:03:32 +0200
committermetamuffin <metamuffin@disroot.org>2025-10-06 23:03:40 +0200
commit176e6bc6c4c29bea3be2aceca99743b997c76c97 (patch)
tree1161e7a966843324756340da4b6452492902fa07 /server/src/entity
parentea86b11b682500160f37b35ea8f06b081cd05036 (diff)
downloadhurrycurry-176e6bc6c4c29bea3be2aceca99743b997c76c97.tar
hurrycurry-176e6bc6c4c29bea3be2aceca99743b997c76c97.tar.bz2
hurrycurry-176e6bc6c4c29bea3be2aceca99743b997c76c97.tar.zst
Move data code to own crate + general data refactor
Diffstat (limited to 'server/src/entity')
-rw-r--r--server/src/entity/campaign.rs28
-rw-r--r--server/src/entity/conveyor.rs23
-rw-r--r--server/src/entity/customers.rs6
-rw-r--r--server/src/entity/environment_effect.rs14
-rw-r--r--server/src/entity/mod.rs157
5 files changed, 40 insertions, 188 deletions
diff --git a/server/src/entity/campaign.rs b/server/src/entity/campaign.rs
index 53ea6582..fdc169d1 100644
--- a/server/src/entity/campaign.rs
+++ b/server/src/entity/campaign.rs
@@ -18,16 +18,16 @@
use super::{Entity, EntityContext};
use crate::{scoreboard::ScoreboardStore, server::GameServerExt};
use anyhow::Result;
+use hurrycurry_data::entities::GateCondition;
use hurrycurry_locale::{trm, TrError};
use hurrycurry_protocol::{
glam::{IVec2, Vec2},
Message, PacketC, PlayerID, TileIndex,
};
-use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone)]
pub struct Map {
- pub location: Vec2,
+ pub pos: Vec2,
pub name: String,
}
@@ -36,7 +36,7 @@ impl Entity for Map {
let mut activate = false;
c.game
.players_spatial_index
- .query(self.location, 0.5, |_, _| activate = true);
+ .query(self.pos, 0.5, |_, _| activate = true);
if activate {
*c.load_map = Some(self.name.clone());
@@ -46,19 +46,11 @@ impl Entity for Map {
}
}
-#[derive(Debug, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "kebab-case")]
-pub enum GateCondition {
- All(Vec<GateCondition>),
- Any(Vec<GateCondition>),
- Stars(String, u8),
-}
-
#[derive(Debug, Clone)]
pub struct Gate {
pub active: bool,
pub unlocked: bool,
- pub location: IVec2,
+ pub pos: IVec2,
pub blocker_tile: TileIndex,
pub condition: GateCondition,
}
@@ -69,7 +61,7 @@ impl Entity for Gate {
self.unlocked = self.condition.check(c.scoreboard);
if !self.unlocked {
c.game
- .set_tile(self.location, Some(self.blocker_tile), c.packet_out);
+ .set_tile(self.pos, Some(self.blocker_tile), c.packet_out);
c.packet_out.push_back(PacketC::FlushMap); // TODO dont send too often
}
}
@@ -81,7 +73,7 @@ impl Entity for Gate {
pos: Option<IVec2>,
_player: PlayerID,
) -> Result<bool, TrError> {
- if !self.unlocked && pos == Some(self.location) {
+ if !self.unlocked && pos == Some(self.pos) {
c.packet_out.push_back(PacketC::ServerMessage {
message: trm!(
"s.campaign.unlock_condition",
@@ -95,7 +87,11 @@ impl Entity for Gate {
}
}
-impl GateCondition {
+trait GateConditionExt {
+ fn check(&self, scoreboard: &ScoreboardStore) -> bool;
+ fn show(&self, scoreboard: &ScoreboardStore) -> Message;
+}
+impl GateConditionExt for GateCondition {
fn check(&self, scoreboard: &ScoreboardStore) -> bool {
match self {
GateCondition::All(cs) => cs.iter().all(|c| c.check(scoreboard)),
@@ -105,7 +101,7 @@ impl GateCondition {
.is_some_and(|s| s.best.first().is_some_and(|b| b.score.stars >= *thres)),
}
}
- pub fn show(&self, scoreboard: &ScoreboardStore) -> Message {
+ fn show(&self, scoreboard: &ScoreboardStore) -> Message {
match self {
GateCondition::All(cs) => cs
.iter()
diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs
index 9c7f5e4d..e31410e3 100644
--- a/server/src/entity/conveyor.rs
+++ b/server/src/entity/conveyor.rs
@@ -18,14 +18,12 @@
use super::{Entity, EntityContext};
use crate::interaction::interact;
use anyhow::{anyhow, bail, Result};
-use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation};
+use hurrycurry_protocol::{glam::IVec2, ItemLocation};
#[derive(Debug, Clone)]
pub struct Conveyor {
pub(super) from: IVec2,
pub(super) to: IVec2,
- pub(super) filter_tile: Option<IVec2>,
- pub(super) filter_item: Option<ItemIndex>,
pub(super) cooldown: f32,
pub(super) max_cooldown: f32,
}
@@ -38,24 +36,7 @@ impl Entity for Conveyor {
.get(&self.from)
.ok_or(anyhow!("conveyor from missing"))?;
- if let Some(from_item) = from.item.as_ref() {
- let filter = if let Some(t) = &self.filter_tile {
- let filter_tile = c
- .game
- .tiles
- .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)
- };
-
- if let Some(filter) = filter {
- if from_item.kind != filter {
- return Ok(());
- }
- }
-
+ if from.item.is_some() {
self.cooldown += c.dt;
if self.cooldown < self.max_cooldown {
return Ok(());
diff --git a/server/src/entity/customers.rs b/server/src/entity/customers.rs
index e3a23830..22522e4e 100644
--- a/server/src/entity/customers.rs
+++ b/server/src/entity/customers.rs
@@ -29,13 +29,13 @@ pub struct Customers {
}
impl Customers {
- pub fn new(scaling_factor: f32) -> Result<Self> {
- Ok(Self {
+ pub fn new(scaling_factor: f32) -> Self {
+ Self {
customers: Default::default(),
spawn_cooldown: 0.,
chair_count: None,
scaling_factor,
- })
+ }
}
}
diff --git a/server/src/entity/environment_effect.rs b/server/src/entity/environment_effect.rs
index 95040954..ba2c395e 100644
--- a/server/src/entity/environment_effect.rs
+++ b/server/src/entity/environment_effect.rs
@@ -16,23 +16,11 @@
*/
use super::{Entity, EntityContext};
+use hurrycurry_data::entities::EnvironmentEffect;
use hurrycurry_protocol::PacketC;
use rand::random;
-use serde::{Deserialize, Serialize};
use std::time::{Duration, Instant};
-#[derive(Clone, Debug, Deserialize, Serialize, Default)]
-pub struct EnvironmentEffect {
- name: String,
- #[serde(default = "default_onoff")]
- on: f32,
- #[serde(default = "default_onoff")]
- off: f32,
-}
-fn default_onoff() -> f32 {
- 40.
-}
-
#[derive(Clone, Debug)]
pub struct EnvironmentEffectController {
config: EnvironmentEffect,
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs
index 928910bc..47d37f3d 100644
--- a/server/src/entity/mod.rs
+++ b/server/src/entity/mod.rs
@@ -27,26 +27,19 @@ pub mod player_portal;
pub mod tram;
pub mod tutorial;
-use crate::{
- data::{ItemTileRegistry, Serverdata},
- entity::pedestrians::Pedestrians,
- scoreboard::ScoreboardStore,
-};
-use anyhow::{anyhow, Result};
+use crate::{entity::pedestrians::Pedestrians, scoreboard::ScoreboardStore};
+use anyhow::Result;
use book::Book;
-use campaign::{Gate, GateCondition, Map};
+use campaign::{Gate, Map};
use conveyor::Conveyor;
use customers::Customers;
-use environment_effect::{EnvironmentController, EnvironmentEffect, EnvironmentEffectController};
+use environment_effect::{EnvironmentController, EnvironmentEffectController};
use hurrycurry_client_lib::Game;
+use hurrycurry_data::{entities::EntityDecl, Serverdata};
use hurrycurry_locale::TrError;
-use hurrycurry_protocol::{
- glam::{IVec2, Vec2},
- Character, PacketC, PacketS, PlayerID,
-};
+use hurrycurry_protocol::{glam::IVec2, Character, Gamedata, PacketC, PacketS, PlayerID};
use item_portal::ItemPortal;
use player_portal::PlayerPortal;
-use serde::{Deserialize, Serialize};
use std::{
any::Any,
collections::{HashMap, VecDeque},
@@ -87,135 +80,29 @@ pub trait Entity: Any {
}
}
-// macro_rules! entities {
-// ($($e:ident),*) => {
-// pub enum DynEntity { $($e($e)),* }
-// impl Entity for DynEntity {
-// fn tick(&mut self, c: EntityContext<'_>) -> Result<()> {
-// match self { $(DynEntity::$e(x) => x.tick(c)),*, }
-// }
-// fn destructor(&mut self, c: EntityContext<'_>) {
-// match self { $(DynEntity::$e(x) => x.destructor(c)),*, }
-// }
-// }
-// };
-// }
-// entities!(
-// Conveyor,
-// ItemPortal,
-// PlayerPortal,
-// Customers,
-// EnvironmentEffectController,
-// EnvironmentController
-// );
-
-#[derive(Debug, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "snake_case")]
-pub enum EntityDecl {
- Conveyor {
- from: Option<IVec2>,
- to: Option<IVec2>,
- filter_dir: Option<IVec2>,
- filter: Option<String>,
- dir: Option<IVec2>,
- speed: Option<f32>,
- },
- ItemPortal {
- from: Option<IVec2>,
- to: IVec2,
- },
- PlayerPortal {
- from: Option<Vec2>,
- to: Vec2,
- },
- Customers {
- scaling_factor: Option<f32>,
- },
- Map {
- name: String,
- location: Option<Vec2>,
- },
- EnvironmentEffect(EnvironmentEffect),
- Environment(Vec<String>),
- Gate {
- location: Option<IVec2>,
- condition: GateCondition,
- },
- Tram {
- length: usize,
- color: Option<i32>,
- points: Vec<Vec2>,
- spacing: f32,
- smoothing: f32,
- },
- Book,
- Pedestrians {
- spawn_delay: f32,
- spawn_delay_stdev: Option<f32>,
- speed: Option<f32>,
- points: Vec<Vec2>,
- },
-}
-
-pub fn construct_entity(
- pos: Option<IVec2>,
- decl: &EntityDecl,
- reg: &ItemTileRegistry,
-) -> Result<DynEntity> {
- Ok(match decl.to_owned() {
- EntityDecl::Book => Box::new(Book(pos.ok_or(anyhow!("book is tile entity"))?)),
- EntityDecl::ItemPortal { from, to } => Box::new(ItemPortal {
- from: from
- .or(pos)
- .ok_or(anyhow!("Item portal start without start"))?,
- to,
- }),
- EntityDecl::PlayerPortal { from, to } => Box::new(PlayerPortal {
- from: from
- .or(pos.map(|v| v.as_vec2()))
- .ok_or(anyhow!("Player portal without start"))?,
- to,
- }),
- EntityDecl::Conveyor {
+pub fn construct_entity(decl: &EntityDecl, data: &Gamedata) -> DynEntity {
+ match decl.to_owned() {
+ EntityDecl::Book { pos } => Box::new(Book(pos)),
+ EntityDecl::ItemPortal { from, to } => Box::new(ItemPortal { from, to }),
+ EntityDecl::PlayerPortal { from, to } => Box::new(PlayerPortal { from, to }),
+ EntityDecl::Conveyor { from, to, speed } => Box::new(Conveyor {
from,
to,
- speed,
- dir,
- filter,
- filter_dir,
- } => {
- let from = from.or(pos).ok_or(anyhow!("Conveyor has no start"))?;
- let to = to
- .or(dir.map(|s| s + from))
- .ok_or(anyhow!("Conveyor has no destination"))?;
- Box::new(Conveyor {
- from,
- to,
- max_cooldown: 1. / speed.unwrap_or(2.),
- filter_tile: filter_dir.map(|o| to + o),
- filter_item: filter.map(|name| reg.register_item(name)),
- cooldown: 0.,
- })
- }
- EntityDecl::Map { name, location } => Box::new(Map {
- location: location
- .or(pos.map(|p| p.as_vec2() + 0.5))
- .ok_or(anyhow!("no location"))?,
- name,
+ max_cooldown: 1. / speed.unwrap_or(2.),
+ cooldown: 0.,
}),
- EntityDecl::Gate {
- condition,
- location,
- } => Box::new(Gate {
+ EntityDecl::Map { name, pos } => Box::new(Map { pos, name }),
+ EntityDecl::Gate { condition, pos } => Box::new(Gate {
condition,
unlocked: false,
- location: location.or(pos).ok_or(anyhow!("no location"))?,
- blocker_tile: reg.register_tile("fence".to_string()),
+ pos,
+ blocker_tile: data
+ .get_tile_by_name("fence")
+ .expect("asserted earlier (tm)"),
active: true,
}),
EntityDecl::Customers { scaling_factor } => {
- reg.register_item("unknown-order".to_owned());
- Box::new(Customers::new(scaling_factor.unwrap_or(0.5))?)
+ Box::new(Customers::new(scaling_factor.unwrap_or(0.5)))
}
EntityDecl::EnvironmentEffect(config) => Box::new(EnvironmentEffectController::new(config)),
EntityDecl::Environment(names) => Box::new(EnvironmentController(names)),
@@ -254,5 +141,5 @@ pub fn construct_entity(
cooldown: 0.,
speed: speed.unwrap_or(0.6),
}),
- })
+ }
}