diff options
author | metamuffin <metamuffin@disroot.org> | 2024-07-06 12:39:57 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-07-06 12:39:57 +0200 |
commit | c56431eb8fcb1ec6758a5aa3cdbba3892989085f (patch) | |
tree | ef3d7b1e5420b231e85f89cb8437c9581bb81494 /server/src | |
parent | 8360741499e11767aa3cbbec0fae43ddaab706f9 (diff) | |
download | hurrycurry-c56431eb8fcb1ec6758a5aa3cdbba3892989085f.tar hurrycurry-c56431eb8fcb1ec6758a5aa3cdbba3892989085f.tar.bz2 hurrycurry-c56431eb8fcb1ec6758a5aa3cdbba3892989085f.tar.zst |
conveyors
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/data.rs | 20 | ||||
-rw-r--r-- | server/src/entity/conveyor.rs | 54 | ||||
-rw-r--r-- | server/src/entity/mod.rs | 42 | ||||
-rw-r--r-- | server/src/game.rs | 27 | ||||
-rw-r--r-- | server/src/lib.rs | 1 |
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; |