Make sure that ball cannot be picked up by the same player instantly

This commit is contained in:
Sofia 2026-07-21 21:54:09 +03:00
parent b93cb1eb39
commit 179f10e449
5 changed files with 38 additions and 13 deletions

View File

@ -8,6 +8,10 @@ use crate::player::{IPlayer, NetTransform};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=RigidBody3D, init)] #[class(base=RigidBody3D, init)]
pub struct Ball { pub struct Ball {
pub dropper: Option<u16>,
alive_for: f64,
base: Base<RigidBody3D>, base: Base<RigidBody3D>,
} }
@ -19,6 +23,10 @@ impl IRigidBody3D for Ball {
.body_entered() .body_entered()
.connect_other(self, |s, body| s.on_collision(body)); .connect_other(self, |s, body| s.on_collision(body));
} }
fn process(&mut self, delta: f64) {
self.alive_for += delta;
}
} }
#[godot_api] #[godot_api]
@ -37,6 +45,12 @@ impl Ball {
if let Ok(player) = node.try_dynify::<dyn IPlayer>() if let Ok(player) = node.try_dynify::<dyn IPlayer>()
&& let Some(player_id) = player.dyn_bind().get_player_id() && let Some(player_id) = player.dyn_bind().get_player_id()
{ {
if let Some(dropper_id) = self.dropper
&& dropper_id == player_id
&& self.alive_for < 1.0
{
return;
}
self.run_deferred(move |s| s.signals().on_ball_pickup().emit(player_id)); self.run_deferred(move |s| s.signals().on_ball_pickup().emit(player_id));
} }
} }

View File

@ -303,27 +303,30 @@ impl Game {
for player in s.players.clone() { for player in s.players.clone() {
s.spawn_player_server(player.id); s.spawn_player_server(player.id);
} }
s.spawn_ball(None); s.spawn_ball(None, None);
}); });
} }
} }
} }
pub fn spawn_ball(&mut self, transform: Option<NetTransform>) { pub fn spawn_ball(&mut self, transform: Option<NetTransform>, player_id: Option<u16>) {
if let Some(map) = &mut self.current_map { if let Some(map) = &mut self.current_map {
let ball = map.bind_mut().spawn_ball(transform); let ball = map.bind_mut().spawn_ball(transform, player_id);
if let Some(ball) = &ball { if let Some(ball) = &ball {
self.world_ball = Some(ball.clone()); self.world_ball = Some(ball.clone());
ball.signals() ball.signals()
.on_ball_pickup() .on_ball_pickup()
.connect_other(self, |s, player_id| s.handle_ball_pickup(player_id)); .connect_other(self, |s, player_id| s.handle_ball_pickup(player_id));
} }
self.run_deferred(|_| { self.run_deferred(move |_| {
if let Some(ball) = ball if let Some(ball) = ball
&& let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer && let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
&& let PeerKind::Server(peer, _) = peer && let PeerKind::Server(peer, _) = peer
{ {
peer.broadcast_reliable(Package::SpawnBall(ball.bind().get_transform())); peer.broadcast_reliable(Package::SpawnBall(
ball.bind().get_transform(),
player_id,
));
} }
}); });
} }

View File

@ -90,11 +90,16 @@ impl Map {
} }
} }
pub fn spawn_ball(&mut self, transform: Option<NetTransform>) -> Option<Gd<Ball>> { pub fn spawn_ball(
&mut self,
transform: Option<NetTransform>,
player_id: Option<u16>,
) -> Option<Gd<Ball>> {
if let Some(ball_spawner) = self.ball_spawner.clone() if let Some(ball_spawner) = self.ball_spawner.clone()
&& let Some(ball_prefab) = &self.ball && let Some(ball_prefab) = &self.ball
{ {
let mut ball = ball_prefab.instantiate_as::<Ball>(); let mut ball = ball_prefab.instantiate_as::<Ball>();
ball.bind_mut().dropper = player_id;
self.base_mut().add_child(&ball); self.base_mut().add_child(&ball);
if let Some(transform) = transform { if let Some(transform) = transform {
ball.set_global_position(transform.location.into()); ball.set_global_position(transform.location.into());

View File

@ -258,9 +258,9 @@ impl INode for NetworkManager {
.handle_kill(source_player_id, target_player_id); .handle_kill(source_player_id, target_player_id);
} }
} }
Package::SpawnBall(transform) => { Package::SpawnBall(transform, player_id) => {
if let Some(game) = &mut Game::singleton() { if let Some(game) = &mut Game::singleton() {
game.bind_mut().spawn_ball(Some(transform)); game.bind_mut().spawn_ball(Some(transform), player_id);
} }
} }
Package::DespawnBall => { Package::DespawnBall => {
@ -594,7 +594,7 @@ pub enum Package {
Shoot(u16, NetVector3, NetTransform, f32), Shoot(u16, NetVector3, NetTransform, f32),
TakeDamage(DamageSource, u16, i32), TakeDamage(DamageSource, u16, i32),
Kill(DamageSource, u16), Kill(DamageSource, u16),
SpawnBall(NetTransform), SpawnBall(NetTransform, Option<u16>),
DespawnBall, DespawnBall,
SwapWeapon(u16, WeaponType), SwapWeapon(u16, WeaponType),
} }

View File

@ -98,10 +98,13 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
)); ));
if let Some(mut game) = Game::singleton() { if let Some(mut game) = Game::singleton() {
if let Some(ball_origin) = &s.get_ball_origin() { if let Some(ball_origin) = &s.get_ball_origin() {
game.bind_mut().spawn_ball(Some(NetTransform { game.bind_mut().spawn_ball(
Some(NetTransform {
location: ball_origin.get_global_position().into(), location: ball_origin.get_global_position().into(),
rotation: ball_origin.get_global_rotation().into(), rotation: ball_origin.get_global_rotation().into(),
})); }),
s.get_player_id(),
);
} }
} }
} }