mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-06 12:53:44 +00:00
fix(replica): write the item component's UGC info, after skill and combat AI
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>
This commit is contained in:
@@ -1074,8 +1074,8 @@ namespace {
|
||||
using enum eReplicaComponentType;
|
||||
return std::array{
|
||||
POSSESSABLE, MODULE_ASSEMBLY, CONTROLLABLE_PHYSICS, SIMPLE_PHYSICS, RIGID_BODY_PHANTOM_PHYSICS, HAVOK_VEHICLE_PHYSICS,
|
||||
PHANTOM_PHYSICS, SOUND_TRIGGER, RACING_SOUND_TRIGGER, BUFF, DESTROYABLE, COLLECTIBLE, PET, CHARACTER, ITEM, INVENTORY,
|
||||
SCRIPT, SKILL, BASE_COMBAT_AI, QUICK_BUILD, MOVING_PLATFORM, SWITCH, VENDOR, DONATION_VENDOR, ACHIEVEMENT_VENDOR,
|
||||
PHANTOM_PHYSICS, SOUND_TRIGGER, RACING_SOUND_TRIGGER, BUFF, DESTROYABLE, COLLECTIBLE, PET, CHARACTER, INVENTORY,
|
||||
SCRIPT, SKILL, BASE_COMBAT_AI, ITEM, QUICK_BUILD, MOVING_PLATFORM, SWITCH, VENDOR, DONATION_VENDOR, ACHIEVEMENT_VENDOR,
|
||||
BOUNCER, SCRIPTED_ACTIVITY, SHOOTING_GALLERY, RACING_CONTROL, LUP_EXHIBIT, MODEL, RENDER, MINI_GAME_CONTROL,
|
||||
};
|
||||
}();
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
#include "ItemComponent.h"
|
||||
|
||||
void ItemComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
|
||||
outBitStream.Write0();
|
||||
// Live wrote the user-generated-content info on every construction of an object with only an item component:
|
||||
// no UGC id, moderation status NoStatus, no description.
|
||||
outBitStream.Write(isConstruction);
|
||||
if (isConstruction) {
|
||||
outBitStream.Write<LWOOBJID>(LWOOBJID_EMPTY); // ug_id
|
||||
outBitStream.Write<uint32_t>(0); // ug_moderation_status NoStatus
|
||||
outBitStream.Write0(); // ug_description
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,11 +172,6 @@ namespace {
|
||||
characterComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||
}
|
||||
|
||||
ItemComponent* itemComponent;
|
||||
if (TryGet(entity, itemComponent)) {
|
||||
itemComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||
}
|
||||
|
||||
InventoryComponent* inventoryComponent;
|
||||
if (TryGet(entity, inventoryComponent)) {
|
||||
inventoryComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||
@@ -197,6 +192,14 @@ namespace {
|
||||
baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||
}
|
||||
|
||||
// The item comes after the skill and combat AI components, as the client reads them (ComponentOrderVector::Initialize
|
||||
// 0x0101f8e0; live constructions of LOT 14535). It used to come before the inventory, which was harmless while
|
||||
// it wrote a single 0 bit.
|
||||
ItemComponent* itemComponent;
|
||||
if (TryGet(entity, itemComponent)) {
|
||||
itemComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||
}
|
||||
|
||||
QuickBuildComponent* quickBuildComponent;
|
||||
if (TryGet(entity, quickBuildComponent)) {
|
||||
DestroyableComponent* destroyableComponent;
|
||||
|
||||
@@ -242,6 +242,25 @@ TEST_F(ReplicaConstructionTest, TemplateFactionMinusOneIsReplicated) {
|
||||
EXPECT_EQ(smashableDestroyable->GetFactionIDs(), std::vector<int32_t>{ 6 });
|
||||
}
|
||||
|
||||
// An object with an item component (and no model component): live wrote the UGC info on every construction (99 of 99
|
||||
// constructions of LOT 14535): ug_id 0, NoStatus, no description. DLU wrote none.
|
||||
TEST_F(ReplicaConstructionTest, ItemConstructionWritesEmptyUgcInfo) {
|
||||
Entity item(15, info);
|
||||
auto* const component = item.AddComponent<ItemComponent>(-1);
|
||||
RakNet::BitStream construction;
|
||||
component->Serialize(construction, true);
|
||||
RakNet::BitStream expected;
|
||||
expected.Write1();
|
||||
expected.Write<LWOOBJID>(0);
|
||||
expected.Write<uint32_t>(0);
|
||||
expected.Write0();
|
||||
ExpectSameBits(construction, expected);
|
||||
|
||||
RakNet::BitStream serialization;
|
||||
component->Serialize(serialization, false);
|
||||
EXPECT_EQ(serialization.GetNumberOfBitsUsed(), 1u);
|
||||
}
|
||||
|
||||
class InventoryConstructionTest : public GameDependenciesTest {
|
||||
protected:
|
||||
// The items of the live sample below (CDClient 1.10.64 values)
|
||||
|
||||
Reference in New Issue
Block a user