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>) { 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 query_player: Query<&mut CashInventory, With>, ) { 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, 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