skullball/rust/src/lobby_world.rs

78 lines
2.2 KiB
Rust

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<Gd<PackedScene>>,
rng: Gd<RandomNumberGenerator>,
menu_players: HashMap<u16, Gd<MenuPlayer>>,
base: Base<Node3D>,
}
#[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::<MenuPlayer>();
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();
}
}
}