Switch to replicon (#80)

This commit is contained in:
PROMETHIA-27
2025-12-08 19:22:17 -05:00
committed by GitHub
parent 7a5d2e6914
commit ff52258ad2
55 changed files with 1212 additions and 2951 deletions

View File

@@ -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)]