diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index 78e3826..281550c 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -24,6 +24,7 @@ use crate::{ remote_player::RemotePlayer, weapon::WeaponType, }, team_resource::TeamResource, + ui::cli::{Command, CommandLinePanel}, }; pub const GAME_MANAGER_GLOBAL: &str = "GameManagerGlobal"; @@ -190,6 +191,19 @@ pub enum GameOptionValue { Number(f64), } +pub struct RespawnBallCommand; +impl Command for RespawnBallCommand { + fn execute(&self, _: &mut CommandLinePanel, _: &[&str]) { + if let Some(game) = &mut Game::singleton() { + game.bind_mut().respawn_ball(); + } + } + + fn help(&self) -> &str { + "respawns the ball" + } +} + #[derive(GodotClass)] #[class(base=Node, init)] pub struct Game { @@ -210,6 +224,7 @@ pub struct Game { pub current_map: Option>, pub world_ball: Option>, + pub ball_holder: Option, pub goals: HashMap, @@ -326,6 +341,28 @@ impl Game { .map(|g| g.cast::()) } + pub fn start_game(&mut self) { + self.game_started = true; + if let Some(map) = &self.selected_map { + if let Some(scene) = &map.bind().scene { + self.base().get_tree().change_scene_to_packed(scene); + } + } + + self.run_deferred(|_| { + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { + if let PeerKind::Server(peer, _) = peer { + peer.broadcast_reliable(Package::GameStarted); + peer.set_accepting_connections(false); + + let mut cli = CommandLinePanel::singleton(); + cli.bind_mut() + .register_command("respawn_ball".to_string(), Box::new(RespawnBallCommand)); + } + } + }); + } + pub fn reset_game(&mut self) { if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer && let PeerKind::Server(peer, _) = peer @@ -375,6 +412,10 @@ impl Game { } s.signals().on_game_finished().emit() }); + + let mut cli = CommandLinePanel::singleton(); + cli.bind_mut() + .unregister_command("respawn_ball".to_string()); } pub fn change_option(&mut self, opt: GameOption, value: GameOptionValue) { @@ -456,24 +497,6 @@ impl Game { } } - pub fn start_game(&mut self) { - self.game_started = true; - if let Some(map) = &self.selected_map { - if let Some(scene) = &map.bind().scene { - self.base().get_tree().change_scene_to_packed(scene); - } - } - - self.run_deferred(|_| { - if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { - if let PeerKind::Server(peer, _) = peer { - peer.broadcast_reliable(Package::GameStarted); - peer.set_accepting_connections(false); - } - } - }); - } - pub fn set_self(&mut self, id: u16) { self.self_id = Some(id); } @@ -628,6 +651,12 @@ impl Game { } pub fn despawn_ball(&mut self) { + if let Some(ball_holder) = self.ball_holder.take() + && let Some(player) = self.find_player_mut(ball_holder).cloned() + { + self.handle_swap_weapon(ball_holder, player.last_held_weapon, false, false); + } + if let Some(mut ball) = self.world_ball.take() { ball.queue_free(); self.run_deferred(|_| { @@ -678,7 +707,10 @@ impl Game { pub fn handle_ball_pickup(&mut self, player_id: u16) { if NetworkManager::singleton().bind_mut().is_host() { self.despawn_ball(); - self.run_deferred(move |s| s.handle_swap_weapon(player_id, WeaponType::Ball, true)); + self.run_deferred(move |s| { + s.handle_swap_weapon(player_id, WeaponType::Ball, true, false) + }); + self.ball_holder = Some(player_id); } } @@ -688,6 +720,7 @@ impl Game { player_id: u16, weapon_type: WeaponType, allow_ball: bool, + drop_ball: bool, ) { if weapon_type == WeaponType::Ball && !allow_ball { return; @@ -699,7 +732,7 @@ impl Game { if weapon_type != WeaponType::Ball { player.last_held_weapon = weapon_type; } - character.dyn_bind_mut().swap_weapon(weapon_type, true); + character.dyn_bind_mut().swap_weapon(weapon_type, drop_ball); let player_id = player.id(); self.run_deferred(move |_| { if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer diff --git a/rust/src/net/protocol.rs b/rust/src/net/protocol.rs index 07d73fb..54ec0da 100644 --- a/rust/src/net/protocol.rs +++ b/rust/src/net/protocol.rs @@ -181,7 +181,8 @@ impl NetworkManager { } Package::SwapWeapon(id, weapon_type) => { if let Some(game) = &mut Game::singleton() { - game.bind_mut().handle_swap_weapon(id, weapon_type, true); + game.bind_mut() + .handle_swap_weapon(id, weapon_type, true, true); } } Package::SetTeam(player_id, team) => { @@ -399,6 +400,7 @@ impl NetworkManager { player.id(), weapon_type, false, + true, ); } } diff --git a/rust/src/ui/chatbox.rs b/rust/src/ui/chatbox.rs index c99e8a5..eb5acd1 100644 --- a/rust/src/ui/chatbox.rs +++ b/rust/src/ui/chatbox.rs @@ -12,6 +12,7 @@ use crate::{ chat::Chat, game_manager::Game, net::network_manager::{NetworkManager, Package, PeerKind}, + ui::cli::CommandLinePanel, }; #[derive(GodotClass)] @@ -85,6 +86,11 @@ impl IVBoxContainer for ChatBox { } fn input(&mut self, event: Gd) { + let cli = CommandLinePanel::singleton(); + if cli.bind().opened { + return; + } + if self.in_game && event.is_action_pressed("open_chat") { if let Some(line_edit) = &mut self.line_edit { let is_visible = line_edit.is_visible(); diff --git a/rust/src/ui/cli.rs b/rust/src/ui/cli.rs index 5c63a05..f3114f2 100644 --- a/rust/src/ui/cli.rs +++ b/rust/src/ui/cli.rs @@ -175,9 +175,17 @@ impl CommandLinePanel { self.publish_message(format!("Unknown command: {}", command), CliColor::Info); } } + + pub fn register_command(&mut self, name: String, command: Box) { + self.commands.insert(name, Rc::new(command)); + } + + pub fn unregister_command(&mut self, name: String) { + self.commands.remove(&name); + } } -trait Command { +pub trait Command { fn execute(&self, cli: &mut CommandLinePanel, params: &[&str]); fn help(&self) -> &str; }