aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-06-26 13:15:00 +0200
committermetamuffin <metamuffin@disroot.org>2024-06-26 13:15:00 +0200
commit9be454fc277d910fe563aac4a792f9a53c32954d (patch)
tree6ec40f910b81e1923302674a846402ed3502b512
parentc126d3d3e84fe3b24b42afc7f68f05342988c8c9 (diff)
downloadhurrycurry-9be454fc277d910fe563aac4a792f9a53c32954d.tar
hurrycurry-9be454fc277d910fe563aac4a792f9a53c32954d.tar.bz2
hurrycurry-9be454fc277d910fe563aac4a792f9a53c32954d.tar.zst
present customers walking through walls
-rw-r--r--readme.md17
-rw-r--r--server/src/customer/mod.rs60
-rw-r--r--server/src/main.rs1
-rw-r--r--server/src/state.rs13
4 files changed, 46 insertions, 45 deletions
diff --git a/readme.md b/readme.md
index 0c03be45..61b10185 100644
--- a/readme.md
+++ b/readme.md
@@ -1,20 +1,3 @@
-<!--
- Undercooked - a game about cooking
- Copyright 2024 metamuffin
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, version 3 of the License only.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
-
--->
# undercooked
A cooperative multiplayer game about cooking.
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(())