skullball/rust/src/map.rs

224 lines
7.6 KiB
Rust

use std::collections::HashMap;
use godot::{classes::CharacterBody3D, prelude::*};
use crate::{
game_manager::{Game, GameManager},
net::util::NetVector3,
pickup::Pickup,
player::{
IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer, remote_player::RemotePlayer,
telegrenade::Telegrenade,
},
replay::{ReplayPlayer, ReplayPlayerState, StandaloneReplayManager},
};
#[derive(GodotClass)]
#[class(base=Node3D, init)]
pub struct Map {
#[export]
pub spawners: Array<Gd<Node3D>>,
#[export]
pub ball_spawner: Option<Gd<Node3D>>,
pickup_counter: u8,
pub pickups: HashMap<u8, DynGd<Node3D, dyn Pickup>>,
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());
} else {
StandaloneReplayManager::singleton()
.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,
team: u8,
is_local: bool,
transform: Option<NetTransform>,
get_remote_data: bool,
) -> Option<DynGd<CharacterBody3D, dyn IPlayer + 'static>> {
if is_local {
if let Some(local_player) = &GameManager::singleton().bind().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.spawners.get(team as usize) {
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) = &GameManager::singleton().bind().remote_player {
let mut node = remote_player.instantiate_as::<RemotePlayer>();
node.bind_mut().player_id = Some(player_id);
if get_remote_data {
let mut node_clone = node.clone();
self.run_deferred(move |_| {
if let Some(game) = &mut Game::singleton()
&& let Some(player) = game.bind().find_player(player_id)
&& let Some(team) = game.bind().get_team(player.data.team)
{
node_clone.bind_mut().player_name = player.data.name.clone();
node_clone.bind_mut().player_color = team.bind().color.clone();
}
});
}
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.spawners.get(team as usize) {
node.bind_mut()
.base_mut()
.set_global_position(spawner.get_global_position());
}
}
Some(node.into_dyn::<dyn IPlayer>().upcast())
} else {
None
}
}
pub fn spawn_replay_player(
&mut self,
player_id: u16,
player: &ReplayPlayer,
state: ReplayPlayerState,
) -> Option<Gd<RemotePlayer>> {
if let Some(replay_player) = &GameManager::singleton().bind().replay_player {
let mut node: Gd<RemotePlayer> = replay_player.instantiate_as();
node.bind_mut().player_id = Some(player_id);
node.bind_mut().player_name = player.name.clone();
node.bind_mut().player_color = player.color.clone().into();
node.bind_mut().replay_mode = true;
self.base_mut().add_child(&node);
node.bind_mut()
.base_mut()
.set_global_position(state.transform.location.into());
node.bind_mut()
.base_mut()
.set_global_rotation(state.transform.rotation.into());
node.bind_mut().set_movement_dir(state.movement_dir.into());
node.bind_mut().apply_look_up(state.look_up);
Some(node)
} 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) = &GameManager::singleton().bind().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
}
}
pub fn spawn_replay_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) = &GameManager::singleton().bind().replay_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
}
}
pub fn register_pickup(&mut self, pickup: DynGd<Node3D, dyn Pickup>) -> u8 {
let id = self.pickup_counter;
self.pickup_counter += 1;
self.pickups.insert(id, pickup);
id
}
pub fn spawn_telegrenade(
&mut self,
location: NetVector3,
velocity: NetVector3,
) -> Option<Gd<Telegrenade>> {
if let Some(prefab) = &GameManager::singleton().bind().telegrenade {
let mut telegrenade = prefab.instantiate_as::<Telegrenade>();
self.base_mut().add_child(&telegrenade);
telegrenade.set_global_position(location.into());
telegrenade.set_linear_velocity(velocity.into());
Some(telegrenade)
} else {
None
}
}
}