Files
HEDZReloaded/crates/shared/src/protocol.rs
2025-07-29 13:32:54 +02:00

118 lines
4.2 KiB
Rust

use crate::{
abilities::BuildExplosionSprite,
animation::AnimationFlags,
camera::{CameraArmRotation, CameraTarget},
character::{self, AnimatedCharacter},
control::{
controller_common::{MovementSpeedFactor, PlayerCharacterController},
controls::ControllerSettings,
},
global_observer,
head::ActiveHead,
heads::ActiveHeads,
loading_assets::GameAssets,
player::{Player, PlayerBodyMesh},
utils::triggers::TriggerAppExt,
};
use avian3d::prelude::{AngularVelocity, CollisionLayers, LinearVelocity};
use bevy::prelude::*;
use happy_feet::{
grounding::GroundingState,
prelude::{
Character, CharacterDrag, CharacterGravity, CharacterMovement, GroundFriction, Grounding,
GroundingConfig, KinematicVelocity, MoveInput, SteppingConfig,
},
};
use lightyear::prelude::{
ActionsChannel, AppComponentExt, PredictionMode, PredictionRegistrationExt,
};
use lightyear_serde::{
SerializationError, reader::ReadInteger, registry::SerializeFns, writer::WriteInteger,
};
use serde::{Deserialize, Serialize};
pub fn plugin(app: &mut App) {
app.register_component::<ActiveHead>();
app.register_component::<ActiveHeads>();
app.register_component::<AngularVelocity>();
app.register_component::<AnimatedCharacter>();
app.register_component::<AnimationFlags>();
app.register_component::<CameraArmRotation>();
app.register_component::<CameraTarget>();
app.register_component::<Character>();
app.register_component::<character::Character>();
app.register_component::<CharacterDrag>();
app.register_component::<CharacterGravity>();
app.register_component::<CharacterMovement>();
app.register_component::<CollisionLayers>();
app.register_component::<ControllerSettings>();
app.register_component::<GltfSceneRoot>();
app.register_component::<GroundFriction>();
app.register_component::<Grounding>();
app.register_component::<GroundingConfig>();
app.register_component::<GroundingState>();
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);
// `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, ActionsChannel>();
global_observer!(app, spawn_gltf_scene_roots);
}
fn transform_should_rollback(this: &Transform, that: &Transform) -> bool {
this.translation.distance_squared(that.translation) >= 0.01f32.powf(2.)
}
#[derive(Component, Reflect, Serialize, Deserialize, PartialEq)]
#[reflect(Component)]
pub enum GltfSceneRoot {
Projectile(String),
}
fn spawn_gltf_scene_roots(
trigger: Trigger<OnAdd, GltfSceneRoot>,
mut commands: Commands,
gltf_roots: Query<&GltfSceneRoot>,
assets: Res<GameAssets>,
gltfs: Res<Assets<Gltf>>,
) -> Result {
let root = gltf_roots.get(trigger.target())?;
let (gltf, index) = match root {
GltfSceneRoot::Projectile(addr) => (
assets.projectiles[format!("{addr}.glb").as_str()].clone(),
0,
),
};
let gltf = gltfs.get(&gltf).unwrap();
let scene = gltf.scenes[index].clone();
commands.entity(trigger.target()).insert(SceneRoot(scene));
Ok(())
}