diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index 523fb2e..ccbfbda 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, SelfSync}, + Package::{self, Kill, SelfSync, TakeDamage}, PeerKind, SyncPackage, }, util::NetVector3, @@ -289,14 +289,28 @@ impl Game { .signals() .on_die() .connect_other(s, move |s| s.on_death(player_id)); - } else if let Ok(mut local_player) = + 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::() { - local_player + 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) + }); } } @@ -310,7 +324,8 @@ impl Game { } } - pub fn spawn_player(&mut self, id: u16, transform: NetPlayerTransform) { + // 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) { let character = map.bind_mut().spawn_player( @@ -323,6 +338,7 @@ impl Game { } } + // Handle a sync package from the server pub fn handle_sync(&mut self, sync_data: HashMap) { for ( player_id, @@ -353,6 +369,7 @@ impl Game { } } + // Handle a jump, either from the server or from a client pub fn handle_jump(&mut self, player_id: u16) { if player_id != self.self_id.unwrap_or(0) { if let Some(player) = self.find_player_mut(player_id) { @@ -361,6 +378,7 @@ impl Game { } } + // Handle shooting, either from the server of from a client pub fn handle_shoot( &mut self, player_id: u16, @@ -381,8 +399,42 @@ impl Game { } } + // Handle taking damage, from server to client + pub fn handle_take_damage(&mut self, player_id: u16, damage: i32) { + if let Some(player) = self.find_player_mut(player_id) { + if let Some(character) = &mut player.character { + character.dyn_bind_mut().take_damage(damage, false); + } + } + } + + // 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(); + } + } + } + + // Called whenever a player takes damage on the server-side + pub fn on_take_damage(&mut self, player_id: u16, damage: i32) { + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { + if let PeerKind::Server(peer, _) = peer { + peer.broadcast_reliable(TakeDamage(player_id, damage)); + } + } + } + + // Called whenever a player dies on the server-side pub fn on_death(&mut self, player_id: u16) { - godot_print!("Player {} has died!", player_id); + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { + if let PeerKind::Server(peer, _) = peer { + godot_print!("Sent kill!"); + peer.broadcast_reliable(Kill(player_id)); + } + } } } diff --git a/rust/src/net/network_manager.rs b/rust/src/net/network_manager.rs index 1fbaded..fbcbdc5 100644 --- a/rust/src/net/network_manager.rs +++ b/rust/src/net/network_manager.rs @@ -214,7 +214,7 @@ impl INode for NetworkManager { } Package::SpawnPlayer(id, transform) => { if let Some(game) = &mut Game::singleton() { - game.bind_mut().spawn_player(id, transform); + game.bind_mut().spawn_player_client(id, transform); } } Package::Sync(sync_data) => { @@ -238,6 +238,16 @@ impl INode for NetworkManager { ); } } + Package::TakeDamage(player_id, damage) => { + if let Some(game) = &mut Game::singleton() { + game.bind_mut().handle_take_damage(player_id, damage); + } + } + Package::Kill(player_id) => { + if let Some(game) = &mut Game::singleton() { + game.bind_mut().handle_kill(player_id); + } + } _ => {} }, } @@ -541,6 +551,8 @@ pub enum Package { SelfSync(SyncPackage), Jump(u16), Shoot(u16, NetVector3, NetPlayerTransform, f32), + TakeDamage(u16, i32), + Kill(u16), } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/rust/src/player.rs b/rust/src/player.rs index 09dd8ad..c893a04 100644 --- a/rust/src/player.rs +++ b/rust/src/player.rs @@ -45,7 +45,7 @@ pub trait IPlayer { fn get_transform(&self) -> NetPlayerTransform; fn jump(&mut self); fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool; - fn take_damage(&mut self, damage: i32); + fn take_damage(&mut self, damage: i32, kill: bool); fn is_dead(&self) -> bool; fn kill(&mut self); } @@ -183,9 +183,10 @@ impl IPlayer for LocalPlayer { } } - fn take_damage(&mut self, damage: i32) { + fn take_damage(&mut self, damage: i32, kill: bool) { + self.run_deferred(move |s| s.signals().on_take_damage().emit(damage)); self.health -= damage; - if self.health <= 0 { + if kill && self.health <= 0 { self.kill(); } } @@ -195,7 +196,7 @@ impl IPlayer for LocalPlayer { } fn kill(&mut self) { - self.signals().on_die().emit(); + self.run_deferred(move |s| s.signals().on_die().emit()); if let Some(mut mesh) = self.soldier_mesh.take() { mesh.queue_free(); } @@ -328,6 +329,8 @@ impl ICharacterBody3D for LocalPlayer { impl LocalPlayer { #[signal] pub fn on_die(); + #[signal] + pub fn on_take_damage(damage: i32); fn set_lock(&mut self, locked: bool) { self.locked = locked; @@ -440,9 +443,10 @@ impl IPlayer for RemotePlayer { } } - fn take_damage(&mut self, damage: i32) { + fn take_damage(&mut self, damage: i32, kill: bool) { + self.run_deferred(move |s| s.signals().on_take_damage().emit(damage)); self.health -= damage; - if self.health <= 0 { + if kill && self.health <= 0 { self.kill(); } } @@ -452,7 +456,7 @@ impl IPlayer for RemotePlayer { } fn kill(&mut self) { - self.signals().on_die().emit(); + self.run_deferred(move |s| s.signals().on_die().emit()); if let Some(mut mesh) = self.soldier_mesh.take() { mesh.queue_free(); } @@ -495,4 +499,6 @@ impl ICharacterBody3D for RemotePlayer { impl RemotePlayer { #[signal] pub fn on_die(); + #[signal] + pub fn on_take_damage(damage: i32); } diff --git a/rust/src/weapon.rs b/rust/src/weapon.rs index 953fe3d..16c6d7c 100644 --- a/rust/src/weapon.rs +++ b/rust/src/weapon.rs @@ -56,7 +56,7 @@ impl Weapon for Raygun { if deal_damage && let Some(target) = target { if let Ok(mut player) = target.collider.try_dynify::() { - player.dyn_bind_mut().take_damage(100); + player.dyn_bind_mut().take_damage(100, true); } } }