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"
// C++
#include <map>
#include <string>
#include <string_view>
#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; }
struct LwoNameValue {
using ValueType = std::map<std::u16string, std::unique_ptr<LDFBaseData>>;
ValueType values;
};
#endif //!__LDFFORMAT__H__

View File

@@ -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<uint32_t>(name.length());
}
};
struct FriendData {
public:
bool isOnline = false;

View File

@@ -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<LDFBaseData>(setting->Copy()));
m_DefaultPosition = info.pos;
m_DefaultRotation = info.rot;
m_Scale = info.scale;

View File

@@ -99,7 +99,7 @@ public:
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;
@@ -312,6 +312,12 @@ public:
template<typename T>
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>
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<DerivedGameMsg&>(msg));
};
};
DerivedGameMsg msg;
RegisterMsg(msg.msgId, castWrapper);
}
@@ -377,7 +383,7 @@ private:
LOT m_TemplateID;
std::vector<LDFBaseData*> m_Settings;
std::vector<LDFBaseData*> 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<typename T>
void Entity::SetNetworkVar(const std::u16string& name, T value, const SystemAddress& sysAddr) {
LDFData<T>* newData = nullptr;
for (auto* data : m_NetworkSettings) {
if (data->GetKey() != name)
continue;
newData = dynamic_cast<LDFData<T>*>(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<LDFData<T>*>(itr->second.get());
if (!lnv) {
// Is of different type
itr->second = std::make_unique<LDFData<T>>(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<LDFData<T>>(name, value)).first;
}
return itr;
}
if (newData == nullptr) {
newData = new LDFData<T>(name, value);
}
template<typename T>
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(newData->GetString(true), sysAddr);
SendNetworkVar(itr->second->GetString(), 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>
@@ -539,26 +548,10 @@ void Entity::SetNetworkVar(const std::u16string& name, std::vector<T> values, co
for (const auto& value : values) {
LDFData<T>* newData = nullptr;
const auto& indexedName = name + u"." + GeneralUtils::to_u16string(index);
for (auto* data : m_NetworkSettings) {
if (data->GetKey() != indexedName)
continue;
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";
const auto itr = InsertNetworkVar<T>(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<T> values, co
template<typename T>
T Entity::GetNetworkVar(const std::u16string& name) {
for (auto* data : m_NetworkSettings) {
if (data == nullptr || data->GetKey() != name)
continue;
T toReturn = LDFData<T>::Default;
auto* typed = dynamic_cast<LDFData<T>*>(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<LDFData<T>*>(itr->second.get());
if (cast) toReturn = cast->GetValue();
}
return LDFData<T>::Default;
return toReturn;
}
/**

View File

@@ -8,6 +8,8 @@
#include "GameMessages.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) {
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<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);
}
@@ -56,7 +58,7 @@ bool ScriptComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& r
auto& scriptInfo = reportInfo.info->PushDebug("Script");
scriptInfo.PushDebug<AMFStringValue>("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<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
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<uint32_t>(extraInfo.name.size());
if (extraInfo.name.size() > 0) {
for (uint32_t i = 0; i < extraInfo.name.size(); ++i) {
bitStream.Write<uint16_t>(extraInfo.name[i]);
bitStream.Write<uint32_t>(extraInfo.size());
if (extraInfo.size() > 0) {
for (uint32_t i = 0; i < extraInfo.size(); ++i) {
bitStream.Write<uint16_t>(extraInfo[i]);
}
bitStream.Write<uint16_t>(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<uint32_t>(attribs.length);
for (uint32_t i = 0; i < attribs.length; ++i) {
bitStream.Write<uint16_t>(attribs.name[i]);
bitStream.Write<uint32_t>(attrs.size());
for (uint32_t i = 0; i < attrs.size(); ++i) {
bitStream.Write<uint16_t>(attrs[i]);
}
bitStream.Write<uint16_t>(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<LWOOBJID, LWONameValue> additionalPlayers;
uint32_t playerChoicesLen;
std::string playerChoices;
int type;