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
This commit is contained in:
David Markowitz 2024-05-22 17:06:52 -07:00 committed by GitHub
parent dc430d9758
commit f0960d48b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 115 additions and 69 deletions

View File

@ -31,22 +31,22 @@ public:
virtual ~LDFBaseData() {} 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 /** Gets a string from the key/value pair
* @param includeKey Whether or not to include the key in the data * @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 * @param includeTypeId Whether or not to include the type id in the data
* @return The string representation of 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. * Given an input string, return the data as a LDF key.
@ -62,7 +62,7 @@ private:
T value; T value;
//! Writes the key to the packet //! Writes the key to the packet
void WriteKey(RakNet::BitStream& packet) { void WriteKey(RakNet::BitStream& packet) const {
packet.Write<uint8_t>(this->key.length() * sizeof(uint16_t)); packet.Write<uint8_t>(this->key.length() * sizeof(uint16_t));
for (uint32_t i = 0; i < this->key.length(); ++i) { for (uint32_t i = 0; i < this->key.length(); ++i) {
packet.Write<uint16_t>(this->key[i]); packet.Write<uint16_t>(this->key[i]);
@ -70,7 +70,7 @@ private:
} }
//! Writes the value to the packet //! Writes the value to the packet
void WriteValue(RakNet::BitStream& packet) { void WriteValue(RakNet::BitStream& packet) const {
packet.Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet.Write(this->value); packet.Write(this->value);
} }
@ -90,7 +90,7 @@ public:
/*! /*!
\return The value \return The value
*/ */
const T& GetValue(void) { return this->value; } const T& GetValue(void) const { return this->value; }
//! Sets the value //! Sets the value
/*! /*!
@ -102,13 +102,13 @@ public:
/*! /*!
\return The value string \return The value string
*/ */
std::string GetValueString(void) { return ""; } std::string GetValueString(void) const { return ""; }
//! Writes the data to a packet //! Writes the data to a packet
/*! /*!
\param packet The packet \param packet The packet
*/ */
void WriteToPacket(RakNet::BitStream& packet) override { void WriteToPacket(RakNet::BitStream& packet) const override {
this->WriteKey(packet); this->WriteKey(packet);
this->WriteValue(packet); this->WriteValue(packet);
} }
@ -117,13 +117,13 @@ public:
/*! /*!
\return The key \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 //! Gets the LDF Type
/*! /*!
\return The LDF value 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 //! Gets the string data
/*! /*!
@ -131,7 +131,7 @@ public:
\param includeTypeId Whether or not to include the type id in the data \param includeTypeId Whether or not to include the type id in the data
\return The string representation of 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) { if (GetValueType() == -1) {
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>"; return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
} }
@ -154,11 +154,11 @@ public:
return stream.str(); return stream.str();
} }
std::string GetValueAsString() override { std::string GetValueAsString() const override {
return this->GetValueString(); return this->GetValueString();
} }
LDFBaseData* Copy() override { LDFBaseData* Copy() const override {
return new LDFData<T>(key, value); return new LDFData<T>(key, value);
} }
@ -166,19 +166,19 @@ public:
}; };
// LDF Types // LDF Types
template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) { return LDF_TYPE_UTF_16; }; template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) const { return LDF_TYPE_UTF_16; };
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) { return LDF_TYPE_S32; }; template<> inline eLDFType LDFData<int32_t>::GetValueType(void) const { return LDF_TYPE_S32; };
template<> inline eLDFType LDFData<float>::GetValueType(void) { return LDF_TYPE_FLOAT; }; template<> inline eLDFType LDFData<float>::GetValueType(void) const { return LDF_TYPE_FLOAT; };
template<> inline eLDFType LDFData<double>::GetValueType(void) { return LDF_TYPE_DOUBLE; }; template<> inline eLDFType LDFData<double>::GetValueType(void) const { return LDF_TYPE_DOUBLE; };
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) { return LDF_TYPE_U32; }; template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) const { return LDF_TYPE_U32; };
template<> inline eLDFType LDFData<bool>::GetValueType(void) { return LDF_TYPE_BOOLEAN; }; template<> inline eLDFType LDFData<bool>::GetValueType(void) const { return LDF_TYPE_BOOLEAN; };
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) { return LDF_TYPE_U64; }; template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) const { return LDF_TYPE_U64; };
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) { return LDF_TYPE_OBJID; }; template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) const { return LDF_TYPE_OBJID; };
template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF_TYPE_UTF_8; }; template<> inline eLDFType LDFData<std::string>::GetValueType(void) const { return LDF_TYPE_UTF_8; };
// The specialized version for std::u16string (UTF-16) // The specialized version for std::u16string (UTF-16)
template<> template<>
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) { inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) const {
packet.Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet.Write<uint32_t>(this->value.length()); packet.Write<uint32_t>(this->value.length());
@ -189,7 +189,7 @@ inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) {
// The specialized version for bool // The specialized version for bool
template<> template<>
inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) { inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) const {
packet.Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet.Write<uint8_t>(this->value); packet.Write<uint8_t>(this->value);
@ -197,7 +197,7 @@ inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) {
// The specialized version for std::string (UTF-8) // The specialized version for std::string (UTF-8)
template<> template<>
inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) { inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) const {
packet.Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet.Write<uint32_t>(this->value.length()); packet.Write<uint32_t>(this->value.length());
@ -206,18 +206,18 @@ inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) {
} }
} }
template<> inline std::string LDFData<std::u16string>::GetValueString() { template<> inline std::string LDFData<std::u16string>::GetValueString() const {
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size()); return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
} }
template<> inline std::string LDFData<int32_t>::GetValueString() { return std::to_string(this->value); } template<> inline std::string LDFData<int32_t>::GetValueString() const { return std::to_string(this->value); }
template<> inline std::string LDFData<float>::GetValueString() { return std::to_string(this->value); } template<> inline std::string LDFData<float>::GetValueString() const { return std::to_string(this->value); }
template<> inline std::string LDFData<double>::GetValueString() { return std::to_string(this->value); } template<> inline std::string LDFData<double>::GetValueString() const { return std::to_string(this->value); }
template<> inline std::string LDFData<uint32_t>::GetValueString() { return std::to_string(this->value); } template<> inline std::string LDFData<uint32_t>::GetValueString() const { return std::to_string(this->value); }
template<> inline std::string LDFData<bool>::GetValueString() { return std::to_string(this->value); } template<> inline std::string LDFData<bool>::GetValueString() const { return std::to_string(this->value); }
template<> inline std::string LDFData<uint64_t>::GetValueString() { return std::to_string(this->value); } template<> inline std::string LDFData<uint64_t>::GetValueString() const { return std::to_string(this->value); }
template<> inline std::string LDFData<LWOOBJID>::GetValueString() { return std::to_string(this->value); } template<> inline std::string LDFData<LWOOBJID>::GetValueString() const { return std::to_string(this->value); }
template<> inline std::string LDFData<std::string>::GetValueString() { return this->value; } template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
#endif //!__LDFFORMAT__H__ #endif //!__LDFFORMAT__H__

View File

@ -558,19 +558,9 @@ void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
itemElement->QueryAttribute("parent", &parent); itemElement->QueryAttribute("parent", &parent);
// End custom xml // End custom xml
std::vector<LDFBaseData*> config; auto* item = new Item(id, lot, inventory, slot, count, bound, {}, parent, subKey);
auto* extraInfo = itemElement->FirstChildElement("x"); item->LoadConfigXml(*itemElement);
if (extraInfo) {
std::string modInfo = extraInfo->Attribute("ma");
LDFBaseData* moduleAssembly = new LDFData<std::u16string>(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);
if (equipped) { if (equipped) {
const auto info = Inventory::FindItemComponent(lot); const auto info = Inventory::FindItemComponent(lot);
@ -676,17 +666,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
itemElement->SetAttribute("parent", item->GetParent()); itemElement->SetAttribute("parent", item->GetParent());
// End custom xml // End custom xml
for (auto* data : item->GetConfig()) { item->SaveConfigXml(*itemElement);
if (data->GetKey() != u"assemblyPartLOTs") {
continue;
}
auto* extraInfo = document.NewElement("x");
extraInfo->SetAttribute("ma", data->GetString(false).c_str());
itemElement->LinkEndChild(extraInfo);
}
bagElement->LinkEndChild(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; BehaviorSlot behaviorSlot = BehaviorSlot::Invalid;
if (slot == 1 ) behaviorSlot = BehaviorSlot::Primary; if (slot == 1) behaviorSlot = BehaviorSlot::Primary;
else if (slot == 2 ) behaviorSlot = BehaviorSlot::Offhand; else if (slot == 2) behaviorSlot = BehaviorSlot::Offhand;
else if (slot == 3 ) behaviorSlot = BehaviorSlot::Neck; else if (slot == 3) behaviorSlot = BehaviorSlot::Neck;
else if (slot == 4 ) behaviorSlot = BehaviorSlot::Head; else if (slot == 4) behaviorSlot = BehaviorSlot::Head;
else if (slot == 5 ) behaviorSlot = BehaviorSlot::Consumable; else if (slot == 5) behaviorSlot = BehaviorSlot::Consumable;
else return false; else return false;
return SetSkill(behaviorSlot, skillId); 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; if (skillId == 0) return false;
const auto index = m_Skills.find(slot); const auto index = m_Skills.find(slot);
if (index != m_Skills.end()) { if (index != m_Skills.end()) {
@ -1623,4 +1603,3 @@ bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId){
m_Skills.insert_or_assign(slot, skillId); m_Skills.insert_or_assign(slot, skillId);
return true; return true;
} }

View File

@ -27,6 +27,23 @@
#include "CDComponentsRegistryTable.h" #include "CDComponentsRegistryTable.h"
#include "CDPackageComponentTable.h" #include "CDPackageComponentTable.h"
namespace {
const std::map<std::string, std::string> 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<LDFBaseData*>& config, const LWOOBJID parent, LWOOBJID subKey, eLootSourceType lootSourceType) { Item::Item(const LWOOBJID id, const LOT lot, Inventory* inventory, const uint32_t slot, const uint32_t count, const bool bound, const std::vector<LDFBaseData*>& config, const LWOOBJID parent, LWOOBJID subKey, eLootSourceType lootSourceType) {
if (!Inventory::IsValidItem(lot)) { if (!Inventory::IsValidItem(lot)) {
return; return;
@ -122,6 +139,10 @@ uint32_t Item::GetSlot() const {
return slot; return slot;
} }
std::vector<LDFBaseData*> Item::GetConfig() const {
return config;
}
std::vector<LDFBaseData*>& Item::GetConfig() { std::vector<LDFBaseData*>& Item::GetConfig() {
return config; return config;
} }
@ -251,7 +272,7 @@ bool Item::Consume() {
auto skills = skillsTable->Query([this](const CDObjectSkills entry) { auto skills = skillsTable->Query([this](const CDObjectSkills entry) {
return entry.objectTemplate == static_cast<uint32_t>(lot); return entry.objectTemplate == static_cast<uint32_t>(lot);
}); });
auto success = false; auto success = false;
@ -515,3 +536,35 @@ Item::~Item() {
config.clear(); 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));
}
}

View File

@ -9,6 +9,10 @@
#include "eInventoryType.h" #include "eInventoryType.h"
#include "eLootSourceType.h" #include "eLootSourceType.h"
namespace tinyxml2 {
class XMLElement;
};
/** /**
* An item that can be stored in an inventory and optionally consumed or equipped * An item that can be stored in an inventory and optionally consumed or equipped
* TODO: ideally this should be a component * TODO: ideally this should be a component
@ -116,6 +120,12 @@ public:
*/ */
std::vector<LDFBaseData*>& GetConfig(); std::vector<LDFBaseData*>& GetConfig();
/**
* Returns current config info for this item, e.g. for rockets
* @return current config info for this item
*/
std::vector<LDFBaseData*> GetConfig() const;
/** /**
* Returns the database info for this item * Returns the database info for this item
* @return the database info for this item * @return the database info for this item
@ -214,6 +224,10 @@ public:
*/ */
void RemoveFromInventory(); void RemoveFromInventory();
void SaveConfigXml(tinyxml2::XMLElement& i) const;
void LoadConfigXml(const tinyxml2::XMLElement& i);
private: private:
/** /**
* The object ID of this item * The object ID of this item