Implement some command line arguments

This commit is contained in:
Sofia 2026-07-22 23:44:55 +03:00
parent aa3504e445
commit b2a906c840
5 changed files with 128 additions and 1 deletions

View File

@ -20,6 +20,7 @@ config/icon="res://icon.svg"
NetworkManagerGlob="*uid://cxuy526twid8s"
CommandLinePanelGlobal="*uid://bsb6asp5o35w3"
GameManagerGlobal="*uid://bii6018k3ip3t"
CliParserGlobal="*uid://c52o7xa0fnr53"
[display]

View File

@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://c52o7xa0fnr53"]
[node name="cli_parser" type="CliParser" unique_id=532112036]

117
rust/src/cli_parser.rs Normal file
View File

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

View File

@ -1,6 +1,7 @@
use godot::prelude::*;
pub mod ball;
pub mod cli_parser;
pub mod game_manager;
pub mod goal;
pub mod killbox;

View File

@ -112,7 +112,11 @@ impl INode for NetworkManager {
}
}
#[godot_api]
impl NetworkManager {
#[signal]
pub fn lobby_joined();
fn poll(&mut self) -> Option<PeerMessage<Package>> {
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) {