diff options
| author | nokoe <nokoe@mailbox.org> | 2026-02-27 19:41:22 +0100 |
|---|---|---|
| committer | nokoe <nokoe@mailbox.org> | 2026-02-27 19:41:22 +0100 |
| commit | c1a20426838a5729c2c874eae73dbb974fcf7906 (patch) | |
| tree | 7138b1a4ca5f7f6b561aa05b0aae05071c581084 /server | |
| parent | 70e6d510ba236730260371a3259ffb16f999f5d4 (diff) | |
| parent | a859bceeddc8e746bba630b3cc197532b68adbcb (diff) | |
| download | hurrycurry-c1a20426838a5729c2c874eae73dbb974fcf7906.tar hurrycurry-c1a20426838a5729c2c874eae73dbb974fcf7906.tar.bz2 hurrycurry-c1a20426838a5729c2c874eae73dbb974fcf7906.tar.zst | |
Merge branch 'stable-rust'
Diffstat (limited to 'server')
| -rw-r--r-- | server/Cargo.toml | 1 | ||||
| -rw-r--r-- | server/bot/Cargo.toml | 1 | ||||
| -rw-r--r-- | server/bot/src/algos/customer.rs | 11 | ||||
| -rw-r--r-- | server/bot/src/algos/frank.rs | 6 | ||||
| -rw-r--r-- | server/bot/src/lib.rs | 9 | ||||
| -rw-r--r-- | server/discover/src/main.rs | 9 | ||||
| -rw-r--r-- | server/registry/src/lobby.rs | 4 | ||||
| -rw-r--r-- | server/registry/src/main.rs | 2 | ||||
| -rw-r--r-- | server/replaytool/Cargo.toml | 1 | ||||
| -rw-r--r-- | server/replaytool/src/main.rs | 1 | ||||
| -rw-r--r-- | server/replaytool/src/render.rs | 16 | ||||
| -rw-r--r-- | server/src/entity/customers.rs | 9 | ||||
| -rw-r--r-- | server/src/entity/pedestrians.rs | 7 | ||||
| -rw-r--r-- | server/src/entity/tag_minigame.rs | 5 | ||||
| -rw-r--r-- | server/src/lib.rs | 10 | ||||
| -rw-r--r-- | server/src/network/mdns.rs | 5 | ||||
| -rw-r--r-- | server/src/network/register.rs | 17 | ||||
| -rw-r--r-- | server/src/server.rs | 3 | ||||
| -rw-r--r-- | server/src/state.rs | 5 |
19 files changed, 68 insertions, 54 deletions
diff --git a/server/Cargo.toml b/server/Cargo.toml index f74854d6..724d571b 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -31,6 +31,7 @@ hurrycurry-protocol = { path = "protocol" } hurrycurry-game-core = { path = "game-core" } hurrycurry-bot = { path = "bot" } hurrycurry-data = { path = "data" } +rand = "0.10.0" [target.'cfg(windows)'.dependencies] windows-registry = "0.6" diff --git a/server/bot/Cargo.toml b/server/bot/Cargo.toml index c78410b3..e73be6e9 100644 --- a/server/bot/Cargo.toml +++ b/server/bot/Cargo.toml @@ -11,6 +11,7 @@ anyhow = "1.0.99" env_logger = "0.11.8" rustls = { version = "0.23.31", features = ["ring"] } clap = { version = "4.5.47", features = ["derive"] } +rand = "0.10.0" [features] # default = ["debug_events"] diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs index 0ed1ba9a..fdd911dc 100644 --- a/server/bot/src/algos/customer.rs +++ b/server/bot/src/algos/customer.rs @@ -18,7 +18,7 @@ use crate::{ BotAlgo, PacketSink, pathfinding::{HoldLocation, Path, find_path}, - random_float, + random_usize, }; use hurrycurry_game_core::Game; use hurrycurry_protocol::{ @@ -26,7 +26,6 @@ use hurrycurry_protocol::{ glam::{IVec2, Vec2}, }; use log::debug; -use std::random::random; #[derive(Debug, Clone)] pub struct Customer { @@ -109,7 +108,8 @@ impl CustomerState { .flatten() .copied() .collect::<Vec<_>>(); //? maybe opt alloc - if let Some(&chair) = chairs.get(random::<usize>(..) % chairs.len().max(1)) + if let Some(&chair) = + chairs.get(random_usize(&mut rand::rng()) % chairs.len().max(1)) && let Some(path) = find_path(game, pos.as_ivec2(), chair) { debug!("{me:?} -> entering"); @@ -131,10 +131,11 @@ impl CustomerState { *ticks += 1; let check = *ticks % 10 == 0; if path.is_done() { - let demand = DemandIndex(random::<usize>(..) % game.data.demands.len()); + let demand = + DemandIndex(random_usize(&mut rand::rng()) % game.data.demands.len()); let requested_item = game.data.demands[demand.0].input; debug!("{me:?} -> waiting"); - let timeout = 90. + random_float() * 60.; + let timeout = 90. + rand::random::<f32>() * 60.; let mut facing = Vec2::ZERO; for off in [IVec2::NEG_X, IVec2::NEG_Y, IVec2::X, IVec2::Y] { if game diff --git a/server/bot/src/algos/frank.rs b/server/bot/src/algos/frank.rs index 8bd6d17b..156d655d 100644 --- a/server/bot/src/algos/frank.rs +++ b/server/bot/src/algos/frank.rs @@ -21,7 +21,7 @@ use crate::{ }; use hurrycurry_game_core::Game; use hurrycurry_protocol::{Message, PacketS, PlayerClass, PlayerID, glam::Vec2}; -use std::random::random; +use rand::{random, seq::IndexedRandom}; pub struct Frank { me: PlayerID, @@ -86,7 +86,7 @@ impl BotAlgo for Frank { out.push(PacketS::Communicate { player: self.me, message: Some(Message::Translation { - id: format!("s.bot.frank.line.{}", random::<u32>(..) % 8), + id: format!("s.bot.frank.line.{}", random::<u32>() % 8), params: vec![Message::Text(player.name.clone())], }), timeout: Some(3.), @@ -122,5 +122,5 @@ fn find_chef(game: &Game, me: PlayerID) -> Option<PlayerID> { .filter(|(i, p)| p.class == PlayerClass::Chef && **i != me) .map(|(i, _)| *i) .collect::<Vec<_>>(); - chefs.get(random::<usize>(..) % chefs.len().max(1)).copied() + chefs.choose(&mut rand::rng()).copied() } diff --git a/server/bot/src/lib.rs b/server/bot/src/lib.rs index 078314b1..31f2132a 100644 --- a/server/bot/src/lib.rs +++ b/server/bot/src/lib.rs @@ -15,7 +15,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#![feature(random)] + pub mod algos; pub mod pathfinding; pub mod step; @@ -24,7 +24,8 @@ use hurrycurry_game_core::Game; use hurrycurry_protocol::PacketS; #[cfg(feature = "debug_events")] use hurrycurry_protocol::{PlayerID, glam::Vec3}; -use std::{collections::VecDeque, random::random}; +use rand::{Rng, RngExt}; +use std::{collections::VecDeque}; pub struct PacketSink<'a> { buf: &'a mut VecDeque<PacketS>, @@ -54,8 +55,8 @@ impl<T: BotAlgo + ?Sized> BotAlgo for Box<T> { } } -fn random_float() -> f32 { - random::<u32>(..) as f32 / u32::MAX as f32 +fn random_usize<T: Rng>(rng: &mut T) -> usize { + usize::from_ne_bytes(rng.random()) } #[cfg(feature = "debug_events")] diff --git a/server/discover/src/main.rs b/server/discover/src/main.rs index 3dcb96bf..8b86af74 100644 --- a/server/discover/src/main.rs +++ b/server/discover/src/main.rs @@ -15,7 +15,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#![feature(never_type)] use anyhow::Result; use clap::Parser; use http_body_util::Full; @@ -37,7 +36,7 @@ struct Args { version: bool, } -fn main() -> Result<()> { +fn main() -> anyhow::Result<()> { let args = Args::parse(); if args.version { println!("{}", env!("CARGO_PKG_VERSION")); @@ -49,8 +48,10 @@ fn main() -> Result<()> { .enable_all() .build()? .block_on(async_main())?; + Ok(()) } -async fn async_main() -> Result<!> { + +async fn async_main() -> Result<anyhow::Error /*TODO: never type*/> { let mdns = ServiceDaemon::new()?; let mdns_events = mdns.browse("_hurrycurry._tcp.local.")?; @@ -113,7 +114,7 @@ async fn async_main() -> Result<!> { service_fn(move |_req| { let entries = entries.clone(); async move { - Ok::<_, !>(match _req.uri().path() { + anyhow::Ok(match _req.uri().path() { "/" => Response::new(Full::new(Bytes::from( "Hurry Curry! local discovery service", ))), diff --git a/server/registry/src/lobby.rs b/server/registry/src/lobby.rs index 3a3880f6..acbb69bd 100644 --- a/server/registry/src/lobby.rs +++ b/server/registry/src/lobby.rs @@ -23,13 +23,13 @@ use tokio::{ use tokio_tungstenite::tungstenite::Message; pub(crate) async fn lobby_wrapper(registry: Arc<RwLock<Registry>>, saddr: SocketAddr) { - let Err(e) = lobby(registry, saddr).await; + let Err(e) = lobby(registry, saddr).await else { unreachable!() }; error!("lobby crashed: {e}"); } const TILES: &[(&str, bool)] = &[("grass", false), ("black-hole", false)]; -async fn lobby(registry: Arc<RwLock<Registry>>, saddr: SocketAddr) -> Result<!> { +async fn lobby(registry: Arc<RwLock<Registry>>, saddr: SocketAddr) -> Result<()> { let ws_listener = TcpListener::bind(saddr).await?; loop { diff --git a/server/registry/src/main.rs b/server/registry/src/main.rs index 924cbe24..224845d3 100644 --- a/server/registry/src/main.rs +++ b/server/registry/src/main.rs @@ -15,7 +15,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#![feature(never_type)] + pub mod conn_test; pub mod list; pub mod lobby; diff --git a/server/replaytool/Cargo.toml b/server/replaytool/Cargo.toml index cc13b4a9..b3055704 100644 --- a/server/replaytool/Cargo.toml +++ b/server/replaytool/Cargo.toml @@ -19,3 +19,4 @@ async-compression = { version = "0.4.30", features = ["zstd", "tokio"] } rustls = { version = "0.23.31", features = ["ring"] } hurrycurry-protocol = { path = "../protocol" } +rand = "0.10.0" diff --git a/server/replaytool/src/main.rs b/server/replaytool/src/main.rs index 7f60287f..8dde133d 100644 --- a/server/replaytool/src/main.rs +++ b/server/replaytool/src/main.rs @@ -15,7 +15,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#![feature(exit_status_error, random)] pub mod record; pub mod render; diff --git a/server/replaytool/src/render.rs b/server/replaytool/src/render.rs index b3290e07..9654256d 100644 --- a/server/replaytool/src/render.rs +++ b/server/replaytool/src/render.rs @@ -17,9 +17,9 @@ */ use crate::replay::replay; -use anyhow::{Context, Result, anyhow}; +use anyhow::{Context, Result, anyhow, bail}; use log::info; -use std::{path::PathBuf, random::random, str::FromStr}; +use std::{path::PathBuf, str::FromStr}; use tokio::{ fs::{File, create_dir_all, remove_dir, remove_file}, io::AsyncWriteExt, @@ -58,9 +58,10 @@ pub struct RenderArgs { pub async fn render(a: RenderArgs) -> Result<()> { let ws_listener = TcpListener::bind(("127.0.0.1", a.port)).await?; - let cwd = PathBuf::from_str("/tmp") - .unwrap() - .join(format!("hurrycurry-render-cfg-{:016x}", random::<u64>(..))); + let cwd = PathBuf::from_str("/tmp").unwrap().join(format!( + "hurrycurry-render-cfg-{:016x}", + rand::random::<u64>() + )); let config = { let (width, height) = a @@ -130,7 +131,10 @@ window/size/viewport_height={height} info!("listening for websockets on {}", ws_listener.local_addr()?); replay(&ws_listener, &a.input).await?; - client.wait().await?.exit_ok()?; + let e = client.wait().await?; + if !e.success() { + bail!("failed with code {:?}", e.code()) + } remove_file(cwd.join("override.cfg")).await?; remove_file(cwd.join("client.pck")).await?; diff --git a/server/src/entity/customers.rs b/server/src/entity/customers.rs index 2e2f82af..d5e1751d 100644 --- a/server/src/entity/customers.rs +++ b/server/src/entity/customers.rs @@ -16,12 +16,11 @@ */ use super::{Entity, EntityContext, bot::BotDriver}; -use crate::random_float; use anyhow::Result; use hurrycurry_bot::algos::Customer; use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, PlayerClass, TileIndex}; -use std::random::random; +use rand::random; pub struct Customers { customers: Vec<BotDriver<Customer>>, @@ -62,12 +61,12 @@ impl Entity for Customers { self.current_spawn_cooldown = self.current_spawn_cooldown.max(0.); if self.customers.len() < max_count && self.current_spawn_cooldown <= 0. { self.current_spawn_cooldown = - self.spawn_cooldown + random_float() * self.spawn_cooldown; + self.spawn_cooldown + random::<f32>() * self.spawn_cooldown; let bot = BotDriver::new( "".to_string(), Character { - color: random(..), - hairstyle: random(..), + color: random(), + hairstyle: random(), headwear: 0, }, PlayerClass::Customer, diff --git a/server/src/entity/pedestrians.rs b/server/src/entity/pedestrians.rs index 0d33bfd0..4fe91464 100644 --- a/server/src/entity/pedestrians.rs +++ b/server/src/entity/pedestrians.rs @@ -21,7 +21,8 @@ use super::{Entity, EntityContext}; use anyhow::Result; use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, PacketS, PlayerClass, PlayerID, glam::Vec2}; -use std::{collections::HashMap, random::random}; +use rand::random; +use std::collections::HashMap; pub struct Pedestrians { pub players: HashMap<PlayerID, usize>, @@ -44,8 +45,8 @@ impl Entity for Pedestrians { id: Some(id), name: "Pedestrian".to_string(), character: Character { - color: random(..), - hairstyle: random(..), + color: random(), + hairstyle: random(), headwear: 0, }, class: PlayerClass::Customer, diff --git a/server/src/entity/tag_minigame.rs b/server/src/entity/tag_minigame.rs index 48558b41..b0f3a711 100644 --- a/server/src/entity/tag_minigame.rs +++ b/server/src/entity/tag_minigame.rs @@ -22,7 +22,8 @@ use hurrycurry_locale::TrError; use hurrycurry_protocol::{ Hand, ItemIndex, ItemLocation, Message, PacketC, PlayerID, TileIndex, glam::IVec2, }; -use std::{collections::HashMap, fmt::Write, random::random}; +use rand::RngExt; +use std::{collections::HashMap, fmt::Write}; #[derive(Debug, Clone)] pub struct TagMinigame { @@ -60,7 +61,7 @@ impl Entity for TagMinigame { if player_ids.is_empty() { break; } - let id = player_ids[random::<usize>(..) % player_ids.len()]; + let id = player_ids[usize::from_ne_bytes(rand::rng().random())]; let player = c.game.players.get_mut(&id).expect("just got the ids"); if let Some(slot) = player.items.get_mut(0) { *slot = Some(Item { diff --git a/server/src/lib.rs b/server/src/lib.rs index c166e665..f2fdfbe6 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -15,7 +15,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#![feature(if_let_guard, iterator_try_collect, stmt_expr_attributes, random)] + pub mod benchmark; pub mod commands; pub mod entity; @@ -25,7 +25,8 @@ pub mod server; pub mod state; use hurrycurry_protocol::glam::Vec2; -use std::{fmt::Display, random::random}; +use rand::random; +use std::fmt::Display; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ConnectionID(pub i64); @@ -50,9 +51,6 @@ impl InterpolateExt for f32 { } } -fn random_float() -> f32 { - random::<u32>(..) as f32 / u32::MAX as f32 -} fn random_gauss() -> f32 { - [(); 12].map(|()| random_float()).iter().sum::<f32>() - 6. + [(); 12].map(|()| random::<f32>()).iter().sum::<f32>() - 6. } diff --git a/server/src/network/mdns.rs b/server/src/network/mdns.rs index 590ad656..b15a197a 100644 --- a/server/src/network/mdns.rs +++ b/server/src/network/mdns.rs @@ -21,7 +21,8 @@ use get_if_addrs::get_if_addrs; use hurrycurry_protocol::VERSION; use log::{info, warn}; use mdns_sd::{ServiceDaemon, ServiceInfo}; -use std::{collections::HashMap, net::SocketAddr, random::random, sync::Arc, time::Duration}; +use rand::random; +use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration}; use tokio::{sync::RwLock, time::interval}; pub async fn mdns_loop(name: String, listen_addr: SocketAddr, state: Arc<RwLock<Server>>) { @@ -33,7 +34,7 @@ pub async fn mdns_loop(name: String, listen_addr: SocketAddr, state: Arc<RwLock< } }; let mut interval = interval(Duration::from_secs(60)); - let hostname = format!("hurrycurry-{}.local.", random::<u64>(..)); // TODO use system hostname + let hostname = format!("hurrycurry-{}.local.", random::<u64>()); // TODO use system hostname loop { interval.tick().await; if let Err(e) = update_service(&d, &state, &name, &hostname, listen_addr).await { diff --git a/server/src/network/register.rs b/server/src/network/register.rs index 060994fe..101d96d1 100644 --- a/server/src/network/register.rs +++ b/server/src/network/register.rs @@ -19,10 +19,10 @@ use crate::server::Server; use anyhow::{Result, bail}; use hurrycurry_protocol::{VERSION, registry::Submission}; use log::{debug, error, info, warn}; +use rand::random; use reqwest::{Client, Url, header::USER_AGENT}; use std::{ net::{IpAddr, Ipv4Addr, Ipv6Addr}, - random::random, str::FromStr, sync::Arc, time::Duration, @@ -57,7 +57,7 @@ impl Register { registry_uri, players: 0, port, - secret: random(..), + secret: random(), state, ip4_client: if no4 { None @@ -108,7 +108,6 @@ impl Register { None } }); - #[rustfmt::skip] match tokio::join!(v4, v6) { (None, None) => info!("no registration sent"), (Some(Ok(())), None) => info!("Registration successful (IPv4)"), @@ -116,9 +115,15 @@ impl Register { (Some(Ok(())), Some(Ok(()))) => info!("Registration successful (IPv4 + IPv6)"), (Some(Err(e)), None) => error!("Registration failed (IPv4): {e}"), (None, Some(Err(e))) => error!("Registration failed (IPv6): {e}"), - (Some(Err(e1)), Some(Err(e2))) => error!("Registration failed (IPv4 + IPv6): {e1}, {e2}"), - (Some(Ok(())), Some(Err(e))) => warn!("Registration partially failed (IPv4 ok, IPv6 fail): {e}"), - (Some(Err(e)), Some(Ok(()))) => warn!("Registration partially failed (IPv4 fail, IPv6 ok): {e}"), + (Some(Err(e1)), Some(Err(e2))) => { + error!("Registration failed (IPv4 + IPv6): {e1}, {e2}") + } + (Some(Ok(())), Some(Err(e))) => { + warn!("Registration partially failed (IPv4 ok, IPv6 fail): {e}") + } + (Some(Err(e)), Some(Ok(()))) => { + warn!("Registration partially failed (IPv4 fail, IPv6 ok): {e}") + } } Ok(()) } diff --git a/server/src/server.rs b/server/src/server.rs index c698d28b..41156e6b 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -18,7 +18,6 @@ use crate::{ ConnectionID, entity::{Entities, EntityContext, construct_entity}, - random_float, scoreboard::ScoreboardStore, }; use anyhow::{Context, Result, anyhow}; @@ -318,7 +317,7 @@ impl GameServerExt for Game { PlayerClass::Customer => serverdata.customer_spawn.unwrap_or(serverdata.chef_spawn), PlayerClass::Bot | PlayerClass::Chef => serverdata.chef_spawn, PlayerClass::Tram => Vec2::ZERO, // should always have custom location - }) + (Vec2::new(random_float(), random_float()) - 0.5); + }) + (Vec2::new(rand::random::<f32>(), rand::random::<f32>()) - 0.5); self.players.insert( id, Player { diff --git a/server/src/state.rs b/server/src/state.rs index 9c5bfb6b..70c5b7f1 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -175,8 +175,9 @@ impl Server { timeout: None, player, .. - } if let Some(command) = text.strip_prefix("/") => { - match self.handle_command_parse(*player, command) { + } if text.strip_prefix("/").is_some() => { + // TODO: replace this by if let guard when stable + match self.handle_command_parse(*player, text.strip_prefix("/").unwrap()) { Ok(packets) => return Ok(packets), Err(e) => { return Ok(vec![PacketC::ServerMessage { |