Live wrote the item component's UGC info on every construction of an
object with an item component (99 of 99 constructions of LOT 14535, a
possessable with item, skill and controllable physics and no Objects row:
ug_id 0, moderation status NoStatus, no description). DLU wrote a 0 bit.
The item component is read after the skill and base-combat-AI components
(ComponentOrderVector::Initialize 0x0101f8e0; live constructions of LOT 14535
have Skill then Item). DLU wrote it before the inventory, which did not show while
it was a single 0 bit next to the skill's 0 bit, but would misalign every
component after it now that it writes more. It now comes after
BASE_COMBAT_AI. The ReplicaComponentOrderTests oracle moves the item the same
way (intended change).
Test: ReplicaConstructionTest.ItemConstructionWritesEmptyUgcInfo,
ReplicaComponentOrderTest.EveryListedComponent (oracle updated).
Check in game: with a second player watching, use a possessable / mount /
vehicle item (e.g. a racing car in the race lobby); it appears, moves and
is left normally for both. Rocket launches and property models look as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
eReplicaComponentType had the destroyable component's registry type (7) named
BUFF, the real buff component (98) as BUFF_REAL, and a made-up DESTROYABLE =
1000 that DestroyableComponent was stored under. Now DESTROYABLE = 7 and
BUFF = 98, as in ComponentsRegistry and the client.
Undone with it:
- Destructible stats came from whichever of the "buff" (7), quick build and
collectible registry ids was set, so the few objects without a type 7 entry
read a DestructibleComponent row with an unrelated id (the NJ dragon relics
16482-16485 via their collectible id, 125 quick build LOTs when placed with
is_smashable). The type 7 entry is used now; objects without one keep the
defaults (is_smashable objects: 1 health, smashable, factions -1 and 6;
collectibles: an empty destroyable). The client does the same
(LWODestroyableComponent::AllocateComponents / DoObjectComponentLoad).
- DestroyableComponent::Reinitialize, an unused copy of that pick order.
- WriteComponents' destroyableSerialized flags: the components are written from
a list in the client's order, and where the destroyable goes (its own place
after the buff, right before a quick build that has no registry entry for it,
or after the render component) is one function.
- The dashboard's registry 7 -> DESTROYABLE mapping; the destroyable type also
has a name there now (1000 was outside magic_enum's range).
Component types are not stored or sent as enum numbers anywhere besides the
CDClient's own values, which now match. migrations/cdserver/4 is unrelated (it
restores LOT 12916's registry rows that migration 0 overwrote) and stays.
Verified: dGameTests ReplicaComponentOrderTests serialize players, enemies,
smashables, quick builds and collectibles with and without a registry entry,
NPCs, pets, vehicles, models and an entity with every listed component with
the new code and a frozen copy of the old WriteComponents, and expect the same
bits for construction and serialization (a deliberately wrong destroyable place
fails them). Full ctest passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>