Switch to replicon (#80)
This commit is contained in:
@@ -1,8 +1,3 @@
|
||||
pub mod channels;
|
||||
pub mod components;
|
||||
pub mod events;
|
||||
pub mod messages;
|
||||
|
||||
use crate::{
|
||||
GameState,
|
||||
abilities::{BuildExplosionSprite, healing::Healing},
|
||||
@@ -12,7 +7,7 @@ use crate::{
|
||||
cash::CashResource,
|
||||
character::{AnimatedCharacter, HedzCharacter},
|
||||
control::{
|
||||
ControlState, ControllerSettings,
|
||||
ControlState, ControllerSettings, Inputs,
|
||||
controller_common::{MovementSpeedFactor, PlayerCharacterController},
|
||||
},
|
||||
cutscene::StartCutscene,
|
||||
@@ -22,14 +17,18 @@ use crate::{
|
||||
hitpoints::Hitpoints,
|
||||
platforms::ActivePlatform,
|
||||
player::{Player, PlayerBodyMesh},
|
||||
protocol::channels::UnorderedReliableChannel,
|
||||
utils::{
|
||||
auto_rotate::AutoRotation, billboards::Billboard, squish_animation::SquishAnimation,
|
||||
triggers::TriggerAppExt,
|
||||
},
|
||||
tick::GameTick,
|
||||
utils::{auto_rotate::AutoRotation, billboards::Billboard, squish_animation::SquishAnimation},
|
||||
};
|
||||
use avian3d::prelude::{
|
||||
AngularInertia, AngularVelocity, CenterOfMass, Collider, ColliderDensity, CollisionLayers,
|
||||
LinearVelocity, LockedAxes, Mass, Position, RigidBody, Rotation,
|
||||
};
|
||||
use avian3d::prelude::{AngularVelocity, CollisionLayers, LinearVelocity, Position, Rotation};
|
||||
use bevy::{platform::collections::HashMap, prelude::*};
|
||||
use bevy_replicon::prelude::{
|
||||
AppRuleExt, Channel, ClientEventAppExt, ClientMessageAppExt, ServerEventAppExt,
|
||||
ServerMessageAppExt, SyncRelatedAppExt,
|
||||
};
|
||||
pub use components::*;
|
||||
pub use events::*;
|
||||
use happy_feet::{
|
||||
@@ -39,146 +38,134 @@ use happy_feet::{
|
||||
GroundingConfig, KinematicVelocity, MoveInput, SteppingConfig,
|
||||
},
|
||||
};
|
||||
use lightyear::prelude::{
|
||||
AppChannelExt, AppComponentExt, AppMessageExt, AppTriggerExt, ChannelMode, ChannelSettings,
|
||||
ComponentReplicationConfig, Confirmed, ConfirmedTick, InterpolationRegistrationExt,
|
||||
NetworkDirection, PredictionHistory, PredictionRegistrationExt, ReliableSettings,
|
||||
input::native::InputPlugin,
|
||||
};
|
||||
use lightyear_serde::{
|
||||
SerializationError, reader::ReadInteger, registry::SerializeFns, writer::WriteInteger,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod components;
|
||||
pub mod events;
|
||||
pub mod messages;
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_plugins(InputPlugin::<ControlState>::default());
|
||||
app.add_client_message::<ControlState>(Channel::Unreliable);
|
||||
|
||||
app.register_type::<ConfirmedTick>();
|
||||
app.register_type::<Confirmed<Position>>();
|
||||
app.register_type::<Confirmed<Rotation>>();
|
||||
app.register_type::<PredictionHistory<Position>>();
|
||||
app.add_client_event::<ClientEnteredPlaying>(Channel::Ordered);
|
||||
|
||||
app.add_server_message::<messages::DespawnTbMapEntity>(Channel::Unordered)
|
||||
.add_server_message::<messages::AssignClientPlayer>(Channel::Unordered);
|
||||
|
||||
app.add_server_event::<ClientHeadChanged>(Channel::Unordered)
|
||||
.add_server_event::<BuildExplosionSprite>(Channel::Unreliable)
|
||||
.add_server_event::<StartCutscene>(Channel::Ordered)
|
||||
.add_server_event::<events::PlaySound>(Channel::Unreliable)
|
||||
.add_server_event::<events::SetGameTick>(Channel::Ordered);
|
||||
|
||||
app.register_type::<PlayerId>();
|
||||
app.register_type::<TbMapEntityId>();
|
||||
app.register_type::<TbMapIdCounter>();
|
||||
app.register_type::<TbMapEntityMapping>();
|
||||
|
||||
app.init_resource::<PlayerIdMap>();
|
||||
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.replicate::<ChildOf>();
|
||||
app.sync_related_entities::<ChildOf>();
|
||||
|
||||
app.register_message::<messages::DespawnTbMapEntity>()
|
||||
.add_direction(NetworkDirection::ServerToClient);
|
||||
app.register_message::<messages::AssignClientPlayer>()
|
||||
.add_direction(NetworkDirection::ServerToClient);
|
||||
app.replicate::<components::GltfSceneRoot>()
|
||||
.replicate_once::<components::PlayerId>()
|
||||
.replicate::<components::TbMapEntityId>()
|
||||
.replicate::<ActiveHead>()
|
||||
.replicate::<ActiveHeads>()
|
||||
.replicate::<ActivePlatform>()
|
||||
.replicate::<AnimatedCharacter>()
|
||||
.replicate::<AnimationFlags>()
|
||||
.replicate_once::<AutoRotation>()
|
||||
.replicate::<Backpack>()
|
||||
.replicate::<BackpackUiState>()
|
||||
.replicate::<Billboard>()
|
||||
.replicate_once::<CameraArmRotation>()
|
||||
.replicate_once::<CameraTarget>()
|
||||
.replicate::<CashResource>()
|
||||
.replicate_once::<HedzCharacter>()
|
||||
.replicate_once::<Healing>()
|
||||
.replicate::<Hitpoints>()
|
||||
.replicate::<Inputs>()
|
||||
.replicate::<Name>()
|
||||
.replicate_once::<Player>()
|
||||
.replicate_once::<PlayerBodyMesh>()
|
||||
.replicate::<SquishAnimation>()
|
||||
.replicate_once::<Transform>()
|
||||
.replicate::<UiActiveHeads>()
|
||||
.replicate_as::<Visibility, SerVisibility>();
|
||||
|
||||
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::<AnimatedCharacter>();
|
||||
app.register_component::<AnimationFlags>();
|
||||
app.register_component::<AutoRotation>()
|
||||
.with_replication_config(ComponentReplicationConfig {
|
||||
replicate_once: true,
|
||||
..default()
|
||||
});
|
||||
app.register_component::<Backpack>();
|
||||
app.register_component::<BackpackUiState>();
|
||||
app.register_component::<Billboard>();
|
||||
app.register_component::<CameraArmRotation>();
|
||||
app.register_component::<CameraTarget>();
|
||||
app.register_component::<CashResource>();
|
||||
app.register_component::<HedzCharacter>();
|
||||
app.register_component::<Healing>();
|
||||
app.register_component::<Hitpoints>();
|
||||
app.register_component::<Name>();
|
||||
app.register_component::<Player>();
|
||||
app.register_component::<PlayerBodyMesh>()
|
||||
.with_replication_config(ComponentReplicationConfig {
|
||||
replicate_once: true,
|
||||
..default()
|
||||
});
|
||||
app.register_component::<SquishAnimation>();
|
||||
// Physics components
|
||||
app.replicate::<AngularInertia>()
|
||||
.replicate::<AngularVelocity>()
|
||||
.replicate::<CenterOfMass>()
|
||||
.replicate_filtered_as::<Collider, NetworkedCollider, Without<SkipReplicateColliders>>()
|
||||
.replicate::<ColliderDensity>()
|
||||
.replicate::<CollisionLayers>()
|
||||
.replicate::<LinearVelocity>()
|
||||
.replicate::<LockedAxes>()
|
||||
.replicate::<Mass>()
|
||||
.replicate::<Position>()
|
||||
.replicate::<RigidBody>()
|
||||
.replicate::<Rotation>();
|
||||
|
||||
// Physics
|
||||
app.register_component::<AngularVelocity>()
|
||||
.add_prediction()
|
||||
.add_should_rollback(|this, that| this.0.distance_squared(that.0) >= 0.01f32.powf(2.0));
|
||||
app.register_component::<CollisionLayers>();
|
||||
app.register_component::<LinearVelocity>()
|
||||
.add_prediction()
|
||||
.add_should_rollback(|this, that| this.0.distance_squared(that.0) >= 0.01f32.powf(2.0));
|
||||
app.register_component::<Position>()
|
||||
.add_prediction()
|
||||
.add_should_rollback(|this, that| this.0.distance_squared(that.0) >= 0.01f32.powf(2.0))
|
||||
.add_linear_correction_fn()
|
||||
.add_linear_interpolation();
|
||||
app.register_component::<Rotation>()
|
||||
.add_prediction()
|
||||
.add_should_rollback(|this, that| this.angle_between(*that) >= 0.01)
|
||||
.add_linear_correction_fn()
|
||||
.add_linear_interpolation();
|
||||
|
||||
// Controller
|
||||
app.register_component::<CharacterDrag>();
|
||||
app.register_component::<CharacterGravity>();
|
||||
app.register_component::<CharacterMovement>();
|
||||
app.register_component::<ControllerSettings>();
|
||||
app.register_component::<GroundFriction>();
|
||||
app.register_component::<Grounding>();
|
||||
app.register_component::<GroundingConfig>();
|
||||
app.register_component::<GroundingState>();
|
||||
app.register_component::<KinematicVelocity>();
|
||||
app.register_component::<MoveInput>();
|
||||
app.register_component::<MovementSpeedFactor>();
|
||||
app.register_component::<PlayerCharacterController>()
|
||||
.with_replication_config(ComponentReplicationConfig {
|
||||
replicate_once: true,
|
||||
..default()
|
||||
});
|
||||
app.register_component::<SteppingConfig>();
|
||||
|
||||
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_event::<BuildExplosionSprite, UnorderedReliableChannel>();
|
||||
app.replicate_event::<StartCutscene, UnorderedReliableChannel>();
|
||||
|
||||
app.replicate_event::<events::ClientHeadChanged, UnorderedReliableChannel>();
|
||||
app.replicate_event::<events::PlaySound, UnorderedReliableChannel>();
|
||||
|
||||
app.register_event::<events::ClientEnteredPlaying>()
|
||||
.add_direction(NetworkDirection::ClientToServer);
|
||||
// Character controller components
|
||||
app.replicate::<CharacterDrag>()
|
||||
.replicate::<CharacterGravity>()
|
||||
.replicate::<CharacterMovement>()
|
||||
.replicate::<ControllerSettings>()
|
||||
.replicate::<GroundFriction>()
|
||||
.replicate::<Grounding>()
|
||||
.replicate::<GroundingConfig>()
|
||||
.replicate::<GroundingState>()
|
||||
.replicate::<KinematicVelocity>()
|
||||
.replicate::<MoveInput>()
|
||||
.replicate::<MovementSpeedFactor>()
|
||||
.replicate_once::<PlayerCharacterController>()
|
||||
.replicate::<SteppingConfig>();
|
||||
|
||||
app.add_systems(
|
||||
OnEnter(GameState::MapLoading),
|
||||
|mut counter: ResMut<TbMapIdCounter>| counter.reset(),
|
||||
);
|
||||
|
||||
global_observer!(app, set_game_tick);
|
||||
global_observer!(app, components::spawn_gltf_scene_roots);
|
||||
}
|
||||
|
||||
fn set_game_tick(on: On<SetGameTick>, mut tick: ResMut<GameTick>) {
|
||||
tick.0 = on.event().0;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum SerVisibility {
|
||||
Inherited,
|
||||
Hidden,
|
||||
Visible,
|
||||
}
|
||||
|
||||
impl From<Visibility> for SerVisibility {
|
||||
fn from(value: Visibility) -> Self {
|
||||
match value {
|
||||
Visibility::Inherited => Self::Inherited,
|
||||
Visibility::Hidden => Self::Hidden,
|
||||
Visibility::Visible => Self::Visible,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SerVisibility> for Visibility {
|
||||
fn from(value: SerVisibility) -> Self {
|
||||
match value {
|
||||
SerVisibility::Inherited => Self::Inherited,
|
||||
SerVisibility::Hidden => Self::Hidden,
|
||||
SerVisibility::Visible => Self::Visible,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A global allocator for `TbMapEntityId` values. Should be reset when a map begins loading.
|
||||
#[derive(Resource, Reflect, Default)]
|
||||
#[reflect(Resource)]
|
||||
|
||||
Reference in New Issue
Block a user