diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/src/data.rs | 20 | ||||
-rw-r--r-- | server/src/entity/conveyor.rs | 7 | ||||
-rw-r--r-- | server/src/entity/mod.rs | 56 | ||||
-rw-r--r-- | server/src/game.rs | 16 | ||||
-rw-r--r-- | server/src/interaction.rs | 8 | ||||
-rw-r--r-- | server/src/lib.rs | 4 |
6 files changed, 77 insertions, 34 deletions
diff --git a/server/src/data.rs b/server/src/data.rs index a1c7e894..c667e760 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -16,7 +16,7 @@ */ use crate::{ - entity::EntityDecl, + entity::{construct_entity, Entity, EntityDecl}, interaction::Recipe, protocol::{DemandIndex, ItemIndex, RecipeIndex, TileIndex}, }; @@ -73,6 +73,8 @@ pub struct InitialMap { customer_spawn: char, #[serde(default)] entities: Vec<EntityDecl>, + #[serde(default)] + tile_entities: HashMap<char, EntityDecl>, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -104,7 +106,7 @@ pub struct Gamedata { #[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>, + #[serde(skip)] pub entities: Vec<Entity>, } #[derive(Debug, Deserialize, Default)] @@ -170,6 +172,7 @@ impl Gamedata { let tile_names = RwLock::new(Vec::new()); let mut recipes = Vec::new(); let mut demands = Vec::new(); + let mut entities = Vec::new(); for mut r in recipes_in { let r2 = r.clone(); @@ -238,6 +241,9 @@ impl Gamedata { .get(&tile) .ok_or(anyhow!("tile {tile} is undefined"))? .clone(); + if let Some(ent) = map_in.tile_entities.get(&tile) { + entities.push(construct_entity(Some(pos), ent)?); + } let itemname = map_in.items.get(&tile).cloned(); let tile = TileIndex(register(&tile_names, tilename)); let item = itemname.map(|i| ItemIndex(register(&item_names, i))); @@ -257,6 +263,14 @@ impl Gamedata { .map(|i| !map_in.collider.contains(i) && !map_in.walkable.contains(i)) .collect(); + entities.extend( + map_in + .entities + .iter() + .map(|decl| construct_entity(None, decl)) + .try_collect::<Vec<_>>()?, + ); + Ok(Gamedata { demands, tile_collide, @@ -265,7 +279,7 @@ impl Gamedata { map_names: HashSet::new(), initial_map, item_names, - entities: map_in.entities, + entities, tile_names, chef_spawn, customer_spawn, diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs index b74c03ef..48d0d154 100644 --- a/server/src/entity/conveyor.rs +++ b/server/src/entity/conveyor.rs @@ -1,4 +1,4 @@ -use super::Entity; +use super::EntityT; use crate::{ data::Gamedata, game::{interact_effect, Tile}, @@ -8,7 +8,7 @@ use anyhow::{anyhow, Result}; use glam::IVec2; use std::collections::{HashMap, VecDeque}; -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct Conveyor { pub(super) from: IVec2, pub(super) to: IVec2, @@ -16,7 +16,7 @@ pub struct Conveyor { pub(super) max_cooldown: f32, } -impl Entity for Conveyor { +impl EntityT for Conveyor { fn tick( &mut self, data: &Gamedata, @@ -46,6 +46,7 @@ impl Entity for Conveyor { Some(to.kind), packet_out, points, + true, ); } diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs index 089c60a5..d286d3bb 100644 --- a/server/src/entity/mod.rs +++ b/server/src/entity/mod.rs @@ -1,15 +1,12 @@ pub mod conveyor; - use crate::{data::Gamedata, game::Tile, protocol::PacketC}; -use anyhow::Result; +use anyhow::{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 { +pub trait EntityT: Clone { fn tick( &mut self, data: &Gamedata, @@ -20,23 +17,54 @@ pub trait Entity { ) -> Result<()>; } +#[derive(Debug, Clone)] +pub enum Entity { + Conveyor(Conveyor), +} +impl EntityT for Entity { + fn tick( + &mut self, + data: &Gamedata, + points: &mut i64, + packet_out: &mut VecDeque<PacketC>, + tiles: &mut HashMap<IVec2, Tile>, + dt: f32, + ) -> Result<()> { + match self { + Entity::Conveyor(x) => x.tick(data, points, packet_out, tiles, dt), + } + } +} + #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum EntityDecl { Conveyor { - from: IVec2, - to: IVec2, + from: Option<IVec2>, + to: Option<IVec2>, + dir: Option<IVec2>, speed: Option<f32>, }, } -pub fn construct_entity(decl: &EntityDecl) -> DynEntity { - match decl.to_owned() { - EntityDecl::Conveyor { from, to, speed } => Box::new(Conveyor { +pub fn construct_entity(pos: Option<IVec2>, decl: &EntityDecl) -> Result<Entity> { + Ok(match decl.to_owned() { + EntityDecl::Conveyor { from, to, - max_cooldown: 1. / speed.unwrap_or(2.), - ..Default::default() - }), - } + speed, + 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"))?; + Entity::Conveyor(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 7609b965..e8d307db 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -18,7 +18,7 @@ use crate::{ customer::DemandState, data::Gamedata, - entity::{construct_entity, DynEntity}, + entity::{Entity, EntityT}, interaction::{interact, tick_slot, InteractEffect, TickEffect}, protocol::{ ItemIndex, ItemLocation, Message, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex, @@ -69,7 +69,7 @@ pub struct Game { packet_out: VecDeque<PacketC>, demand: Option<DemandState>, pub points: i64, - entities: Vec<DynEntity>, + entities: Vec<Entity>, end: Option<Instant>, } @@ -117,12 +117,7 @@ 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(); + self.entities = self.data.entities.clone(); for (&p, (tile, item)) in &self.data.initial_map { self.tiles.insert( @@ -364,6 +359,7 @@ impl Game { None, &mut self.packet_out, &mut self.points, + false, ) } else { let player = self @@ -381,6 +377,7 @@ impl Game { Some(tile.kind), &mut self.packet_out, &mut self.points, + false, ) } } @@ -523,11 +520,12 @@ pub fn interact_effect( this_tile_kind: Option<TileIndex>, packet_out: &mut VecDeque<PacketC>, points: &mut i64, + automated: bool, ) { let this_had_item = this.is_some(); let other_had_item = other.is_some(); - if let Some(effect) = interact(&data, edge, this_tile_kind, this, other, points) { + if let Some(effect) = interact(&data, edge, this_tile_kind, this, other, points, automated) { match effect { InteractEffect::Put => packet_out.push_back(PacketC::MoveItem { from: other_loc, diff --git a/server/src/interaction.rs b/server/src/interaction.rs index 85df9925..bca480f5 100644 --- a/server/src/interaction.rs +++ b/server/src/interaction.rs @@ -122,10 +122,12 @@ pub fn interact( this: &mut Option<Item>, other: &mut Option<Item>, points: &mut i64, + automated: bool, ) -> Option<InteractEffect> { - let interactable = tile - .map(|tile| data.is_tile_interactable(tile)) - .unwrap_or(true); + let interactable = automated + || tile + .map(|tile| data.is_tile_interactable(tile)) + .unwrap_or(true); if interactable && other.is_none() { if let Some(item) = this { if let Some(active) = &mut item.active { diff --git a/server/src/lib.rs b/server/src/lib.rs index 890e5148..96fb954a 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -15,11 +15,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#![feature(if_let_guard, map_many_mut, let_chains)] +#![feature(if_let_guard, map_many_mut, let_chains, iterator_try_collect)] pub mod customer; pub mod data; +pub mod entity; pub mod game; pub mod interaction; pub mod protocol; pub mod state; -pub mod entity; |