diff --git a/godot/scenes/game_manager.tscn b/godot/scenes/game_manager.tscn index 46eef7c..b10cf7b 100644 --- a/godot/scenes/game_manager.tscn +++ b/godot/scenes/game_manager.tscn @@ -3,4 +3,5 @@ [ext_resource type="MapResource" uid="uid://c7n1tacc7a73t" path="res://maps/default_map.tres" id="1_glms7"] [node name="game_manager" type="GameManager" unique_id=1442044769] +respawn_timer = 5.0 maps = Array[MapResource]([ExtResource("1_glms7")]) diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index ccbfbda..99cdb78 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -9,7 +9,7 @@ use crate::{ net::{ network_manager::{ NetworkManager, - Package::{self, Kill, SelfSync, TakeDamage}, + Package::{self, Kill, SelfSync, SpawnPlayer, TakeDamage}, PeerKind, SyncPackage, }, util::NetVector3, @@ -22,6 +22,9 @@ pub const GAME_MANAGER_GLOBAL: &str = "GameManagerGlobal"; #[derive(GodotClass)] #[class(base=Node, init)] pub struct GameManager { + #[export] + pub respawn_timer: f64, + pub game: Option>, base: Base, @@ -51,6 +54,7 @@ impl GameManager { let mut game = Game::new_alloc(); game.bind_mut().is_host = is_host; game.bind_mut().maps = self.maps.clone(); + game.bind_mut().respawn_timer = self.respawn_timer; self.run_deferred(|s| { if let Some(game) = &s.game { @@ -78,6 +82,9 @@ impl GameManager { #[derive(GodotClass)] #[class(base=Node, init)] pub struct Game { + #[export] + pub respawn_timer: f64, + pub selected_map_idx: u8, pub selected_map: Option>, pub maps: Array>, @@ -143,6 +150,25 @@ impl INode for Game { } } } + + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { + if let PeerKind::Server(peer, _) = peer { + for player in self.players.clone() { + if let Some(character) = player.character { + if character.dyn_bind().dead_for() > self.respawn_timer { + let character = self.spawn_player_server(player.id); + + if let Some(character) = character { + peer.broadcast_reliable(SpawnPlayer( + player.id, + character.dyn_bind().get_transform(), + )); + } + } + } + } + } + } } } @@ -272,64 +298,72 @@ impl Game { } else { self.run_deferred(|s| { for player in s.players.clone() { - let player_id = player.id; - if let Some(mut map) = s.current_map.clone() { - let mut character = map.bind_mut().spawn_player( - &player, - player.id == s.self_id.unwrap_or(0), - None, - ); - - if let Some(character) = &mut character { - if let Ok(mut local_player) = - character.clone().try_cast::() - { - local_player - .bind_mut() - .signals() - .on_die() - .connect_other(s, move |s| s.on_death(player_id)); - local_player - .bind_mut() - .signals() - .on_take_damage() - .connect_other(s, move |s, damage| { - s.on_take_damage(player_id, damage) - }); - } else if let Ok(mut remote_player) = - character.clone().try_cast::() - { - remote_player - .bind_mut() - .signals() - .on_die() - .connect_other(s, move |s| s.on_death(player_id)); - remote_player - .bind_mut() - .signals() - .on_take_damage() - .connect_other(s, move |s, damage| { - s.on_take_damage(player_id, damage) - }); - } - } - - if let Some(player) = s.find_player_mut(player_id) { - player.character = character; - } - } + s.spawn_player_server(player.id); } }); } } } + pub fn spawn_player_server(&mut self, id: u16) -> Option> { + if let Some(player) = self.find_player_mut(id) + && let Some(character) = &mut player.character + { + // This is a respawn, remove old character + character.queue_free(); + } + + if let Some(mut map) = self.current_map.clone() { + let mut character = + map.bind_mut() + .spawn_player(id, id == self.self_id.unwrap_or(0), None); + + if let Some(character) = &mut character { + if let Ok(mut local_player) = character.clone().try_cast::() { + local_player + .bind_mut() + .signals() + .on_die() + .connect_other(self, move |s| s.on_death(id)); + local_player + .bind_mut() + .signals() + .on_take_damage() + .connect_other(self, move |s, damage| s.on_take_damage(id, damage)); + } else if let Ok(mut remote_player) = character.clone().try_cast::() { + remote_player + .bind_mut() + .signals() + .on_die() + .connect_other(self, move |s| s.on_death(id)); + remote_player + .bind_mut() + .signals() + .on_take_damage() + .connect_other(self, move |s, damage| s.on_take_damage(id, damage)); + } + } + + if let Some(player) = self.find_player_mut(id) { + player.character = character.clone(); + } + character + } else { + None + } + } + // Method called on the client-side whenever a player has spawned pub fn spawn_player_client(&mut self, id: u16, transform: NetPlayerTransform) { if let Some(map) = &mut self.current_map { if let Some(player) = self.players.iter_mut().find(|p| p.id == id) { + if let Some(character) = &mut player.character { + // This is a respawn, delete old character + character.queue_free(); + } + let character = map.bind_mut().spawn_player( - player, + player.id, player.id == self.self_id.unwrap_or(0), Some(transform), ); @@ -410,7 +444,6 @@ impl Game { // Handle dying, from server to client pub fn handle_kill(&mut self, player_id: u16) { - godot_print!("Got kill!"); if let Some(player) = self.find_player_mut(player_id) { if let Some(character) = &mut player.character { character.dyn_bind_mut().kill(); diff --git a/rust/src/map.rs b/rust/src/map.rs index 6b04b98..c9d3c44 100644 --- a/rust/src/map.rs +++ b/rust/src/map.rs @@ -34,14 +34,14 @@ impl Map { pub fn spawn_player( &mut self, - player: &Player, + player_id: u16, is_local: bool, transform: Option, ) -> Option> { if is_local { if let Some(local_player) = &self.local_player { let mut node = local_player.instantiate_as::(); - node.bind_mut().player_id = Some(player.id); + node.bind_mut().player_id = Some(player_id); self.base_mut().add_child(&node); if let Some(transform) = transform { node.bind_mut() @@ -63,7 +63,7 @@ impl Map { } } else if let Some(remote_player) = &self.remote_player { let mut node = remote_player.instantiate_as::(); - node.bind_mut().player_id = Some(player.id); + node.bind_mut().player_id = Some(player_id); self.base_mut().add_child(&node); if let Some(transform) = transform { node.bind_mut() diff --git a/rust/src/player.rs b/rust/src/player.rs index a76d8cc..f33700d 100644 --- a/rust/src/player.rs +++ b/rust/src/player.rs @@ -48,6 +48,7 @@ pub trait IPlayer { fn take_damage(&mut self, damage: i32, kill: bool); fn is_dead(&self) -> bool; fn kill(&mut self); + fn dead_for(&self) -> f64; } pub trait PlayerMovement { @@ -108,6 +109,7 @@ pub struct LocalPlayer { shoot_cd: f64, is_dead: bool, + dead_for: f64, locked: bool, @@ -201,6 +203,10 @@ impl IPlayer for LocalPlayer { self.is_dead } + fn dead_for(&self) -> f64 { + self.dead_for + } + fn kill(&mut self) { self.run_deferred(move |s| s.signals().on_die().emit()); if let Some(mut mesh) = self.soldier_mesh.take() { @@ -243,6 +249,10 @@ impl ICharacterBody3D for LocalPlayer { } fn process(&mut self, delta: f64) { + if self.is_dead { + self.dead_for += delta; + } + self.shoot_cd -= delta; let input_direction = if self.locked { @@ -381,6 +391,7 @@ pub struct RemotePlayer { look_up: f32, is_dead: bool, + dead_for: f64, shoot_cd: f64, @@ -472,6 +483,10 @@ impl IPlayer for RemotePlayer { self.is_dead } + fn dead_for(&self) -> f64 { + self.dead_for + } + fn kill(&mut self) { self.run_deferred(move |s| s.signals().on_die().emit()); if let Some(mut mesh) = self.soldier_mesh.take() { @@ -499,6 +514,10 @@ impl ICharacterBody3D for RemotePlayer { } fn process(&mut self, delta: f64) { + if self.is_dead { + self.dead_for += delta; + } + self.player_update(delta); self.shoot_cd -= delta;