use godot::{ classes::{Button, IPanel, OptionButton, Panel, TextEdit, VBoxContainer}, prelude::*, }; use crate::{ game_manager::{Game, GameManager, 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>, 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() { 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(); } } impl LobbyPanel { 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.allow_any_map); } } 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)); } } } } }