skullball/rust/src/cli_parser.rs
2026-07-30 19:20:47 +03:00

119 lines
3.3 KiB
Rust

use std::net::SocketAddr;
use godot::{classes::Os, prelude::*};
use crate::{
game::{Game, GameManager},
net::network_manager::NetworkManager,
};
#[derive(Debug, Default, Clone)]
pub struct Options {
host: Option<u16>,
join: Option<SocketAddr>,
map: Option<String>,
}
impl Options {
fn process_arg(&mut self, arg: &str, params: Vec<String>) {
match arg {
"host" => {
if let Some(port) = params.first()
&& let Ok(port) = port.parse::<u16>()
{
self.host = Some(port);
}
}
"join" => {
if let Some(addr) = params.first()
&& let Ok(addr) = addr.parse::<SocketAddr>()
{
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<Options>,
base: Base<Node3D>,
}
#[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::<Vec<_>>();
let mut current_command: Option<String> = None;
let mut params: Vec<String> = Vec::new();
for arg in args {
if arg.starts_with("--") {
if let Some(command) = current_command.take() {
options.process_arg(&command, params.drain(..).collect::<Vec<_>>());
}
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::<Vec<_>>());
}
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_directly(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().forced_map_selection = true;
game.bind_mut().change_map_selection(map_idx as u8, true);
}
}
}
}