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; | 
