summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-06 12:39:57 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-06 12:39:57 +0200
commitc56431eb8fcb1ec6758a5aa3cdbba3892989085f (patch)
treeef3d7b1e5420b231e85f89cb8437c9581bb81494 /server/src
parent8360741499e11767aa3cbbec0fae43ddaab706f9 (diff)
downloadhurrycurry-c56431eb8fcb1ec6758a5aa3cdbba3892989085f.tar
hurrycurry-c56431eb8fcb1ec6758a5aa3cdbba3892989085f.tar.bz2
hurrycurry-c56431eb8fcb1ec6758a5aa3cdbba3892989085f.tar.zst
conveyors
Diffstat (limited to 'server/src')
-rw-r--r--server/src/data.rs20
-rw-r--r--server/src/entity/conveyor.rs54
-rw-r--r--server/src/entity/mod.rs42
-rw-r--r--server/src/game.rs27
-rw-r--r--server/src/lib.rs1
5 files changed, 133 insertions, 11 deletions
diff --git a/server/src/data.rs b/server/src/data.rs
index 46f7ed28..62a7f5d8 100644
--- a/server/src/data.rs
+++ b/server/src/data.rs
@@ -16,6 +16,7 @@
*/
use crate::{
+ entity::EntityDecl,
interaction::Recipe,
protocol::{DemandIndex, ItemIndex, RecipeIndex, TileIndex},
};
@@ -64,11 +65,14 @@ pub struct RecipeDecl {
pub struct InitialMap {
map: Vec<String>,
tiles: HashMap<char, String>,
+ #[serde(default)]
items: HashMap<char, String>,
collider: Vec<String>,
walkable: Vec<String>,
chef_spawn: char,
customer_spawn: char,
+ #[serde(default)]
+ entities: Vec<EntityDecl>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -88,19 +92,18 @@ pub struct Demand {
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
+#[rustfmt::skip]
pub struct Gamedata {
- #[serde(skip)]
- pub recipes: Vec<Recipe>,
- #[serde(skip)]
- pub demands: Vec<Demand>,
pub item_names: Vec<String>,
pub tile_names: Vec<String>,
pub tile_collide: Vec<bool>,
pub tile_interact: Vec<bool>,
- #[serde(skip)]
- pub initial_map: HashMap<IVec2, (TileIndex, Option<ItemIndex>)>,
- pub chef_spawn: Vec2,
- pub customer_spawn: Vec2,
+ #[serde(skip)] pub recipes: Vec<Recipe>,
+ #[serde(skip)] pub demands: Vec<Demand>,
+ #[serde(skip)] pub initial_map: HashMap<IVec2, (TileIndex, Option<ItemIndex>)>,
+ #[serde(skip)] pub chef_spawn: Vec2,
+ #[serde(skip)] pub customer_spawn: Vec2,
+ #[serde(skip)] pub entities: Vec<EntityDecl>,
}
#[derive(Debug, Deserialize, Default)]
@@ -258,6 +261,7 @@ impl Gamedata {
recipes,
initial_map,
item_names,
+ entities: map_in.entities,
tile_names,
chef_spawn,
customer_spawn,
diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs
new file mode 100644
index 00000000..b74c03ef
--- /dev/null
+++ b/server/src/entity/conveyor.rs
@@ -0,0 +1,54 @@
+use super::Entity;
+use crate::{
+ data::Gamedata,
+ game::{interact_effect, Tile},
+ protocol::{ItemLocation, PacketC},
+};
+use anyhow::{anyhow, Result};
+use glam::IVec2;
+use std::collections::{HashMap, VecDeque};
+
+#[derive(Debug, Default)]
+pub struct Conveyor {
+ pub(super) from: IVec2,
+ pub(super) to: IVec2,
+ pub(super) cooldown: f32,
+ pub(super) max_cooldown: f32,
+}
+
+impl Entity for Conveyor {
+ fn tick(
+ &mut self,
+ data: &Gamedata,
+ points: &mut i64,
+ packet_out: &mut VecDeque<PacketC>,
+ tiles: &mut HashMap<IVec2, Tile>,
+ dt: f32,
+ ) -> Result<()> {
+ let [from, to] = tiles
+ .get_many_mut([&self.from, &self.to])
+ .ok_or(anyhow!("conveyor does ends in itself"))?;
+
+ if from.item.is_some() {
+ self.cooldown += dt;
+ if self.cooldown < self.max_cooldown {
+ return Ok(());
+ }
+ self.cooldown = 0.;
+
+ interact_effect(
+ data,
+ true,
+ &mut to.item,
+ ItemLocation::Tile(self.to),
+ &mut from.item,
+ ItemLocation::Tile(self.from),
+ Some(to.kind),
+ packet_out,
+ points,
+ );
+ }
+
+ Ok(())
+ }
+}
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs
new file mode 100644
index 00000000..089c60a5
--- /dev/null
+++ b/server/src/entity/mod.rs
@@ -0,0 +1,42 @@
+pub mod conveyor;
+
+use crate::{data::Gamedata, game::Tile, protocol::PacketC};
+use anyhow::Result;
+use conveyor::Conveyor;
+use glam::IVec2;
+use serde::{Deserialize, Serialize};
+use std::collections::{HashMap, VecDeque};
+
+pub type DynEntity = Box<dyn Entity + Send + Sync + 'static>;
+
+pub trait Entity {
+ fn tick(
+ &mut self,
+ data: &Gamedata,
+ points: &mut i64,
+ packet_out: &mut VecDeque<PacketC>,
+ tiles: &mut HashMap<IVec2, Tile>,
+ dt: f32,
+ ) -> Result<()>;
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum EntityDecl {
+ Conveyor {
+ from: IVec2,
+ to: IVec2,
+ speed: Option<f32>,
+ },
+}
+
+pub fn construct_entity(decl: &EntityDecl) -> DynEntity {
+ match decl.to_owned() {
+ EntityDecl::Conveyor { from, to, speed } => Box::new(Conveyor {
+ from,
+ to,
+ max_cooldown: 1. / speed.unwrap_or(2.),
+ ..Default::default()
+ }),
+ }
+}
diff --git a/server/src/game.rs b/server/src/game.rs
index 838a71e4..13ee5410 100644
--- a/server/src/game.rs
+++ b/server/src/game.rs
@@ -18,6 +18,7 @@
use crate::{
customer::DemandState,
data::Gamedata,
+ entity::{construct_entity, DynEntity},
interaction::{interact, tick_slot, InteractEffect, TickEffect},
protocol::{
ItemIndex, ItemLocation, Message, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex,
@@ -68,6 +69,7 @@ pub struct Game {
packet_out: VecDeque<PacketC>,
demand: Option<DemandState>,
pub points: i64,
+ entities: Vec<DynEntity>,
end: Option<Instant>,
}
@@ -76,10 +78,11 @@ impl Game {
Self {
data: Gamedata::default().into(),
packet_out: Default::default(),
- players: Default::default(),
- tiles: Default::default(),
+ players: HashMap::new(),
+ tiles: HashMap::new(),
demand: None,
end: None,
+ entities: vec![],
points: 0,
}
}
@@ -112,6 +115,12 @@ impl Game {
self.data = gamedata.into();
self.points = 0;
self.end = timer.map(|dur| Instant::now() + dur);
+ self.entities = self
+ .data
+ .entities
+ .iter()
+ .map(|decl| construct_entity(decl))
+ .collect();
for (&p, (tile, item)) in &self.data.initial_map {
self.tiles.insert(
@@ -476,6 +485,18 @@ impl Game {
}
}
+ for entity in &mut self.entities {
+ if let Err(e) = entity.tick(
+ &self.data,
+ &mut self.points,
+ &mut self.packet_out,
+ &mut self.tiles,
+ dt,
+ ) {
+ warn!("entity tick failed: {e}")
+ }
+ }
+
return self.end.map(|t| t < Instant::now()).unwrap_or_default();
}
}
@@ -486,7 +507,7 @@ impl From<TileIndex> for Tile {
}
}
-fn interact_effect(
+pub fn interact_effect(
data: &Gamedata,
edge: bool,
this: &mut Option<Item>,
diff --git a/server/src/lib.rs b/server/src/lib.rs
index b8929bd6..890e5148 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -22,3 +22,4 @@ pub mod game;
pub mod interaction;
pub mod protocol;
pub mod state;
+pub mod entity;