use std::net::SocketAddr; use godot::{prelude::*, tools::get_autoload_by_name}; use serde::{Deserialize, Serialize}; pub const GAME_MANAGER_GLOBAL: &str = "GameManagerGlobal"; #[derive(GodotClass)] #[class(base=Node, init)] pub struct GameManager { pub game: Option>, base: Base, } #[godot_api] impl GameManager { #[signal] pub fn on_players_updated(); #[signal] pub fn on_new_player(id: u16); #[signal] pub fn on_player_disconnected(id: u16); pub fn singleton() -> Gd { get_autoload_by_name::(GAME_MANAGER_GLOBAL) } pub fn init_game(&mut self, is_host: bool) { if let Some(mut game) = self.game.take() { game.queue_free(); } let mut game = Game::new_alloc(); game.bind_mut().is_host = is_host; self.run_deferred(|s| { if let Some(game) = &s.game { game.signals() .on_new_player() .connect_other(s, |s, id| s.signals().on_new_player().emit(id)); game.signals() .on_player_disconnected() .connect_other(s, |s, id| s.signals().on_player_disconnected().emit(id)); game.signals() .on_players_updated() .connect_other(s, |s| s.signals().on_players_updated().emit()); } }); self.base_mut().add_child(&game); self.game = Some(game); } } #[derive(GodotClass)] #[class(base=Node, init)] pub struct Game { is_host: bool, player_counter: u16, pub self_id: Option, pub players: Vec, base: Base, } #[godot_api] impl Game { #[signal] pub fn on_players_updated(); #[signal] pub fn on_new_player(id: u16); #[signal] pub fn on_player_disconnected(id: u16); pub fn singleton() -> Option> { GameManager::singleton() .get_child(0) .map(|g| g.cast::()) } pub fn set_self(&mut self, id: u16) { self.self_id = Some(id); } pub fn new_player(&mut self, addr: SocketAddr, name: String) -> u16 { let id = self.player_counter; self.player_counter += 1; self.players.push(Player { id, connection_addr: addr, name, ping: 0, }); self.signals().on_new_player().emit(id); id } pub fn set_players(&mut self, players: Vec) { self.players = players; for player in self.players.clone() { self.signals().on_new_player().emit(player.id); } } pub fn find_player_by_addr(&self, addr: &SocketAddr) -> Option<&Player> { self.players.iter().find(|p| p.connection_addr == *addr) } pub fn get_player(&self, player_id: u16) -> Option<&Player> { self.players.iter().find(|p| p.id == player_id) } pub fn remove_player(&mut self, id: u16) { self.players.retain(|p| p.id != id); self.signals().on_player_disconnected().emit(id); } pub fn update_player_nick(&mut self, player_id: u16, nick: String) { if let Some(player) = self.players.iter_mut().find(|p| p.id == player_id) { player.name = nick; } self.run_deferred(|s| s.signals().on_players_updated().emit()); } pub fn update_player_ping(&mut self, player_id: u16, ping: u128) { if let Some(player) = self.players.iter_mut().find(|p| p.id == player_id) { player.ping = ping; } self.run_deferred(|s| s.signals().on_players_updated().emit()); } } #[derive(Clone, Deserialize, Serialize, Debug)] pub struct Player { pub id: u16, pub connection_addr: SocketAddr, pub name: String, pub ping: u128, }