diff --git a/dGame/dComponents/CollectibleComponent.cpp b/dGame/dComponents/CollectibleComponent.cpp index fe9d2759a..3d2137e6c 100644 --- a/dGame/dComponents/CollectibleComponent.cpp +++ b/dGame/dComponents/CollectibleComponent.cpp @@ -42,8 +42,9 @@ bool CollectibleComponent::CountsFor(const Entity& player) const { } } +// LWOCollectibleComponent::Deserialize (0x00c45ec0) reads the id on construction only void CollectibleComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) { - outBitStream.Write(GetCollectibleId()); + if (isConstruction) outBitStream.Write(GetCollectibleId()); } bool CollectibleComponent::MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportMsg) { diff --git a/dGame/dUtilities/ReplicaDecoder.cpp b/dGame/dUtilities/ReplicaDecoder.cpp index 6a2acfde4..6c5f4328a 100644 --- a/dGame/dUtilities/ReplicaDecoder.cpp +++ b/dGame/dUtilities/ReplicaDecoder.cpp @@ -389,7 +389,8 @@ namespace { } if (r.Bit()) j["onThreatList"] = r.Bit(); } }, - { COLLECTIBLE, [](Reader& r, json& j, bool, const auto&) { j["collectibleID"] = r.Get(); } }, + // LWOCollectibleComponent::Deserialize: the id on construction only + { COLLECTIBLE, [](Reader& r, json& j, bool initial, const auto&) { if (initial) j["collectibleID"] = r.Get(); } }, // LWOPetComponent::Deserialize: everything under the dirty bit, the names on updates too { PET, [](Reader& r, json& j, bool, const auto&) { if (!r.Bit()) return; diff --git a/tests/dGameTests/dComponentsTests/CollectibleComponentTests.cpp b/tests/dGameTests/dComponentsTests/CollectibleComponentTests.cpp index 930265c76..74f16c1c8 100644 --- a/tests/dGameTests/dComponentsTests/CollectibleComponentTests.cpp +++ b/tests/dGameTests/dComponentsTests/CollectibleComponentTests.cpp @@ -2,6 +2,7 @@ // the player has that mission. #include "GameDependencies.h" +#include "BitStream.h" #include "GameMessages.h" #include "CDClientDatabase.h" #include "CDClientManager.h" @@ -60,6 +61,24 @@ TEST_F(CollectibleComponentTests, RequirementMissionIsRead) { EXPECT_EQ(other.AddComponent(999, 5)->GetRequirementMission(), -1); // no row } +// LWOCollectibleComponent::Deserialize reads the 16-bit id on construction and nothing on an update. DLU wrote the id +// on updates too, which the client read as the next components' flag bits. +TEST_F(CollectibleComponentTests, TheIdIsWrittenOnConstructionOnly) { + Entity object(22, info); + auto* const collectible = object.AddComponent(78, 5); + + RakNet::BitStream construction; + collectible->Serialize(construction, true); + ASSERT_EQ(construction.GetNumberOfBitsUsed(), 16u); + int16_t id{}; + construction.Read(id); + EXPECT_EQ(id, 5); + + RakNet::BitStream update; + collectible->Serialize(update, false); + EXPECT_EQ(update.GetNumberOfBitsUsed(), 0u); +} + TEST_F(CollectibleComponentTests, AchievementsAndMissingMissionsAlwaysCount) { Entity player(42, info); player.AddComponent(-1);