Replicate Sounds (#68)
This commit is contained in:
170
crates/shared/src/protocol/mod.rs
Normal file
170
crates/shared/src/protocol/mod.rs
Normal file
@@ -0,0 +1,170 @@
|
||||
pub mod channels;
|
||||
pub mod components;
|
||||
pub mod events;
|
||||
pub mod messages;
|
||||
|
||||
use crate::{
|
||||
GameState,
|
||||
abilities::{BuildExplosionSprite, healing::Healing},
|
||||
animation::AnimationFlags,
|
||||
backpack::{Backpack, backpack_ui::BackpackUiState},
|
||||
camera::{CameraArmRotation, CameraTarget},
|
||||
cash::CashResource,
|
||||
character::{self, AnimatedCharacter},
|
||||
control::{
|
||||
ControlState,
|
||||
controller_common::{MovementSpeedFactor, PlayerCharacterController},
|
||||
controls::ControllerSettings,
|
||||
},
|
||||
cutscene::StartCutscene,
|
||||
global_observer,
|
||||
head::ActiveHead,
|
||||
heads::{ActiveHeads, heads_ui::UiActiveHeads},
|
||||
hitpoints::Hitpoints,
|
||||
platforms::ActivePlatform,
|
||||
player::{Player, PlayerBodyMesh},
|
||||
protocol::channels::UnorderedReliableChannel,
|
||||
utils::triggers::TriggerAppExt,
|
||||
};
|
||||
use avian3d::prelude::{AngularVelocity, CollisionLayers, LinearVelocity};
|
||||
use bevy::prelude::*;
|
||||
pub use components::*;
|
||||
pub use events::*;
|
||||
use happy_feet::{
|
||||
grounding::GroundingState,
|
||||
prelude::{
|
||||
CharacterDrag, CharacterGravity, CharacterMovement, GroundFriction, Grounding,
|
||||
GroundingConfig, KinematicVelocity, MoveInput, SteppingConfig,
|
||||
},
|
||||
};
|
||||
use lightyear::prelude::{
|
||||
AppChannelExt, AppComponentExt, AppMessageExt, AppTriggerExt, ChannelMode, ChannelSettings,
|
||||
NetworkDirection, PredictionMode, PredictionRegistrationExt, ReliableSettings,
|
||||
input::native::InputPlugin,
|
||||
};
|
||||
use lightyear_serde::{
|
||||
SerializationError, reader::ReadInteger, registry::SerializeFns, writer::WriteInteger,
|
||||
};
|
||||
use std::{collections::HashMap, time::Duration};
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_plugins(InputPlugin::<ControlState>::default());
|
||||
|
||||
app.register_type::<PlayerId>();
|
||||
app.register_type::<TbMapEntityId>();
|
||||
app.register_type::<TbMapIdCounter>();
|
||||
app.register_type::<TbMapEntityMapping>();
|
||||
|
||||
app.init_resource::<TbMapIdCounter>();
|
||||
app.init_resource::<TbMapEntityMapping>();
|
||||
|
||||
app.add_channel::<UnorderedReliableChannel>(ChannelSettings {
|
||||
mode: ChannelMode::UnorderedReliable(ReliableSettings::default()),
|
||||
send_frequency: Duration::from_millis(100),
|
||||
priority: 1.0,
|
||||
})
|
||||
.add_direction(NetworkDirection::Bidirectional);
|
||||
|
||||
app.add_message::<messages::DespawnTbMapEntity>()
|
||||
.add_direction(NetworkDirection::ServerToClient);
|
||||
app.add_message::<messages::AssignClientPlayer>()
|
||||
.add_direction(NetworkDirection::ServerToClient);
|
||||
|
||||
app.register_component::<components::GltfSceneRoot>();
|
||||
app.register_component::<components::PlayerId>();
|
||||
app.register_component::<components::TbMapEntityId>();
|
||||
app.register_component::<ActiveHead>();
|
||||
app.register_component::<ActiveHeads>();
|
||||
app.register_component::<ActivePlatform>();
|
||||
app.register_component::<AngularVelocity>();
|
||||
app.register_component::<AnimatedCharacter>();
|
||||
app.register_component::<AnimationFlags>();
|
||||
app.register_component::<Backpack>();
|
||||
app.register_component::<BackpackUiState>();
|
||||
app.register_component::<CameraArmRotation>();
|
||||
app.register_component::<CameraTarget>();
|
||||
app.register_component::<CashResource>();
|
||||
app.register_component::<happy_feet::prelude::Character>();
|
||||
app.register_component::<character::HedzCharacter>();
|
||||
app.register_component::<CharacterDrag>();
|
||||
app.register_component::<CharacterGravity>();
|
||||
app.register_component::<CharacterMovement>();
|
||||
app.register_component::<CollisionLayers>();
|
||||
app.register_component::<ControllerSettings>();
|
||||
app.register_component::<GroundFriction>();
|
||||
app.register_component::<Grounding>();
|
||||
app.register_component::<GroundingConfig>();
|
||||
app.register_component::<GroundingState>();
|
||||
app.register_component::<Healing>();
|
||||
app.register_component::<Hitpoints>();
|
||||
app.register_component::<KinematicVelocity>();
|
||||
app.register_component::<LinearVelocity>();
|
||||
app.register_component::<MoveInput>();
|
||||
app.register_component::<MovementSpeedFactor>();
|
||||
app.register_component::<Name>();
|
||||
app.register_component::<Player>();
|
||||
app.register_component::<PlayerBodyMesh>();
|
||||
app.register_component::<PlayerCharacterController>();
|
||||
app.register_component::<SteppingConfig>();
|
||||
app.register_component::<Transform>()
|
||||
.add_prediction(PredictionMode::Full)
|
||||
.add_should_rollback(transform_should_rollback);
|
||||
app.register_component::<UiActiveHeads>();
|
||||
// `Visibility` isn't `(De)Serialize`, so we have to provide custom serde for it.
|
||||
app.register_component_custom_serde::<Visibility>(SerializeFns {
|
||||
serialize: |comp, writer| writer.write_u8(*comp as u8).map_err(SerializationError::Io),
|
||||
deserialize: |reader| {
|
||||
let byte = reader.read_u8().map_err(SerializationError::Io)?;
|
||||
Ok(match byte {
|
||||
0 => Visibility::Inherited,
|
||||
1 => Visibility::Hidden,
|
||||
2 => Visibility::Visible,
|
||||
_ => return Err(SerializationError::InvalidValue),
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
app.replicate_trigger::<BuildExplosionSprite, UnorderedReliableChannel>();
|
||||
app.replicate_trigger::<StartCutscene, UnorderedReliableChannel>();
|
||||
|
||||
app.replicate_trigger::<events::ClientHeadChanged, UnorderedReliableChannel>();
|
||||
app.replicate_trigger::<events::PlaySound, UnorderedReliableChannel>();
|
||||
|
||||
app.add_trigger::<events::ClientEnteredPlaying>()
|
||||
.add_direction(NetworkDirection::ClientToServer);
|
||||
|
||||
app.add_systems(
|
||||
OnEnter(GameState::MapLoading),
|
||||
|mut counter: ResMut<TbMapIdCounter>| counter.reset(),
|
||||
);
|
||||
|
||||
global_observer!(app, components::spawn_gltf_scene_roots);
|
||||
}
|
||||
|
||||
fn transform_should_rollback(this: &Transform, that: &Transform) -> bool {
|
||||
this.translation.distance_squared(that.translation) >= 0.01f32.powf(2.)
|
||||
}
|
||||
|
||||
/// A global allocator for `TbMapEntityId` values. Should be reset when a map begins loading.
|
||||
#[derive(Resource, Reflect, Default)]
|
||||
#[reflect(Resource)]
|
||||
pub struct TbMapIdCounter(u64);
|
||||
|
||||
impl TbMapIdCounter {
|
||||
pub fn reset(&mut self) {
|
||||
self.0 = 0;
|
||||
}
|
||||
|
||||
pub fn alloc(&mut self) -> TbMapEntityId {
|
||||
let id = self.0;
|
||||
self.0 += 1;
|
||||
TbMapEntityId { id }
|
||||
}
|
||||
}
|
||||
|
||||
/// A mapping from TbMapEntityId to clientside map entity. When the serverside is spawned and the client's
|
||||
/// components migrated to it, or the clientside is despawned because the serverside is already despawned,
|
||||
/// the Id entry is removed from this mapping.
|
||||
#[derive(Resource, Reflect, Default, Deref, DerefMut)]
|
||||
#[reflect(Resource)]
|
||||
pub struct TbMapEntityMapping(pub HashMap<u64, Entity>);
|
||||
Reference in New Issue
Block a user