121 lines
3.8 KiB
Rust
121 lines
3.8 KiB
Rust
use godot::{classes::CharacterBody3D, prelude::*};
|
|
|
|
use crate::{
|
|
ball::Ball,
|
|
game_manager::Game,
|
|
net::util::NetVector3,
|
|
player::{IPlayer, LocalPlayer, NetTransform, RemotePlayer},
|
|
};
|
|
|
|
#[derive(GodotClass)]
|
|
#[class(base=Node3D, init)]
|
|
pub struct Map {
|
|
#[export]
|
|
pub spawner: Option<Gd<Node3D>>,
|
|
#[export]
|
|
pub ball_spawner: Option<Gd<Node3D>>,
|
|
#[export]
|
|
pub local_player: Option<Gd<PackedScene>>,
|
|
#[export]
|
|
pub remote_player: Option<Gd<PackedScene>>,
|
|
#[export]
|
|
pub ball: 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<NetTransform>,
|
|
) -> 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
|
|
}
|
|
}
|
|
|
|
pub fn spawn_ball(
|
|
&mut self,
|
|
transform: Option<NetTransform>,
|
|
velocity: Option<NetVector3>,
|
|
player_id: Option<u16>,
|
|
) -> Option<Gd<Ball>> {
|
|
if let Some(ball_spawner) = self.ball_spawner.clone()
|
|
&& let Some(ball_prefab) = &self.ball
|
|
{
|
|
let mut ball = ball_prefab.instantiate_as::<Ball>();
|
|
ball.bind_mut().dropper = player_id;
|
|
self.base_mut().add_child(&ball);
|
|
if let Some(transform) = transform {
|
|
ball.set_global_position(transform.location.into());
|
|
ball.set_global_rotation(transform.rotation.into());
|
|
} else {
|
|
ball.set_global_position(ball_spawner.get_global_position());
|
|
}
|
|
if let Some(velocity) = velocity {
|
|
ball.set_linear_velocity(velocity.into());
|
|
}
|
|
Some(ball)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|