use godot::{ classes::{ Button, CheckBox, Control, GridContainer, IPanel, Label, OptionButton, Panel, TextEdit, VBoxContainer, }, prelude::*, }; use crate::{ game_manager::{Game, GameManager, GameOption, GameOptionValue, GameOptions}, net::network_manager::{NetworkManager, Package, PeerKind}, ui::player_listing::PlayerListing, }; #[derive(GodotClass)] #[class(base=Panel, init)] pub struct LobbyPanel { #[export] players_list: Option>, #[export] name_field: Option>, #[export] player_listing_prefab: Option>, #[export] ready_button: Option>, #[export] map_selection: Option>, #[export] options_panel: Option>, #[export] options_grid: Option>, is_ready: bool, base: Base, } #[godot_api] impl IPanel for LobbyPanel { fn ready(&mut self) { GameManager::singleton() .signals() .on_new_player() .connect_other(self, |s, _| s.update_players(true)); GameManager::singleton() .signals() .on_player_disconnected() .connect_other(self, |s, _| s.update_players(true)); GameManager::singleton() .signals() .on_players_updated() .connect_other(self, |s| s.update_players(false)); GameManager::singleton() .signals() .on_map_changed() .connect_other(self, |s, id| s.update_map_selection(id)); if let Some(ready_button) = &self.ready_button { ready_button .signals() .pressed() .connect_other(self, |s| s.on_ready()); } if let Some(map_selection) = &self.map_selection { map_selection .signals() .item_selected() .connect_other(self, |s, id| { s.update_map_selection(id as u8); }); } if let Some(game) = Game::singleton() { game.signals().options_changed().connect_other(self, |s| { s.run_deferred(|s| { if let Some(game) = Game::singleton() { s.on_game_opts_update( &game.bind().opts, NetworkManager::singleton().bind().is_host(), ); } }); }); if let Some(map_selection) = &mut self.map_selection { for map in game.bind().maps.iter_shared() { map_selection.add_item(&map.bind().name); } map_selection.select(0); } let is_host = if let Some(peer) = &NetworkManager::singleton().bind().peer { peer.is_host() } else { false }; self.on_game_opts_update(&game.bind().opts, is_host); } self.update_map_selection(0); if let Some(name_field) = &self.name_field { name_field .signals() .text_changed() .connect_other(self, |s| { if let Some(name_field) = &s.name_field { if let Some(game) = &mut Game::singleton() { let player_id = game.bind().self_id; if let Some(player_id) = player_id { game.bind_mut().update_player_nick( player_id, name_field.get_text().to_string(), ); } } NetworkManager::singleton() .bind_mut() .update_nick(name_field.get_text().to_string()); } }); } self.update_players(true); if let Some(peer) = &NetworkManager::singleton().bind().peer && peer.is_host() { if let Some(button) = &mut self.ready_button { button.set_text("Start Game"); button.set_disabled(true); } } self.update_ready_button(); let mut nodes = Vec::new(); if let Some(game) = Game::singleton() { for (option, value) in &game.bind().opts.values { let mut label = Label::new_alloc(); label.set_text(&format!("{}:", option.to_string())); nodes.push(label.upcast()); let value_node = match value { GameOptionValue::Boolean(value) => { let mut checkbox = CheckBox::new_alloc(); checkbox.set_pressed(*value); checkbox.set_disabled(!NetworkManager::singleton().bind().is_host()); let checkbox_clone = checkbox.clone(); let option = option.clone(); checkbox.signals().pressed().connect_other(self, move |s| { s.option_changed( option, GameOptionValue::Boolean(checkbox_clone.is_pressed()), ); }); checkbox.upcast::() } }; nodes.push(value_node); } } if let Some(grid) = &mut self.options_grid { for node in nodes { grid.add_child(&node); } } } } #[godot_api] impl LobbyPanel { #[func] fn open_options(&mut self) { if let Some(panel) = &mut self.options_panel { panel.set_visible(true); } } #[func] fn close_options(&mut self) { if let Some(panel) = &mut self.options_panel { panel.set_visible(false); } } fn option_changed(&mut self, key: GameOption, value: GameOptionValue) { if let Some(game) = &mut Game::singleton() { game.bind_mut().change_option(key, value); } } fn on_game_opts_update(&mut self, opts: &GameOptions, is_host: bool) { if let Some(selection) = &mut self.map_selection { selection.set_disabled(!is_host && !opts.is_true(GameOption::AllowAnyMap)); } } fn update_ready_button(&mut self) { if let Some(game) = Game::singleton() && let Some(peer) = &NetworkManager::singleton().bind().peer { if let PeerKind::Server(_, _) = peer && let Some(button) = &mut self.ready_button { let all_ready = game.bind().players.iter().all(|p| p.ready); button.set_disabled(!all_ready); } } } pub fn update_players(&mut self, replace: bool) { self.update_ready_button(); if let Some(list) = &mut self.players_list { if replace { for child in list.get_children().iter_shared() { list.remove_child(&child); } if let Some(game) = &Game::singleton() { if let Some(prefab) = &self.player_listing_prefab { for player in &game.bind().players { if let Some(node) = prefab.instantiate() { let mut listing = node.cast::(); listing.bind_mut().player_id = Some(player.id()); listing.bind_mut().update_teams(game.bind().get_teams()); listing.bind_mut().update(); list.add_child(&listing); } } } } } else { for child in list.get_children().iter_shared() { let mut listing = child.cast::(); if let Some(game) = Game::singleton() { listing.bind_mut().update_teams(game.bind().get_teams()); } listing.bind_mut().update(); } } } } pub fn on_ready(&mut self) { let is_host = if let Some(peer) = &NetworkManager::singleton().bind().peer { peer.is_host() } else { false }; if !is_host { self.is_ready = !self.is_ready; if let Some(button) = &mut self.ready_button { if self.is_ready { button.set_text("Ready"); } else { button.set_text("Not Ready"); } } if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { if let PeerKind::Client(peer, socket_addr) = peer { peer.send_reliable(&socket_addr, Package::SetReady(0, self.is_ready)); } } } else { if let Some(game) = &mut Game::singleton() { game.bind_mut().start_game(); } } } pub fn update_map_selection(&mut self, idx: u8) { if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { match peer { PeerKind::Client(peer, addr) => { if let Some(map_selection) = &mut self.map_selection { map_selection.select(idx as i32); self.run_deferred(|s| s.update_players(false)); peer.send_reliable(addr, Package::SelectMap(idx)); } } PeerKind::Server(peer, _) => { if let Some(game) = &mut Game::singleton() { game.bind_mut().change_map_selection(idx, false); } self.run_deferred(|s| s.update_players(false)); peer.broadcast_reliable(Package::SelectMap(idx)); } } } } }