diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-06-03 19:45:05 +0200 | 
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-06-03 19:45:08 +0200 | 
| commit | 9ee7eef2919feffe4e0695494d4027e8ec011808 (patch) | |
| tree | 4fbb5347e7166911d08ae31dd3c20556b61c943e | |
| parent | 63f7321e50b251d19f20dc929fc37a45cccdbb38 (diff) | |
| download | hurrycurry-9ee7eef2919feffe4e0695494d4027e8ec011808.tar hurrycurry-9ee7eef2919feffe4e0695494d4027e8ec011808.tar.bz2 hurrycurry-9ee7eef2919feffe4e0695494d4027e8ec011808.tar.zst | |
Add pedestrians (and custom spawn locations)
| -rw-r--r-- | Cargo.lock | 92 | ||||
| -rw-r--r-- | data/maps/debug.yaml | 4 | ||||
| -rw-r--r-- | data/maps/debug2.yaml | 4 | ||||
| -rw-r--r-- | pixel-client/src/game.rs | 1 | ||||
| -rw-r--r-- | server/Cargo.toml | 1 | ||||
| -rw-r--r-- | server/bot/src/main.rs | 1 | ||||
| -rw-r--r-- | server/editor/src/main.rs | 1 | ||||
| -rw-r--r-- | server/protocol/src/lib.rs | 3 | ||||
| -rw-r--r-- | server/src/entity/bot.rs | 1 | ||||
| -rw-r--r-- | server/src/entity/mod.rs | 22 | ||||
| -rw-r--r-- | server/src/entity/pedestrians.rs | 86 | ||||
| -rw-r--r-- | server/src/entity/tram.rs | 1 | ||||
| -rw-r--r-- | server/src/main.rs | 1 | ||||
| -rw-r--r-- | server/src/server.rs | 11 | ||||
| -rw-r--r-- | test-client/main.ts | 3 | 
15 files changed, 203 insertions, 29 deletions
| @@ -958,7 +958,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"  dependencies = [   "cfg-if",   "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4",  ]  [[package]] @@ -1157,7 +1169,7 @@ dependencies = [   "hurrycurry-client-lib",   "hurrycurry-protocol",   "log", - "rand 0.9.0-alpha.2", + "rand 0.9.1",   "rustls",  ] @@ -1250,7 +1262,7 @@ dependencies = [   "futures-util",   "hurrycurry-protocol",   "log", - "rand 0.9.0-alpha.2", + "rand 0.9.1",   "rustls",   "serde",   "serde_json", @@ -1275,7 +1287,8 @@ dependencies = [   "log",   "mdns-sd",   "pollster", - "rand 0.9.0-alpha.2", + "rand 0.9.1", + "rand_distr",   "reqwest",   "serde",   "serde_json", @@ -1582,6 +1595,12 @@ dependencies = [  ]  [[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]]  name = "libyml"  version = "0.0.5"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1742,7 +1761,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"  dependencies = [   "hermit-abi 0.3.9",   "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1",   "windows-sys 0.52.0",  ] @@ -1857,6 +1876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"  dependencies = [   "autocfg", + "libm",  ]  [[package]] @@ -1997,7 +2017,7 @@ dependencies = [   "hurrycurry-client-lib",   "hurrycurry-protocol",   "log", - "rand 0.9.0-alpha.2", + "rand 0.9.1",   "rustls",   "sdl2",   "serde", @@ -2188,6 +2208,12 @@ dependencies = [  ]  [[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]]  name = "rand"  version = "0.8.5"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2200,13 +2226,12 @@ dependencies = [  [[package]]  name = "rand" -version = "0.9.0-alpha.2" +version = "0.9.1"  source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e256ff62cee3e03def855c4d4260106d2bb1696fdc01af03e9935b993720a5" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"  dependencies = [ - "rand_chacha 0.9.0-alpha.2", - "rand_core 0.9.0-alpha.2", - "zerocopy", + "rand_chacha 0.9.0", + "rand_core 0.9.3",  ]  [[package]] @@ -2221,12 +2246,12 @@ dependencies = [  [[package]]  name = "rand_chacha" -version = "0.9.0-alpha.2" +version = "0.9.0"  source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d299e9db34f6623b2a9e86c015d6e173d5f46d64d4b9b8cc46ae8a982a50b04c" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"  dependencies = [   "ppv-lite86", - "rand_core 0.9.0-alpha.2", + "rand_core 0.9.3",  ]  [[package]] @@ -2235,17 +2260,26 @@ version = "0.6.4"  source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"  dependencies = [ - "getrandom", + "getrandom 0.2.15",  ]  [[package]]  name = "rand_core" -version = "0.9.0-alpha.2" +version = "0.9.3"  source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e93f5a5e3c528cda9acb0928c31b2ba868c551cc46e67b778075e34aab9906" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"  dependencies = [ - "getrandom", - "zerocopy", + "getrandom 0.3.3", +] + +[[package]] +name = "rand_distr" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +dependencies = [ + "num-traits", + "rand 0.9.1",  ]  [[package]] @@ -2451,7 +2485,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"  dependencies = [   "cc",   "cfg-if", - "getrandom", + "getrandom 0.2.15",   "libc",   "spin",   "untrusted", @@ -3432,6 +3466,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"  [[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]]  name = "wasm-bindgen"  version = "0.2.92"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3756,6 +3799,15 @@ dependencies = [  ]  [[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]]  name = "xdg"  version = "2.5.2"  source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/data/maps/debug.yaml b/data/maps/debug.yaml index 2e902315..90cd3480 100644 --- a/data/maps/debug.yaml +++ b/data/maps/debug.yaml @@ -102,10 +102,6 @@ entities:      - !environment_effect { name: rain, on: 60, off: 40 }      - !environment_effect { name: wind, on: 60, off: 40 }      - !environment [night] -    - !tram -      length: 3 -      character: 51 -      points: [[1, 2], [15, 2], [15, 8], [1, 8]]  tile_entities:      "}": !conveyor { dir: [1, 0], filter: dough-foodprocessor } diff --git a/data/maps/debug2.yaml b/data/maps/debug2.yaml index 02e67809..3c849045 100644 --- a/data/maps/debug2.yaml +++ b/data/maps/debug2.yaml @@ -102,6 +102,10 @@ entities:        points: [[3, 3], [23, 3], [23, 15], [3, 15]]        smoothing: 3.        spacing: 0.3625 +    - !pedestrians +      points: [[7, 7], [19, 7], [19, 13], [7, 13]] +      spawn_delay: 0.5 +      spawn_delay_stdev: 1  chef_spawn: "~"  customer_spawn: "!" diff --git a/pixel-client/src/game.rs b/pixel-client/src/game.rs index cbcc62d5..cfac7082 100644 --- a/pixel-client/src/game.rs +++ b/pixel-client/src/game.rs @@ -91,6 +91,7 @@ impl Game {              name: config.username.clone(),              class: PlayerClass::Chef,              character: 0, +            position: None,          });          Self { diff --git a/server/Cargo.toml b/server/Cargo.toml index 06a22798..8f68fd17 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -15,6 +15,7 @@ tokio-tungstenite = "0.24.0"  futures-util = "0.3.30"  serde_yml = "0.0.12"  rand = "0.9.0-alpha.2" +rand_distr = "0.5.1"  shlex = "1.3.0"  clap = { version = "4.5.18", features = ["derive"] }  reqwest = { version = "0.12.7", optional = true, default-features = false, features = [ diff --git a/server/bot/src/main.rs b/server/bot/src/main.rs index 918be7e1..56eedc13 100644 --- a/server/bot/src/main.rs +++ b/server/bot/src/main.rs @@ -59,6 +59,7 @@ fn main() -> Result<()> {          character: args.character,          class: PlayerClass::Bot,          id: None, +        position: None,      });      let mut bots = Vec::new(); diff --git a/server/editor/src/main.rs b/server/editor/src/main.rs index 2c05dfbc..620daeb5 100644 --- a/server/editor/src/main.rs +++ b/server/editor/src/main.rs @@ -411,6 +411,7 @@ fn start_map_bot(address: &str, own_addr: &str, mapname: &str) -> Result<()> {          character: 0,          class: PlayerClass::Bot,          id: None, +        position: None,      });      let mut timer = 10.; diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 4f0d5d67..db65ddd2 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -116,6 +116,9 @@ pub enum PacketS {          class: PlayerClass,          #[serde(skip)] // TODO fix bincode can still set id          id: Option<PlayerID>, // used entity bots that cant receive a response +        #[serde(skip)] // TODO fix bincode aswell +        #[bincode(with_serde)] +        position: Option<Vec2>, // used entity bots that spawn in different locations      },      Leave {          player: PlayerID, diff --git a/server/src/entity/bot.rs b/server/src/entity/bot.rs index 6e6c9162..922cc55e 100644 --- a/server/src/entity/bot.rs +++ b/server/src/entity/bot.rs @@ -57,6 +57,7 @@ impl<T: BotAlgo + Any> Entity for BotDriver<T> {                  character,                  id: Some(self.id),                  class, +                position: None,              })          } diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs index ddafc2f7..75ea0e9b 100644 --- a/server/src/entity/mod.rs +++ b/server/src/entity/mod.rs @@ -22,12 +22,14 @@ pub mod conveyor;  pub mod customers;  pub mod environment_effect;  pub mod item_portal; +pub mod pedestrians;  pub mod player_portal;  pub mod tram;  pub mod tutorial;  use crate::{      data::{ItemTileRegistry, Serverdata}, +    entity::pedestrians::Pedestrians,      message::TrError,      scoreboard::ScoreboardStore,  }; @@ -45,7 +47,10 @@ use hurrycurry_protocol::{  use item_portal::ItemPortal;  use player_portal::PlayerPortal;  use serde::{Deserialize, Serialize}; -use std::{any::Any, collections::VecDeque}; +use std::{ +    any::Any, +    collections::{HashMap, VecDeque}, +};  use tram::Tram;  pub type DynEntity = Box<dyn Entity + Send + Sync + 'static>; @@ -143,6 +148,11 @@ pub enum EntityDecl {          smoothing: f32,      },      Book, +    Pedestrians { +        spawn_delay: f32, +        spawn_delay_stdev: f32, +        points: Vec<Vec2>, +    },  }  pub fn construct_entity( @@ -222,5 +232,15 @@ pub fn construct_entity(              spacing,              smoothing,          }), +        EntityDecl::Pedestrians { +            spawn_delay, +            spawn_delay_stdev, +            points, +        } => Box::new(Pedestrians { +            players: HashMap::new(), +            points, +            spawn_delay_distr: rand_distr::Normal::new(spawn_delay, spawn_delay_stdev).unwrap(), +            cooldown: 0., +        }),      })  } diff --git a/server/src/entity/pedestrians.rs b/server/src/entity/pedestrians.rs new file mode 100644 index 00000000..9b433ded --- /dev/null +++ b/server/src/entity/pedestrians.rs @@ -0,0 +1,86 @@ +use std::collections::HashMap; + +/* +    Hurry Curry! - a game about cooking +    Copyright 2025 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/>. + +*/ +use super::{Entity, EntityContext}; +use anyhow::Result; +use hurrycurry_protocol::{glam::Vec2, PacketS, PlayerClass, PlayerID}; +use rand::{random, rng}; +use rand_distr::Distribution; + +pub struct Pedestrians { +    pub players: HashMap<PlayerID, usize>, +    pub points: Vec<Vec2>, +    pub spawn_delay_distr: rand_distr::Normal<f32>, +    pub cooldown: f32, +} + +impl Entity for Pedestrians { +    fn finished(&self) -> bool { +        false +    } +    fn tick(&mut self, c: EntityContext<'_>) -> Result<()> { +        self.cooldown -= c.dt; +        if self.cooldown <= 0. && self.players.len() < 32 { +            let id = PlayerID(random()); +            c.packet_in.push_back(PacketS::Join { +                name: "Pedestrian".to_string(), +                character: 0, +                class: PlayerClass::Customer, +                id: Some(id), +                position: self.points.get(0).copied(), +            }); +            self.players.insert(id, 0); +            self.cooldown += self.spawn_delay_distr.sample(&mut rng()).max(0.1); +        } + +        let mut remove = Vec::new(); + +        for (id, index) in &mut self.players { +            if let Some(player) = c.game.players.get(id) { +                let diff = self.points[*index] - player.movement.position; +                if diff.length() < 0.8 { +                    *index += 1; +                    if *index >= self.points.len() { +                        remove.push(*id) +                    } +                } else { +                    c.packet_in.push_back(PacketS::Movement { +                        player: *id, +                        dir: diff, +                        boost: false, +                        pos: None, +                    }); +                } +            } +        } + +        for id in remove { +            if self.players.remove(&id).is_some() { +                c.packet_in.push_back(PacketS::Leave { player: id }); +            } +        } + +        Ok(()) +    } +    fn destructor(&mut self, c: EntityContext<'_>) { +        for (id, _) in self.players.drain() { +            c.packet_in.push_back(PacketS::Leave { player: id }) +        } +    } +} diff --git a/server/src/entity/tram.rs b/server/src/entity/tram.rs index 5b7fcaa8..26a191aa 100644 --- a/server/src/entity/tram.rs +++ b/server/src/entity/tram.rs @@ -43,6 +43,7 @@ impl Entity for Tram {                      character: self.character,                      class: PlayerClass::Bot,                      id: Some(id), +                    position: None,                  });                  self.ids.push(id);              } diff --git a/server/src/main.rs b/server/src/main.rs index 7f3de073..b1dc503b 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -359,6 +359,7 @@ mod test {                          character: 1,                          class: PlayerClass::Chef,                          id: None, +                        position: None,                      },                  )                  .await diff --git a/server/src/server.rs b/server/src/server.rs index a06f4f36..f9342add 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -76,6 +76,7 @@ pub trait GameServerExt {          character: i32,          class: PlayerClass,          serverdata: &Serverdata, +        custom_position: Option<Vec2>,          packet_out: Option<&mut VecDeque<PacketC>>,      );      fn prime_client(&self) -> Vec<PacketC>; @@ -143,7 +144,7 @@ impl GameServerExt for Game {              }          }          for (id, (name, character, class)) in players { -            self.join_player(id, name, character, class, serverdata, None); +            self.join_player(id, name, character, class, serverdata, None, None);          }          packet_out.extend(self.prime_client()); @@ -247,12 +248,13 @@ impl GameServerExt for Game {          character: i32,          class: PlayerClass,          serverdata: &Serverdata, +        custom_position: Option<Vec2>,          packet_out: Option<&mut VecDeque<PacketC>>,      ) { -        let position = match class { +        let position = custom_position.unwrap_or(match class {              PlayerClass::Customer => serverdata.customer_spawn,              PlayerClass::Bot | PlayerClass::Chef => serverdata.chef_spawn, -        } + (Vec2::new(random(), random()) - 0.5); +        }) + (Vec2::new(random(), random()) - 0.5);          self.players.insert(              id,              Player { @@ -353,6 +355,7 @@ impl Server {                  load_map: &mut None,              });          } +        self.tick(0.);          self.game.load(              gamedata,              &serverdata, @@ -375,6 +378,7 @@ impl Server {                  character,                  id,                  class, +                position,              } => {                  if name.chars().count() > 32 || name.len() > 64 {                      return Err(tre!( @@ -397,6 +401,7 @@ impl Server {                      character,                      class,                      &self.data, +                    position,                      Some(&mut self.packet_out),                  );                  replies.push(PacketC::Joined { id }) diff --git a/test-client/main.ts b/test-client/main.ts index f52e7f40..ef38494d 100644 --- a/test-client/main.ts +++ b/test-client/main.ts @@ -327,7 +327,7 @@ export let chat: null | HTMLInputElement = null;  const QUICK_COMMANDS: { [key: string]: string } = {      "Numpad1": "/start junior", -    "Numpad2": "/start senior", +    "Numpad2": "/start debug2",      "Numpad3": "/start sophomore",      "Numpad4": "/start debug",      "Numpad5": "/start 5star", @@ -336,6 +336,7 @@ const QUICK_COMMANDS: { [key: string]: string } = {      "Numpad9": "/start-tutorial plate:bun",      "Numpad7": "/end-tutorial",      "Numpad0": "/end", +    "NumpadEnter": "/r",  }  export const keys_down = new Set(); | 
