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>, #[export] pub ball_spawner: Option>, pickup_counter: u8, pub pickups: HashMap>, base: Base, } #[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, get_remote_data: bool, ) -> Option> { if is_local { if let Some(local_player) = &GameManager::singleton().bind().local_player { let mut node = local_player.instantiate_as::(); 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::().upcast()) } else { None } } else if let Some(remote_player) = &GameManager::singleton().bind().remote_player { let mut node = remote_player.instantiate_as::(); 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::().upcast()) } else { None } } pub fn spawn_replay_player( &mut self, player_id: u16, player: &ReplayPlayer, state: ReplayPlayerState, ) -> Option> { if let Some(replay_player) = &GameManager::singleton().bind().replay_player { let mut node: Gd = 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, velocity: Option, player_id: Option, ) -> Option> { 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.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, velocity: Option, player_id: Option, ) -> Option> { 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.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) -> 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> { if let Some(prefab) = &GameManager::singleton().bind().telegrenade { let mut telegrenade = prefab.instantiate_as::(); self.base_mut().add_child(&telegrenade); telegrenade.set_global_position(location.into()); telegrenade.set_linear_velocity(velocity.into()); Some(telegrenade) } else { None } } }