use std::{collections::HashMap, f32::consts::PI}; use godot::{classes::RandomNumberGenerator, prelude::*}; use crate::{game::Game, player::menu_player::MenuPlayer}; #[derive(GodotClass)] #[class(base=Node3D, init)] pub struct LobbyWorld { #[export] menu_player_scene: Option>, rng: Gd, menu_players: HashMap>, base: Base, } #[godot_api] impl INode3D for LobbyWorld { fn ready(&mut self) { if let Some(game) = Game::singleton() { for player in &game.bind().players { self.spawn_player(player.id()); } game.signals() .on_new_player() .connect_other(self, Self::on_new_player); game.signals() .on_player_disconnected() .connect_other(self, Self::on_player_disconnected); game.signals() .on_players_updated() .connect_other(self, Self::update_players); } } } impl LobbyWorld { fn on_new_player(&mut self, player_id: u16) { self.spawn_player(player_id); } fn on_player_disconnected(&mut self, player_id: u16) { if let Some(mut player) = self.menu_players.remove(&player_id) { player.queue_free(); } } fn spawn_player(&mut self, player_id: u16) { self.run_deferred(move |s| { if let Some(scene) = s.menu_player_scene.clone() { let x = s.rng.randf_range(-2., 2.); let z = s.rng.randf_range(-2., 2.); let rotation = s.rng.randf_range(PI / 4., PI / 2.); let mut menu_player = scene.instantiate_as::(); menu_player.bind_mut().player_id = Some(player_id); s.menu_players.insert(player_id, menu_player.clone()); s.base_mut().add_child(&menu_player); menu_player.bind_mut().update(); menu_player.set_position(Vector3::new(x, 0., z)); menu_player.set_rotation(Vector3::UP * rotation); } }); } fn update_players(&mut self) { for (_, player) in &mut self.menu_players { player.bind_mut().update(); } } }