aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/customer/mod.rs60
-rw-r--r--server/src/main.rs1
-rw-r--r--server/src/state.rs13
3 files changed, 46 insertions, 28 deletions
diff --git a/server/src/customer/mod.rs b/server/src/customer/mod.rs
index 185133e7..0b300b6e 100644
--- a/server/src/customer/mod.rs
+++ b/server/src/customer/mod.rs
@@ -24,8 +24,9 @@ use crate::{
protocol::{DemandIndex, ItemIndex, Message, PacketC, PacketS, PlayerID},
state::State,
};
+use anyhow::{anyhow, Result};
use glam::{IVec2, Vec2};
-use log::{debug, error};
+use log::{debug, error, warn};
use movement::MovementBase;
use pathfinding::{find_path, Path};
use rand::{random, thread_rng};
@@ -81,12 +82,12 @@ struct Customer {
pub async fn customer(gstate: Arc<RwLock<State>>, mut grx: broadcast::Receiver<PacketC>) {
let mut state = CustomerManager {
+ disabled: true,
customer_id_counter: PlayerID(0),
walkable: Default::default(),
chairs: Default::default(),
items: Default::default(),
customers: Default::default(),
- disabled: true,
demand: DemandState {
data: Gamedata::default(),
},
@@ -101,7 +102,13 @@ pub async fn customer(gstate: Arc<RwLock<State>>, mut grx: broadcast::Receiver<P
loop {
tokio::select! {
packet = grx.recv() => {
- let packet = packet.unwrap();
+ let packet = match packet {
+ Ok(p) => p,
+ Err(e) => {
+ warn!("{e}");
+ continue;
+ }
+ };
match packet {
PacketC::PutItem { .. }
| PacketC::TakeItem { .. }
@@ -115,7 +122,9 @@ pub async fn customer(gstate: Arc<RwLock<State>>, mut grx: broadcast::Receiver<P
}
_ = interval.tick() => {
if !state.disabled {
- state.tick(&mut packets_out, 0.04);
+ if let Err(e) = state.tick(&mut packets_out, 0.04) {
+ warn!("error caught: {e}")
+ }
for (player,packet) in packets_out.drain(..) {
if let Err(e) = gstate.write().await.packet_in(player, packet).await {
error!("customer misbehaved: {e}")
@@ -159,22 +168,25 @@ impl CustomerManager {
self.customers.remove(&id);
}
PacketC::UpdateMap {
- tile: pos,
- kind: Some(tile),
- ..
+ tile: pos, kind, ..
} => {
- let tilename = self.demand.data.tile_name(tile);
- if !self.demand.data.is_tile_colliding(tile) {
- self.walkable.insert(pos);
- }
- if tilename == "chair" {
- self.chairs.insert(pos, true);
+ if let Some(kind) = kind {
+ let tilename = self.demand.data.tile_name(kind);
+ if !self.demand.data.is_tile_colliding(kind) {
+ self.walkable.insert(pos);
+ }
+ if tilename == "chair" {
+ self.chairs.insert(pos, true);
+ }
+ } else {
+ self.chairs.remove(&pos);
+ self.walkable.remove(&pos);
}
}
_ => (),
}
}
- pub fn tick(&mut self, packets_out: &mut Vec<(PlayerID, PacketS)>, dt: f32) {
+ pub fn tick(&mut self, packets_out: &mut Vec<(PlayerID, PacketS)>, dt: f32) -> Result<()> {
if self.customers.len() < self.demand.target_customer_count() {
self.customer_id_counter.0 -= 1;
let id = self.customer_id_counter;
@@ -185,13 +197,9 @@ impl CustomerManager {
character: -2,
},
));
- let chair = select_chair(&mut self.chairs);
- let path = find_path(
- &self.walkable,
- self.demand.data.customer_spawn.as_ivec2(),
- chair,
- )
- .expect("no path");
+ let chair = select_chair(&mut self.chairs).ok_or(anyhow!("no free chair found"))?;
+ let to = self.demand.data.customer_spawn.as_ivec2();
+ let path = find_path(&self.walkable, to, chair).ok_or(anyhow!("no path to {to}"))?;
self.customers.insert(
id,
Customer {
@@ -292,7 +300,7 @@ impl CustomerManager {
p.movement.position.as_ivec2(),
self.demand.data.customer_spawn.as_ivec2(),
)
- .expect("no path to exit");
+ .ok_or(anyhow!("no path to exit"))?;
*self.chairs.get_mut(&chair).unwrap() = true;
p.state = CustomerState::Exiting { path }
}
@@ -310,16 +318,16 @@ impl CustomerManager {
for c in customers_to_remove {
self.customers.remove(&c).unwrap();
}
+ Ok(())
}
}
-pub fn select_chair(chairs: &mut HashMap<IVec2, bool>) -> IVec2 {
+pub fn select_chair(chairs: &mut HashMap<IVec2, bool>) -> Option<IVec2> {
use rand::seq::IteratorRandom;
let (chosen, free) = chairs
.iter_mut()
.filter(|(_p, free)| **free)
- .choose(&mut thread_rng())
- .unwrap();
+ .choose(&mut thread_rng())?;
*free = false;
- *chosen
+ Some(*chosen)
}
diff --git a/server/src/main.rs b/server/src/main.rs
index 6773bf29..b3e6334d 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -99,6 +99,7 @@ async fn main() -> Result<()> {
}
});
spawn(async move {
+ info!("{id:?} joined");
while let Some(Ok(message)) = read.next().await {
match message {
Message::Text(line) => {
diff --git a/server/src/state.rs b/server/src/state.rs
index 98f92a24..08d8516a 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -17,7 +17,11 @@ pub struct State {
#[derive(Parser)]
#[clap(multicall = true)]
enum Command {
- Start { spec: String },
+ Start {
+ #[arg(default_value = "default-small-default")]
+ spec: String,
+ },
+ End,
}
impl State {
@@ -60,7 +64,12 @@ impl State {
async fn handle_command(&mut self, command: Command) -> Result<()> {
match command {
Command::Start { spec } => {
- self.game.load(self.index.generate(spec)?);
+ let data = self.index.generate(spec)?;
+ self.game.load(data);
+ }
+ Command::End => {
+ self.game
+ .load(self.index.generate("none-lobby-none".to_string())?);
}
}
Ok(())