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(); |