From f0960d48b21d4d558ad378d6bcf9c7c0d6f8ba3d Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 22 May 2024 17:06:52 -0700 Subject: [PATCH] Add more modular saving of config data for items (#1591) * stubbing for saving item extra data * add declaration to header * modularize loading for all possible extra data * move logic to Item * remove extra map --- dCommon/LDFFormat.h | 74 ++++++++++++------------ dGame/dComponents/InventoryComponent.cpp | 41 ++++--------- dGame/dInventory/Item.cpp | 55 +++++++++++++++++- dGame/dInventory/Item.h | 14 +++++ 4 files changed, 115 insertions(+), 69 deletions(-) diff --git a/dCommon/LDFFormat.h b/dCommon/LDFFormat.h index 2cd9156c..054ddb42 100644 --- a/dCommon/LDFFormat.h +++ b/dCommon/LDFFormat.h @@ -31,22 +31,22 @@ public: virtual ~LDFBaseData() {} - virtual void WriteToPacket(RakNet::BitStream& packet) = 0; + virtual void WriteToPacket(RakNet::BitStream& packet) const = 0; - virtual const std::u16string& GetKey() = 0; + virtual const std::u16string& GetKey() const = 0; - virtual eLDFType GetValueType() = 0; + virtual eLDFType GetValueType() const = 0; /** Gets a string from the key/value pair * @param includeKey Whether or not to include the key in the data * @param includeTypeId Whether or not to include the type id in the data * @return The string representation of the data */ - virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0; + virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) const = 0; - virtual std::string GetValueAsString() = 0; + virtual std::string GetValueAsString() const = 0; - virtual LDFBaseData* Copy() = 0; + virtual LDFBaseData* Copy() const = 0; /** * Given an input string, return the data as a LDF key. @@ -62,7 +62,7 @@ private: T value; //! Writes the key to the packet - void WriteKey(RakNet::BitStream& packet) { + void WriteKey(RakNet::BitStream& packet) const { packet.Write(this->key.length() * sizeof(uint16_t)); for (uint32_t i = 0; i < this->key.length(); ++i) { packet.Write(this->key[i]); @@ -70,7 +70,7 @@ private: } //! Writes the value to the packet - void WriteValue(RakNet::BitStream& packet) { + void WriteValue(RakNet::BitStream& packet) const { packet.Write(this->GetValueType()); packet.Write(this->value); } @@ -90,7 +90,7 @@ public: /*! \return The value */ - const T& GetValue(void) { return this->value; } + const T& GetValue(void) const { return this->value; } //! Sets the value /*! @@ -102,13 +102,13 @@ public: /*! \return The value string */ - std::string GetValueString(void) { return ""; } + std::string GetValueString(void) const { return ""; } //! Writes the data to a packet /*! \param packet The packet */ - void WriteToPacket(RakNet::BitStream& packet) override { + void WriteToPacket(RakNet::BitStream& packet) const override { this->WriteKey(packet); this->WriteValue(packet); } @@ -117,13 +117,13 @@ public: /*! \return The key */ - const std::u16string& GetKey(void) override { return this->key; } + const std::u16string& GetKey(void) const override { return this->key; } //! Gets the LDF Type /*! \return The LDF value type */ - eLDFType GetValueType(void) override { return LDF_TYPE_UNKNOWN; } + eLDFType GetValueType(void) const override { return LDF_TYPE_UNKNOWN; } //! Gets the string data /*! @@ -131,7 +131,7 @@ public: \param includeTypeId Whether or not to include the type id in the data \return The string representation of the data */ - std::string GetString(const bool includeKey = true, const bool includeTypeId = true) override { + std::string GetString(const bool includeKey = true, const bool includeTypeId = true) const override { if (GetValueType() == -1) { return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:"; } @@ -154,11 +154,11 @@ public: return stream.str(); } - std::string GetValueAsString() override { + std::string GetValueAsString() const override { return this->GetValueString(); } - LDFBaseData* Copy() override { + LDFBaseData* Copy() const override { return new LDFData(key, value); } @@ -166,19 +166,19 @@ public: }; // LDF Types -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_UTF_16; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_S32; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_FLOAT; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_DOUBLE; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_U32; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_BOOLEAN; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_U64; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_OBJID; }; -template<> inline eLDFType LDFData::GetValueType(void) { return LDF_TYPE_UTF_8; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_UTF_16; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_S32; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_FLOAT; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_DOUBLE; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_U32; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_BOOLEAN; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_U64; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_OBJID; }; +template<> inline eLDFType LDFData::GetValueType(void) const { return LDF_TYPE_UTF_8; }; // The specialized version for std::u16string (UTF-16) template<> -inline void LDFData::WriteValue(RakNet::BitStream& packet) { +inline void LDFData::WriteValue(RakNet::BitStream& packet) const { packet.Write(this->GetValueType()); packet.Write(this->value.length()); @@ -189,7 +189,7 @@ inline void LDFData::WriteValue(RakNet::BitStream& packet) { // The specialized version for bool template<> -inline void LDFData::WriteValue(RakNet::BitStream& packet) { +inline void LDFData::WriteValue(RakNet::BitStream& packet) const { packet.Write(this->GetValueType()); packet.Write(this->value); @@ -197,7 +197,7 @@ inline void LDFData::WriteValue(RakNet::BitStream& packet) { // The specialized version for std::string (UTF-8) template<> -inline void LDFData::WriteValue(RakNet::BitStream& packet) { +inline void LDFData::WriteValue(RakNet::BitStream& packet) const { packet.Write(this->GetValueType()); packet.Write(this->value.length()); @@ -206,18 +206,18 @@ inline void LDFData::WriteValue(RakNet::BitStream& packet) { } } -template<> inline std::string LDFData::GetValueString() { +template<> inline std::string LDFData::GetValueString() const { return GeneralUtils::UTF16ToWTF8(this->value, this->value.size()); } -template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() const { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() const { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() const { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() const { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() const { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() const { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() const { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString() { return this->value; } +template<> inline std::string LDFData::GetValueString() const { return this->value; } #endif //!__LDFFORMAT__H__ diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 60dd071c..acb27796 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -558,19 +558,9 @@ void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) { itemElement->QueryAttribute("parent", &parent); // End custom xml - std::vector config; + auto* item = new Item(id, lot, inventory, slot, count, bound, {}, parent, subKey); - auto* extraInfo = itemElement->FirstChildElement("x"); - - if (extraInfo) { - std::string modInfo = extraInfo->Attribute("ma"); - - LDFBaseData* moduleAssembly = new LDFData(u"assemblyPartLOTs", GeneralUtils::ASCIIToUTF16(modInfo.substr(2, modInfo.size() - 1))); - - config.push_back(moduleAssembly); - } - - const auto* item = new Item(id, lot, inventory, slot, count, bound, config, parent, subKey); + item->LoadConfigXml(*itemElement); if (equipped) { const auto info = Inventory::FindItemComponent(lot); @@ -676,17 +666,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) { itemElement->SetAttribute("parent", item->GetParent()); // End custom xml - for (auto* data : item->GetConfig()) { - if (data->GetKey() != u"assemblyPartLOTs") { - continue; - } - - auto* extraInfo = document.NewElement("x"); - - extraInfo->SetAttribute("ma", data->GetString(false).c_str()); - - itemElement->LinkEndChild(extraInfo); - } + item->SaveConfigXml(*itemElement); bagElement->LinkEndChild(itemElement); } @@ -1600,18 +1580,18 @@ void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument& document) { } -bool InventoryComponent::SetSkill(int32_t slot, uint32_t skillId){ +bool InventoryComponent::SetSkill(int32_t slot, uint32_t skillId) { BehaviorSlot behaviorSlot = BehaviorSlot::Invalid; - if (slot == 1 ) behaviorSlot = BehaviorSlot::Primary; - else if (slot == 2 ) behaviorSlot = BehaviorSlot::Offhand; - else if (slot == 3 ) behaviorSlot = BehaviorSlot::Neck; - else if (slot == 4 ) behaviorSlot = BehaviorSlot::Head; - else if (slot == 5 ) behaviorSlot = BehaviorSlot::Consumable; + if (slot == 1) behaviorSlot = BehaviorSlot::Primary; + else if (slot == 2) behaviorSlot = BehaviorSlot::Offhand; + else if (slot == 3) behaviorSlot = BehaviorSlot::Neck; + else if (slot == 4) behaviorSlot = BehaviorSlot::Head; + else if (slot == 5) behaviorSlot = BehaviorSlot::Consumable; else return false; return SetSkill(behaviorSlot, skillId); } -bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId){ +bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId) { if (skillId == 0) return false; const auto index = m_Skills.find(slot); if (index != m_Skills.end()) { @@ -1623,4 +1603,3 @@ bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId){ m_Skills.insert_or_assign(slot, skillId); return true; } - diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index b6193692..32603761 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -27,6 +27,23 @@ #include "CDComponentsRegistryTable.h" #include "CDPackageComponentTable.h" +namespace { + const std::map ExtraSettingAbbreviations = { + { "assemblyPartLOTs", "ma" }, + { "blueprintID", "b" }, + { "userModelID", "ui" }, + { "userModelName", "un" }, + { "userModelDesc", "ud" }, + { "userModelHasBhvr", "ub" }, + { "userModelBehaviors", "ubh" }, + { "userModelBehaviorSourceID", "ubs" }, + { "userModelPhysicsType", "up" }, + { "userModelMod", "um" }, + { "userModelOpt", "uo" }, + { "reforgedLOT", "rl" }, + }; +} + Item::Item(const LWOOBJID id, const LOT lot, Inventory* inventory, const uint32_t slot, const uint32_t count, const bool bound, const std::vector& config, const LWOOBJID parent, LWOOBJID subKey, eLootSourceType lootSourceType) { if (!Inventory::IsValidItem(lot)) { return; @@ -122,6 +139,10 @@ uint32_t Item::GetSlot() const { return slot; } +std::vector Item::GetConfig() const { + return config; +} + std::vector& Item::GetConfig() { return config; } @@ -251,7 +272,7 @@ bool Item::Consume() { auto skills = skillsTable->Query([this](const CDObjectSkills entry) { return entry.objectTemplate == static_cast(lot); - }); + }); auto success = false; @@ -515,3 +536,35 @@ Item::~Item() { config.clear(); } + +void Item::SaveConfigXml(tinyxml2::XMLElement& i) const { + tinyxml2::XMLElement* x = nullptr; + + for (const auto* config : this->config) { + const auto& key = GeneralUtils::UTF16ToWTF8(config->GetKey()); + const auto saveKey = ExtraSettingAbbreviations.find(key); + if (saveKey == ExtraSettingAbbreviations.end()) { + continue; + } + + if (!x) { + x = i.InsertNewChildElement("x"); + } + + const auto dataToSave = config->GetString(false); + x->SetAttribute(saveKey->second.c_str(), dataToSave.c_str()); + } +} + +void Item::LoadConfigXml(const tinyxml2::XMLElement& i) { + const auto* x = i.FirstChildElement("x"); + if (!x) return; + + for (const auto& pair : ExtraSettingAbbreviations) { + const auto* data = x->Attribute(pair.second.c_str()); + if (!data) continue; + + const auto value = pair.first + "=" + data; + config.push_back(LDFBaseData::DataFromString(value)); + } +} diff --git a/dGame/dInventory/Item.h b/dGame/dInventory/Item.h index 04d05d7c..72ff264c 100644 --- a/dGame/dInventory/Item.h +++ b/dGame/dInventory/Item.h @@ -9,6 +9,10 @@ #include "eInventoryType.h" #include "eLootSourceType.h" +namespace tinyxml2 { + class XMLElement; +}; + /** * An item that can be stored in an inventory and optionally consumed or equipped * TODO: ideally this should be a component @@ -116,6 +120,12 @@ public: */ std::vector& GetConfig(); + /** + * Returns current config info for this item, e.g. for rockets + * @return current config info for this item + */ + std::vector GetConfig() const; + /** * Returns the database info for this item * @return the database info for this item @@ -214,6 +224,10 @@ public: */ void RemoveFromInventory(); + void SaveConfigXml(tinyxml2::XMLElement& i) const; + + void LoadConfigXml(const tinyxml2::XMLElement& i); + private: /** * The object ID of this item