From da5c0f8fb7711e842a91802081c05980ab7bb81c Mon Sep 17 00:00:00 2001 From: extrawurst <776816+extrawurst@users.noreply.github.com> Date: Mon, 22 Dec 2025 03:44:43 +0100 Subject: [PATCH] fix cash in multiplayer (#97) * replicate it * use collision observer to simplify * pass entity of player that receives cash for a duplicate head --- crates/hedz_reloaded/src/backpack/mod.rs | 2 +- crates/hedz_reloaded/src/cash.rs | 82 ++++++++++++++----- crates/hedz_reloaded/src/player.rs | 31 +------ .../hedz_reloaded/src/protocol/components.rs | 2 + crates/hedz_reloaded/src/protocol/mod.rs | 3 +- crates/hedz_reloaded/src/tb_entities.rs | 23 ------ 6 files changed, 69 insertions(+), 74 deletions(-) diff --git a/crates/hedz_reloaded/src/backpack/mod.rs b/crates/hedz_reloaded/src/backpack/mod.rs index d2f558e..b7d4c59 100644 --- a/crates/hedz_reloaded/src/backpack/mod.rs +++ b/crates/hedz_reloaded/src/backpack/mod.rs @@ -54,7 +54,7 @@ fn on_head_collect( let (mut backpack, active_heads) = query.get_mut(entity)?; if backpack.contains(head) || active_heads.contains(head) { - cmds.trigger(CashCollectEvent); + cmds.trigger(CashCollectEvent { entity }); } else { backpack.insert(head, heads_db.as_ref()); } diff --git a/crates/hedz_reloaded/src/cash.rs b/crates/hedz_reloaded/src/cash.rs index 181f854..c665dff 100644 --- a/crates/hedz_reloaded/src/cash.rs +++ b/crates/hedz_reloaded/src/cash.rs @@ -1,9 +1,17 @@ -use crate::{GameState, global_observer, protocol::PlaySound, server_observer}; -use avian3d::prelude::Rotation; +use crate::{ + GameState, global_observer, + physics_layers::GameLayer, + player::Player, + protocol::{GltfSceneRoot, PlaySound, is_server}, + server_observer, + tb_entities::CashSpawn, +}; +use avian3d::prelude::*; use bevy::prelude::*; +use bevy_replicon::prelude::*; use serde::{Deserialize, Serialize}; -#[derive(Component, Reflect, Default)] +#[derive(Component, Reflect, Default, Deserialize, Serialize)] #[reflect(Component)] #[require(Transform)] pub struct Cash; @@ -17,28 +25,64 @@ pub struct CashInventory { pub cash: i32, } -#[derive(Event)] -pub struct CashCollectEvent; - -pub fn plugin(app: &mut App) { - app.add_systems(Update, rotate.run_if(in_state(GameState::Playing))); - - server_observer!(app, on_cash_collect); +#[derive(EntityEvent)] +pub struct CashCollectEvent { + pub entity: Entity, } -fn on_cash_collect( - _trigger: On, +pub fn plugin(app: &mut App) { + app.add_systems(OnEnter(GameState::Playing), setup.run_if(is_server)); + app.add_systems(Update, rotate.run_if(in_state(GameState::Playing))); + + server_observer!(app, on_cash_collected); +} + +fn setup(mut commands: Commands, query: Query>) { + for entity in query.iter() { + commands + .entity(entity) + .insert(( + Name::new("cash"), + GltfSceneRoot::Cash, + Cash, + Collider::cuboid(2., 3.0, 2.), + CollisionLayers::new(GameLayer::CollectibleSensors, LayerMask::ALL), + RigidBody::Kinematic, + CollisionEventsEnabled, + Sensor, + Replicated, + )) + .observe(on_cash_collision); + } +} + +fn on_cash_collected( + trigger: On, mut commands: Commands, - mut cash: Single<&mut CashInventory>, + mut query_player: Query<&mut CashInventory, With>, ) { - use bevy_replicon::prelude::{SendMode, ServerTriggerExt, ToClients}; + if let Ok(mut cash) = query_player.get_mut(trigger.entity) { + commands.server_trigger(ToClients { + mode: SendMode::Broadcast, + message: PlaySound::CashCollect, + }); - commands.server_trigger(ToClients { - mode: SendMode::Broadcast, - message: PlaySound::CashCollect, - }); + cash.cash += 100; + } +} - cash.cash += 100; +fn on_cash_collision( + trigger: On, + mut commands: Commands, + query_player: Query<&Player>, +) { + let collectable = trigger.event().collider1; + let collider = trigger.event().collider2; + + if query_player.contains(collider) { + commands.trigger(CashCollectEvent { entity: collider }); + commands.entity(collectable).despawn(); + } } fn rotate(time: Res