Files
HEDZReloaded/crates/hedz_reloaded/src/cash.rs
extrawurst da5c0f8fb7 fix cash in multiplayer (#97)
* replicate it
* use collision observer to simplify
* pass entity of player that receives cash for a duplicate head
2025-12-21 21:44:43 -05:00

95 lines
2.5 KiB
Rust

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, Deserialize, Serialize)]
#[reflect(Component)]
#[require(Transform)]
pub struct Cash;
#[derive(Component, Reflect, Default)]
#[reflect(Component)]
struct CashText;
#[derive(Component, Reflect, Default, Serialize, Deserialize, PartialEq)]
pub struct CashInventory {
pub cash: i32,
}
#[derive(EntityEvent)]
pub struct CashCollectEvent {
pub entity: Entity,
}
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<Entity, With<CashSpawn>>) {
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<CashCollectEvent>,
mut commands: Commands,
mut query_player: Query<&mut CashInventory, With<Player>>,
) {
if let Ok(mut cash) = query_player.get_mut(trigger.entity) {
commands.server_trigger(ToClients {
mode: SendMode::Broadcast,
message: PlaySound::CashCollect,
});
cash.cash += 100;
}
}
fn on_cash_collision(
trigger: On<CollisionStart>,
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<Time>, mut query: Query<&mut Rotation, With<Cash>>) {
for mut rotation in query.iter_mut() {
rotation.0 = rotation
.0
.mul_quat(Quat::from_rotation_y(time.delta_secs()));
}
}