diff --git a/rc_core/src/persist/combat.rs b/rc_core/src/persist/combat.rs index 6b9a7ed..ee91456 100644 --- a/rc_core/src/persist/combat.rs +++ b/rc_core/src/persist/combat.rs @@ -389,7 +389,7 @@ fn default_rotation() -> GameEventSequence { auto_heal: true, }, multiplayer: GameEvent { - map: GameMap::Mars1, + map: GameMap::Earth1, visibility: GameVisibility::Poor, mode: GameType::SuddenDeath, auto_heal: true, @@ -449,7 +449,7 @@ fn default_rotation() -> GameEventSequence { auto_heal: true, }, multiplayer: GameEvent { - map: GameMap::Mars1, + map: GameMap::Earth2, visibility: GameVisibility::Poor, mode: GameType::SuddenDeath, auto_heal: true, diff --git a/rc_core/src/persist/config/cubes_json.rs b/rc_core/src/persist/config/cubes_json.rs index d290554..f26fd01 100644 --- a/rc_core/src/persist/config/cubes_json.rs +++ b/rc_core/src/persist/config/cubes_json.rs @@ -262,6 +262,7 @@ impl super::ConfigProvider for CubeConfig { super::ServerConfig { database: self.settings.server.database.clone(), auto_signup: self.settings.server.auto_signup, + queue_mode: super::QueueChangeMode::from_persist(self.settings.server.queue_mode.clone()), } } diff --git a/rc_core/src/persist/config/mod.rs b/rc_core/src/persist/config/mod.rs index 0249568..ccd49d7 100644 --- a/rc_core/src/persist/config/mod.rs +++ b/rc_core/src/persist/config/mod.rs @@ -2,7 +2,7 @@ mod cubes_json; pub use cubes_json::CubeConfig; mod traits; -pub use traits::{ConfigProvider, CompleteCampaignProvider, DevMessageProvider, ServerConfig, GarageUpgrades, GarageUpgradeIncrement, ChatSystemConfig, GameEventSequence, GameEvents, GameRotationStrategy, GameEvent, GameMap, GameVisibility, GameType, SingleplayerConfig, VehicleInfo, VehicleDescriptor}; +pub use traits::{ConfigProvider, CompleteCampaignProvider, DevMessageProvider, ServerConfig, GarageUpgrades, GarageUpgradeIncrement, ChatSystemConfig, GameEventSequence, GameEvents, GameRotationStrategy, GameEvent, GameMap, GameVisibility, GameType, SingleplayerConfig, VehicleInfo, VehicleDescriptor, QueueChangeMode}; pub type ConfigImpl = CubeConfig; diff --git a/rc_core/src/persist/config/traits.rs b/rc_core/src/persist/config/traits.rs index b99bde0..d83dcba 100644 --- a/rc_core/src/persist/config/traits.rs +++ b/rc_core/src/persist/config/traits.rs @@ -104,6 +104,23 @@ pub struct TypedDevMessage { pub struct ServerConfig { pub database: String, pub auto_signup: bool, + pub queue_mode: QueueChangeMode, +} + +pub enum QueueChangeMode { + Upgrade, // move enqueued players into newer gamemode + Notify, // send match change + Ignore, // do nothing +} + +impl QueueChangeMode { + pub(super) fn from_persist(persist: crate::persist::settings::QueueMode) -> Self { + match persist { + crate::persist::settings::QueueMode::Upgrade => Self::Upgrade, + crate::persist::settings::QueueMode::Notify => Self::Notify, + crate::persist::settings::QueueMode::Ignore => Self::Ignore, + } + } } #[derive(Clone, Debug)] diff --git a/rc_core/src/persist/mod.rs b/rc_core/src/persist/mod.rs index 4c99291..5d9e650 100644 --- a/rc_core/src/persist/mod.rs +++ b/rc_core/src/persist/mod.rs @@ -27,7 +27,7 @@ mod client_config; pub use client_config::GameplaySettings; mod settings; -pub use settings::Settings; +pub use settings::{Settings, QueueMode}; mod chat; pub use chat::{ChatConfig, ChatCommand, ChatOperation, BuiltInChatOperation}; diff --git a/rc_core/src/persist/settings.rs b/rc_core/src/persist/settings.rs index 8a90660..01e5c54 100644 --- a/rc_core/src/persist/settings.rs +++ b/rc_core/src/persist/settings.rs @@ -74,6 +74,16 @@ pub struct ServerSettings { pub database: String, #[serde(default)] pub auto_signup: bool, + #[serde(default)] + pub queue_mode: QueueMode, +} + +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub enum QueueMode { + Upgrade, // move enqueued players into newer gamemode + #[default] + Notify, // send match change + Ignore, // do nothing } fn default_db_conn() -> String { @@ -84,5 +94,6 @@ fn default_server_conf() -> ServerSettings { ServerSettings { database: default_db_conn(), auto_signup: false, + queue_mode: QueueMode::Notify, } } diff --git a/rc_lobby_room/src/lobby.rs b/rc_lobby_room/src/lobby.rs index 4ce439a..ff84c08 100644 --- a/rc_lobby_room/src/lobby.rs +++ b/rc_lobby_room/src/lobby.rs @@ -1,5 +1,22 @@ use std::{collections::HashMap, hash::Hash}; +#[derive(Clone, Copy)] +pub enum GamemodeChangeStrategy { + Upgrade, // move enqueued players into newer gamemode + Notify, // send match change + Ignore, // do nothing +} + +impl GamemodeChangeStrategy { + fn from_core(core: oj_rc_core::persist::config::QueueChangeMode) -> Self { + match core { + oj_rc_core::persist::config::QueueChangeMode::Upgrade => Self::Upgrade, + oj_rc_core::persist::config::QueueChangeMode::Notify => Self::Notify, + oj_rc_core::persist::config::QueueChangeMode::Ignore => Self::Ignore, + } + } +} + #[derive(Hash, Eq, PartialEq, Clone)] struct QueueKey { map: String, @@ -22,10 +39,11 @@ pub struct QueueHandler { hostport: u16, network_conf: crate::data::network::NetworkConfigData, cpu_counter: std::sync::Arc, + change_strategy: GamemodeChangeStrategy, } impl QueueHandler { - pub fn new(conf: &oj_rc_core::ConfigImpl, game_host: &str, cpu_counter: std::sync::Arc,) -> Self { + pub fn new(conf: &oj_rc_core::ConfigImpl, game_host: &str, cpu_counter: std::sync::Arc) -> Self { let (domain, port_str) = game_host.split_once(':').expect("Invalid redirect address (must be domain:port)"); Self { users_in_queue: tokio::sync::Mutex::new(HashMap::new()), @@ -35,6 +53,7 @@ impl QueueHandler { hostport: port_str.parse().expect("Invalid redirect port"), network_conf: crate::data::network::NetworkConfigData::from_conf(oj_rc_core::ConfigProvider::<()>::network_config(conf)), cpu_counter, + change_strategy: GamemodeChangeStrategy::from_core(>::server_config(conf).queue_mode), } } @@ -42,7 +61,7 @@ impl QueueHandler { use std::hash::Hasher; let mut hasher = std::hash::DefaultHasher::new(); key.hash(&mut hasher); - chrono::Utc::now().timestamp().hash(&mut hasher); + chrono::Utc::now().timestamp_micros().hash(&mut hasher); let guid = oj_rc_core::persist::user::uuid_sanitize(hasher.finish() as i64); let guid_str = oj_rc_core::persist::user::i64_as_uuid_str(guid); let player_descs = players.iter().map(|x| oj_rc_core::persist::user::PlayerLobbyDescriptor { @@ -120,6 +139,47 @@ impl QueueHandler { user_id: user.user_id(), }; let mut lock = self.users_in_queue.lock().await; + // handle game event change + if !lock.contains_key(&key) && lock.len() == 1 { + log::debug!("Game event change detected"); + match self.change_strategy { + GamemodeChangeStrategy::Upgrade => { + let mut new_queue_map = std::collections::HashMap::>::with_capacity(lock.len()); + let mut count = 0; + for (_key, mut users) in lock.drain() { + count += users.len(); + if let Some(values) = new_queue_map.get_mut(&key) { + values.append(&mut users); + } else { + new_queue_map.insert(key.clone(), users); + } + + } + *lock = new_queue_map; + if count != 0 { + log::info!("Upgraded {} users in queue to new gamemode", count); + } + }, + GamemodeChangeStrategy::Notify => { + let mut count = 0; + for (_key, users) in lock.drain() { + count += users.len(); + for player in users { + player.emitter.emit(crate::events::enqueue_error::QueueJoinError { + code: oj_rc_core::data::error_codes::LobbyReasonCode::EventSystemExpired as i16, + text: "Please requeue".to_owned(), + }); + } + } + if count != 0 { + log::info!("Notified {} users in queue of new gamemode", count); + } + }, + GamemodeChangeStrategy::Ignore => { + log::debug!("Gamemode appears to have changed, ignoring already-queued players"); + } + } + } let players_len = if let Some(players) = lock.get_mut(&key) { new_player.player.team = (players.len() % 2) as _; // alternate teams players.push(new_player); diff --git a/rc_lobby_room/src/main.rs b/rc_lobby_room/src/main.rs index 73cf7f6..5ee5dfa 100644 --- a/rc_lobby_room/src/main.rs +++ b/rc_lobby_room/src/main.rs @@ -78,7 +78,7 @@ async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAdd if let Ok(user_info) = user_state.user() { queue.leave_queue(user_info.as_ref().as_ref()).await; } else { - log::info!("Unauthenticated user disconnected"); + log::debug!("Unauthenticated user disconnected"); } log::debug!("Goodbye connection from address {}", address); }