diff --git a/dCommon/LDFFormat.h b/dCommon/LDFFormat.h index 7c2e939b..c9ee2836 100644 --- a/dCommon/LDFFormat.h +++ b/dCommon/LDFFormat.h @@ -6,6 +6,7 @@ #include "GeneralUtils.h" // C++ +#include #include #include #include @@ -226,4 +227,9 @@ template<> inline std::string LDFData::GetValueString() const { return template<> inline std::string LDFData::GetValueString() const { return this->value; } +struct LwoNameValue { + using ValueType = std::map>; + ValueType values; +}; + #endif //!__LDFFORMAT__H__ diff --git a/dCommon/dEnums/dCommonVars.h b/dCommon/dEnums/dCommonVars.h index fc1ccded..c3ed1b14 100644 --- a/dCommon/dEnums/dCommonVars.h +++ b/dCommon/dEnums/dCommonVars.h @@ -111,18 +111,6 @@ private: constexpr LWOSCENEID LWOSCENEID_INVALID = -1; -struct LWONameValue { - uint32_t length = 0; //!< The length of the name - std::u16string name; //!< The name - - LWONameValue() = default; - - LWONameValue(const std::u16string& name) { - this->name = name; - this->length = static_cast(name.length()); - } -}; - struct FriendData { public: bool isOnline = false; diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index d88aa1d5..27d408eb 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -124,7 +124,7 @@ Entity::Entity(const LWOOBJID& objectID, const EntityInfo& info, User* parentUse m_IsParentChildDirty = true; m_Settings = info.settings; - m_NetworkSettings = info.networkSettings; + for (const auto* setting : info.networkSettings) m_NetworkSettings.values.insert_or_assign(setting->GetKey(), std::unique_ptr(setting->Copy())); m_DefaultPosition = info.pos; m_DefaultRotation = info.rot; m_Scale = info.scale; diff --git a/dGame/Entity.h b/dGame/Entity.h index c07bd3f4..4feed15c 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -99,7 +99,7 @@ public: const std::vector& GetSettings() const { return m_Settings; } - const std::vector& GetNetworkSettings() const { return m_NetworkSettings; } + const LwoNameValue& GetNetworkSettings() const { return m_NetworkSettings; } bool GetIsDead() const; @@ -312,6 +312,12 @@ public: template void SetNetworkVar(const std::u16string& name, std::vector value, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS); + template + void SetNetworkVar(const std::string& name, T value, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS); + + template + LwoNameValue::ValueType::iterator InsertNetworkVar(const std::u16string& name, T value); + template T GetNetworkVar(const std::u16string& name); @@ -360,7 +366,7 @@ public: // This is the actual function that will be registered, which casts the base GameMsg to the derived type const auto castWrapper = [boundFunction](GameMessages::GameMsg& msg) { return boundFunction(static_cast(msg)); - }; + }; DerivedGameMsg msg; RegisterMsg(msg.msgId, castWrapper); } @@ -377,7 +383,7 @@ private: LOT m_TemplateID; std::vector m_Settings; - std::vector m_NetworkSettings; + LwoNameValue m_NetworkSettings; NiPoint3 m_DefaultPosition; NiQuaternion m_DefaultRotation = QuatUtils::IDENTITY; @@ -503,32 +509,35 @@ void Entity::SetVar(const std::u16string& name, T value) { } template -void Entity::SetNetworkVar(const std::u16string& name, T value, const SystemAddress& sysAddr) { - LDFData* newData = nullptr; - - for (auto* data : m_NetworkSettings) { - if (data->GetKey() != name) - continue; - - newData = dynamic_cast*>(data); - if (newData != nullptr) { - newData->SetValue(value); - } else { // If we're changing types - m_NetworkSettings.erase( - std::remove(m_NetworkSettings.begin(), m_NetworkSettings.end(), data), m_NetworkSettings.end() - ); - delete data; +LwoNameValue::ValueType::iterator Entity::InsertNetworkVar(const std::u16string& name, T value) { + auto itr = m_NetworkSettings.values.find(name); + if (itr != m_NetworkSettings.values.end()) { + auto lnv = dynamic_cast*>(itr->second.get()); + if (!lnv) { + // Is of different type + itr->second = std::make_unique>(name, value); + } else { + // Is the same type and exists + lnv->SetValue(value); } - - break; + } else { + // Doesn't exist + itr = m_NetworkSettings.values.insert_or_assign(name, std::make_unique>(name, value)).first; } + + return itr; +} - if (newData == nullptr) { - newData = new LDFData(name, value); - } +template +void Entity::SetNetworkVar(const std::u16string& name, T value, const SystemAddress& sysAddr) { + const auto itr = InsertNetworkVar(name, value); - m_NetworkSettings.push_back(newData); - SendNetworkVar(newData->GetString(true), sysAddr); + SendNetworkVar(itr->second->GetString(), sysAddr); +} + +template +void Entity::SetNetworkVar(const std::string& name, T value, const SystemAddress& sysAddr) { + SetNetworkVar(GeneralUtils::UTF8ToUTF16(name), value, sysAddr); } template @@ -539,26 +548,10 @@ void Entity::SetNetworkVar(const std::u16string& name, std::vector values, co for (const auto& value : values) { LDFData* newData = nullptr; const auto& indexedName = name + u"." + GeneralUtils::to_u16string(index); - - for (auto* data : m_NetworkSettings) { - if (data->GetKey() != indexedName) - continue; - - newData = dynamic_cast*>(data); - newData->SetValue(value); - break; - } - - if (newData == nullptr) { - newData = new LDFData(indexedName, value); - } - - m_NetworkSettings.push_back(newData); - - if (index == values.size()) { - updates << newData->GetString(true); - } else { - updates << newData->GetString(true) << "\n"; + const auto itr = InsertNetworkVar(indexedName, value); + updates << itr->second->GetString(); + if (index != values.size()) { + updates << "\n"; } index++; @@ -569,18 +562,15 @@ void Entity::SetNetworkVar(const std::u16string& name, std::vector values, co template T Entity::GetNetworkVar(const std::u16string& name) { - for (auto* data : m_NetworkSettings) { - if (data == nullptr || data->GetKey() != name) - continue; + T toReturn = LDFData::Default; - auto* typed = dynamic_cast*>(data); - if (typed == nullptr) - continue; - - return typed->GetValue(); + const auto itr = m_NetworkSettings.values.find(name); + if (itr != m_NetworkSettings.values.cend()) { + auto* cast = dynamic_cast*>(itr->second.get()); + if (cast) toReturn = cast->GetValue(); } - return LDFData::Default; + return toReturn; } /** diff --git a/dGame/dComponents/ScriptComponent.cpp b/dGame/dComponents/ScriptComponent.cpp index 87b6e6e1..2c9be34b 100644 --- a/dGame/dComponents/ScriptComponent.cpp +++ b/dGame/dComponents/ScriptComponent.cpp @@ -8,6 +8,8 @@ #include "GameMessages.h" #include "Amf3.h" +#include + ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client) : Component(parent, componentID) { m_Serialized = serialized; m_Client = client; @@ -20,7 +22,7 @@ ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, cons void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { const auto& networkSettings = m_Parent->GetNetworkSettings(); - auto hasNetworkSettings = !networkSettings.empty(); + auto hasNetworkSettings = !networkSettings.values.empty(); outBitStream.Write(hasNetworkSettings); if (hasNetworkSettings) { @@ -28,9 +30,9 @@ void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitial // First write the most inner LDF data RakNet::BitStream ldfData; ldfData.Write(0); - ldfData.Write(networkSettings.size()); + ldfData.Write(networkSettings.values.size()); - for (auto* networkSetting : networkSettings) { + for (const auto& networkSetting : networkSettings.values | std::views::values) { networkSetting->WriteToPacket(ldfData); } @@ -56,7 +58,7 @@ bool ScriptComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& r auto& scriptInfo = reportInfo.info->PushDebug("Script"); scriptInfo.PushDebug("Script Name") = m_ScriptName.empty() ? "None" : m_ScriptName; auto& networkSettings = scriptInfo.PushDebug("Network Settings"); - for (const auto* const setting : m_Parent->GetNetworkSettings()) { + for (const auto& setting : m_Parent->GetNetworkSettings().values | std::views::values) { networkSettings.PushDebug(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString(); } diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 5edd47f2..aab491aa 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -465,20 +465,20 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System bitStream.Write(lootSourceType != eLootSourceType::NONE); // Loot source if (lootSourceType != eLootSourceType::NONE) bitStream.Write(lootSourceType); - LWONameValue extraInfo; + std::u16string extraInfo; auto config = item->GetConfig(); for (auto* data : config) { - extraInfo.name += GeneralUtils::ASCIIToUTF16(data->GetString()) + u","; + extraInfo += GeneralUtils::ASCIIToUTF16(data->GetString()) + u","; } - if (extraInfo.name.length() > 0) extraInfo.name.pop_back(); // remove the last comma + if (extraInfo.length() > 0) extraInfo.pop_back(); // remove the last comma - bitStream.Write(extraInfo.name.size()); - if (extraInfo.name.size() > 0) { - for (uint32_t i = 0; i < extraInfo.name.size(); ++i) { - bitStream.Write(extraInfo.name[i]); + bitStream.Write(extraInfo.size()); + if (extraInfo.size() > 0) { + for (uint32_t i = 0; i < extraInfo.size(); ++i) { + bitStream.Write(extraInfo[i]); } bitStream.Write(0x00); } @@ -743,13 +743,9 @@ void GameMessages::SendBroadcastTextToChatbox(Entity* entity, const SystemAddres bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::BROADCAST_TEXT_TO_CHATBOX); - LWONameValue attribs; - attribs.name = attrs; - attribs.length = attrs.size(); - - bitStream.Write(attribs.length); - for (uint32_t i = 0; i < attribs.length; ++i) { - bitStream.Write(attribs.name[i]); + bitStream.Write(attrs.size()); + for (uint32_t i = 0; i < attrs.size(); ++i) { + bitStream.Write(attrs[i]); } bitStream.Write(0x00); // Null Terminator @@ -5266,7 +5262,8 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream& inStream, En int eInvType = INVENTORY_MAX; bool eLootTypeSourceIsDefault = false; int eLootTypeSource = LOOTTYPE_NONE; - LWONameValue extraInfo; + int32_t extraInfoLength = 0; + std::u16string extraInfo; bool forceDeletion = true; bool iLootTypeSourceIsDefault = false; LWOOBJID iLootTypeSource = LWOOBJID_EMPTY; @@ -5292,12 +5289,12 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream& inStream, En if (eInvTypeIsDefault) inStream.Read(eInvType); inStream.Read(eLootTypeSourceIsDefault); if (eLootTypeSourceIsDefault) inStream.Read(eLootTypeSource); - inStream.Read(extraInfo.length); - if (extraInfo.length > 0) { - for (uint32_t i = 0; i < extraInfo.length; ++i) { + inStream.Read(extraInfoLength); + if (extraInfoLength > 0) { + for (uint32_t i = 0; i < extraInfoLength; ++i) { uint16_t character; inStream.Read(character); - extraInfo.name.push_back(character); + extraInfo.push_back(character); } uint16_t nullTerm; inStream.Read(nullTerm); @@ -5754,7 +5751,6 @@ void GameMessages::HandleUseNonEquipmentItem(RakNet::BitStream& inStream, Entity void GameMessages::HandleMatchRequest(RakNet::BitStream& inStream, Entity* entity) { LWOOBJID activator; - //std::map additionalPlayers; uint32_t playerChoicesLen; std::string playerChoices; int type;