skullball/rust/src/map.rs
2026-07-20 22:43:10 +03:00

88 lines
2.8 KiB
Rust

use godot::{classes::CharacterBody3D, prelude::*};
use crate::{
game_manager::{Game, Player},
player::{IPlayer, LocalPlayer, NetPlayerTransform, RemotePlayer},
};
#[derive(GodotClass)]
#[class(base=Node3D, init)]
pub struct Map {
#[export]
pub spawner: Option<Gd<Node3D>>,
#[export]
pub local_player: Option<Gd<PackedScene>>,
#[export]
pub remote_player: Option<Gd<PackedScene>>,
base: Base<Node3D>,
}
#[godot_api]
impl INode3D for Map {
fn ready(&mut self) {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().on_map_loaded(self.to_gd());
}
}
}
#[godot_api]
impl Map {
#[signal]
pub fn on_loaded();
pub fn spawn_player(
&mut self,
player_id: u16,
is_local: bool,
transform: Option<NetPlayerTransform>,
) -> Option<DynGd<CharacterBody3D, dyn IPlayer + 'static>> {
if is_local {
if let Some(local_player) = &self.local_player {
let mut node = local_player.instantiate_as::<LocalPlayer>();
node.bind_mut().player_id = Some(player_id);
self.base_mut().add_child(&node);
if let Some(transform) = transform {
node.bind_mut()
.base_mut()
.set_global_position(transform.location.into());
node.bind_mut()
.base_mut()
.set_global_rotation(transform.rotation.into());
} else {
if let Some(spawner) = &self.spawner {
node.bind_mut()
.base_mut()
.set_global_position(spawner.get_global_position());
}
}
Some(node.into_dyn::<dyn IPlayer>().upcast())
} else {
None
}
} else if let Some(remote_player) = &self.remote_player {
let mut node = remote_player.instantiate_as::<RemotePlayer>();
node.bind_mut().player_id = Some(player_id);
self.base_mut().add_child(&node);
if let Some(transform) = transform {
node.bind_mut()
.base_mut()
.set_global_position(transform.location.into());
node.bind_mut()
.base_mut()
.set_global_rotation(transform.rotation.into());
} else {
if let Some(spawner) = &self.spawner {
node.bind_mut()
.base_mut()
.set_global_position(spawner.get_global_position());
}
}
Some(node.into_dyn::<dyn IPlayer>().upcast())
} else {
None
}
}
}