summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-08-13 13:25:14 +0200
committermetamuffin <metamuffin@disroot.org>2024-08-13 16:03:38 +0200
commita8376aab4159a449a205de3ed7fdcaa5f6ca6369 (patch)
tree18683ebb64f9d41fb856d5e302f537785bb03f3d /server/src
parent16ff78180669411326d42ea32d4a9260c018236c (diff)
downloadhurrycurry-a8376aab4159a449a205de3ed7fdcaa5f6ca6369.tar
hurrycurry-a8376aab4159a449a205de3ed7fdcaa5f6ca6369.tar.bz2
hurrycurry-a8376aab4159a449a205de3ed7fdcaa5f6ca6369.tar.zst
access entities as trait object
Diffstat (limited to 'server/src')
-rw-r--r--server/src/bin/graph.rs2
-rw-r--r--server/src/data.rs11
-rw-r--r--server/src/entity/bot.rs13
-rw-r--r--server/src/entity/conveyor.rs4
-rw-r--r--server/src/entity/customers/mod.rs4
-rw-r--r--server/src/entity/environment_effect.rs6
-rw-r--r--server/src/entity/item_portal.rs4
-rw-r--r--server/src/entity/mod.rs70
-rw-r--r--server/src/entity/player_portal.rs4
-rw-r--r--server/src/server.rs12
10 files changed, 76 insertions, 54 deletions
diff --git a/server/src/bin/graph.rs b/server/src/bin/graph.rs
index 62dc47a2..c16bfe2d 100644
--- a/server/src/bin/graph.rs
+++ b/server/src/bin/graph.rs
@@ -30,7 +30,7 @@ async fn main() -> Result<()> {
.nth(1)
.ok_or(anyhow!("first arg should be recipe set name"))?;
- let (data, _) = index.generate(format!("sushibar-{rn}")).await?;
+ let (data, _, _) = index.generate(format!("sushibar-{rn}")).await?;
for i in 0..data.item_names.len() {
println!("i{i} [label=\"{}\"]", data.item_name(ItemIndex(i)))
diff --git a/server/src/data.rs b/server/src/data.rs
index f0a85cca..021de525 100644
--- a/server/src/data.rs
+++ b/server/src/data.rs
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::entity::{construct_entity, Entity, EntityDecl};
+use crate::entity::{construct_entity, Entities, EntityDecl};
use anyhow::{anyhow, bail, Result};
use hurrycurry_protocol::{
glam::{IVec2, Vec2},
@@ -97,7 +97,7 @@ pub struct Demand {
pub points: i64,
}
-#[derive(Debug, Clone, Default)]
+#[derive(Debug,Clone, Default)]
#[rustfmt::skip]
pub struct Serverdata {
pub spec: String,
@@ -105,7 +105,6 @@ pub struct Serverdata {
pub chef_spawn: Vec2,
pub customer_spawn: Vec2,
pub score_baseline: i64,
- pub entities: Vec<Entity>,
}
#[derive(Debug, Deserialize, Default)]
@@ -144,7 +143,7 @@ impl DataIndex {
Ok(read_to_string(path).await?)
}
- pub async fn generate(&self, spec: String) -> Result<(Gamedata, Serverdata)> {
+ pub async fn generate(&self, spec: String) -> Result<(Gamedata, Serverdata, Entities)> {
let (map, recipes) = spec.split_once("-").unwrap_or((spec.as_str(), "default"));
let map_in = serde_yml::from_str(&self.read_map(map).await?)?;
@@ -166,7 +165,7 @@ pub fn build_data(
map_name: String,
map_in: InitialMap,
recipes_in: Vec<RecipeDecl>,
-) -> Result<(Gamedata, Serverdata)> {
+) -> Result<(Gamedata, Serverdata, Entities)> {
let reg = ItemTileRegistry::default();
let mut recipes = Vec::new();
let mut entities = Vec::new();
@@ -324,8 +323,8 @@ pub fn build_data(
chef_spawn,
customer_spawn,
score_baseline: map_in.score_baseline,
- entities,
},
+ entities,
))
}
diff --git a/server/src/entity/bot.rs b/server/src/entity/bot.rs
new file mode 100644
index 00000000..06477e8a
--- /dev/null
+++ b/server/src/entity/bot.rs
@@ -0,0 +1,13 @@
+use super::{EntityContext, Entity};
+use anyhow::Result;
+use hurrycurry_bot::BotAlgo;
+
+pub struct BotDriver {
+ algo: Box<dyn BotAlgo>,
+}
+
+impl Entity for BotDriver {
+ fn tick(&mut self, c: EntityContext<'_>) -> Result<()> {
+ Ok(())
+ }
+}
diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs
index f7f091c7..5602e082 100644
--- a/server/src/entity/conveyor.rs
+++ b/server/src/entity/conveyor.rs
@@ -15,7 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::{EntityContext, EntityT};
+use super::{EntityContext, Entity};
use crate::server::interact_effect;
use anyhow::{anyhow, Result};
use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation};
@@ -30,7 +30,7 @@ pub struct Conveyor {
pub(super) max_cooldown: f32,
}
-impl EntityT for Conveyor {
+impl Entity for Conveyor {
fn tick(&mut self, c: EntityContext) -> Result<()> {
let from = c
.game
diff --git a/server/src/entity/customers/mod.rs b/server/src/entity/customers/mod.rs
index 85da2c07..5038eaf2 100644
--- a/server/src/entity/customers/mod.rs
+++ b/server/src/entity/customers/mod.rs
@@ -18,7 +18,7 @@
pub mod demands;
mod pathfinding;
-use super::{EntityContext, EntityT};
+use super::{EntityContext, Entity};
use crate::{data::Demand, server::Server};
use anyhow::{anyhow, bail, Result};
use fake::{faker, Fake};
@@ -74,7 +74,7 @@ impl Customers {
}
}
-impl EntityT for Customers {
+impl Entity for Customers {
fn tick(&mut self, c: EntityContext) -> Result<()> {
// self.spawn_cooldown -= dt;
// self.spawn_cooldown = self.spawn_cooldown.max(0.);
diff --git a/server/src/entity/environment_effect.rs b/server/src/entity/environment_effect.rs
index 8f54d29c..b0e811c3 100644
--- a/server/src/entity/environment_effect.rs
+++ b/server/src/entity/environment_effect.rs
@@ -15,7 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::{EntityContext, EntityT};
+use super::{EntityContext, Entity};
use hurrycurry_protocol::PacketC;
use rand::random;
use serde::{Deserialize, Serialize};
@@ -49,7 +49,7 @@ impl EnvironmentEffectController {
}
}
}
-impl EntityT for EnvironmentEffectController {
+impl Entity for EnvironmentEffectController {
fn tick(&mut self, c: EntityContext) -> anyhow::Result<()> {
if self.next_transition < Instant::now() {
if self.active {
@@ -73,7 +73,7 @@ impl EntityT for EnvironmentEffectController {
#[derive(Debug, Clone)]
pub struct EnvironmentController(pub Vec<String>);
-impl EntityT for EnvironmentController {
+impl Entity for EnvironmentController {
fn tick(&mut self, c: EntityContext) -> anyhow::Result<()> {
if c.game.environment_effects.is_empty() {
c.game.environment_effects.extend(self.0.clone());
diff --git a/server/src/entity/item_portal.rs b/server/src/entity/item_portal.rs
index be6acd06..faaa210b 100644
--- a/server/src/entity/item_portal.rs
+++ b/server/src/entity/item_portal.rs
@@ -15,7 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::{EntityContext, EntityT};
+use super::{EntityContext, Entity};
use crate::server::interact_effect;
use anyhow::{anyhow, Result};
use hurrycurry_protocol::{glam::IVec2, ItemLocation};
@@ -26,7 +26,7 @@ pub struct ItemPortal {
pub(super) to: IVec2,
}
-impl EntityT for ItemPortal {
+impl Entity for ItemPortal {
fn tick(&mut self, c: EntityContext) -> Result<()> {
let [from, to] = c
.game
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs
index 10d0c155..efee6a6d 100644
--- a/server/src/entity/mod.rs
+++ b/server/src/entity/mod.rs
@@ -15,6 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+pub mod bot;
pub mod conveyor;
pub mod customers;
pub mod environment_effect;
@@ -29,44 +30,51 @@ use environment_effect::{EnvironmentController, EnvironmentEffect, EnvironmentEf
use hurrycurry_client_lib::Game;
use hurrycurry_protocol::{
glam::{IVec2, Vec2},
- ItemIndex, PacketC, Recipe, TileIndex,
+ ItemIndex, PacketC, PacketS, Recipe, TileIndex,
};
use item_portal::ItemPortal;
use player_portal::PlayerPortal;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet, VecDeque};
+pub type DynEntity = Box<dyn Entity + Send + Sync + 'static>;
+pub type Entities = Vec<DynEntity>;
+
pub struct EntityContext<'a> {
pub game: &'a mut Game,
pub packet_out: &'a mut VecDeque<PacketC>,
+ pub packet_in: &'a mut VecDeque<PacketS>,
pub score_changed: &'a mut bool,
pub dt: f32,
}
-pub trait EntityT: Clone {
+pub trait Entity {
fn tick(&mut self, c: EntityContext<'_>) -> Result<()>;
+ fn destructor(&mut self, _c: EntityContext<'_>) {}
}
-macro_rules! entities {
- ($($e:ident),*) => {
- #[derive(Debug, Clone)]
- pub enum Entity { $($e($e)),* }
- impl EntityT for Entity {
- fn tick(&mut self, c: EntityContext<'_>) -> Result<()> {
- match self { $(Entity::$e(x) => x.tick(c)),*, }
- }
- }
- };
-}
-
-entities!(
- Conveyor,
- ItemPortal,
- PlayerPortal,
- Customers,
- EnvironmentEffectController,
- EnvironmentController
-);
+// macro_rules! entities {
+// ($($e:ident),*) => {
+// #[derive(Debug)]
+// pub enum Entity { $($e($e)),* }
+// impl EntityT for Entity {
+// fn tick(&mut self, c: EntityContext<'_>) -> Result<()> {
+// match self { $(Entity::$e(x) => x.tick(c)),*, }
+// }
+// fn destructor(&mut self, c: EntityContext<'_>) {
+// match self { $(Entity::$e(x) => x.destructor(c)),*, }
+// }
+// }
+// };
+// }
+// entities!(
+// Conveyor,
+// ItemPortal,
+// PlayerPortal,
+// Customers,
+// EnvironmentEffectController,
+// EnvironmentController
+// );
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
@@ -101,13 +109,13 @@ pub fn construct_entity(
raw_demands: &[(ItemIndex, Option<ItemIndex>, f32)],
recipes: &[Recipe],
initial_map: &HashMap<IVec2, (TileIndex, Option<ItemIndex>)>,
-) -> Result<Entity> {
+) -> Result<DynEntity> {
Ok(match decl.to_owned() {
- EntityDecl::ItemPortal { from, to } => Entity::ItemPortal(ItemPortal {
+ EntityDecl::ItemPortal { from, to } => Box::new(ItemPortal {
from: from.or(pos).ok_or(anyhow!("no item portal start"))?,
to,
}),
- EntityDecl::PlayerPortal { from, to } => Entity::PlayerPortal(PlayerPortal {
+ EntityDecl::PlayerPortal { from, to } => Box::new(PlayerPortal {
from: from
.or(pos.map(|v| v.as_vec2()))
.ok_or(anyhow!("no player portal start"))?,
@@ -125,7 +133,7 @@ pub fn construct_entity(
let to = to
.or(dir.map(|s| s + from))
.ok_or(anyhow!("conveyor has no destination"))?;
- Entity::Conveyor(Conveyor {
+ Box::new(Conveyor {
from,
to,
max_cooldown: 1. / speed.unwrap_or(2.),
@@ -142,13 +150,9 @@ pub fn construct_entity(
.filter(|(_, (tile, _))| *tile == chair)
.map(|(e, _)| (*e, true))
.collect();
- Entity::Customers(Customers::new(chairs, demands)?)
- }
- EntityDecl::EnvironmentEffect(config) => {
- Entity::EnvironmentEffectController(EnvironmentEffectController::new(config))
- }
- EntityDecl::Environment(names) => {
- Entity::EnvironmentController(EnvironmentController(names))
+ Box::new(Customers::new(chairs, demands)?)
}
+ EntityDecl::EnvironmentEffect(config) => Box::new(EnvironmentEffectController::new(config)),
+ EntityDecl::Environment(names) => Box::new(EnvironmentController(names)),
})
}
diff --git a/server/src/entity/player_portal.rs b/server/src/entity/player_portal.rs
index 11442677..53ba9c39 100644
--- a/server/src/entity/player_portal.rs
+++ b/server/src/entity/player_portal.rs
@@ -15,7 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::{EntityContext, EntityT};
+use super::{EntityContext, Entity};
use anyhow::{anyhow, Result};
use hurrycurry_protocol::{glam::Vec2, PacketC};
@@ -25,7 +25,7 @@ pub struct PlayerPortal {
pub(super) to: Vec2,
}
-impl EntityT for PlayerPortal {
+impl Entity for PlayerPortal {
fn tick(&mut self, c: EntityContext) -> Result<()> {
let mut players = Vec::new();
c.game
diff --git a/server/src/server.rs b/server/src/server.rs
index f4ccbf35..faac080f 100644
--- a/server/src/server.rs
+++ b/server/src/server.rs
@@ -17,7 +17,7 @@
*/
use crate::{
data::Serverdata,
- entity::{Entity, EntityContext, EntityT},
+ entity::{Entities, EntityContext},
interaction::{interact, tick_slot, InteractEffect, TickEffect},
};
use anyhow::{anyhow, bail, Result};
@@ -36,7 +36,7 @@ use std::{
pub struct ServerState {
pub data: Arc<Serverdata>,
- entities: Vec<Entity>,
+ pub entities: Entities,
pub lobby: bool,
pub player_id_counter: PlayerID,
pub score_changed: bool,
@@ -224,12 +224,13 @@ impl ServerState {
impl Server<'_> {
pub fn load(
&mut self,
- (gamedata, serverdata): (Gamedata, Serverdata),
+ (gamedata, serverdata, entities): (Gamedata, Serverdata, Entities),
timer: Option<Duration>,
packet_out: &mut VecDeque<PacketC>,
) {
self.game.load(gamedata, &serverdata, timer, packet_out);
self.state.data = serverdata.into();
+ self.state.entities = entities;
}
pub fn join_player(
@@ -585,16 +586,21 @@ impl Server<'_> {
);
}
+ let mut packet_in = VecDeque::new();
for entity in self.state.entities.iter_mut() {
if let Err(e) = entity.tick(EntityContext {
game: self.game,
packet_out,
score_changed: &mut self.state.score_changed,
+ packet_in: &mut packet_in,
dt,
}) {
warn!("entity tick failed: {e}")
}
}
+ for p in packet_in.drain(..) {
+ let _ = self.packet_in(p, &mut vec![], packet_out);
+ }
let now = Instant::now();