diff --git a/dGame/dComponents/ModelComponent.cpp b/dGame/dComponents/ModelComponent.cpp index b09c655a0..eb5f06927 100644 --- a/dGame/dComponents/ModelComponent.cpp +++ b/dGame/dComponents/ModelComponent.cpp @@ -156,6 +156,11 @@ void ModelComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialU outBitStream.Write(m_OriginalPosition); // Original position outBitStream.Write(m_OriginalRotation); // Original rotation + // The client makes the mutable model component, which reads the behaviors and editing info, only for objects whose + // config (the settings sent with a model) has propertyObjectID or inInventory; the plain one it makes for every + // other model reads only the block above, as live wrote it + if (!m_Parent->HasVar(u"propertyObjectID") && !m_Parent->GetVar(u"inInventory")) return; + outBitStream.Write1(); // We are writing behavior info outBitStream.Write(m_Behaviors.size()); // Number of behaviors outBitStream.Write(m_IsPaused); // Is this model paused diff --git a/tests/dGameTests/dComponentsTests/ModelComponentTests.cpp b/tests/dGameTests/dComponentsTests/ModelComponentTests.cpp new file mode 100644 index 000000000..23373fa93 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/ModelComponentTests.cpp @@ -0,0 +1,55 @@ +#include "GameDependencies.h" + +#include "BitStream.h" +#include "CDClientManager.h" +#include "CDComponentsRegistryTable.h" +#include "Entity.h" +#include "GameMessages.h" +#include "ModelComponent.h" + +#include + +class ModelComponentTests : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + CDClientManager::GetEntriesMutable().insert_or_assign(static_cast(info.lot), 0); + } + + void TearDown() override { + TearDownDependencies(); + } + + // The bits a model's serialization writes + static uint32_t SerializedBits(Entity& entity) { + auto* model = entity.AddComponent(-1); + RakNet::BitStream bitStream; + model->Serialize(bitStream, true); + return bitStream.GetNumberOfBitsUsed(); + } +}; + +// Item block (1 + 64 + 32 + 1), model block (1 + 1 + 32 + 96 + 128) +constexpr uint32_t ModelBlockBits = 98 + 258; +// Behavior info: flag, count, paused, and on the initial update the editing info flag +constexpr uint32_t BehaviorBits = 1 + 32 + 1 + 1; + +// The client reads the behaviors only for property and inventory models (ObjectLoader2::LoadModelBehaviorsComponent) +TEST_F(ModelComponentTests, OtherModelsHaveNoBehaviorInfo) { + Entity entity(1, info); + EXPECT_EQ(SerializedBits(entity), ModelBlockBits); +} + +TEST_F(ModelComponentTests, PropertyModelsHaveBehaviorInfo) { + EntityInfo propertyInfo = info; + propertyInfo.settings.Insert(u"propertyObjectID", true); + Entity entity(1, propertyInfo); + EXPECT_EQ(SerializedBits(entity), ModelBlockBits + BehaviorBits); +} + +TEST_F(ModelComponentTests, InventoryModelsHaveBehaviorInfo) { + EntityInfo inventoryInfo = info; + inventoryInfo.settings.Insert(u"inInventory", true); + Entity entity(1, inventoryInfo); + EXPECT_EQ(SerializedBits(entity), ModelBlockBits + BehaviorBits); +}