remove usage of xmldoc as a ptr (#1538)

resolves a memory leak in BrickDatabase, adds stability to character save doc.

Tested that saving manually via force-save, logout and /crash all saved my position and my removed banana as expected.
The doc was always deleted on character destruction and on any updates, so this is just a semantic change (and now we no longer have new'd tinyxml2::documents on the heap)
This commit is contained in:
David Markowitz
2024-04-08 13:13:49 -07:00
committed by GitHub
parent be0a2f6f14
commit 28ce8ac54d
23 changed files with 125 additions and 144 deletions

View File

@@ -326,9 +326,9 @@ Entity* BuffComponent::GetParent() const {
return m_Parent;
}
void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
void BuffComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
// Load buffs
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff");
@@ -386,15 +386,15 @@ void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
}
}
void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
void BuffComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
// Save buffs
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff");
if (buffElement == nullptr) {
buffElement = doc->NewElement("buff");
buffElement = doc.NewElement("buff");
dest->LinkEndChild(buffElement);
} else {
@@ -402,7 +402,7 @@ void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
}
for (const auto& [id, buff] : m_Buffs) {
auto* buffEntry = doc->NewElement("b");
auto* buffEntry = doc.NewElement("b");
// TODO: change this if to if (buff.cancelOnZone || buff.cancelOnLogout) handling at some point. No current way to differentiate between zone transfer and logout.
if (buff.cancelOnZone) continue;

View File

@@ -57,9 +57,9 @@ public:
Entity* GetParent() const;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -186,9 +186,9 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
m_GMLevel = gmlevel;
}
void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
void CharacterComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag while loading XML!");
return;
@@ -299,8 +299,8 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
}
}
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* minifig = doc->FirstChildElement("obj")->FirstChildElement("mf");
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* minifig = doc.FirstChildElement("obj")->FirstChildElement("mf");
if (!minifig) {
LOG("Failed to find mf tag while updating XML!");
return;
@@ -320,7 +320,7 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// done with minifig
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag while updating XML!");
return;
@@ -338,11 +338,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// Set the zone statistics of the form <zs><s/> ... <s/></zs>
auto zoneStatistics = character->FirstChildElement("zs");
if (!zoneStatistics) zoneStatistics = doc->NewElement("zs");
if (!zoneStatistics) zoneStatistics = doc.NewElement("zs");
zoneStatistics->DeleteChildren();
for (auto pair : m_ZoneStatistics) {
auto zoneStatistic = doc->NewElement("s");
auto zoneStatistic = doc.NewElement("s");
zoneStatistic->SetAttribute("map", pair.first);
zoneStatistic->SetAttribute("ac", pair.second.m_AchievementsCollected);

View File

@@ -70,8 +70,8 @@ public:
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
~CharacterComponent() override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -21,11 +21,11 @@ void Component::OnUse(Entity* originator) {
}
void Component::UpdateXml(tinyxml2::XMLDocument* doc) {
void Component::UpdateXml(tinyxml2::XMLDocument& doc) {
}
void Component::LoadFromXml(tinyxml2::XMLDocument* doc) {
void Component::LoadFromXml(const tinyxml2::XMLDocument& doc) {
}

View File

@@ -34,13 +34,13 @@ public:
* Save data from this componennt to character XML
* @param doc the document to write data to
*/
virtual void UpdateXml(tinyxml2::XMLDocument* doc);
virtual void UpdateXml(tinyxml2::XMLDocument& doc);
/**
* Load base data for this component from character XML
* @param doc the document to read data from
*/
virtual void LoadFromXml(tinyxml2::XMLDocument* doc);
virtual void LoadFromXml(const tinyxml2::XMLDocument& doc);
virtual void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);

View File

@@ -158,8 +158,8 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
}
}
void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
void ControllablePhysicsComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag!");
return;
@@ -178,8 +178,8 @@ void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
m_DirtyPosition = true;
}
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag while updating XML!");
return;

View File

@@ -28,8 +28,8 @@ public:
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
/**
* Sets the position of this entity, also ensures this update is serialized next tick.

View File

@@ -185,8 +185,8 @@ void DestroyableComponent::Update(float deltaTime) {
m_DamageCooldownTimer -= deltaTime;
}
void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
void DestroyableComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
if (!dest) {
LOG("Failed to find dest tag!");
return;
@@ -207,8 +207,8 @@ void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
m_DirtyHealth = true;
}
void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
if (!dest) {
LOG("Failed to find dest tag!");
return;

View File

@@ -26,8 +26,8 @@ public:
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
/**
* Initializes the component using a different LOT

View File

@@ -38,7 +38,7 @@
#include "CDObjectSkillsTable.h"
#include "CDSkillBehaviorTable.h"
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) {
InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
this->m_Dirty = true;
this->m_Equipped = {};
this->m_Pushed = {};
@@ -48,7 +48,8 @@ InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* do
const auto lot = parent->GetLOT();
if (lot == 1) {
LoadXml(document);
auto* character = m_Parent->GetCharacter();
if (character) LoadXml(character->GetXMLDoc());
CheckProxyIntegrity();
@@ -472,10 +473,10 @@ bool InventoryComponent::HasSpaceForLoot(const std::unordered_map<LOT, int32_t>&
return true;
}
void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) {
void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
LoadPetXml(document);
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv");
auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
if (inventoryElement == nullptr) {
LOG("Failed to find 'inv' xml element!");
@@ -594,10 +595,10 @@ void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) {
}
}
void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
UpdatePetXml(document);
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv");
auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
if (inventoryElement == nullptr) {
LOG("Failed to find 'inv' xml element!");
@@ -631,7 +632,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
bags->DeleteChildren();
for (const auto* inventory : inventoriesToSave) {
auto* bag = document->NewElement("b");
auto* bag = document.NewElement("b");
bag->SetAttribute("t", inventory->GetType());
bag->SetAttribute("m", static_cast<unsigned int>(inventory->GetSize()));
@@ -654,14 +655,14 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
continue;
}
auto* bagElement = document->NewElement("in");
auto* bagElement = document.NewElement("in");
bagElement->SetAttribute("t", inventory->GetType());
for (const auto& pair : inventory->GetItems()) {
auto* item = pair.second;
auto* itemElement = document->NewElement("i");
auto* itemElement = document.NewElement("i");
itemElement->SetAttribute("l", item->GetLot());
itemElement->SetAttribute("id", item->GetId());
@@ -680,7 +681,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
continue;
}
auto* extraInfo = document->NewElement("x");
auto* extraInfo = document.NewElement("x");
extraInfo->SetAttribute("ma", data->GetString(false).c_str());
@@ -1542,8 +1543,8 @@ void InventoryComponent::PurgeProxies(Item* item) {
}
}
void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) {
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet");
void InventoryComponent::LoadPetXml(const tinyxml2::XMLDocument& document) {
auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
if (petInventoryElement == nullptr) {
m_Pets.clear();
@@ -1574,19 +1575,19 @@ void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) {
}
}
void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) {
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet");
void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument& document) {
auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
if (petInventoryElement == nullptr) {
petInventoryElement = document->NewElement("pet");
petInventoryElement = document.NewElement("pet");
document->FirstChildElement("obj")->LinkEndChild(petInventoryElement);
document.FirstChildElement("obj")->LinkEndChild(petInventoryElement);
}
petInventoryElement->DeleteChildren();
for (const auto& pet : m_Pets) {
auto* petElement = document->NewElement("p");
auto* petElement = document.NewElement("p");
petElement->SetAttribute("id", pet.first);
petElement->SetAttribute("l", pet.second.lot);

View File

@@ -38,12 +38,12 @@ enum class eItemType : int32_t;
class InventoryComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
InventoryComponent(Entity* parent);
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadXml(tinyxml2::XMLDocument* document);
void UpdateXml(tinyxml2::XMLDocument* document) override;
void LoadXml(const tinyxml2::XMLDocument& document);
void UpdateXml(tinyxml2::XMLDocument& document) override;
/**
* Returns an inventory of the specified type, if it exists
@@ -470,13 +470,13 @@ private:
* Saves all the pet information stored in inventory items to the database
* @param document the xml doc to save to
*/
void LoadPetXml(tinyxml2::XMLDocument* document);
void LoadPetXml(const tinyxml2::XMLDocument& document);
/**
* Loads all the pet information from an xml doc into items
* @param document the xml doc to load from
*/
void UpdatePetXml(tinyxml2::XMLDocument* document);
void UpdatePetXml(tinyxml2::XMLDocument& document);
};
#endif

View File

@@ -13,8 +13,8 @@ LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component
m_CharacterVersion = eCharacterVersion::LIVE;
}
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl");
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
if (!level) {
LOG("Failed to find lvl tag while updating XML!");
return;
@@ -24,8 +24,8 @@ void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
level->SetAttribute("cv", static_cast<uint32_t>(m_CharacterVersion));
}
void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl");
void LevelProgressionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
if (!level) {
LOG("Failed to find lvl tag while loading XML!");
return;

View File

@@ -27,13 +27,13 @@ public:
* Save data from this componennt to character XML
* @param doc the document to write data to
*/
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
/**
* Load base data for this component from character XML
* @param doc the document to read data from
*/
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
/**
* Gets the current level of the entity

View File

@@ -504,10 +504,8 @@ bool MissionComponent::RequiresItem(const LOT lot) {
}
void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
if (doc == nullptr) return;
auto* mis = doc->FirstChildElement("obj")->FirstChildElement("mis");
void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* mis = doc.FirstChildElement("obj")->FirstChildElement("mis");
if (mis == nullptr) return;
@@ -523,7 +521,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
auto* mission = new Mission(this, missionId);
mission->LoadFromXml(doneM);
mission->LoadFromXml(*doneM);
doneM = doneM->NextSiblingElement();
@@ -540,7 +538,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
auto* mission = new Mission(this, missionId);
mission->LoadFromXml(currentM);
mission->LoadFromXml(*currentM);
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
mission->SetUniqueMissionOrderID(missionOrder);
@@ -554,25 +552,23 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
}
void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
if (doc == nullptr) return;
void MissionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
auto shouldInsertMis = false;
auto* obj = doc->FirstChildElement("obj");
auto* obj = doc.FirstChildElement("obj");
auto* mis = obj->FirstChildElement("mis");
if (mis == nullptr) {
mis = doc->NewElement("mis");
mis = doc.NewElement("mis");
shouldInsertMis = true;
}
mis->DeleteChildren();
auto* done = doc->NewElement("done");
auto* cur = doc->NewElement("cur");
auto* done = doc.NewElement("done");
auto* cur = doc.NewElement("cur");
for (const auto& pair : m_Missions) {
auto* mission = pair.second;
@@ -580,10 +576,10 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
if (mission) {
const auto complete = mission->IsComplete();
auto* m = doc->NewElement("m");
auto* m = doc.NewElement("m");
if (complete) {
mission->UpdateXml(m);
mission->UpdateXml(*m);
done->LinkEndChild(m);
@@ -591,7 +587,7 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
}
if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID());
mission->UpdateXml(m);
mission->UpdateXml(*m);
cur->LinkEndChild(m);
}

View File

@@ -31,8 +31,8 @@ public:
explicit MissionComponent(Entity* parent);
~MissionComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags);
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
/**
* Returns all the missions for this entity, mapped by mission ID