From a6e6e66d28059c9651b29afef42df11cf1a90d48 Mon Sep 17 00:00:00 2001 From: Sofia Date: Mon, 27 Jul 2026 22:43:57 +0300 Subject: [PATCH] Propagate teleport when teleport grenade collides --- godot/scenes/misc/teleport_grenade.tscn | 2 ++ rust/src/game_manager.rs | 8 ++++++++ rust/src/net/network_manager.rs | 1 + rust/src/net/protocol.rs | 5 +++++ rust/src/player/local_player.rs | 4 ++++ rust/src/player/mod.rs | 10 ++++++++++ rust/src/player/remote_player.rs | 4 ++++ rust/src/player/telegrenade.rs | 26 ++++++++++++++++++++++--- 8 files changed, 57 insertions(+), 3 deletions(-) diff --git a/godot/scenes/misc/teleport_grenade.tscn b/godot/scenes/misc/teleport_grenade.tscn index dc1d7e0..9b0cab1 100644 --- a/godot/scenes/misc/teleport_grenade.tscn +++ b/godot/scenes/misc/teleport_grenade.tscn @@ -15,6 +15,8 @@ size = Vector3(0.1, 0.1, 0.1) [node name="teleport_grenade" type="Telegrenade" unique_id=1670808846] collision_layer = 0 collision_mask = 4 +contact_monitor = true +max_contacts_reported = 1 [node name="collision_shape_3d" type="CollisionShape3D" parent="." unique_id=1124839205] shape = SubResource("SphereShape3D_1cgct") diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index c55e961..44222d1 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -1300,6 +1300,14 @@ impl Game { character.dyn_bind_mut().try_throw_telegrenade(to.into()); } } + + pub fn handle_telegrenade_teleport(&mut self, player_id: u16, to: NetVector3) { + if let Some(player) = self.find_player_mut(player_id) + && let Some(character) = &mut player.character + { + character.dyn_bind_mut().telegrenade_teleport(to.into()); + } + } } #[derive(Clone, Debug)] diff --git a/rust/src/net/network_manager.rs b/rust/src/net/network_manager.rs index b908699..fb005c0 100644 --- a/rust/src/net/network_manager.rs +++ b/rust/src/net/network_manager.rs @@ -316,6 +316,7 @@ pub enum Package { Announcement(u16, Announcement), Pickup(u8, u16), ThrowTelegrenade(u16, NetVector3), + TelegrenadeTeleport(u16, NetVector3), // End-of-Game packages FinishGame, diff --git a/rust/src/net/protocol.rs b/rust/src/net/protocol.rs index b45d724..c437854 100644 --- a/rust/src/net/protocol.rs +++ b/rust/src/net/protocol.rs @@ -238,6 +238,11 @@ impl NetworkManager { } } } + Package::TelegrenadeTeleport(player_id, to) => { + if let Some(game) = &mut Game::singleton() { + game.bind_mut().handle_telegrenade_teleport(player_id, to); + } + } _ => {} }, }, diff --git a/rust/src/player/local_player.rs b/rust/src/player/local_player.rs index c59e97c..4de0ccc 100644 --- a/rust/src/player/local_player.rs +++ b/rust/src/player/local_player.rs @@ -341,6 +341,10 @@ impl IPlayer for LocalPlayer { self.telegrenade.clone() } + fn telegrenade_teleport(&mut self, to: Vector3) { + self.telegrenade_teleport_common(to); + } + fn as_gd(&self) -> DynGd { self.to_gd().into_dyn().upcast() } diff --git a/rust/src/player/mod.rs b/rust/src/player/mod.rs index 6126b15..938205b 100644 --- a/rust/src/player/mod.rs +++ b/rust/src/player/mod.rs @@ -70,6 +70,7 @@ pub trait IPlayer { fn try_throw_telegrenade(&mut self, to: Vector3) -> bool; fn set_telegrenade(&mut self, telegrenade: Option>); fn get_telegrenade(&self) -> Option>; + fn telegrenade_teleport(&mut self, to: Vector3); fn as_gd(&self) -> DynGd; } @@ -82,6 +83,7 @@ pub trait PlayerCommon { fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool) -> bool; fn try_punch_common(&mut self, to: Vector3, deal_damage: bool) -> bool; fn throw_telegrenade_common(&mut self, to: Vector3) -> bool; + fn telegrenade_teleport_common(&mut self, to: Vector3); } impl PlayerCommon for T { @@ -290,6 +292,14 @@ impl PlayerCommon for T { true } + + fn telegrenade_teleport_common(&mut self, to: Vector3) { + if let Some(mut telegrenade) = self.get_telegrenade() { + telegrenade.queue_free(); + } + self.set_telegrenade(None); + self.base_mut().set_global_position(to); + } } #[derive(Clone, Copy, Debug, Serialize, Deserialize)] diff --git a/rust/src/player/remote_player.rs b/rust/src/player/remote_player.rs index ecf499d..dbac0f1 100644 --- a/rust/src/player/remote_player.rs +++ b/rust/src/player/remote_player.rs @@ -281,6 +281,10 @@ impl IPlayer for RemotePlayer { self.telegrenade.clone() } + fn telegrenade_teleport(&mut self, to: Vector3) { + self.telegrenade_teleport_common(to); + } + fn as_gd(&self) -> DynGd { self.to_gd().into_dyn().upcast() } diff --git a/rust/src/player/telegrenade.rs b/rust/src/player/telegrenade.rs index 57ff447..ddbbd1c 100644 --- a/rust/src/player/telegrenade.rs +++ b/rust/src/player/telegrenade.rs @@ -4,7 +4,10 @@ use godot::{ }; use crate::{ - net::util::NetVector3, + net::{ + network_manager::{NetworkManager, Package, PeerKind}, + util::NetVector3, + }, player::{IPlayer, NetTransform}, }; @@ -18,11 +21,28 @@ pub struct Telegrenade { #[godot_api] impl IRigidBody3D for Telegrenade { - fn ready(&mut self) {} + fn ready(&mut self) { + self.base() + .signals() + .body_entered() + .connect_other(self, |s, _| s.on_collision()); + } } impl Telegrenade { - pub fn teleport(&mut self) {} + pub fn on_collision(&mut self) { + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer + && let PeerKind::Server(peer, _) = peer + && let Some(mut player) = self.player.clone() + { + let pos = self.base().get_global_position(); + player.dyn_bind_mut().telegrenade_teleport(pos); + peer.broadcast_reliable(Package::TelegrenadeTeleport( + player.dyn_bind().get_player_id().unwrap_or(0), + pos.into(), + )); + } + } pub fn get_transform(&self) -> NetTransform { NetTransform {