From 131239538bcf71471bcd73cfd87c37e8f257d496 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:42:43 -0700 Subject: [PATCH] Entity: Add missing destroyable case (#1228) Adds a missing edge case on the client where you may have the is_smashable flag set, but dont actually have a destroyable component. In this case you should create only a destroyable component and add it to the component and serialize it last after all other data. We also needed to add the set_faction var reading and setting as this is how Oliver Sudden actually gets their faction since they have no actual information in the database, it is all stored in ldf keys. Tested that Oliver Sudden no longer logs Unable to unserialize logs when serialized or constructed. --- dGame/Entity.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 52b34931c..3f87dec56 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -345,7 +345,7 @@ void Entity::Initialize() { int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF); int rebuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD); - int componentID = 0; + int componentID = -1; if (collectibleComponentID > 0) componentID = collectibleComponentID; if (rebuildComponentID > 0) componentID = rebuildComponentID; if (buffComponentID > 0) componentID = buffComponentID; @@ -353,7 +353,8 @@ void Entity::Initialize() { CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable(); std::vector destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); }); - if (buffComponentID > 0 || collectibleComponentID > 0) { + bool isSmashable = GetVarAs(u"is_smashable") != 0; + if (buffComponentID > 0 || collectibleComponentID > 0 || isSmashable) { DestroyableComponent* comp = new DestroyableComponent(this); if (m_Character) { comp->LoadFromXml(m_Character->GetXMLDoc()); @@ -394,7 +395,7 @@ void Entity::Initialize() { } // extraInfo overrides. Client ORs the database smashable and the luz smashable. - comp->SetIsSmashable(comp->GetIsSmashable() | (GetVarAs(u"is_smashable") != 0)); + comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable); } } else { comp->SetHealth(1); @@ -427,6 +428,19 @@ void Entity::Initialize() { } } + // override the factions if needed. + auto setFaction = GetVarAsString(u"set_faction"); + if (!setFaction.empty()) { + // TODO also split on space here however we do not have a general util for splitting on multiple characters yet. + std::vector factionsToAdd = GeneralUtils::SplitString(setFaction, ';'); + int32_t factionToAdd; + for (const auto faction : factionsToAdd) { + if (GeneralUtils::TryParse(faction, factionToAdd)) { + comp->AddFaction(factionToAdd, true); + } + } + } + m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp)); } @@ -1223,7 +1237,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType renderComponent->Serialize(outBitStream, bIsInitialUpdate); } - if (modelComponent) { + if (modelComponent || !destroyableSerialized) { DestroyableComponent* destroyableComponent; if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);