diff --git a/godot/project.godot b/godot/project.godot index bf55598..9d41ae9 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -20,6 +20,7 @@ config/icon="res://icon.svg" NetworkManagerGlob="*uid://cxuy526twid8s" CommandLinePanelGlobal="*uid://bsb6asp5o35w3" GameManagerGlobal="*uid://bii6018k3ip3t" +CliParserGlobal="*uid://c52o7xa0fnr53" [display] diff --git a/godot/scenes/misc/cli_parser.tscn b/godot/scenes/misc/cli_parser.tscn new file mode 100644 index 0000000..ad85d5a --- /dev/null +++ b/godot/scenes/misc/cli_parser.tscn @@ -0,0 +1,3 @@ +[gd_scene format=3 uid="uid://c52o7xa0fnr53"] + +[node name="cli_parser" type="CliParser" unique_id=532112036] diff --git a/rust/src/cli_parser.rs b/rust/src/cli_parser.rs new file mode 100644 index 0000000..2098b9e --- /dev/null +++ b/rust/src/cli_parser.rs @@ -0,0 +1,117 @@ +use std::net::SocketAddr; + +use godot::{classes::Os, prelude::*}; + +use crate::{ + game_manager::{Game, GameManager}, + net::network_manager::NetworkManager, +}; + +#[derive(Debug, Default, Clone)] +pub struct Options { + host: Option, + join: Option, + map: Option, +} + +impl Options { + fn process_arg(&mut self, arg: &str, params: Vec) { + match arg { + "host" => { + if let Some(port) = params.first() + && let Ok(port) = port.parse::() + { + self.host = Some(port); + } + } + "join" => { + if let Some(addr) = params.first() + && let Ok(addr) = addr.parse::() + { + self.join = Some(addr); + } + } + "map" => { + if let Some(map_name) = params.first() { + self.map = Some(map_name.clone()); + } + } + _ => {} + } + } +} + +#[derive(GodotClass)] +#[class(base=Node3D, init)] +pub struct CliParser { + pub opts: Option, + + base: Base, +} + +#[godot_api] +impl INode3D for CliParser { + fn ready(&mut self) { + let mut options = Options::default(); + + let args = Os::singleton() + .get_cmdline_user_args() + .to_vec() + .iter() + .map(|v| v.to_string()) + .collect::>(); + + let mut current_command: Option = None; + let mut params: Vec = Vec::new(); + for arg in args { + if arg.starts_with("--") { + if let Some(command) = current_command.take() { + options.process_arg(&command, params.drain(..).collect::>()); + } + let (_, arg) = arg.split_at(2); + current_command = Some(arg.to_string()); + } else { + params.push(arg); + } + } + + if let Some(command) = current_command.take() { + options.process_arg(&command, params.drain(..).collect::>()); + } + + self.opts = Some(options.clone()); + + NetworkManager::singleton() + .bind_mut() + .signals() + .lobby_joined() + .connect_other(self, |s| s.on_join_lobby()); + + if let Some(port) = options.host { + NetworkManager::singleton().bind_mut().host(port); + } else if let Some(addr) = options.join { + NetworkManager::singleton().bind_mut().join(addr); + } + } +} + +impl CliParser { + pub fn on_join_lobby(&self) { + if let Some(opts) = &self.opts + && let Some(map_name) = &opts.map + && let Some(mut game) = Game::singleton() + { + let map = GameManager::singleton() + .bind() + .maps + .iter_shared() + .enumerate() + .find(|(_, map)| { + map.bind().name.to_string().to_lowercase() == map_name.to_lowercase() + }); + if let Some((map_idx, _)) = map { + game.bind_mut().change_map_selection(map_idx as u8, true); + } + } + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 3e1f9f6..2b4bafb 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,6 +1,7 @@ use godot::prelude::*; pub mod ball; +pub mod cli_parser; pub mod game_manager; pub mod goal; pub mod killbox; diff --git a/rust/src/net/network_manager.rs b/rust/src/net/network_manager.rs index cb38568..a5b653e 100644 --- a/rust/src/net/network_manager.rs +++ b/rust/src/net/network_manager.rs @@ -112,7 +112,11 @@ impl INode for NetworkManager { } } +#[godot_api] impl NetworkManager { + #[signal] + pub fn lobby_joined(); + fn poll(&mut self) -> Option> { let mut cli = CommandLinePanel::singleton(); @@ -213,9 +217,10 @@ impl NetworkManager { } } - pub fn swap_to_lobby(&self, is_host: bool) { + pub fn swap_to_lobby(&mut self, is_host: bool) { GameManager::singleton().bind_mut().init_game(is_host); GameManager::singleton().bind().go_to_lobby(); + self.run_deferred(|s| s.signals().lobby_joined().emit()); } pub fn update_nick(&mut self, nick: String) {