change network settings from vector to LwoNameValue

This commit is contained in:
David Markowitz
2026-06-11 22:14:44 -07:00
parent 9f8d300340
commit adf9200c9a
6 changed files with 73 additions and 91 deletions

View File

@@ -6,6 +6,7 @@
#include "GeneralUtils.h" #include "GeneralUtils.h"
// C++ // C++
#include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <sstream> #include <sstream>
@@ -226,4 +227,9 @@ template<> inline std::string LDFData<LWOOBJID>::GetValueString() const { return
template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; } template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
struct LwoNameValue {
using ValueType = std::map<std::u16string, std::unique_ptr<LDFBaseData>>;
ValueType values;
};
#endif //!__LDFFORMAT__H__ #endif //!__LDFFORMAT__H__

View File

@@ -111,18 +111,6 @@ private:
constexpr LWOSCENEID LWOSCENEID_INVALID = -1; 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<uint32_t>(name.length());
}
};
struct FriendData { struct FriendData {
public: public:
bool isOnline = false; bool isOnline = false;

View File

@@ -124,7 +124,7 @@ Entity::Entity(const LWOOBJID& objectID, const EntityInfo& info, User* parentUse
m_IsParentChildDirty = true; m_IsParentChildDirty = true;
m_Settings = info.settings; 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<LDFBaseData>(setting->Copy()));
m_DefaultPosition = info.pos; m_DefaultPosition = info.pos;
m_DefaultRotation = info.rot; m_DefaultRotation = info.rot;
m_Scale = info.scale; m_Scale = info.scale;

View File

@@ -99,7 +99,7 @@ public:
const std::vector<LDFBaseData*>& GetSettings() const { return m_Settings; } const std::vector<LDFBaseData*>& GetSettings() const { return m_Settings; }
const std::vector<LDFBaseData*>& GetNetworkSettings() const { return m_NetworkSettings; } const LwoNameValue& GetNetworkSettings() const { return m_NetworkSettings; }
bool GetIsDead() const; bool GetIsDead() const;
@@ -312,6 +312,12 @@ public:
template<typename T> template<typename T>
void SetNetworkVar(const std::u16string& name, std::vector<T> value, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS); void SetNetworkVar(const std::u16string& name, std::vector<T> value, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
template<typename T>
void SetNetworkVar(const std::string& name, T value, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
template<typename T>
LwoNameValue::ValueType::iterator InsertNetworkVar(const std::u16string& name, T value);
template<typename T> template<typename T>
T GetNetworkVar(const std::u16string& name); 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 // 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) { const auto castWrapper = [boundFunction](GameMessages::GameMsg& msg) {
return boundFunction(static_cast<DerivedGameMsg&>(msg)); return boundFunction(static_cast<DerivedGameMsg&>(msg));
}; };
DerivedGameMsg msg; DerivedGameMsg msg;
RegisterMsg(msg.msgId, castWrapper); RegisterMsg(msg.msgId, castWrapper);
} }
@@ -377,7 +383,7 @@ private:
LOT m_TemplateID; LOT m_TemplateID;
std::vector<LDFBaseData*> m_Settings; std::vector<LDFBaseData*> m_Settings;
std::vector<LDFBaseData*> m_NetworkSettings; LwoNameValue m_NetworkSettings;
NiPoint3 m_DefaultPosition; NiPoint3 m_DefaultPosition;
NiQuaternion m_DefaultRotation = QuatUtils::IDENTITY; NiQuaternion m_DefaultRotation = QuatUtils::IDENTITY;
@@ -503,32 +509,35 @@ void Entity::SetVar(const std::u16string& name, T value) {
} }
template<typename T> template<typename T>
void Entity::SetNetworkVar(const std::u16string& name, T value, const SystemAddress& sysAddr) { LwoNameValue::ValueType::iterator Entity::InsertNetworkVar(const std::u16string& name, T value) {
LDFData<T>* newData = nullptr; auto itr = m_NetworkSettings.values.find(name);
if (itr != m_NetworkSettings.values.end()) {
for (auto* data : m_NetworkSettings) { auto lnv = dynamic_cast<LDFData<T>*>(itr->second.get());
if (data->GetKey() != name) if (!lnv) {
continue; // Is of different type
itr->second = std::make_unique<LDFData<T>>(name, value);
newData = dynamic_cast<LDFData<T>*>(data); } else {
if (newData != nullptr) { // Is the same type and exists
newData->SetValue(value); lnv->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;
} }
} else {
break; // Doesn't exist
itr = m_NetworkSettings.values.insert_or_assign(name, std::make_unique<LDFData<T>>(name, value)).first;
} }
return itr;
}
if (newData == nullptr) { template<typename T>
newData = new LDFData<T>(name, value); void Entity::SetNetworkVar(const std::u16string& name, T value, const SystemAddress& sysAddr) {
} const auto itr = InsertNetworkVar<T>(name, value);
m_NetworkSettings.push_back(newData); SendNetworkVar(itr->second->GetString(), sysAddr);
SendNetworkVar(newData->GetString(true), sysAddr); }
template<typename T>
void Entity::SetNetworkVar(const std::string& name, T value, const SystemAddress& sysAddr) {
SetNetworkVar(GeneralUtils::UTF8ToUTF16(name), value, sysAddr);
} }
template<typename T> template<typename T>
@@ -539,26 +548,10 @@ void Entity::SetNetworkVar(const std::u16string& name, std::vector<T> values, co
for (const auto& value : values) { for (const auto& value : values) {
LDFData<T>* newData = nullptr; LDFData<T>* newData = nullptr;
const auto& indexedName = name + u"." + GeneralUtils::to_u16string(index); const auto& indexedName = name + u"." + GeneralUtils::to_u16string(index);
const auto itr = InsertNetworkVar<T>(indexedName, value);
for (auto* data : m_NetworkSettings) { updates << itr->second->GetString();
if (data->GetKey() != indexedName) if (index != values.size()) {
continue; updates << "\n";
newData = dynamic_cast<LDFData<T>*>(data);
newData->SetValue(value);
break;
}
if (newData == nullptr) {
newData = new LDFData<T>(indexedName, value);
}
m_NetworkSettings.push_back(newData);
if (index == values.size()) {
updates << newData->GetString(true);
} else {
updates << newData->GetString(true) << "\n";
} }
index++; index++;
@@ -569,18 +562,15 @@ void Entity::SetNetworkVar(const std::u16string& name, std::vector<T> values, co
template<typename T> template<typename T>
T Entity::GetNetworkVar(const std::u16string& name) { T Entity::GetNetworkVar(const std::u16string& name) {
for (auto* data : m_NetworkSettings) { T toReturn = LDFData<T>::Default;
if (data == nullptr || data->GetKey() != name)
continue;
auto* typed = dynamic_cast<LDFData<T>*>(data); const auto itr = m_NetworkSettings.values.find(name);
if (typed == nullptr) if (itr != m_NetworkSettings.values.cend()) {
continue; auto* cast = dynamic_cast<LDFData<T>*>(itr->second.get());
if (cast) toReturn = cast->GetValue();
return typed->GetValue();
} }
return LDFData<T>::Default; return toReturn;
} }
/** /**

View File

@@ -8,6 +8,8 @@
#include "GameMessages.h" #include "GameMessages.h"
#include "Amf3.h" #include "Amf3.h"
#include <ranges>
ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client) : Component(parent, componentID) { ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client) : Component(parent, componentID) {
m_Serialized = serialized; m_Serialized = serialized;
m_Client = client; m_Client = client;
@@ -20,7 +22,7 @@ ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, cons
void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) { void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
if (bIsInitialUpdate) { if (bIsInitialUpdate) {
const auto& networkSettings = m_Parent->GetNetworkSettings(); const auto& networkSettings = m_Parent->GetNetworkSettings();
auto hasNetworkSettings = !networkSettings.empty(); auto hasNetworkSettings = !networkSettings.values.empty();
outBitStream.Write(hasNetworkSettings); outBitStream.Write(hasNetworkSettings);
if (hasNetworkSettings) { if (hasNetworkSettings) {
@@ -28,9 +30,9 @@ void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitial
// First write the most inner LDF data // First write the most inner LDF data
RakNet::BitStream ldfData; RakNet::BitStream ldfData;
ldfData.Write<uint8_t>(0); ldfData.Write<uint8_t>(0);
ldfData.Write<uint32_t>(networkSettings.size()); ldfData.Write<uint32_t>(networkSettings.values.size());
for (auto* networkSetting : networkSettings) { for (const auto& networkSetting : networkSettings.values | std::views::values) {
networkSetting->WriteToPacket(ldfData); networkSetting->WriteToPacket(ldfData);
} }
@@ -56,7 +58,7 @@ bool ScriptComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& r
auto& scriptInfo = reportInfo.info->PushDebug("Script"); auto& scriptInfo = reportInfo.info->PushDebug("Script");
scriptInfo.PushDebug<AMFStringValue>("Script Name") = m_ScriptName.empty() ? "None" : m_ScriptName; scriptInfo.PushDebug<AMFStringValue>("Script Name") = m_ScriptName.empty() ? "None" : m_ScriptName;
auto& networkSettings = scriptInfo.PushDebug("Network Settings"); 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<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString(); networkSettings.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString();
} }

View File

@@ -465,20 +465,20 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System
bitStream.Write(lootSourceType != eLootSourceType::NONE); // Loot source bitStream.Write(lootSourceType != eLootSourceType::NONE); // Loot source
if (lootSourceType != eLootSourceType::NONE) bitStream.Write(lootSourceType); if (lootSourceType != eLootSourceType::NONE) bitStream.Write(lootSourceType);
LWONameValue extraInfo; std::u16string extraInfo;
auto config = item->GetConfig(); auto config = item->GetConfig();
for (auto* data : config) { 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<uint32_t>(extraInfo.name.size()); bitStream.Write<uint32_t>(extraInfo.size());
if (extraInfo.name.size() > 0) { if (extraInfo.size() > 0) {
for (uint32_t i = 0; i < extraInfo.name.size(); ++i) { for (uint32_t i = 0; i < extraInfo.size(); ++i) {
bitStream.Write<uint16_t>(extraInfo.name[i]); bitStream.Write<uint16_t>(extraInfo[i]);
} }
bitStream.Write<uint16_t>(0x00); bitStream.Write<uint16_t>(0x00);
} }
@@ -743,13 +743,9 @@ void GameMessages::SendBroadcastTextToChatbox(Entity* entity, const SystemAddres
bitStream.Write(entity->GetObjectID()); bitStream.Write(entity->GetObjectID());
bitStream.Write(MessageType::Game::BROADCAST_TEXT_TO_CHATBOX); bitStream.Write(MessageType::Game::BROADCAST_TEXT_TO_CHATBOX);
LWONameValue attribs; bitStream.Write<uint32_t>(attrs.size());
attribs.name = attrs; for (uint32_t i = 0; i < attrs.size(); ++i) {
attribs.length = attrs.size(); bitStream.Write<uint16_t>(attrs[i]);
bitStream.Write<uint32_t>(attribs.length);
for (uint32_t i = 0; i < attribs.length; ++i) {
bitStream.Write<uint16_t>(attribs.name[i]);
} }
bitStream.Write<uint16_t>(0x00); // Null Terminator bitStream.Write<uint16_t>(0x00); // Null Terminator
@@ -5266,7 +5262,8 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream& inStream, En
int eInvType = INVENTORY_MAX; int eInvType = INVENTORY_MAX;
bool eLootTypeSourceIsDefault = false; bool eLootTypeSourceIsDefault = false;
int eLootTypeSource = LOOTTYPE_NONE; int eLootTypeSource = LOOTTYPE_NONE;
LWONameValue extraInfo; int32_t extraInfoLength = 0;
std::u16string extraInfo;
bool forceDeletion = true; bool forceDeletion = true;
bool iLootTypeSourceIsDefault = false; bool iLootTypeSourceIsDefault = false;
LWOOBJID iLootTypeSource = LWOOBJID_EMPTY; LWOOBJID iLootTypeSource = LWOOBJID_EMPTY;
@@ -5292,12 +5289,12 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream& inStream, En
if (eInvTypeIsDefault) inStream.Read(eInvType); if (eInvTypeIsDefault) inStream.Read(eInvType);
inStream.Read(eLootTypeSourceIsDefault); inStream.Read(eLootTypeSourceIsDefault);
if (eLootTypeSourceIsDefault) inStream.Read(eLootTypeSource); if (eLootTypeSourceIsDefault) inStream.Read(eLootTypeSource);
inStream.Read(extraInfo.length); inStream.Read(extraInfoLength);
if (extraInfo.length > 0) { if (extraInfoLength > 0) {
for (uint32_t i = 0; i < extraInfo.length; ++i) { for (uint32_t i = 0; i < extraInfoLength; ++i) {
uint16_t character; uint16_t character;
inStream.Read(character); inStream.Read(character);
extraInfo.name.push_back(character); extraInfo.push_back(character);
} }
uint16_t nullTerm; uint16_t nullTerm;
inStream.Read(nullTerm); inStream.Read(nullTerm);
@@ -5754,7 +5751,6 @@ void GameMessages::HandleUseNonEquipmentItem(RakNet::BitStream& inStream, Entity
void GameMessages::HandleMatchRequest(RakNet::BitStream& inStream, Entity* entity) { void GameMessages::HandleMatchRequest(RakNet::BitStream& inStream, Entity* entity) {
LWOOBJID activator; LWOOBJID activator;
//std::map<LWOOBJID, LWONameValue> additionalPlayers;
uint32_t playerChoicesLen; uint32_t playerChoicesLen;
std::string playerChoices; std::string playerChoices;
int type; int type;