aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/data.rs20
-rw-r--r--server/src/entity/conveyor.rs7
-rw-r--r--server/src/entity/mod.rs56
-rw-r--r--server/src/game.rs16
-rw-r--r--server/src/interaction.rs8
-rw-r--r--server/src/lib.rs4
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;