summaryrefslogtreecommitdiff
path: root/server/src/entity
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/entity')
-rw-r--r--server/src/entity/conveyor.rs29
-rw-r--r--server/src/entity/customers/mod.rs368
-rw-r--r--server/src/entity/environment_effect.rs38
-rw-r--r--server/src/entity/item_portal.rs25
-rw-r--r--server/src/entity/mod.rs16
-rw-r--r--server/src/entity/player_portal.rs24
6 files changed, 245 insertions, 255 deletions
diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs
index b370356c..f7f091c7 100644
--- a/server/src/entity/conveyor.rs
+++ b/server/src/entity/conveyor.rs
@@ -1,5 +1,3 @@
-use std::collections::VecDeque;
-
/*
Hurry Curry! - a game about cooking
Copyright 2024 metamuffin
@@ -17,10 +15,10 @@ use std::collections::VecDeque;
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::EntityT;
-use crate::game::{interact_effect, Game};
+use super::{EntityContext, EntityT};
+use crate::server::interact_effect;
use anyhow::{anyhow, Result};
-use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation, PacketC};
+use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation};
#[derive(Debug, Clone)]
pub struct Conveyor {
@@ -33,15 +31,17 @@ pub struct Conveyor {
}
impl EntityT for Conveyor {
- fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()> {
- let from = game
+ fn tick(&mut self, c: EntityContext) -> Result<()> {
+ let from = c
+ .game
.tiles
.get(&self.from)
.ok_or(anyhow!("conveyor from missing"))?;
if let Some(from_item) = from.item.as_ref() {
let filter = if let Some(t) = &self.filter_tile {
- let filter_tile = game
+ let filter_tile = c
+ .game
.tiles
.get(t)
.ok_or(anyhow!("conveyor filter missing"))?;
@@ -56,28 +56,29 @@ impl EntityT for Conveyor {
}
}
- self.cooldown += dt;
+ self.cooldown += c.dt;
if self.cooldown < self.max_cooldown {
return Ok(());
}
self.cooldown = 0.;
- let [from, to] = game
+ let [from, to] = c
+ .game
.tiles
.get_many_mut([&self.from, &self.to])
.ok_or(anyhow!("conveyor does ends in itself"))?;
interact_effect(
- &game.data,
+ &c.game.data,
true,
&mut to.item,
ItemLocation::Tile(self.to),
&mut from.item,
ItemLocation::Tile(self.from),
Some(to.kind),
- packet_out,
- &mut game.score,
- &mut game.score_changed,
+ c.packet_out,
+ &mut c.game.score,
+ c.score_changed,
true,
);
}
diff --git a/server/src/entity/customers/mod.rs b/server/src/entity/customers/mod.rs
index 221351a5..85da2c07 100644
--- a/server/src/entity/customers/mod.rs
+++ b/server/src/entity/customers/mod.rs
@@ -18,8 +18,8 @@
pub mod demands;
mod pathfinding;
-use super::EntityT;
-use crate::{data::Demand, game::Game};
+use super::{EntityContext, EntityT};
+use crate::{data::Demand, server::Server};
use anyhow::{anyhow, bail, Result};
use fake::{faker, Fake};
use hurrycurry_protocol::{glam::IVec2, DemandIndex, Message, PacketC, PacketS, PlayerID};
@@ -75,190 +75,190 @@ impl Customers {
}
impl EntityT for Customers {
- fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()> {
- self.spawn_cooldown -= dt;
- self.spawn_cooldown = self.spawn_cooldown.max(0.);
- if self.customers.len() < 5 && self.spawn_cooldown <= 0. {
- self.spawn_cooldown = 10. + random::<f32>() * 10.;
- let id = game.join_player(
- faker::name::fr_fr::Name().fake(),
- -1 - (random::<u16>() as i32),
- packet_out,
- );
+ fn tick(&mut self, c: EntityContext) -> Result<()> {
+ // self.spawn_cooldown -= dt;
+ // self.spawn_cooldown = self.spawn_cooldown.max(0.);
+ // if self.customers.len() < 5 && self.spawn_cooldown <= 0. {
+ // self.spawn_cooldown = 10. + random::<f32>() * 10.;
+ // let id = game.join_player(
+ // faker::name::fr_fr::Name().fake(),
+ // -1 - (random::<u16>() as i32),
+ // packet_out,
+ // );
- let chair = self.select_chair().ok_or(anyhow!("no free chair found"))?;
- let from = game.data.customer_spawn.as_ivec2();
- let path = find_path(&game.walkable, from, chair)
- .ok_or(anyhow!("no path from {from} to {chair}"))?;
- info!("{id:?} -> entering");
- self.customers
- .insert(id, CustomerState::Entering { path, chair });
- }
- let mut customers_to_remove = Vec::new();
- for (&player, state) in &mut self.customers {
- let Some(playerdata) = game.players.get_mut(&player) else {
- continue;
- };
+ // let chair = self.select_chair().ok_or(anyhow!("no free chair found"))?;
+ // let from = game.data.customer_spawn.as_ivec2();
+ // let path = find_path(&game.walkable, from, chair)
+ // .ok_or(anyhow!("no path from {from} to {chair}"))?;
+ // info!("{id:?} -> entering");
+ // self.customers
+ // .insert(id, CustomerState::Entering { path, chair });
+ // }
+ // let mut customers_to_remove = Vec::new();
+ // for (&player, state) in &mut self.customers {
+ // let Some(playerdata) = game.players.get_mut(&player) else {
+ // continue;
+ // };
- match state {
- CustomerState::Entering { path, chair } => {
- playerdata
- .movement
- .input(path.next_direction(playerdata.position()), false);
- if path.is_done() {
- let demand = DemandIndex(random::<u32>() as usize % self.demands.len());
- self.cpackets.push_back(PacketS::Communicate {
- message: Some(Message::Item(self.demands[demand.0].from)),
- persist: true,
- player,
- });
- info!("{player:?} -> waiting");
- *state = CustomerState::Waiting {
- chair: *chair,
- timeout: 90. + random::<f32>() * 60.,
- demand,
- };
- }
- }
- CustomerState::Waiting {
- chair,
- demand,
- timeout,
- } => {
- playerdata
- .movement
- .input((chair.as_vec2() + 0.5) - playerdata.position(), false);
- *timeout -= dt;
- if *timeout <= 0. {
- self.cpackets.push_back(PacketS::Communicate {
- message: None,
- persist: true,
- player,
- });
- self.cpackets.push_back(PacketS::Communicate {
- message: Some(Message::Effect("angry".to_string())),
- persist: false,
- player,
- });
- let path = find_path(
- &game.walkable,
- playerdata.position().as_ivec2(),
- game.data.customer_spawn.as_ivec2(),
- )
- .expect("no path to exit");
- *self.chairs.get_mut(chair).unwrap() = true;
- game.score.demands_failed += 1;
- game.score.points -= 1;
- game.score_changed = true;
- info!("{player:?} -> exiting");
- *state = CustomerState::Exiting { path }
- } else {
- let demand_data = &self.demands[demand.0];
- let demand_pos = [IVec2::NEG_X, IVec2::NEG_Y, IVec2::X, IVec2::Y]
- .into_iter()
- .find_map(|off| {
- let pos = *chair + off;
- if game
- .tiles
- .get(&pos)
- .map(|t| {
- t.item
- .as_ref()
- .map(|i| i.kind == demand_data.from)
- .unwrap_or_default()
- })
- .unwrap_or_default()
- {
- Some(pos)
- } else {
- None
- }
- });
- if let Some(pos) = demand_pos {
- self.cpackets.push_back(PacketS::Communicate {
- persist: true,
- message: None,
- player,
- });
- self.cpackets.push_back(PacketS::Communicate {
- message: Some(Message::Effect("satisfied".to_string())),
- persist: false,
- player,
- });
- self.cpackets.push_back(PacketS::Interact {
- pos: Some(pos),
- player,
- });
- self.cpackets
- .push_back(PacketS::Interact { pos: None, player });
- info!("{player:?} -> eating");
- *state = CustomerState::Eating {
- demand: *demand,
- target: pos,
- progress: 0.,
- chair: *chair,
- }
- }
- }
- }
- CustomerState::Eating {
- demand,
- target,
- progress,
- chair,
- } => {
- playerdata
- .movement
- .input((chair.as_vec2() + 0.5) - playerdata.position(), false);
- let demand = &self.demands[demand.0];
- *progress += dt / demand.duration;
- if *progress >= 1. {
- self.cpackets.push_back(PacketS::ReplaceHand {
- player,
- item: demand.to,
- });
- if demand.to.is_some() {
- self.cpackets.push_back(PacketS::Interact {
- player,
- pos: Some(*target),
- });
- self.cpackets
- .push_back(PacketS::Interact { player, pos: None });
- }
- let path = find_path(
- &game.walkable,
- playerdata.position().as_ivec2(),
- game.data.customer_spawn.as_ivec2(),
- )
- .ok_or(anyhow!("no path to exit"))?;
- *self.chairs.get_mut(chair).unwrap() = true;
- game.score.demands_completed += 1;
- game.score.points += demand.points;
- game.score_changed = true;
- info!("{player:?} -> exiting");
- *state = CustomerState::Exiting { path }
- }
- }
- CustomerState::Exiting { path } => {
- playerdata
- .movement
- .input(path.next_direction(playerdata.position()), false);
- if path.is_done() {
- info!("{player:?} -> leave");
- self.cpackets.push_back(PacketS::Leave { player });
- customers_to_remove.push(player);
- }
- }
- }
- }
- for c in customers_to_remove {
- self.customers.remove(&c).unwrap();
- }
- for packet in self.cpackets.drain(..) {
- if let Err(err) = game.packet_in(packet, &mut vec![], packet_out) {
- warn!("demand packet {err}");
- }
- }
+ // match state {
+ // CustomerState::Entering { path, chair } => {
+ // playerdata
+ // .movement
+ // .input(path.next_direction(playerdata.position()), false);
+ // if path.is_done() {
+ // let demand = DemandIndex(random::<u32>() as usize % self.demands.len());
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: Some(Message::Item(self.demands[demand.0].from)),
+ // persist: true,
+ // player,
+ // });
+ // info!("{player:?} -> waiting");
+ // *state = CustomerState::Waiting {
+ // chair: *chair,
+ // timeout: 90. + random::<f32>() * 60.,
+ // demand,
+ // };
+ // }
+ // }
+ // CustomerState::Waiting {
+ // chair,
+ // demand,
+ // timeout,
+ // } => {
+ // playerdata
+ // .movement
+ // .input((chair.as_vec2() + 0.5) - playerdata.position(), false);
+ // *timeout -= dt;
+ // if *timeout <= 0. {
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: None,
+ // persist: true,
+ // player,
+ // });
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: Some(Message::Effect("angry".to_string())),
+ // persist: false,
+ // player,
+ // });
+ // let path = find_path(
+ // &game.walkable,
+ // playerdata.position().as_ivec2(),
+ // game.data.customer_spawn.as_ivec2(),
+ // )
+ // .expect("no path to exit");
+ // *self.chairs.get_mut(chair).unwrap() = true;
+ // game.score.demands_failed += 1;
+ // game.score.points -= 1;
+ // game.score_changed = true;
+ // info!("{player:?} -> exiting");
+ // *state = CustomerState::Exiting { path }
+ // } else {
+ // let demand_data = &self.demands[demand.0];
+ // let demand_pos = [IVec2::NEG_X, IVec2::NEG_Y, IVec2::X, IVec2::Y]
+ // .into_iter()
+ // .find_map(|off| {
+ // let pos = *chair + off;
+ // if game
+ // .tiles
+ // .get(&pos)
+ // .map(|t| {
+ // t.item
+ // .as_ref()
+ // .map(|i| i.kind == demand_data.from)
+ // .unwrap_or_default()
+ // })
+ // .unwrap_or_default()
+ // {
+ // Some(pos)
+ // } else {
+ // None
+ // }
+ // });
+ // if let Some(pos) = demand_pos {
+ // self.cpackets.push_back(PacketS::Communicate {
+ // persist: true,
+ // message: None,
+ // player,
+ // });
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: Some(Message::Effect("satisfied".to_string())),
+ // persist: false,
+ // player,
+ // });
+ // self.cpackets.push_back(PacketS::Interact {
+ // pos: Some(pos),
+ // player,
+ // });
+ // self.cpackets
+ // .push_back(PacketS::Interact { pos: None, player });
+ // info!("{player:?} -> eating");
+ // *state = CustomerState::Eating {
+ // demand: *demand,
+ // target: pos,
+ // progress: 0.,
+ // chair: *chair,
+ // }
+ // }
+ // }
+ // }
+ // CustomerState::Eating {
+ // demand,
+ // target,
+ // progress,
+ // chair,
+ // } => {
+ // playerdata
+ // .movement
+ // .input((chair.as_vec2() + 0.5) - playerdata.position(), false);
+ // let demand = &self.demands[demand.0];
+ // *progress += dt / demand.duration;
+ // if *progress >= 1. {
+ // self.cpackets.push_back(PacketS::ReplaceHand {
+ // player,
+ // item: demand.to,
+ // });
+ // if demand.to.is_some() {
+ // self.cpackets.push_back(PacketS::Interact {
+ // player,
+ // pos: Some(*target),
+ // });
+ // self.cpackets
+ // .push_back(PacketS::Interact { player, pos: None });
+ // }
+ // let path = find_path(
+ // &game.walkable,
+ // playerdata.position().as_ivec2(),
+ // game.data.customer_spawn.as_ivec2(),
+ // )
+ // .ok_or(anyhow!("no path to exit"))?;
+ // *self.chairs.get_mut(chair).unwrap() = true;
+ // game.score.demands_completed += 1;
+ // game.score.points += demand.points;
+ // game.score_changed = true;
+ // info!("{player:?} -> exiting");
+ // *state = CustomerState::Exiting { path }
+ // }
+ // }
+ // CustomerState::Exiting { path } => {
+ // playerdata
+ // .movement
+ // .input(path.next_direction(playerdata.position()), false);
+ // if path.is_done() {
+ // info!("{player:?} -> leave");
+ // self.cpackets.push_back(PacketS::Leave { player });
+ // customers_to_remove.push(player);
+ // }
+ // }
+ // }
+ // }
+ // for c in customers_to_remove {
+ // self.customers.remove(&c).unwrap();
+ // }
+ // for packet in self.cpackets.drain(..) {
+ // if let Err(err) = game.packet_in(packet, &mut vec![], packet_out) {
+ // warn!("demand packet {err}");
+ // }
+ // }
Ok(())
}
}
diff --git a/server/src/entity/environment_effect.rs b/server/src/entity/environment_effect.rs
index f369bce4..8f54d29c 100644
--- a/server/src/entity/environment_effect.rs
+++ b/server/src/entity/environment_effect.rs
@@ -15,15 +15,11 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::EntityT;
-use crate::game::Game;
+use super::{EntityContext, EntityT};
use hurrycurry_protocol::PacketC;
use rand::random;
use serde::{Deserialize, Serialize};
-use std::{
- collections::VecDeque,
- time::{Duration, Instant},
-};
+use std::time::{Duration, Instant};
#[derive(Clone, Debug, Deserialize, Serialize, Default)]
pub struct EnvironmentEffect {
@@ -54,26 +50,21 @@ impl EnvironmentEffectController {
}
}
impl EntityT for EnvironmentEffectController {
- fn tick(
- &mut self,
- game: &mut Game,
- packet_out: &mut VecDeque<PacketC>,
- _dt: f32,
- ) -> anyhow::Result<()> {
+ fn tick(&mut self, c: EntityContext) -> anyhow::Result<()> {
if self.next_transition < Instant::now() {
if self.active {
self.next_transition +=
Duration::from_secs_f32(self.config.on + (0.5 + random::<f32>()));
self.active = false;
- game.environment_effects.remove(&self.config.name);
+ c.game.environment_effects.remove(&self.config.name);
} else {
self.next_transition +=
Duration::from_secs_f32(self.config.off * (0.5 + random::<f32>()));
self.active = true;
- game.environment_effects.insert(self.config.name.clone());
+ c.game.environment_effects.insert(self.config.name.clone());
}
- packet_out.push_back(PacketC::Environment {
- effects: game.environment_effects.clone(),
+ c.packet_out.push_back(PacketC::Environment {
+ effects: c.game.environment_effects.clone(),
})
}
Ok(())
@@ -83,16 +74,11 @@ impl EntityT for EnvironmentEffectController {
#[derive(Debug, Clone)]
pub struct EnvironmentController(pub Vec<String>);
impl EntityT for EnvironmentController {
- fn tick(
- &mut self,
- game: &mut Game,
- packet_out: &mut VecDeque<PacketC>,
- _dt: f32,
- ) -> anyhow::Result<()> {
- if game.environment_effects.is_empty() {
- game.environment_effects.extend(self.0.clone());
- packet_out.push_back(PacketC::Environment {
- effects: game.environment_effects.clone(),
+ fn tick(&mut self, c: EntityContext) -> anyhow::Result<()> {
+ if c.game.environment_effects.is_empty() {
+ c.game.environment_effects.extend(self.0.clone());
+ c.packet_out.push_back(PacketC::Environment {
+ effects: c.game.environment_effects.clone(),
})
}
Ok(())
diff --git a/server/src/entity/item_portal.rs b/server/src/entity/item_portal.rs
index f63ff274..be6acd06 100644
--- a/server/src/entity/item_portal.rs
+++ b/server/src/entity/item_portal.rs
@@ -15,11 +15,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::EntityT;
-use crate::game::{interact_effect, Game};
+use super::{EntityContext, EntityT};
+use crate::server::interact_effect;
use anyhow::{anyhow, Result};
-use hurrycurry_protocol::{glam::IVec2, ItemLocation, PacketC};
-use std::collections::VecDeque;
+use hurrycurry_protocol::{glam::IVec2, ItemLocation};
#[derive(Debug, Default, Clone)]
pub struct ItemPortal {
@@ -28,29 +27,25 @@ pub struct ItemPortal {
}
impl EntityT for ItemPortal {
- fn tick(
- &mut self,
- game: &mut Game,
- packet_out: &mut VecDeque<PacketC>,
- _dt: f32,
- ) -> Result<()> {
- let [from, to] = game
+ fn tick(&mut self, c: EntityContext) -> Result<()> {
+ let [from, to] = c
+ .game
.tiles
.get_many_mut([&self.from, &self.to])
.ok_or(anyhow!("conveyor does ends in itself"))?;
if from.item.is_some() {
interact_effect(
- &game.data,
+ &c.game.data,
true,
&mut to.item,
ItemLocation::Tile(self.to),
&mut from.item,
ItemLocation::Tile(self.from),
Some(to.kind),
- packet_out,
- &mut game.score,
- &mut game.score_changed,
+ c.packet_out,
+ &mut c.game.score,
+ c.score_changed,
true,
);
}
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs
index 94718dd1..10d0c155 100644
--- a/server/src/entity/mod.rs
+++ b/server/src/entity/mod.rs
@@ -21,11 +21,12 @@ pub mod environment_effect;
pub mod item_portal;
pub mod player_portal;
-use crate::{data::ItemTileRegistry, game::Game};
+use crate::data::ItemTileRegistry;
use anyhow::{anyhow, Result};
use conveyor::Conveyor;
use customers::{demands::generate_demands, Customers};
use environment_effect::{EnvironmentController, EnvironmentEffect, EnvironmentEffectController};
+use hurrycurry_client_lib::Game;
use hurrycurry_protocol::{
glam::{IVec2, Vec2},
ItemIndex, PacketC, Recipe, TileIndex,
@@ -35,8 +36,15 @@ use player_portal::PlayerPortal;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet, VecDeque};
+pub struct EntityContext<'a> {
+ pub game: &'a mut Game,
+ pub packet_out: &'a mut VecDeque<PacketC>,
+ pub score_changed: &'a mut bool,
+ pub dt: f32,
+}
+
pub trait EntityT: Clone {
- fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()>;
+ fn tick(&mut self, c: EntityContext<'_>) -> Result<()>;
}
macro_rules! entities {
@@ -44,8 +52,8 @@ macro_rules! entities {
#[derive(Debug, Clone)]
pub enum Entity { $($e($e)),* }
impl EntityT for Entity {
- fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()> {
- match self { $(Entity::$e(x) => x.tick(game, packet_out, dt)),*, }
+ fn tick(&mut self, c: EntityContext<'_>) -> Result<()> {
+ match self { $(Entity::$e(x) => x.tick(c)),*, }
}
}
};
diff --git a/server/src/entity/player_portal.rs b/server/src/entity/player_portal.rs
index 6ee04f15..11442677 100644
--- a/server/src/entity/player_portal.rs
+++ b/server/src/entity/player_portal.rs
@@ -15,11 +15,9 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::EntityT;
-use crate::game::Game;
+use super::{EntityContext, EntityT};
use anyhow::{anyhow, Result};
use hurrycurry_protocol::{glam::Vec2, PacketC};
-use std::collections::VecDeque;
#[derive(Debug, Default, Clone)]
pub struct PlayerPortal {
@@ -28,19 +26,21 @@ pub struct PlayerPortal {
}
impl EntityT for PlayerPortal {
- fn tick(
- &mut self,
- game: &mut Game,
- _packet_out: &mut VecDeque<PacketC>,
- _dt: f32,
- ) -> Result<()> {
+ fn tick(&mut self, c: EntityContext) -> Result<()> {
let mut players = Vec::new();
- game.players_spatial_index
+ c.game
+ .players_spatial_index
.query(self.from, 0.5, |pid, _| players.push(pid));
- for p in players {
- let p = game.players.get_mut(&p).ok_or(anyhow!("player missing"))?;
+ for pid in players {
+ let p = c
+ .game
+ .players
+ .get_mut(&pid)
+ .ok_or(anyhow!("player missing"))?;
p.movement.position = self.to;
+ c.packet_out
+ .push_back(PacketC::MovementSync { player: pid });
}
Ok(())