namespace AcDream.Core.World; /// /// Server-specified palette composition for a live-mode entity. Gets /// handed to so the texture cache can /// compose the effective palette (base with sub-palette overlays) at /// decode time and use it when decoding palette-indexed textures /// (PFID_P8 / PFID_INDEX16). Non-palette textures ignore this entirely. /// /// /// Semantics (ported from Chorizite.ACProtocol.Types.Subpalette docs /// and confirmed against ACE's CalculateObjDesc): /// /// /// BasePaletteId — the entity's base palette dat id /// (0x04XXXXXX). Comes from ObjDesc.Palette. Acts /// as the starting point before subpalette overlays are applied. /// Each overlay entry (SubPaletteId, Offset, Length) /// means "copy the first Length*8 colors from the /// subpalette into the base palette starting at index /// Offset*8." Length=0 is a sentinel meaning "entire /// palette" (Chorizite documents it as defaulting to 256*8 /// which is effectively everything). /// /// /// /// Palette overlays are per-entity, not per-part: all parts of a /// character share the same composed palette (skin color is consistent /// across the whole body even if different body parts use different /// meshes). /// /// public sealed record PaletteOverride( uint BasePaletteId, IReadOnlyList SubPalettes) { /// /// One overlay range in a . Offset and /// Length are the raw bytes the server sent; callers multiply by 8 /// to get palette-index units. /// public readonly record struct SubPaletteRange( uint SubPaletteId, byte Offset, byte Length); }