diff --git a/crates/benilla-app/src/entities.rs b/crates/benilla-app/src/entities.rs index 92de7054..a324a5f2 100644 --- a/crates/benilla-app/src/entities.rs +++ b/crates/benilla-app/src/entities.rs @@ -28,6 +28,10 @@ use display::{ mod attach; use attach::{attach_entity_visuals, build_dressup_preview, build_glue_pet, build_glue_preview}; +/// Composited body skins by look, built off the main thread. +mod skin_composite; +use skin_composite::{land_skin_composites, SkinComposites, SkinKey, SkinSections}; + /// The dynamic point lights an entity's own model carries, such as a held torch. mod carried_light; use carried_light::spawn_carried_lights; @@ -371,34 +375,28 @@ struct GameObjects { #[derive(Resource)] struct Characters(CharacterGeosets); -/// The `CharSections` skin lookup; without it a player's body skin stays untextured. -#[derive(Resource)] -struct SkinSections(CharSections); - /// Character-creation data (body displays, race and class combos, appearance ranges). #[derive(Resource)] pub(crate) struct CharCreate(pub(crate) CharCreateCatalog); -/// Composited body skins by look, so every player wearing a look shares one 256² atlas. -#[derive(Resource, Default)] -struct SkinComposites(benilla_assets::SpatialCache>); +/// When a net entity arrived, on the appear fade's clock: the reference stamps a unit's fade as its +/// create block is processed (`0x465c50` → `0x5fb880`, a player's through `0x5debe0` → +/// `0x613af0` at `0x5fb956` → `0x614f80`), before its model or composite is ready, so the ramp runs +/// from here however long the visual waits. A mount child carries its rider's, as the reference +/// writes the unit's one fade onto the mount model (`0x614ae6`–`0x614af4`, `0x614b9e`–`0x614bba`). +#[derive(Component, Clone, Copy, Debug, PartialEq)] +pub(crate) struct Arrival(pub(crate) f32); -/// What decides a composited body skin: race and sex pick the `CharSections` rows, the dials pick -/// the variations, and `equip` holds the worn armour display ids by body slot − 2. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub(super) struct SkinKey { - pub(super) race: u8, - pub(super) sex: u8, - pub(super) skin: u8, - pub(super) face: u8, - pub(super) facial_hair: u8, - pub(super) hair_style: u8, - pub(super) hair_color: u8, - pub(super) equip: [u32; 8], - /// The guild emblem: two guilds' members wear one tabard display but must not share an atlas. - pub(super) emblem: Option, - /// The tabard designer's preview: the emblem paints over an empty tabard slot. - pub(super) tabard_preview: bool, +/// Stamp each net entity's [`Arrival`] the frame it streams in. +fn stamp_arrivals( + mut commands: Commands, + time: Res