chore: cleanup pointer management for LDF data (#1995)

* change network settings from vector to LwoNameValue

* move settings on Entity to managed memory

* Migrate more members

* chore: remove pointer leakage from raw ldf pointers

* feedback

* fix ci
This commit is contained in:
David Markowitz
2026-06-14 20:54:52 -07:00
committed by GitHub
parent 90db1ac699
commit 0101933f5c
67 changed files with 676 additions and 754 deletions

View File

@@ -34,12 +34,12 @@ jobs:
if: ${{ matrix.os == 'windows-2025' }} if: ${{ matrix.os == 'windows-2025' }}
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3 uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3
with: with:
vs-version: '[17,18)' vs-version: '[18,19)'
msbuild-architecture: x64 msbuild-architecture: x64
- name: Get CMake 3.x - name: Get CMake
uses: lukka/get-cmake@591817e96fcad43505fb4eae36172462abb3a42e # v4.3.3 uses: lukka/get-cmake@591817e96fcad43505fb4eae36172462abb3a42e # v4.3.3
with: with:
cmakeVersion: "~3.25.0" cmakeVersion: "latest"
- name: cmake - name: cmake
uses: lukka/run-cmake@5d55ea7949e25f69f0ecb516d8d572297e03a956 # v10.9 uses: lukka/run-cmake@5d55ea7949e25f69f0ecb516d8d572297e03a956 # v10.9
with: with:

View File

@@ -16,10 +16,6 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions

View File

@@ -49,7 +49,7 @@
"inherits": "default", "inherits": "default",
"displayName": "[Multi] Windows (MSVC)", "displayName": "[Multi] Windows (MSVC)",
"description": "Set architecture to 64-bit (b/c RakNet)", "description": "Set architecture to 64-bit (b/c RakNet)",
"generator": "Visual Studio 17 2022", "generator": "Visual Studio 18 2026",
"binaryDir": "${sourceDir}/build/msvc", "binaryDir": "${sourceDir}/build/msvc",
"architecture": { "architecture": {
"value": "x64" "value": "x64"

View File

@@ -49,11 +49,10 @@ if (UNIX)
elseif (WIN32) elseif (WIN32)
include(FetchContent) include(FetchContent)
# TODO Keep an eye on the zlib repository for an update to disable testing. Don't forget to update CMakePresets
FetchContent_Declare( FetchContent_Declare(
zlib zlib
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip URL https://github.com/madler/zlib/archive/refs/tags/v1.3.2.zip
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1 URL_HASH MD5=adbba6eef8960c3412818b2e241f46dc
GIT_PROGRESS TRUE GIT_PROGRESS TRUE
GIT_SHALLOW 1 GIT_SHALLOW 1
) )
@@ -62,12 +61,12 @@ elseif (WIN32)
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW) set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
# Disable warning about the minimum version of cmake used for bcrypt being deprecated in the future # Disable warning about the minimum version of cmake used for bcrypt being deprecated in the future
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
# Disable zlib tests
set(ZLIB_BUILD_TESTING OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(zlib) FetchContent_MakeAvailable(zlib)
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR}) set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}")
add_library(ZLIB::ZLIB ALIAS zlib)
else () else ()
message( message(
FATAL_ERROR FATAL_ERROR

View File

@@ -10,163 +10,151 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
using LDFKey = std::string_view;
using LDFTypeAndValue = std::string_view;
using LDFType = std::string_view;
using LDFValue = std::string_view;
//! Returns a pointer to a LDFData value based on string format //! Returns a pointer to a LDFData value based on string format
LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) { std::unique_ptr<LDFBaseData> LDFBaseData::DataFromString(const std::string_view& format) {
std::unique_ptr<LDFBaseData> toReturn;
// A valid LDF must be at least 3 characters long (=0:) is the shortest valid LDF (empty UTF-16 key with no initial value) // A valid LDF must be at least 3 characters long (=0:) is the shortest valid LDF (empty UTF-16 key with no initial value)
if (format.empty() || format.length() <= 2) return nullptr; if (!format.empty() && format.length() > 2) {
auto equalsPosition = format.find('='); auto equalsPosition = format.find('=');
// You can have an empty key, just make sure the type and value might exist // You can have an empty key, just make sure the type and value might exist
if (equalsPosition == std::string::npos || equalsPosition == (format.size() - 1)) return nullptr; if (equalsPosition != std::string::npos && equalsPosition != (format.size() - 1)) {
std::pair<LDFKey, LDFTypeAndValue> keyValue; const std::string_view keyValue = format.substr(0, equalsPosition);
keyValue.first = format.substr(0, equalsPosition); const std::string_view typeAndValue = format.substr(equalsPosition + 1, format.size());
keyValue.second = format.substr(equalsPosition + 1, format.size());
std::u16string key = GeneralUtils::ASCIIToUTF16(keyValue.first); const auto key = GeneralUtils::ASCIIToUTF16(keyValue);
auto colonPosition = keyValue.second.find(':'); const auto colonPosition = typeAndValue.find(':');
// If : is the first thing after an =, then this is an invalid LDF since // If : is the first thing after an =, then this is an invalid LDF since
// we dont have a type to use. // we dont have a type to use.
if (colonPosition == std::string::npos || colonPosition == 0) return nullptr; if (colonPosition != std::string::npos && colonPosition != 0) {
const std::string_view ldfType = typeAndValue.substr(0, colonPosition);
const std::string_view ldfValue = typeAndValue.substr(colonPosition + 1, typeAndValue.size());
std::pair<LDFType, LDFValue> ldfTypeAndValue; // Only allow empty values for string values.
ldfTypeAndValue.first = keyValue.second.substr(0, colonPosition); if (!ldfValue.empty() || (ldfType == "0" /* UTF-16 */ || ldfType == "13" /* UTF-8 */)) {
ldfTypeAndValue.second = keyValue.second.substr(colonPosition + 1, keyValue.second.size()); const eLDFType type = GeneralUtils::TryParse<eLDFType>(ldfType, LDF_TYPE_UNKNOWN);
switch (type) {
case LDF_TYPE_UTF_16: {
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfValue);
toReturn.reset(new LDFData<std::u16string>(key, data));
break;
}
// Only allow empty values for string values. case LDF_TYPE_S32: {
if (ldfTypeAndValue.second.size() == 0 && !(ldfTypeAndValue.first == "0" || ldfTypeAndValue.first == "13")) return nullptr; const auto data = GeneralUtils::TryParse<int32_t>(ldfValue);
if (data) {
toReturn.reset(new LDFData<int32_t>(key, data.value()));
} else {
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfValue.data(), format.data());
}
eLDFType type; break;
char* storage; }
try {
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
} catch (std::exception) {
LOG("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
return nullptr;
}
LDFBaseData* returnValue = nullptr; case LDF_TYPE_FLOAT: {
switch (type) { const auto data = GeneralUtils::TryParse<float>(ldfValue);
case LDF_TYPE_UTF_16: { if (data) {
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfTypeAndValue.second); toReturn.reset(new LDFData<float>(key, data.value()));
returnValue = new LDFData<std::u16string>(key, data); } else {
break; LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfValue.data(), format.data());
} }
break;
}
case LDF_TYPE_S32: { case LDF_TYPE_DOUBLE: {
const auto data = GeneralUtils::TryParse<int32_t>(ldfTypeAndValue.second); const auto data = GeneralUtils::TryParse<double>(ldfValue);
if (!data) { if (data) {
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); toReturn.reset(new LDFData<double>(key, data.value()));
return nullptr; } else {
} LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfValue.data(), format.data());
returnValue = new LDFData<int32_t>(key, data.value()); }
break;
}
break; case LDF_TYPE_U32:
} {
uint32_t data;
bool parsed = true;
// Have to do this really weird parsing to allow for copy ellision
if (ldfValue == "true") {
data = 1;
} else if (ldfValue == "false") {
data = 0;
} else {
const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfValue);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfValue.data(), format.data());
parsed = false;
} else {
data = dataOptional.value();
}
}
case LDF_TYPE_FLOAT: { if (parsed) toReturn.reset(new LDFData<uint32_t>(key, data));
const auto data = GeneralUtils::TryParse<float>(ldfTypeAndValue.second); break;
if (!data) { }
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<float>(key, data.value());
break;
}
case LDF_TYPE_DOUBLE: { case LDF_TYPE_BOOLEAN: {
const auto data = GeneralUtils::TryParse<double>(ldfTypeAndValue.second); bool data;
if (!data) { bool parsed = true;
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); // Have to do this really weird parsing to allow for copy ellision
return nullptr; if (ldfValue == "true") {
} data = true;
returnValue = new LDFData<double>(key, data.value()); } else if (ldfValue == "false") {
break; data = false;
} } else {
const auto dataOptional = GeneralUtils::TryParse<bool>(ldfValue);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfValue.data(), format.data());
parsed = false;
} else {
data = dataOptional.value();
}
}
case LDF_TYPE_U32: if (parsed) toReturn.reset(new LDFData<bool>(key, data));
{ break;
uint32_t data; }
if (ldfTypeAndValue.second == "true") { case LDF_TYPE_U64: {
data = 1; const auto data = GeneralUtils::TryParse<uint64_t>(ldfValue);
} else if (ldfTypeAndValue.second == "false") { if (data) {
data = 0; toReturn.reset(new LDFData<uint64_t>(key, data.value()));
} else { } else {
const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfTypeAndValue.second); LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfValue.data(), format.data());
if (!dataOptional) { }
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); break;
return nullptr; }
case LDF_TYPE_OBJID: {
const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfValue);
if (data) {
toReturn.reset(new LDFData<LWOOBJID>(key, data.value()));
} else {
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfValue.data(), format.data());
}
break;
}
case LDF_TYPE_UTF_8: {
toReturn.reset(new LDFData<std::string>(key, ldfValue.data()));
break;
}
case LDF_TYPE_UNKNOWN:
[[fallthrough]];
default: {
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfValue.data(), format.data());
break;
}
}
}
} }
data = dataOptional.value();
} }
returnValue = new LDFData<uint32_t>(key, data);
break;
} }
case LDF_TYPE_BOOLEAN: { return toReturn;
bool data;
if (ldfTypeAndValue.second == "true") {
data = true;
} else if (ldfTypeAndValue.second == "false") {
data = false;
} else {
const auto dataOptional = GeneralUtils::TryParse<bool>(ldfTypeAndValue.second);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
data = dataOptional.value();
}
returnValue = new LDFData<bool>(key, data);
break;
}
case LDF_TYPE_U64: {
const auto data = GeneralUtils::TryParse<uint64_t>(ldfTypeAndValue.second);
if (!data) {
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<uint64_t>(key, data.value());
break;
}
case LDF_TYPE_OBJID: {
const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfTypeAndValue.second);
if (!data) {
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<LWOOBJID>(key, data.value());
break;
}
case LDF_TYPE_UTF_8: {
std::string data = ldfTypeAndValue.second.data();
returnValue = new LDFData<std::string>(key, data);
break;
}
case LDF_TYPE_UNKNOWN: {
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
break;
}
default: {
LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
break;
}
}
return returnValue;
} }

View File

@@ -1,11 +1,12 @@
#ifndef __LDFFORMAT__H__ #ifndef LDFFORMAT_H
#define __LDFFORMAT__H__ #define LDFFORMAT_H
// Custom Classes // Custom Classes
#include "dCommonVars.h" #include "dCommonVars.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
// C++ // C++
#include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <sstream> #include <sstream>
@@ -46,17 +47,17 @@ public:
virtual std::string GetValueAsString() const = 0; virtual std::string GetValueAsString() const = 0;
virtual LDFBaseData* Copy() const = 0; virtual std::unique_ptr<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.
*/ */
static LDFBaseData* DataFromString(const std::string_view& format); static std::unique_ptr<LDFBaseData> DataFromString(const std::string_view& format);
}; };
template<typename T> template<typename T>
class LDFData: public LDFBaseData { class LDFData : public LDFBaseData {
private: private:
std::u16string key; std::u16string key;
T value; T value;
@@ -164,8 +165,8 @@ public:
return this->GetValueString(); return this->GetValueString();
} }
LDFBaseData* Copy() const override { std::unique_ptr<LDFBaseData> Copy() const override {
return new LDFData<T>(key, value); return std::make_unique<LDFData<T>>(key, value);
} }
inline static const T Default = {}; inline static const T Default = {};
@@ -226,4 +227,81 @@ 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; }
#endif //!__LDFFORMAT__H__ struct LwoNameValue {
using LDFPtr = std::unique_ptr<LDFBaseData>;
using ValueType = std::map<std::u16string, LDFPtr>;
LwoNameValue& operator=(const LwoNameValue& other) {
this->values = other.Copy();
return *this;
}
template<typename T>
void Insert(const std::u16string& key, const T& value) {
this->values.insert_or_assign(key, std::unique_ptr(std::make_unique<LDFData<T>>(key, value)));
}
void Insert(const std::u16string& key, const char* value) {
this->Insert<std::string>(key, value);
}
void Insert(const std::u16string& key, const char16_t* value) {
this->Insert<std::u16string>(key, value);
}
template<typename T>
void Insert(const std::string& key, const T& value) {
this->Insert<T>(GeneralUtils::UTF8ToUTF16(key), value);
}
void Insert(const std::string& key, const char* value) {
this->Insert<std::string>(GeneralUtils::UTF8ToUTF16(key), value);
}
void Insert(const std::string& key, const char16_t* value) {
this->Insert<std::u16string>(GeneralUtils::UTF8ToUTF16(key), value);
}
const LDFPtr& ParseInsert(const std::string& data) {
LDFPtr toInsert(LDFBaseData::DataFromString(data));
return toInsert ?
this->values.insert_or_assign(toInsert->GetKey(), std::move(toInsert)).first->second :
this->values.insert_or_assign(u"FAILED_TO_PARSE_" + GeneralUtils::UTF8ToUTF16(data), std::make_unique<LDFData<std::string>>("", "")).first->second;
}
const LDFPtr& ParseInsert(const std::u16string& data) {
return this->ParseInsert(GeneralUtils::UTF16ToWTF8(data));
}
ValueType::const_iterator begin() const {
return this->values.cbegin();
}
ValueType::const_iterator end() const {
return this->values.cend();
}
void Erase(const std::u16string& key) {
this->values.erase(key);
}
void Erase(const std::string& key) {
this->Erase(GeneralUtils::ASCIIToUTF16(key));
}
LwoNameValue() = default;
LwoNameValue(const LwoNameValue& other) {
this->values = other.Copy();
}
ValueType values;
private:
ValueType Copy() const {
ValueType copy;
for (const auto& [key, value] : this->values) copy.insert_or_assign(key, value->Copy());
return copy;
}
};
#endif //!LDFFORMAT_H

View File

@@ -1,6 +1,8 @@
#ifndef __NIPOINT3_H__ #ifndef __NIPOINT3_H__
#define __NIPOINT3_H__ #define __NIPOINT3_H__
#ifndef GLM_ENABLE_EXPERIMENTAL
# define GLM_ENABLE_EXPERIMENTAL
#endif
/*! /*!
\file NiPoint3.hpp \file NiPoint3.hpp
\brief Defines a point in space in XYZ coordinates \brief Defines a point in space in XYZ coordinates

View File

@@ -1,6 +1,8 @@
#ifndef NIQUATERNION_H #ifndef NIQUATERNION_H
#define NIQUATERNION_H #define NIQUATERNION_H
#ifndef GLM_ENABLE_EXPERIMENTAL
# define GLM_ENABLE_EXPERIMENTAL
#endif
// Custom Classes // Custom Classes
#include "NiPoint3.h" #include "NiPoint3.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

@@ -949,13 +949,13 @@ void Entity::SetGMLevel(eGameMasterLevel value) {
} }
} }
void Entity::WriteLDFData(const std::vector<LDFBaseData*>& ldf, RakNet::BitStream& outBitStream) const { void Entity::WriteLDFData(const LwoNameValue& ldf, RakNet::BitStream& outBitStream) const {
RakNet::BitStream settingStream; RakNet::BitStream settingStream;
int32_t numberOfValidKeys = ldf.size(); int32_t numberOfValidKeys = ldf.values.size();
// Writing keys value pairs the client does not expect to receive or interpret will result in undefined behavior, // Writing keys value pairs the client does not expect to receive or interpret will result in undefined behavior,
// so we need to filter out any keys that are not valid and fix the number of valid keys to be correct. // so we need to filter out any keys that are not valid and fix the number of valid keys to be correct.
for (LDFBaseData* data : ldf) { for (const auto& data : ldf.values | std::views::values) {
if (data && data->GetValueType() != eLDFType::LDF_TYPE_UNKNOWN) { if (data && data->GetValueType() != eLDFType::LDF_TYPE_UNKNOWN) {
data->WriteToPacket(settingStream); data->WriteToPacket(settingStream);
} else { } else {
@@ -987,16 +987,16 @@ void Entity::WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacke
const auto& syncLDF = GetVar<std::vector<std::u16string>>(u"syncLDF"); const auto& syncLDF = GetVar<std::vector<std::u16string>>(u"syncLDF");
// Only sync for models. // Only sync for models.
if (!m_Settings.empty() && (GetComponent<ModelComponent>() && !GetComponent<PetComponent>())) { if (!m_Settings.values.empty() && (GetComponent<ModelComponent>() && !GetComponent<PetComponent>())) {
outBitStream.Write1(); // Has ldf data outBitStream.Write1(); // Has ldf data
WriteLDFData(m_Settings, outBitStream); WriteLDFData(m_Settings, outBitStream);
} else if (!syncLDF.empty()) { } else if (!syncLDF.empty()) {
// Find all the ldf data we need to write // Find all the ldf data we need to write
std::vector<LDFBaseData*> ldfData; LwoNameValue ldfData;
ldfData.reserve(m_Settings.size());
for (const auto& data : syncLDF) { for (const auto& data : syncLDF) {
ldfData.push_back(GetVarData(data)); const auto* toInsert = GetVarData(data);
if (toInsert) ldfData.values.insert_or_assign(data, toInsert->Copy());
} }
outBitStream.Write1(); // Has ldf data outBitStream.Write1(); // Has ldf data
@@ -2045,13 +2045,7 @@ void Entity::SetI64(const std::u16string& name, const int64_t value) {
} }
bool Entity::HasVar(const std::u16string& name) const { bool Entity::HasVar(const std::u16string& name) const {
for (auto* data : m_Settings) { return m_Settings.values.contains(name);
if (data->GetKey() == name) {
return true;
}
}
return false;
} }
uint16_t Entity::GetNetworkId() const { uint16_t Entity::GetNetworkId() const {
@@ -2083,24 +2077,13 @@ void Entity::SendNetworkVar(const std::string& data, const SystemAddress& sysAdd
GameMessages::SendSetNetworkScriptVar(this, sysAddr, data); GameMessages::SendSetNetworkScriptVar(this, sysAddr, data);
} }
LDFBaseData* Entity::GetVarData(const std::u16string& name) const { const LDFBaseData* const Entity::GetVarData(const std::u16string& name) const {
for (auto* data : m_Settings) { const auto itr = m_Settings.values.find(name);
if (data == nullptr) { return itr != m_Settings.values.cend() ? itr->second.get() : nullptr;
continue;
}
if (data->GetKey() != name) {
continue;
}
return data;
}
return nullptr;
} }
std::string Entity::GetVarAsString(const std::u16string& name) const { std::string Entity::GetVarAsString(const std::u16string& name) const {
auto* data = GetVarData(name); const auto* const data = GetVarData(name);
return data ? data->GetValueAsString() : ""; return data ? data->GetValueAsString() : "";
} }
@@ -2276,7 +2259,7 @@ bool Entity::MsgRequestServerObjectInfo(GameMessages::RequestServerObjectInfo& r
} }
auto& configData = objectInfo.PushDebug("Config Data"); auto& configData = objectInfo.PushDebug("Config Data");
for (const auto config : m_Settings) { for (const auto& config : m_Settings.values | std::views::values) {
configData.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(config->GetKey())) = config->GetValueAsString(); configData.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(config->GetKey())) = config->GetValueAsString();
} }

View File

@@ -97,9 +97,9 @@ public:
LWOOBJID GetSpawnerID() const { return m_SpawnerID; } LWOOBJID GetSpawnerID() const { return m_SpawnerID; }
const std::vector<LDFBaseData*>& GetSettings() const { return m_Settings; } const LwoNameValue& 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);
@@ -324,11 +330,6 @@ public:
template<typename ComponentType, typename... VaArgs> template<typename ComponentType, typename... VaArgs>
ComponentType* AddComponent(VaArgs... args); ComponentType* AddComponent(VaArgs... args);
/**
* Get the LDF data.
*/
LDFBaseData* GetVarData(const std::u16string& name) const;
/** /**
* Get the LDF value and convert it to a string. * Get the LDF value and convert it to a string.
*/ */
@@ -360,7 +361,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);
} }
@@ -371,13 +372,20 @@ public:
static Observable<Entity*, const PositionUpdate&> OnPlayerPositionUpdate; static Observable<Entity*, const PositionUpdate&> OnPlayerPositionUpdate;
private: private:
void WriteLDFData(const std::vector<LDFBaseData*>& ldf, RakNet::BitStream& outBitStream) const;
/**
* Get the LDF data.
*/
const LDFBaseData* const GetVarData(const std::u16string& name) const;
template<typename T>
LwoNameValue::ValueType::iterator InsertLnvData(LwoNameValue& lnv, const std::u16string& key, T value);
void WriteLDFData(const LwoNameValue& ldf, RakNet::BitStream& outBitStream) const;
LWOOBJID m_ObjectID; LWOOBJID m_ObjectID;
LOT m_TemplateID; LOT m_TemplateID;
std::vector<LDFBaseData*> m_Settings; LwoNameValue 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;
@@ -459,13 +467,13 @@ T* Entity::GetComponent() const {
template<typename T> template<typename T>
const T& Entity::GetVar(const std::u16string& name) const { const T& Entity::GetVar(const std::u16string& name) const {
auto* data = GetVarData(name); const auto* const data = GetVarData(name);
if (data == nullptr) { if (data == nullptr) {
return LDFData<T>::Default; return LDFData<T>::Default;
} }
auto* typed = dynamic_cast<LDFData<T>*>(data); auto* typed = dynamic_cast<const LDFData<T>* const>(data);
if (typed == nullptr) { if (typed == nullptr) {
return LDFData<T>::Default; return LDFData<T>::Default;
@@ -483,52 +491,44 @@ T Entity::GetVarAs(const std::u16string& name) const {
template<typename T> template<typename T>
void Entity::SetVar(const std::u16string& name, T value) { void Entity::SetVar(const std::u16string& name, T value) {
auto* data = GetVarData(name); InsertLnvData<T>(m_Settings, name, value);
}
if (data == nullptr) { template<typename T>
auto* data = new LDFData<T>(name, value); LwoNameValue::ValueType::iterator Entity::InsertLnvData(LwoNameValue& lnv, const std::u16string& key, T value) {
auto itr = lnv.values.find(key);
m_Settings.push_back(data); if (itr != lnv.values.end()) {
auto* lnvCast = dynamic_cast<LDFData<T>*>(itr->second.get());
return; if (!lnvCast) {
// Is of different type
itr->second = std::make_unique<LDFData<T>>(key, value);
} else {
// Is the same type and exists
lnvCast->SetValue(value);
}
} else {
// Doesn't exist
itr = lnv.values.insert_or_assign(key, std::make_unique<LDFData<T>>(key, value)).first;
} }
auto* typed = dynamic_cast<LDFData<T>*>(data); return itr;
}
if (typed == nullptr) { template<typename T>
return; LwoNameValue::ValueType::iterator Entity::InsertNetworkVar(const std::u16string& name, T value) {
} return InsertLnvData<T>(m_NetworkSettings, name, value);
typed->SetValue(value);
} }
template<typename T> template<typename T>
void Entity::SetNetworkVar(const std::u16string& name, T value, const SystemAddress& sysAddr) { void Entity::SetNetworkVar(const std::u16string& name, T value, const SystemAddress& sysAddr) {
LDFData<T>* newData = nullptr; const auto itr = InsertNetworkVar<T>(name, value);
for (auto* data : m_NetworkSettings) { SendNetworkVar(itr->second->GetString(), sysAddr);
if (data->GetKey() != name) }
continue;
newData = dynamic_cast<LDFData<T>*>(data); template<typename T>
if (newData != nullptr) { void Entity::SetNetworkVar(const std::string& name, T value, const SystemAddress& sysAddr) {
newData->SetValue(value); SetNetworkVar(GeneralUtils::UTF8ToUTF16(name), value, sysAddr);
} else { // If we're changing types
m_NetworkSettings.erase(
std::remove(m_NetworkSettings.begin(), m_NetworkSettings.end(), data), m_NetworkSettings.end()
);
delete data;
}
break;
}
if (newData == nullptr) {
newData = new LDFData<T>(name, value);
}
m_NetworkSettings.push_back(newData);
SendNetworkVar(newData->GetString(true), sysAddr);
} }
template<typename T> template<typename T>
@@ -537,28 +537,11 @@ void Entity::SetNetworkVar(const std::u16string& name, std::vector<T> values, co
auto index = 1; auto index = 1;
for (const auto& value : values) { for (const auto& value : values) {
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 +552,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

@@ -39,10 +39,10 @@ Leaderboard::~Leaderboard() {
} }
void Leaderboard::Clear() { void Leaderboard::Clear() {
for (auto& entry : entries) for (auto ldfData : entry) delete ldfData; entries.clear();
} }
inline void WriteLeaderboardRow(std::ostringstream& leaderboard, const uint32_t& index, LDFBaseData* data) { inline void WriteLeaderboardRow(std::ostringstream& leaderboard, const uint32_t& index, const std::unique_ptr<LDFBaseData>& data) {
leaderboard << "\nResult[0].Row[" << index << "]." << data->GetString(); leaderboard << "\nResult[0].Row[" << index << "]." << data->GetString();
} }
@@ -59,8 +59,8 @@ void Leaderboard::Serialize(RakNet::BitStream& bitStream) const {
int32_t rowNumber = 0; int32_t rowNumber = 0;
for (auto& entry : entries) { for (auto& entry : entries) {
for (auto* data : entry) { for (const auto& data : entry.values | std::views::values) {
WriteLeaderboardRow(leaderboard, rowNumber, data); if (data) WriteLeaderboardRow(leaderboard, rowNumber, data);
} }
rowNumber++; rowNumber++;
} }
@@ -85,57 +85,56 @@ void QueryToLdf(Leaderboard& leaderboard, const std::vector<ILeaderboard::Entry>
for (const auto& leaderboardEntry : leaderboardEntries) { for (const auto& leaderboardEntry : leaderboardEntries) {
constexpr int32_t MAX_NUM_DATA_PER_ROW = 9; constexpr int32_t MAX_NUM_DATA_PER_ROW = 9;
auto& entry = leaderboard.PushBackEntry(); auto& entry = leaderboard.PushBackEntry();
entry.reserve(MAX_NUM_DATA_PER_ROW); entry.Insert<uint64_t>(u"CharacterID", leaderboardEntry.charId);
entry.push_back(new LDFData<uint64_t>(u"CharacterID", leaderboardEntry.charId)); entry.Insert<uint64_t>(u"LastPlayed", leaderboardEntry.lastPlayedTimestamp);
entry.push_back(new LDFData<uint64_t>(u"LastPlayed", leaderboardEntry.lastPlayedTimestamp)); entry.Insert<int32_t>(u"NumPlayed", leaderboardEntry.numTimesPlayed);
entry.push_back(new LDFData<int32_t>(u"NumPlayed", leaderboardEntry.numTimesPlayed)); entry.Insert<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(leaderboardEntry.name));
entry.push_back(new LDFData<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(leaderboardEntry.name))); entry.Insert<uint64_t>(u"RowNumber", leaderboardEntry.ranking);
entry.push_back(new LDFData<uint64_t>(u"RowNumber", leaderboardEntry.ranking));
switch (leaderboard.GetLeaderboardType()) { switch (leaderboard.GetLeaderboardType()) {
case ShootingGallery: case ShootingGallery:
entry.push_back(new LDFData<int32_t>(u"Score", leaderboardEntry.primaryScore)); entry.Insert<int32_t>(u"Score", leaderboardEntry.primaryScore);
// Score:1 // Score:1
entry.push_back(new LDFData<int32_t>(u"Streak", leaderboardEntry.secondaryScore)); entry.Insert<int32_t>(u"Streak", leaderboardEntry.secondaryScore);
// Streak:1 // Streak:1
entry.push_back(new LDFData<float>(u"HitPercentage", leaderboardEntry.tertiaryScore)); entry.Insert<float>(u"HitPercentage", leaderboardEntry.tertiaryScore);
// HitPercentage:3 between 0 and 1 // HitPercentage:3 between 0 and 1
break; break;
case Racing: case Racing:
entry.push_back(new LDFData<float>(u"BestTime", leaderboardEntry.primaryScore)); entry.Insert<float>(u"BestTime", leaderboardEntry.primaryScore);
// BestLapTime:3 // BestLapTime:3
entry.push_back(new LDFData<float>(u"BestLapTime", leaderboardEntry.secondaryScore)); entry.Insert<float>(u"BestLapTime", leaderboardEntry.secondaryScore);
// BestTime:3 // BestTime:3
entry.push_back(new LDFData<int32_t>(u"License", 1)); entry.Insert<int32_t>(u"License", 1);
// License:1 - 1 if player has completed mission 637 and 0 otherwise // License:1 - 1 if player has completed mission 637 and 0 otherwise
entry.push_back(new LDFData<int32_t>(u"NumWins", leaderboardEntry.numWins)); entry.Insert<int32_t>(u"NumWins", leaderboardEntry.numWins);
// NumWins:1 // NumWins:1
break; break;
case UnusedLeaderboard4: case UnusedLeaderboard4:
entry.push_back(new LDFData<int32_t>(u"Points", leaderboardEntry.primaryScore)); entry.Insert<int32_t>(u"Points", leaderboardEntry.primaryScore);
// Points:1 // Points:1
break; break;
case MonumentRace: case MonumentRace:
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.primaryScore)); entry.Insert<int32_t>(u"Time", leaderboardEntry.primaryScore);
// Time:1(?) // Time:1(?)
break; break;
case FootRace: case FootRace:
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.primaryScore)); entry.Insert<int32_t>(u"Time", leaderboardEntry.primaryScore);
// Time:1 // Time:1
break; break;
case Survival: case Survival:
entry.push_back(new LDFData<int32_t>(u"Points", leaderboardEntry.primaryScore)); entry.Insert<int32_t>(u"Points", leaderboardEntry.primaryScore);
// Points:1 // Points:1
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.secondaryScore)); entry.Insert<int32_t>(u"Time", leaderboardEntry.secondaryScore);
// Time:1 // Time:1
break; break;
case SurvivalNS: case SurvivalNS:
entry.push_back(new LDFData<int32_t>(u"Wave", leaderboardEntry.primaryScore)); entry.Insert<int32_t>(u"Wave", leaderboardEntry.primaryScore);
// Wave:1 // Wave:1
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.secondaryScore)); entry.Insert<int32_t>(u"Time", leaderboardEntry.secondaryScore);
// Time:1 // Time:1
break; break;
case Donations: case Donations:
entry.push_back(new LDFData<int32_t>(u"Score", leaderboardEntry.primaryScore)); entry.Insert<int32_t>(u"Score", leaderboardEntry.primaryScore);
// Score:1 // Score:1
break; break;
case None: case None:

View File

@@ -70,8 +70,7 @@ public:
private: private:
using LeaderboardEntry = std::vector<LDFBaseData*>; using LeaderboardEntries = std::vector<LwoNameValue>;
using LeaderboardEntries = std::vector<LeaderboardEntry>;
LeaderboardEntries entries; LeaderboardEntries entries;
LWOOBJID relatedPlayer; LWOOBJID relatedPlayer;
@@ -81,7 +80,7 @@ private:
bool weekly; bool weekly;
uint32_t numResults; uint32_t numResults;
public: public:
LeaderboardEntry& PushBackEntry() { LwoNameValue& PushBackEntry() {
return entries.emplace_back(); return entries.emplace_back();
} }

View File

@@ -24,6 +24,7 @@
#include "WorldPackets.h" #include "WorldPackets.h"
#include "MessageType/Game.h" #include "MessageType/Game.h"
#include <ctime> #include <ctime>
#include <ranges>
CharacterComponent::CharacterComponent(Entity* parent, const int32_t componentID, Character* character, const SystemAddress& systemAddress) : Component(parent, componentID) { CharacterComponent::CharacterComponent(Entity* parent, const int32_t componentID, Character* character, const SystemAddress& systemAddress) : Component(parent, componentID) {
m_Character = character; m_Character = character;
@@ -491,7 +492,7 @@ Item* CharacterComponent::RocketEquip(Entity* player) {
if (!rocket) return rocket; if (!rocket) return rocket;
// build and define the rocket config // build and define the rocket config
for (LDFBaseData* data : rocket->GetConfig()) { for (const auto& data : rocket->GetConfig().values | std::views::values) {
if (data->GetKey() == u"assemblyPartLOTs") { if (data->GetKey() == u"assemblyPartLOTs") {
std::string newRocketStr = data->GetValueAsString() + ";"; std::string newRocketStr = data->GetValueAsString() + ";";
GeneralUtils::ReplaceInString(newRocketStr, "+", ";"); GeneralUtils::ReplaceInString(newRocketStr, "+", ";");

View File

@@ -881,9 +881,9 @@ void DestroyableComponent::FixStats() {
int32_t currentImagination = destroyableComponent->GetImagination(); int32_t currentImagination = destroyableComponent->GetImagination();
// Unequip all items // Unequip all items
auto equipped = inventoryComponent->GetEquippedItems(); const auto equipped = inventoryComponent->GetEquippedItems();
for (auto& equippedItem : equipped) { for (const auto& equippedItem : equipped) {
// Get the item with the item ID // Get the item with the item ID
auto* item = inventoryComponent->FindItemById(equippedItem.second.id); auto* item = inventoryComponent->FindItemById(equippedItem.second.id);
@@ -924,7 +924,7 @@ void DestroyableComponent::FixStats() {
buffComponent->ReApplyBuffs(); buffComponent->ReApplyBuffs();
// Requip all items // Requip all items
for (auto& equippedItem : equipped) { for (const auto& equippedItem : equipped) {
// Get the item with the item ID // Get the item with the item ID
auto* item = inventoryComponent->FindItemById(equippedItem.second.id); auto* item = inventoryComponent->FindItemById(equippedItem.second.id);

View File

@@ -173,7 +173,7 @@ void InventoryComponent::AddItem(
const uint32_t count, const uint32_t count,
eLootSourceType lootSourceType, eLootSourceType lootSourceType,
eInventoryType inventoryType, eInventoryType inventoryType,
const std::vector<LDFBaseData*>& config, const LwoNameValue& config,
const LWOOBJID parent, const LWOOBJID parent,
const bool showFlyingLoot, const bool showFlyingLoot,
bool isModMoveAndEquip, bool isModMoveAndEquip,
@@ -204,7 +204,7 @@ void InventoryComponent::AddItem(
auto* inventory = GetInventory(inventoryType); auto* inventory = GetInventory(inventoryType);
if (!config.empty() || bound) { if (!config.values.empty() || bound) {
const auto slot = preferredSlot != -1 && inventory->IsSlotEmpty(preferredSlot) ? preferredSlot : inventory->FindEmptySlot(); const auto slot = preferredSlot != -1 && inventory->IsSlotEmpty(preferredSlot) ? preferredSlot : inventory->FindEmptySlot();
if (slot == -1) { if (slot == -1) {
@@ -356,7 +356,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in
const auto subkey = item->GetSubKey(); const auto subkey = item->GetSubKey();
if (subkey == LWOOBJID_EMPTY && item->GetConfig().empty() && (!item->GetBound() || (item->GetBound() && item->GetInfo().isBOP))) { if (subkey == LWOOBJID_EMPTY && item->GetConfig().values.empty() && (!item->GetBound() || (item->GetBound() && item->GetInfo().isBOP))) {
auto left = std::min<uint32_t>(count, origin->GetLotCount(lot)); auto left = std::min<uint32_t>(count, origin->GetLotCount(lot));
while (left > 0) { while (left > 0) {
@@ -379,11 +379,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in
isModMoveAndEquip = false; isModMoveAndEquip = false;
} }
} else { } else {
std::vector<LDFBaseData*> config; const auto config = item->GetConfig();
for (auto* const data : item->GetConfig()) {
config.push_back(data->Copy());
}
const auto delta = std::min<uint32_t>(item->GetCount(), count); const auto delta = std::min<uint32_t>(item->GetCount(), count);
@@ -744,18 +740,17 @@ void InventoryComponent::Serialize(RakNet::BitStream& outBitStream, const bool b
outBitStream.Write0(); outBitStream.Write0();
bool flag = !item.config.empty(); bool flag = !item.config.values.empty();
outBitStream.Write(flag); outBitStream.Write(flag);
if (flag) { if (flag) {
RakNet::BitStream ldfStream; RakNet::BitStream ldfStream;
ldfStream.Write<int32_t>(item.config.size()); // Key count ldfStream.Write<int32_t>(item.config.values.size()); // Key count
for (LDFBaseData* data : item.config) { for (const auto& data : item.config.values | std::views::values) {
if (data->GetKey() == u"assemblyPartLOTs") { if (data->GetKey() == u"assemblyPartLOTs") {
std::string newRocketStr = data->GetValueAsString() + ";"; std::string newRocketStr = data->GetValueAsString() + ";";
GeneralUtils::ReplaceInString(newRocketStr, "+", ";"); GeneralUtils::ReplaceInString(newRocketStr, "+", ";");
LDFData<std::u16string>* ldf_data = new LDFData<std::u16string>(u"assemblyPartLOTs", GeneralUtils::ASCIIToUTF16(newRocketStr)); LDFData<std::u16string> ldf_data(u"assemblyPartLOTs", GeneralUtils::ASCIIToUTF16(newRocketStr));
ldf_data->WriteToPacket(ldfStream); ldf_data.WriteToPacket(ldfStream);
delete ldf_data;
} else { } else {
data->WriteToPacket(ldfStream); data->WriteToPacket(ldfStream);
} }
@@ -782,7 +777,7 @@ void InventoryComponent::Update(float deltaTime) {
} }
} }
void InventoryComponent::UpdateSlot(const std::string& location, EquippedItem item, bool keepCurrent) { void InventoryComponent::UpdateSlot(const std::string& location, const EquippedItem& item, bool keepCurrent) {
const auto index = m_Equipped.find(location); const auto index = m_Equipped.find(location);
if (index != m_Equipped.end()) { if (index != m_Equipped.end()) {
@@ -1080,7 +1075,7 @@ void InventoryComponent::PushEquippedItems() {
} }
void InventoryComponent::PopEquippedItems() { void InventoryComponent::PopEquippedItems() {
auto current = m_Equipped; const auto current = m_Equipped;
for (const auto& pair : current) { for (const auto& pair : current) {
auto* const item = FindItemById(pair.second.id); auto* const item = FindItemById(pair.second.id);
@@ -1876,7 +1871,7 @@ bool InventoryComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo
slot.PushDebug<AMFBoolValue>("Bind on equip") = item->GetInfo().isBOE; slot.PushDebug<AMFBoolValue>("Bind on equip") = item->GetInfo().isBOE;
slot.PushDebug<AMFBoolValue>("Is currently bound") = item->GetBound(); slot.PushDebug<AMFBoolValue>("Is currently bound") = item->GetBound();
auto& extra = slot.PushDebug("Extra Info"); auto& extra = slot.PushDebug("Extra Info");
for (const auto* const setting : item->GetConfig()) { for (const auto& setting : item->GetConfig().values | std::views::values) {
if (setting) extra.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString(); if (setting) extra.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString();
} }
} }
@@ -1892,7 +1887,7 @@ bool InventoryComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo
equipSlot.PushDebug<AMFIntValue>("Slot") = info.slot; equipSlot.PushDebug<AMFIntValue>("Slot") = info.slot;
equipSlot.PushDebug<AMFIntValue>("Count") = info.count; equipSlot.PushDebug<AMFIntValue>("Count") = info.count;
auto& extra = equipSlot.PushDebug("Extra Info"); auto& extra = equipSlot.PushDebug("Extra Info");
for (const auto* const setting : info.config) { for (const auto& setting : info.config.values | std::views::values) {
if (setting) extra.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString(); if (setting) extra.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString();
} }
} }

View File

@@ -134,7 +134,7 @@ public:
uint32_t count, uint32_t count,
eLootSourceType lootSourceType = eLootSourceType::NONE, eLootSourceType lootSourceType = eLootSourceType::NONE,
eInventoryType inventoryType = INVALID, eInventoryType inventoryType = INVALID,
const std::vector<LDFBaseData*>& config = {}, const LwoNameValue& config = {},
LWOOBJID parent = LWOOBJID_EMPTY, LWOOBJID parent = LWOOBJID_EMPTY,
bool showFlyingLoot = true, bool showFlyingLoot = true,
bool isModMoveAndEquip = false, bool isModMoveAndEquip = false,
@@ -213,7 +213,7 @@ public:
* @param item the item to place * @param item the item to place
* @param keepCurrent stores the item in an additional temp slot if there's already an item equipped * @param keepCurrent stores the item in an additional temp slot if there's already an item equipped
*/ */
void UpdateSlot(const std::string& location, EquippedItem item, bool keepCurrent = false); void UpdateSlot(const std::string& location, const EquippedItem& item, bool keepCurrent = false);
/** /**
* Removes a slot from the inventory * Removes a slot from the inventory

View File

@@ -221,8 +221,8 @@ void ModelComponent::RemoveBehavior(MoveToInventoryMessage& msg, const bool keep
auto* const inventoryComponent = playerEntity->GetComponent<InventoryComponent>(); auto* const inventoryComponent = playerEntity->GetComponent<InventoryComponent>();
if (inventoryComponent && !behavior.GetIsLoot()) { if (inventoryComponent && !behavior.GetIsLoot()) {
// config is owned by the item // config is owned by the item
std::vector<LDFBaseData*> config; LwoNameValue config;
config.push_back(new LDFData<std::string>(u"userModelName", behavior.GetName())); config.Insert(u"userModelName", behavior.GetName());
inventoryComponent->AddItem(7965, 1, eLootSourceType::PROPERTY, eInventoryType::BEHAVIORS, config, LWOOBJID_EMPTY, true, false, msg.GetBehaviorId()); inventoryComponent->AddItem(7965, 1, eLootSourceType::PROPERTY, eInventoryType::BEHAVIORS, config, LWOOBJID_EMPTY, true, false, msg.GetBehaviorId());
} }
} }

View File

@@ -12,7 +12,6 @@
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
#include "PhysicsComponent.h" #include "PhysicsComponent.h"
class LDFBaseData;
class Entity; class Entity;
class dpEntity; class dpEntity;
enum class ePhysicsEffectType : uint32_t ; enum class ePhysicsEffectType : uint32_t ;

View File

@@ -346,10 +346,7 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
info.spawner = nullptr; info.spawner = nullptr;
info.spawnerID = spawnerID; info.spawnerID = spawnerID;
info.spawnerNodeID = 0; info.spawnerNodeID = 0;
info.settings = item->GetConfig();
for (auto* setting : item->GetConfig()) {
info.settings.push_back(setting->Copy());
}
Entity* newEntity = Game::entityManager->CreateEntity(info); Entity* newEntity = Game::entityManager->CreateEntity(info);
if (newEntity != nullptr) { if (newEntity != nullptr) {
@@ -393,11 +390,11 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
auto* spawner = Game::zoneManager->GetSpawner(spawnerId); auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0)); info.nodes[0]->config.Insert<LWOOBJID>(u"modelBehaviors", 0);
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"userModelID", info.spawnerID)); info.nodes[0]->config.Insert<LWOOBJID>(u"userModelID", info.spawnerID);
info.nodes[0]->config.push_back(new LDFData<int>(u"modelType", 2)); info.nodes[0]->config.Insert<int>(u"modelType", 2);
info.nodes[0]->config.push_back(new LDFData<bool>(u"propertyObjectID", true)); info.nodes[0]->config.Insert<bool>(u"propertyObjectID", true);
info.nodes[0]->config.push_back(new LDFData<int>(u"componentWhitelist", 1)); info.nodes[0]->config.Insert<int>(u"componentWhitelist", 1);
auto* model = spawner->Spawn(); auto* model = spawner->Spawn();
auto* modelComponent = model->GetComponent<ModelComponent>(); auto* modelComponent = model->GetComponent<ModelComponent>();
@@ -476,28 +473,19 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
if (model->GetLOT() == 14) { if (model->GetLOT() == 14) {
//add it to the inv //add it to the inv
std::vector<LDFBaseData*> settings; LwoNameValue actualConfig;
//fill our settings with BBB gurbage //fill our settings with BBB gurbage
LDFBaseData* ldfBlueprintID = new LDFData<LWOOBJID>(u"blueprintid", model->GetVar<LWOOBJID>(u"blueprintid")); actualConfig.Insert(u"blueprintid", model->GetVar<LWOOBJID>(u"blueprintid"));
LDFBaseData* userModelDesc = new LDFData<std::u16string>(u"userModelDesc", u"A cool model you made!"); actualConfig.Insert(u"userModelDesc", u"A cool model you made!");
LDFBaseData* userModelHasBhvr = new LDFData<bool>(u"userModelHasBhvr", false); actualConfig.Insert(u"userModelHasBhvr", false);
LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", model->GetVar<LWOOBJID>(u"userModelID")); actualConfig.Insert(u"userModelID", model->GetVar<LWOOBJID>(u"userModelID"));
LDFBaseData* userModelMod = new LDFData<bool>(u"userModelMod", false); actualConfig.Insert(u"userModelMod", false);
LDFBaseData* userModelName = new LDFData<std::u16string>(u"userModelName", u"My Cool Model"); actualConfig.Insert(u"userModelName", u"My Cool Model");
LDFBaseData* propertyObjectID = new LDFData<bool>(u"userModelOpt", true); actualConfig.Insert(u"userModelOpt", true);
LDFBaseData* modelType = new LDFData<int>(u"userModelPhysicsType", 2); actualConfig.Insert(u"userModelPhysicsType", 2);
settings.push_back(ldfBlueprintID); inventoryComponent->AddItem(6662, 1, eLootSourceType::DELETION, eInventoryType::MODELS_IN_BBB, actualConfig, LWOOBJID_EMPTY, false, false, spawnerId);
settings.push_back(userModelDesc);
settings.push_back(userModelHasBhvr);
settings.push_back(userModelID);
settings.push_back(userModelMod);
settings.push_back(userModelName);
settings.push_back(propertyObjectID);
settings.push_back(modelType);
inventoryComponent->AddItem(6662, 1, eLootSourceType::DELETION, eInventoryType::MODELS_IN_BBB, settings, LWOOBJID_EMPTY, false, false, spawnerId);
auto* item = inventoryComponent->FindItemBySubKey(spawnerId); auto* item = inventoryComponent->FindItemBySubKey(spawnerId);
if (item == nullptr) { if (item == nullptr) {
@@ -615,23 +603,23 @@ void PropertyManagementComponent::Load() {
info.spawnerID = databaseModel.id; info.spawnerID = databaseModel.id;
std::vector<LDFBaseData*> settings; LwoNameValue& settings = node->config;
//BBB property models need to have extra stuff set for them: //BBB property models need to have extra stuff set for them:
if (databaseModel.lot == 14) { if (databaseModel.lot == 14) {
LWOOBJID blueprintID = databaseModel.ugcId; LWOOBJID blueprintID = databaseModel.ugcId;
settings.push_back(new LDFData<LWOOBJID>(u"blueprintid", blueprintID)); settings.Insert<LWOOBJID>(u"blueprintid", blueprintID);
settings.push_back(new LDFData<int>(u"componentWhitelist", 1)); settings.Insert<int>(u"componentWhitelist", 1);
settings.push_back(new LDFData<int>(u"modelType", 2)); settings.Insert<int>(u"modelType", 2);
settings.push_back(new LDFData<bool>(u"propertyObjectID", true)); settings.Insert<bool>(u"propertyObjectID", true);
settings.push_back(new LDFData<LWOOBJID>(u"userModelID", databaseModel.id)); settings.Insert<LWOOBJID>(u"userModelID", databaseModel.id);
} else { } else {
settings.push_back(new LDFData<int>(u"modelType", 2)); settings.Insert<int>(u"modelType", 2);
settings.push_back(new LDFData<LWOOBJID>(u"userModelID", databaseModel.id)); settings.Insert<LWOOBJID>(u"userModelID", databaseModel.id);
settings.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0)); settings.Insert<LWOOBJID>(u"modelBehaviors", 0);
settings.push_back(new LDFData<bool>(u"propertyObjectID", true)); settings.Insert<bool>(u"propertyObjectID", true);
settings.push_back(new LDFData<int>(u"componentWhitelist", 1)); settings.Insert<int>(u"componentWhitelist", 1);
} }
std::ostringstream userModelBehavior; std::ostringstream userModelBehavior;
@@ -646,9 +634,7 @@ void PropertyManagementComponent::Load() {
firstAdded = true; firstAdded = true;
} }
settings.push_back(new LDFData<std::string>(u"userModelBehaviors", userModelBehavior.str())); settings.Insert<std::string>(u"userModelBehaviors", userModelBehavior.str());
node->config = settings;
const auto spawnerId = Game::zoneManager->MakeSpawner(info); const auto spawnerId = Game::zoneManager->MakeSpawner(info);

View File

@@ -26,6 +26,7 @@
#include "dZoneManager.h" #include "dZoneManager.h"
#include "CDActivitiesTable.h" #include "CDActivitiesTable.h"
#include "eStateChangeType.h" #include "eStateChangeType.h"
#include <ranges>
#include <ctime> #include <ctime>
#ifndef M_PI #ifndef M_PI
@@ -57,6 +58,7 @@ RacingControlComponent::RacingControlComponent(Entity* parent, const int32_t com
CDActivitiesTable* activitiesTable = CDClientManager::GetTable<CDActivitiesTable>(); CDActivitiesTable* activitiesTable = CDClientManager::GetTable<CDActivitiesTable>();
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.instanceMapID == worldID); }); std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.instanceMapID == worldID); });
for (CDActivities activity : activities) m_ActivityID = activity.ActivityID; for (CDActivities activity : activities) m_ActivityID = activity.ActivityID;
RegisterMsg(&RacingControlComponent::MsgConfigureRacingControl);
} }
RacingControlComponent::~RacingControlComponent() {} RacingControlComponent::~RacingControlComponent() {}
@@ -178,11 +180,10 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
moduleAssemblyComponent->SetSubKey(item->GetSubKey()); moduleAssemblyComponent->SetSubKey(item->GetSubKey());
moduleAssemblyComponent->SetUseOptionalParts(false); moduleAssemblyComponent->SetUseOptionalParts(false);
for (auto* config : item->GetConfig()) { const auto& lnv = item->GetConfig().values;
if (config->GetKey() == u"assemblyPartLOTs") { const auto itr = lnv.find(u"assemblyPartLOTs");
moduleAssemblyComponent->SetAssemblyPartsLOTs( if (itr != lnv.end()) {
GeneralUtils::ASCIIToUTF16(config->GetValueAsString())); moduleAssemblyComponent->SetAssemblyPartsLOTs(GeneralUtils::ASCIIToUTF16(itr->second->GetValueAsString()));
}
} }
} }
@@ -871,10 +872,10 @@ void RacingControlComponent::Update(float deltaTime) {
} }
} }
void RacingControlComponent::MsgConfigureRacingControl(const GameMessages::ConfigureRacingControl& msg) { bool RacingControlComponent::MsgConfigureRacingControl(const GameMessages::ConfigureRacingControl& msg) {
for (const auto& dataUnique : msg.racingSettings) { for (const auto& dataUnique : msg.racingSettings | std::views::values) {
if (!dataUnique) continue; if (!dataUnique) continue;
const auto* const data = dataUnique.get(); const auto* const data = dataUnique.get();
if (data->GetKey() == u"Race_PathName" && data->GetValueType() == LDF_TYPE_UTF_16) { if (data->GetKey() == u"Race_PathName" && data->GetValueType() == LDF_TYPE_UTF_16) {
m_PathName = static_cast<const LDFData<std::u16string>*>(data)->GetValue(); m_PathName = static_cast<const LDFData<std::u16string>*>(data)->GetValue();
} else if (data->GetKey() == u"activityID" && data->GetValueType() == LDF_TYPE_S32) { } else if (data->GetKey() == u"activityID" && data->GetValueType() == LDF_TYPE_S32) {
@@ -886,4 +887,5 @@ void RacingControlComponent::MsgConfigureRacingControl(const GameMessages::Confi
m_MinimumPlayersForGroupAchievements = static_cast<const LDFData<int32_t>*>(data)->GetValue(); m_MinimumPlayersForGroupAchievements = static_cast<const LDFData<int32_t>*>(data)->GetValue();
} }
} }
return true;
} }

View File

@@ -152,7 +152,7 @@ public:
*/ */
RacingPlayerInfo* GetPlayerData(LWOOBJID playerID); RacingPlayerInfo* GetPlayerData(LWOOBJID playerID);
void MsgConfigureRacingControl(const GameMessages::ConfigureRacingControl& msg); bool MsgConfigureRacingControl(const GameMessages::ConfigureRacingControl& msg);
private: private:

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

@@ -125,8 +125,7 @@ void SkillComponent::SyncPlayerProjectile(const LWOOBJID projectileId, RakNet::B
this->m_managedProjectiles.erase(this->m_managedProjectiles.begin() + index); this->m_managedProjectiles.erase(this->m_managedProjectiles.begin() + index);
GameMessages::ActivityNotify notify; GameMessages::ActivityNotify notify;
notify.notification.push_back( std::make_unique<LDFData<int32_t>>(u"shot_done", sync_entry.skillId)); notify.notification.Insert<int32_t>(u"shot_done", sync_entry.skillId);
m_Parent->OnActivityNotify(notify); m_Parent->OnActivityNotify(notify);
} }

View File

@@ -34,7 +34,7 @@ struct EntityInfo {
LOT lot; LOT lot;
NiPoint3 pos; NiPoint3 pos;
NiQuaternion rot = QuatUtils::IDENTITY; NiQuaternion rot = QuatUtils::IDENTITY;
std::vector<LDFBaseData*> settings; LwoNameValue settings;
std::vector<LDFBaseData*> networkSettings; LwoNameValue networkSettings;
float scale; float scale;
}; };

View File

@@ -46,6 +46,7 @@
#include <sstream> #include <sstream>
#include <future> #include <future>
#include <chrono> #include <chrono>
#include <ranges>
#include "RakString.h" #include "RakString.h"
//CDB includes: //CDB includes:
@@ -465,20 +466,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(); const auto& config = item->GetConfig();
for (auto* data : config) { for (const auto& data : config.values | std::views::values) {
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 +744,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
@@ -2621,11 +2618,11 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream& inStream, Entity* ent
info.spawnerID = entity->GetObjectID(); info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0; info.spawnerNodeID = 0;
info.settings.push_back(new LDFData<LWOOBJID>(u"blueprintid", blueprintIDs[i])); info.settings.Insert<LWOOBJID>(u"blueprintid", blueprintIDs[i]);
info.settings.push_back(new LDFData<int>(u"componentWhitelist", 1)); info.settings.Insert<int>(u"componentWhitelist", 1);
info.settings.push_back(new LDFData<int>(u"modelType", 2)); info.settings.Insert<int>(u"modelType", 2);
info.settings.push_back(new LDFData<bool>(u"propertyObjectID", true)); info.settings.Insert<bool>(u"propertyObjectID", true);
info.settings.push_back(new LDFData<LWOOBJID>(u"userModelID", modelIDs[i])); info.settings.Insert<LWOOBJID>(u"userModelID", modelIDs[i]);
Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr); Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr);
if (newEntity) { if (newEntity) {
Game::entityManager->ConstructEntity(newEntity); Game::entityManager->ConstructEntity(newEntity);
@@ -5266,7 +5263,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 +5290,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);
@@ -5505,10 +5503,8 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream& inStream, Entity*
//inv->UnequipItem(inv->GetItemStackByLOT(6086, eInventoryType::ITEMS)); // take off the thinking cap //inv->UnequipItem(inv->GetItemStackByLOT(6086, eInventoryType::ITEMS)); // take off the thinking cap
//Game::entityManager->SerializeEntity(entity); //Game::entityManager->SerializeEntity(entity);
const auto moduleAssembly = new LDFData<std::u16string>(u"assemblyPartLOTs", modules); LwoNameValue config;
config.Insert(u"assemblyPartLOTs", modules);
std::vector<LDFBaseData*> config;
config.push_back(moduleAssembly);
LWOOBJID newID = ObjectIDManager::GetPersistentID(); LWOOBJID newID = ObjectIDManager::GetPersistentID();
@@ -5754,7 +5750,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;
@@ -6309,7 +6304,7 @@ namespace GameMessages {
bitStream.Write(id); bitStream.Write(id);
std::string toWrite; std::string toWrite;
for (const auto* item : localizeParams) { for (const auto& item : localizeParams | std::views::values) {
toWrite += item->GetString() + "\n"; toWrite += item->GetString() + "\n";
} }
if (!toWrite.empty()) toWrite.pop_back(); if (!toWrite.empty()) toWrite.pop_back();

View File

@@ -13,6 +13,7 @@
#include "Brick.h" #include "Brick.h"
#include "MessageType/Game.h" #include "MessageType/Game.h"
#include "eGameMasterLevel.h" #include "eGameMasterLevel.h"
#include "LDFFormat.h"
class AMFBaseValue; class AMFBaseValue;
class AMFArrayValue; class AMFArrayValue;
@@ -711,7 +712,7 @@ namespace GameMessages {
bool translate{}; bool translate{};
int32_t time{}; int32_t time{};
std::u16string id{}; std::u16string id{};
std::vector<LDFBaseData*> localizeParams{}; LwoNameValue localizeParams{};
std::u16string imageName{}; std::u16string imageName{};
std::u16string text{}; std::u16string text{};
void Serialize(RakNet::BitStream& bitStream) const override; void Serialize(RakNet::BitStream& bitStream) const override;
@@ -734,7 +735,7 @@ namespace GameMessages {
struct ConfigureRacingControl : public GameMsg { struct ConfigureRacingControl : public GameMsg {
ConfigureRacingControl() : GameMsg(MessageType::Game::CONFIGURE_RACING_CONTROL) {} ConfigureRacingControl() : GameMsg(MessageType::Game::CONFIGURE_RACING_CONTROL) {}
std::vector<std::unique_ptr<LDFBaseData>> racingSettings{}; LwoNameValue racingSettings{};
}; };
struct SetModelToBuild : public GameMsg { struct SetModelToBuild : public GameMsg {
@@ -754,7 +755,7 @@ namespace GameMessages {
struct ActivityNotify : public GameMsg { struct ActivityNotify : public GameMsg {
ActivityNotify() : GameMsg(MessageType::Game::ACTIVITY_NOTIFY) {} ActivityNotify() : GameMsg(MessageType::Game::ACTIVITY_NOTIFY) {}
std::vector<std::unique_ptr<LDFBaseData>> notification{}; LwoNameValue notification{};
}; };
struct ShootingGalleryFire : public GameMsg { struct ShootingGalleryFire : public GameMsg {

View File

@@ -31,5 +31,5 @@ struct EquippedItem
/** /**
* The configuration of the item with any extra data * The configuration of the item with any extra data
*/ */
std::vector<LDFBaseData*> config = {}; LwoNameValue config = {};
}; };

View File

@@ -28,6 +28,7 @@
#include "CDObjectSkillsTable.h" #include "CDObjectSkillsTable.h"
#include "CDComponentsRegistryTable.h" #include "CDComponentsRegistryTable.h"
#include "CDPackageComponentTable.h" #include "CDPackageComponentTable.h"
#include <ranges>
namespace { namespace {
const std::map<std::string, std::string> ExtraSettingAbbreviations = { const std::map<std::string, std::string> ExtraSettingAbbreviations = {
@@ -46,7 +47,7 @@ namespace {
}; };
} }
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 LwoNameValue& config, const LWOOBJID parent, LWOOBJID subKey, eLootSourceType lootSourceType) {
if (!Inventory::IsValidItem(lot)) { if (!Inventory::IsValidItem(lot)) {
return; return;
} }
@@ -71,7 +72,7 @@ Item::Item(
Inventory* inventory, Inventory* inventory,
const uint32_t slot, const uint32_t slot,
const uint32_t count, const uint32_t count,
const std::vector<LDFBaseData*>& config, const LwoNameValue& config,
const LWOOBJID parent, const LWOOBJID parent,
bool showFlyingLoot, bool showFlyingLoot,
bool isModMoveAndEquip, bool isModMoveAndEquip,
@@ -131,11 +132,11 @@ uint32_t Item::GetSlot() const {
return slot; return slot;
} }
std::vector<LDFBaseData*> Item::GetConfig() const { const LwoNameValue& Item::GetConfig() const {
return config; return config;
} }
std::vector<LDFBaseData*>& Item::GetConfig() { LwoNameValue& Item::GetConfig() {
return config; return config;
} }
@@ -379,7 +380,7 @@ void Item::UseNonEquip(Item* item) {
} }
void Item::Disassemble(const eInventoryType inventoryType) { void Item::Disassemble(const eInventoryType inventoryType) {
for (auto* data : config) { for (const auto& data : config.values | std::views::values) {
if (data->GetKey() == u"assemblyPartLOTs") { if (data->GetKey() == u"assemblyPartLOTs") {
auto modStr = data->GetValueAsString(); auto modStr = data->GetValueAsString();
@@ -530,18 +531,12 @@ void Item::RemoveFromInventory() {
Item::~Item() { Item::~Item() {
delete preconditions; delete preconditions;
for (auto* value : config) {
delete value;
}
config.clear();
} }
void Item::SaveConfigXml(tinyxml2::XMLElement& i) const { void Item::SaveConfigXml(tinyxml2::XMLElement& i) const {
tinyxml2::XMLElement* x = nullptr; tinyxml2::XMLElement* x = nullptr;
for (const auto* config : this->config) { for (const auto& config : config.values | std::views::values) {
const auto& key = GeneralUtils::UTF16ToWTF8(config->GetKey()); const auto& key = GeneralUtils::UTF16ToWTF8(config->GetKey());
const auto saveKey = ExtraSettingAbbreviations.find(key); const auto saveKey = ExtraSettingAbbreviations.find(key);
if (saveKey == ExtraSettingAbbreviations.end()) { if (saveKey == ExtraSettingAbbreviations.end()) {
@@ -561,12 +556,11 @@ void Item::LoadConfigXml(const tinyxml2::XMLElement& i) {
const auto* x = i.FirstChildElement("x"); const auto* x = i.FirstChildElement("x");
if (!x) return; if (!x) return;
for (const auto& pair : ExtraSettingAbbreviations) { for (const auto& [fullName, abbreviation] : ExtraSettingAbbreviations) {
const auto* data = x->Attribute(pair.second.c_str()); const auto* data = x->Attribute(abbreviation.c_str());
if (!data) continue; if (!data) continue;
const auto value = pair.first + "=" + data; config.ParseInsert(fullName + "=" + data);
config.push_back(LDFBaseData::DataFromString(value));
} }
} }

View File

@@ -40,7 +40,7 @@ public:
uint32_t slot, uint32_t slot,
uint32_t count, uint32_t count,
bool bound, bool bound,
const std::vector<LDFBaseData*>& config, const LwoNameValue& config,
LWOOBJID parent, LWOOBJID parent,
LWOOBJID subKey, LWOOBJID subKey,
eLootSourceType lootSourceType = eLootSourceType::NONE eLootSourceType lootSourceType = eLootSourceType::NONE
@@ -64,7 +64,7 @@ public:
Inventory* inventory, Inventory* inventory,
uint32_t slot = 0, uint32_t slot = 0,
uint32_t count = 1, uint32_t count = 1,
const std::vector<LDFBaseData*>& config = {}, const LwoNameValue& config = {},
LWOOBJID parent = LWOOBJID_EMPTY, LWOOBJID parent = LWOOBJID_EMPTY,
bool showFlyingLoot = true, bool showFlyingLoot = true,
bool isModMoveAndEquip = false, bool isModMoveAndEquip = false,
@@ -118,13 +118,13 @@ public:
* Returns current config info for this item, e.g. for rockets * Returns current config info for this item, e.g. for rockets
* @return current config info for this item * @return current config info for this item
*/ */
std::vector<LDFBaseData*>& GetConfig(); LwoNameValue& GetConfig();
/** /**
* Returns current config info for this item, e.g. for rockets * Returns current config info for this item, e.g. for rockets
* @return current config info for this item * @return current config info for this item
*/ */
std::vector<LDFBaseData*> GetConfig() const; const LwoNameValue& GetConfig() const;
/** /**
* Returns the database info for this item * Returns the database info for this item
@@ -269,7 +269,7 @@ private:
/** /**
* Config data for this item, e.g. for rocket parts and car parts * Config data for this item, e.g. for rocket parts and car parts
*/ */
std::vector<LDFBaseData*> config; LwoNameValue config;
/** /**
* The inventory this item belongs to * The inventory this item belongs to

View File

@@ -218,7 +218,6 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string&
uint32_t activityId; uint32_t activityId;
uint32_t lot; uint32_t lot;
uint32_t collectionId; uint32_t collectionId;
std::vector<LDFBaseData*> settings;
switch (type) { switch (type) {
case eMissionTaskType::UNKNOWN: case eMissionTaskType::UNKNOWN:

View File

@@ -802,7 +802,7 @@ namespace DEVGMCommands {
info.spawner = nullptr; info.spawner = nullptr;
info.spawnerID = entity->GetObjectID(); info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0; info.spawnerNodeID = 0;
info.settings = { new LDFData<bool>(u"SpawnedFromSlashCommand", true) }; info.settings.Insert<bool>(u"SpawnedFromSlashCommand", true);
Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr); Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr);
@@ -844,7 +844,7 @@ namespace DEVGMCommands {
info.spawner = nullptr; info.spawner = nullptr;
info.spawnerID = entity->GetObjectID(); info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0; info.spawnerNodeID = 0;
info.settings = { new LDFData<bool>(u"SpawnedFromSlashCommand", true) }; info.settings.Insert(u"SpawnedFromSlashCommand", true);
auto playerPosition = entity->GetPosition(); auto playerPosition = entity->GetPosition();
while (numberToSpawn > 0) { while (numberToSpawn > 0) {
@@ -1268,10 +1268,10 @@ namespace DEVGMCommands {
auto* inventoryComponent = entity->GetComponent<InventoryComponent>(); auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
if (!inventoryComponent) return; if (!inventoryComponent) return;
std::vector<LDFBaseData*> data{}; LwoNameValue config;
data.push_back(new LDFData<int32_t>(u"reforgedLOT", reforgedItem.value())); config.Insert<LOT>(u"reforgedLOT", reforgedItem.value());
inventoryComponent->AddItem(baseItem.value(), 1, eLootSourceType::MODERATION, eInventoryType::INVALID, data); inventoryComponent->AddItem(baseItem.value(), 1, eLootSourceType::MODERATION, eInventoryType::INVALID, config);
} }
void Crash(Entity* entity, const SystemAddress& sysAddr, const std::string args) { void Crash(Entity* entity, const SystemAddress& sysAddr, const std::string args) {

View File

@@ -45,10 +45,8 @@ void VanityUtilities::SpawnVanity() {
info.pos = { 259.5f, 246.4f, -705.2f }; info.pos = { 259.5f, 246.4f, -705.2f };
info.rot = { 0.0f, 0.0f, 1.0f, 0.0f }; info.rot = { 0.0f, 0.0f, 1.0f, 0.0f };
info.spawnerID = Game::entityManager->GetZoneControlEntity()->GetObjectID(); info.spawnerID = Game::entityManager->GetZoneControlEntity()->GetObjectID();
info.settings = { info.settings.Insert<bool>(u"hasCustomText", true);
new LDFData<bool>(u"hasCustomText", true), info.settings.Insert<std::string>(u"customText", ParseMarkdown((BinaryPathFinder::GetBinaryDir() / "vanity/TESTAMENT.md").string()));
new LDFData<std::string>(u"customText", ParseMarkdown((BinaryPathFinder::GetBinaryDir() / "vanity/TESTAMENT.md").string()))
};
auto* entity = Game::entityManager->CreateEntity(info); auto* entity = Game::entityManager->CreateEntity(info);
Game::entityManager->ConstructEntity(entity); Game::entityManager->ConstructEntity(entity);
@@ -231,7 +229,7 @@ void ParseXml(const std::string& file) {
auto* configElement = object->FirstChildElement("config"); auto* configElement = object->FirstChildElement("config");
std::vector<std::u16string> keys = {}; std::vector<std::u16string> keys = {};
std::vector<LDFBaseData*> config = {}; LwoNameValue config;
if (configElement) { if (configElement) {
for (auto* key = configElement->FirstChildElement("key"); key != nullptr; for (auto* key = configElement->FirstChildElement("key"); key != nullptr;
key = key->NextSiblingElement("key")) { key = key->NextSiblingElement("key")) {
@@ -239,16 +237,16 @@ void ParseXml(const std::string& file) {
auto* data = key->GetText(); auto* data = key->GetText();
if (!data) continue; if (!data) continue;
LDFBaseData* configData = LDFBaseData::DataFromString(data); const auto& configData = config.ParseInsert(data);
if (configData->GetKey() == u"useLocationsAsRandomSpawnPoint" && configData->GetValueType() == eLDFType::LDF_TYPE_BOOLEAN) { if (configData->GetKey() == u"useLocationsAsRandomSpawnPoint" && configData->GetValueType() == eLDFType::LDF_TYPE_BOOLEAN) {
useLocationsAsRandomSpawnPoint = static_cast<bool>(configData); useLocationsAsRandomSpawnPoint = static_cast<const LDFData<bool>*>(configData.get())->GetValue();
config.Erase(u"useLocationsAsRandomSpawnPoint");
continue; continue;
} }
keys.push_back(configData->GetKey()); keys.push_back(configData->GetKey());
config.push_back(configData);
} }
} }
if (!keys.empty()) config.push_back(new LDFData<std::vector<std::u16string>>(u"syncLDF", keys)); if (!keys.empty()) config.Insert<std::vector<std::u16string>>(u"syncLDF", keys);
VanityObject objectData{ VanityObject objectData{
.m_Name = name, .m_Name = name,

View File

@@ -19,7 +19,7 @@ struct VanityObject {
std::vector<LOT> m_Equipment; std::vector<LOT> m_Equipment;
std::vector<std::string> m_Phrases; std::vector<std::string> m_Phrases;
std::map<uint32_t, std::vector<VanityObjectLocation>> m_Locations; std::map<uint32_t, std::vector<VanityObjectLocation>> m_Locations;
std::vector<LDFBaseData*> m_Config; LwoNameValue m_Config;
}; };

View File

@@ -11,6 +11,7 @@
#include "BitStreamUtils.h" #include "BitStreamUtils.h"
#include <iostream> #include <iostream>
#include <ranges>
void HTTPMonitorInfo::Serialize(RakNet::BitStream& bitStream) const { void HTTPMonitorInfo::Serialize(RakNet::BitStream& bitStream) const {
bitStream.Write(port); bitStream.Write(port);
@@ -88,18 +89,18 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, int64_t rep
RakNet::BitStream data; RakNet::BitStream data;
std::vector<std::unique_ptr<LDFBaseData>> ldfData; LwoNameValue ldfData;
ldfData.push_back(std::move(make_unique<LDFData<LWOOBJID>>(u"objid", player))); ldfData.Insert<LWOOBJID>(u"objid", player);
ldfData.push_back(std::move(make_unique<LDFData<LOT>>(u"template", 1))); ldfData.Insert<LOT>(u"template", 1);
ldfData.push_back(std::move(make_unique<LDFData<string>>(u"xmlData", xmlData))); ldfData.Insert<string>(u"xmlData", xmlData);
ldfData.push_back(std::move(make_unique<LDFData<u16string>>(u"name", username))); ldfData.Insert<u16string>(u"name", username);
ldfData.push_back(std::move(make_unique<LDFData<int32_t>>(u"gmlevel", static_cast<int32_t>(gm)))); ldfData.Insert<int32_t>(u"gmlevel", static_cast<int32_t>(gm));
ldfData.push_back(std::move(make_unique<LDFData<int32_t>>(u"chatmode", static_cast<int32_t>(gm)))); ldfData.Insert<int32_t>(u"chatmode", static_cast<int32_t>(gm));
ldfData.push_back(std::move(make_unique<LDFData<int64_t>>(u"reputation", reputation))); ldfData.Insert<int64_t>(u"reputation", reputation);
ldfData.push_back(std::move(make_unique<LDFData<int32_t>>(u"propertycloneid", cloneID))); ldfData.Insert<int32_t>(u"propertycloneid", cloneID);
data.Write<uint32_t>(ldfData.size()); data.Write<uint32_t>(ldfData.values.size());
for (const auto& toSerialize : ldfData) toSerialize->WriteToPacket(data); for (const auto& toSerialize : ldfData | std::views::values) toSerialize->WriteToPacket(data);
//Compress the data before sending: //Compress the data before sending:
const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed()); const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed());

View File

@@ -97,17 +97,14 @@ void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t
info.pos = objectPosition; info.pos = objectPosition;
info.rot = rotation; info.rot = rotation;
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.settings = { info.settings.Insert<std::string>(u"rebuild_activators",
new LDFData<std::string>(u"rebuild_activators",
std::to_string(objectPosition.x + forward.x) + "\x1f" + std::to_string(objectPosition.x + forward.x) + "\x1f" +
std::to_string(objectPosition.y) + "\x1f" + std::to_string(objectPosition.y) + "\x1f" +
std::to_string(objectPosition.z + forward.z) std::to_string(objectPosition.z + forward.z));
), info.settings.Insert<int32_t>(u"respawn", 100000);
new LDFData<int32_t>(u"respawn", 100000), info.settings.Insert<float>(u"rebuild_reset_time", 15);
new LDFData<float>(u"rebuild_reset_time", 15), info.settings.Insert<bool>(u"no_timed_spawn", true);
new LDFData<bool>(u"no_timed_spawn", true), info.settings.Insert<LWOOBJID>(u"Dragon", self->GetObjectID());
new LDFData<LWOOBJID>(u"Dragon", self->GetObjectID())
};
auto* golemObject = Game::entityManager->CreateEntity(info); auto* golemObject = Game::entityManager->CreateEntity(info);

View File

@@ -113,17 +113,14 @@ void FvMaelstromDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_
info.pos = objectPosition; info.pos = objectPosition;
info.rot = rotation; info.rot = rotation;
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.settings = { info.settings.Insert<std::string>(u"rebuild_activators",
new LDFData<std::string>(u"rebuild_activators",
std::to_string(objectPosition.x + forward.x) + "\x1f" + std::to_string(objectPosition.x + forward.x) + "\x1f" +
std::to_string(objectPosition.y) + "\x1f" + std::to_string(objectPosition.y) + "\x1f" +
std::to_string(objectPosition.z + forward.z) std::to_string(objectPosition.z + forward.z));
), info.settings.Insert<int32_t>(u"respawn", 100000);
new LDFData<int32_t>(u"respawn", 100000), info.settings.Insert<float>(u"rebuild_reset_time", 15);
new LDFData<float>(u"rebuild_reset_time", 15), info.settings.Insert<bool>(u"no_timed_spawn", true);
new LDFData<bool>(u"no_timed_spawn", true), info.settings.Insert<LWOOBJID>(u"Dragon", self->GetObjectID());
new LDFData<LWOOBJID>(u"Dragon", self->GetObjectID())
};
auto* golemObject = Game::entityManager->CreateEntity(info); auto* golemObject = Game::entityManager->CreateEntity(info);

View File

@@ -82,15 +82,12 @@ void BaseEnemyApe::OnTimerDone(Entity* self, std::string timerName) {
entityInfo.spawnerID = self->GetObjectID(); entityInfo.spawnerID = self->GetObjectID();
entityInfo.lot = self->GetVar<LOT>(u"QuickbuildAnchorLOT") != 0 entityInfo.lot = self->GetVar<LOT>(u"QuickbuildAnchorLOT") != 0
? self->GetVar<LOT>(u"QuickbuildAnchorLOT") : 7549; ? self->GetVar<LOT>(u"QuickbuildAnchorLOT") : 7549;
entityInfo.settings = { entityInfo.settings.Insert<std::string>(u"rebuild_activators",
new LDFData<std::string>(u"rebuild_activators",
std::to_string(objectPosition.GetX()) + "\x1f" + std::to_string(objectPosition.GetX()) + "\x1f" +
std::to_string(objectPosition.GetY()) + "\x1f" + std::to_string(objectPosition.GetY()) + "\x1f" +
std::to_string(objectPosition.GetZ()) std::to_string(objectPosition.GetZ()));
), entityInfo.settings.Insert<bool>(u"no_timed_spawn", true);
new LDFData<bool>(u"no_timed_spawn", true), entityInfo.settings.Insert<LWOOBJID>(u"ape", self->GetObjectID());
new LDFData<LWOOBJID>(u"ape", self->GetObjectID())
};
auto* anchor = Game::entityManager->CreateEntity(entityInfo, nullptr, self); auto* anchor = Game::entityManager->CreateEntity(entityInfo, nullptr, self);
Game::entityManager->ConstructEntity(anchor); Game::entityManager->ConstructEntity(anchor);

View File

@@ -23,7 +23,7 @@ void BaseEnemyMech::OnDie(Entity* self, Entity* killer) {
NiPoint3 newLoc = { controlPhys->GetPosition().x, dpWorld::GetNavMesh()->GetHeightAtPoint(controlPhys->GetPosition()), controlPhys->GetPosition().z }; NiPoint3 newLoc = { controlPhys->GetPosition().x, dpWorld::GetNavMesh()->GetHeightAtPoint(controlPhys->GetPosition()), controlPhys->GetPosition().z };
EntityInfo info = EntityInfo(); EntityInfo info = EntityInfo();
std::vector<LDFBaseData*> cfg; LwoNameValue cfg;
std::u16string activatorPosStr; std::u16string activatorPosStr;
activatorPosStr += (GeneralUtils::to_u16string(controlPhys->GetPosition().x)); activatorPosStr += (GeneralUtils::to_u16string(controlPhys->GetPosition().x));
activatorPosStr.push_back(0x1f); activatorPosStr.push_back(0x1f);
@@ -31,8 +31,7 @@ void BaseEnemyMech::OnDie(Entity* self, Entity* killer) {
activatorPosStr.push_back(0x1f); activatorPosStr.push_back(0x1f);
activatorPosStr += (GeneralUtils::to_u16string(controlPhys->GetPosition().z)); activatorPosStr += (GeneralUtils::to_u16string(controlPhys->GetPosition().z));
LDFBaseData* activatorPos = new LDFData<std::u16string>(u"rebuild_activators", activatorPosStr); cfg.Insert<std::u16string>(u"rebuild_activators", activatorPosStr);
cfg.push_back(activatorPos);
info.lot = qbTurretLOT; info.lot = qbTurretLOT;
info.pos = newLoc; info.pos = newLoc;
info.rot = controlPhys->GetRotation(); info.rot = controlPhys->GetRotation();

View File

@@ -71,9 +71,7 @@ void ZoneAgSpiderQueen::OnTimerDone(Entity* self, std::string timerName) {
info.pos = spawnTarget->GetPosition(); info.pos = spawnTarget->GetPosition();
info.rot = spawnTarget->GetRotation(); info.rot = spawnTarget->GetRotation();
info.lot = chestObject; info.lot = chestObject;
info.settings = { info.settings.Insert(u"parent_tag", self->GetObjectID());
new LDFData<LWOOBJID>(u"parent_tag", self->GetObjectID())
};
auto* chest = Game::entityManager->CreateEntity(info); auto* chest = Game::entityManager->CreateEntity(info);
Game::entityManager->ConstructEntity(chest); Game::entityManager->ConstructEntity(chest);

View File

@@ -37,12 +37,10 @@ void AmSkullkinTower::SpawnLegs(Entity* self, const std::string& loc) {
return; return;
} }
std::vector<LDFBaseData*> config = { new LDFData<std::string>(u"Leg", loc) };
EntityInfo info{}; EntityInfo info{};
info.lot = legLOT; info.lot = legLOT;
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.settings = config; info.settings.Insert("Leg", loc);
info.rot = newRot; info.rot = newRot;
if (loc == "Right") { if (loc == "Right") {

View File

@@ -204,12 +204,10 @@ void PetDigServer::SpawnPet(Entity* self, const Entity* owner, const DigInfo dig
info.pos = self->GetPosition(); info.pos = self->GetPosition();
info.rot = self->GetRotation(); info.rot = self->GetRotation();
info.spawnerID = self->GetSpawnerID(); info.spawnerID = self->GetSpawnerID();
info.settings = { info.settings.Insert<LWOOBJID>(u"tamer", owner->GetObjectID());
new LDFData<LWOOBJID>(u"tamer", owner->GetObjectID()), info.settings.Insert<std::string>(u"group", "pet" + std::to_string(owner->GetObjectID()));
new LDFData<std::string>(u"group", "pet" + std::to_string(owner->GetObjectID())), info.settings.Insert<std::string>(u"spawnAnim", "spawn-pet");
new LDFData<std::string>(u"spawnAnim", "spawn-pet"), info.settings.Insert<float>(u"spawnTimer", 1.0);
new LDFData<float>(u"spawnTimer", 1.0)
};
auto* spawnedPet = Game::entityManager->CreateEntity(info); auto* spawnedPet = Game::entityManager->CreateEntity(info);
Game::entityManager->ConstructEntity(spawnedPet); Game::entityManager->ConstructEntity(spawnedPet);

View File

@@ -66,14 +66,12 @@ void QbSpawner::OnTimerDone(Entity* self, std::string timerName) {
info.rot = newRot; info.rot = newRot;
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.spawnerNodeID = 0; info.spawnerNodeID = 0;
info.settings = { info.settings.Insert<bool>(u"no_timed_spawn", true);
new LDFData<bool>(u"no_timed_spawn", true), info.settings.Insert<float>(u"aggroRadius", 70);
new LDFData<float>(u"aggroRadius", 70), info.settings.Insert<float>(u"softtetherRadius", 80);
new LDFData<float>(u"softtetherRadius", 80), info.settings.Insert<float>(u"tetherRadius", 90);
new LDFData<float>(u"tetherRadius", 90), info.settings.Insert<float>(u"wanderRadius", 5);
new LDFData<float>(u"wanderRadius", 5), info.settings.Insert<int>(u"mobTableLoc", i);
new LDFData<int>(u"mobTableLoc", i)
};
auto* child = Game::entityManager->CreateEntity(info, nullptr, self); auto* child = Game::entityManager->CreateEntity(info, nullptr, self);
Game::entityManager->ConstructEntity(child); Game::entityManager->ConstructEntity(child);

View File

@@ -34,12 +34,10 @@ void NsConcertChoiceBuildManager::SpawnCrate(Entity* self) {
info.pos = self->GetPosition(); info.pos = self->GetPosition();
info.rot = self->GetRotation(); info.rot = self->GetRotation();
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.settings = { info.settings.Insert<bool>(u"startsQBActivator", true);
new LDFData<bool>(u"startsQBActivator", true), info.settings.Insert<std::string>(u"grpNameQBShowBricks", crate.group + std::to_string(groupNumber));
new LDFData<std::string>(u"grpNameQBShowBricks", crate.group + std::to_string(groupNumber)), info.settings.Insert<std::u16string>(u"groupID", GeneralUtils::ASCIIToUTF16("Crate_" + group));
new LDFData<std::u16string>(u"groupID", GeneralUtils::ASCIIToUTF16("Crate_" + group)), info.settings.Insert<float>(u"crateTime", crate.time);
new LDFData<float>(u"crateTime", crate.time),
};
auto* spawnedCrate = Game::entityManager->CreateEntity(info); auto* spawnedCrate = Game::entityManager->CreateEntity(info);
Game::entityManager->ConstructEntity(spawnedCrate); Game::entityManager->ConstructEntity(spawnedCrate);

View File

@@ -89,7 +89,7 @@ void NtCombatChallengeServer::SpawnTargetDummy(Entity* self) {
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.pos = self->GetPosition(); info.pos = self->GetPosition();
info.rot = self->GetRotation(); info.rot = self->GetRotation();
info.settings = { new LDFData<std::string>(u"custom_script_server", "scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_DUMMY.lua") }; info.settings.Insert(u"custom_script_server", "scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_DUMMY.lua");
auto* dummy = Game::entityManager->CreateEntity(info, nullptr, self); auto* dummy = Game::entityManager->CreateEntity(info, nullptr, self);

View File

@@ -95,10 +95,8 @@ void ZoneAgProperty::LoadInstance(Entity* self) {
for (auto* spawner : Game::zoneManager->GetSpawnersByName(self->GetVar<std::string>(InstancerSpawner))) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(self->GetVar<std::string>(InstancerSpawner))) {
for (auto* spawnerNode : spawner->m_Info.nodes) { for (auto* spawnerNode : spawner->m_Info.nodes) {
spawnerNode->config.push_back( spawnerNode->config.Insert<std::string>(u"custom_script_server", R"(scripts\ai\GENERAL\L_INSTANCE_EXIT_TRANSFER_PLAYER_TO_LAST_NON_INSTANCE.lua)");
new LDFData<std::string>(u"custom_script_server", spawnerNode->config.Insert<std::u16string>(u"transferText", u"SPIDER_QUEEN_EXIT_QUESTION");
R"(scripts\ai\GENERAL\L_INSTANCE_EXIT_TRANSFER_PLAYER_TO_LAST_NON_INSTANCE.lua)"));
spawnerNode->config.push_back(new LDFData<std::u16string>(u"transferText", u"SPIDER_QUEEN_EXIT_QUESTION"));
} }
} }

View File

@@ -515,9 +515,7 @@ void NjMonastryBossInstance::FightOver(Entity* self) {
info.pos = treasureChest->GetPosition(); info.pos = treasureChest->GetPosition();
info.rot = treasureChest->GetRotation(); info.rot = treasureChest->GetRotation();
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.settings = { info.settings.Insert<LWOOBJID>(u"parent_tag", self->GetObjectID());
new LDFData<LWOOBJID>(u"parent_tag", self->GetObjectID())
};
// Finally spawn a treasure chest at the correct spawn point // Finally spawn a treasure chest at the correct spawn point
auto* chestObject = Game::entityManager->CreateEntity(info); auto* chestObject = Game::entityManager->CreateEntity(info);

View File

@@ -21,9 +21,7 @@ void StinkyFishTarget::OnSkillEventFired(Entity* self, Entity* caster, const std
entityInfo.pos = self->GetPosition(); entityInfo.pos = self->GetPosition();
entityInfo.rot = self->GetRotation(); entityInfo.rot = self->GetRotation();
entityInfo.spawnerID = self->GetObjectID(); entityInfo.spawnerID = self->GetObjectID();
entityInfo.settings = { entityInfo.settings.Insert(u"no_timed_spawn", true);
new LDFData<bool>(u"no_timed_spawn", true)
};
auto* fish = Game::entityManager->CreateEntity(entityInfo); auto* fish = Game::entityManager->CreateEntity(entityInfo);
Game::entityManager->ConstructEntity(fish); Game::entityManager->ConstructEntity(fish);

View File

@@ -26,12 +26,10 @@ void SpawnPetBaseServer::OnUse(Entity* self, Entity* user) {
info.rot = spawner->GetRotation(); info.rot = spawner->GetRotation();
info.lot = self->GetVar<LOT>(u"petLOT"); info.lot = self->GetVar<LOT>(u"petLOT");
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.settings = { info.settings.Insert<LWOOBJID>(u"tamer", user->GetObjectID());
new LDFData<LWOOBJID>(u"tamer", user->GetObjectID()), info.settings.Insert<std::u16string>(u"groupID", petType + (GeneralUtils::to_u16string(user->GetObjectID())) + u";" + petType + u"s");
new LDFData<std::u16string>(u"groupID", petType + (GeneralUtils::to_u16string(user->GetObjectID())) + u";" + petType + u"s"), info.settings.Insert<std::u16string>(u"spawnAnim", self->GetVar<std::u16string>(u"spawnAnim"));
new LDFData<std::u16string>(u"spawnAnim", self->GetVar<std::u16string>(u"spawnAnim")), info.settings.Insert<float_t>(u"spawnTimer", 1.0f);
new LDFData<float_t>(u"spawnTimer", 1.0f)
};
auto* pet = Game::entityManager->CreateEntity(info); auto* pet = Game::entityManager->CreateEntity(info);
Game::entityManager->ConstructEntity(pet); Game::entityManager->ConstructEntity(pet);

View File

@@ -38,10 +38,8 @@ void FvPandaSpawnerServer::OnCollisionPhantom(Entity* self, Entity* target) {
info.spawnerID = target->GetObjectID(); info.spawnerID = target->GetObjectID();
info.pos = self->GetPosition(); info.pos = self->GetPosition();
info.lot = 5643; info.lot = 5643;
info.settings = { info.settings.Insert<LWOOBJID>(u"tamer", target->GetObjectID());
new LDFData<LWOOBJID>(u"tamer", target->GetObjectID()), info.settings.Insert<std::u16string>(u"groupID", u"panda" + (GeneralUtils::to_u16string(target->GetObjectID())) + u";pandas");
new LDFData<std::u16string>(u"groupID", u"panda" + (GeneralUtils::to_u16string(target->GetObjectID())) + u";pandas")
};
auto* panda = Game::entityManager->CreateEntity(info); auto* panda = Game::entityManager->CreateEntity(info);
Game::entityManager->ConstructEntity(panda); Game::entityManager->ConstructEntity(panda);

View File

@@ -66,7 +66,7 @@ void GfBanana::OnHit(Entity* self, Entity* attacker) {
info.pos.z -= QuatUtils::Right(rotation).z * 5; info.pos.z -= QuatUtils::Right(rotation).z * 5;
info.rot = rotation; info.rot = rotation;
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.settings = { new LDFData<uint32_t>(u"motionType", 5) }; info.settings.Insert<uint32_t>(u"motionType", 5);
auto* const newEn = Game::entityManager->CreateEntity(info, nullptr, self); auto* const newEn = Game::entityManager->CreateEntity(info, nullptr, self);
Game::entityManager->ConstructEntity(newEn); Game::entityManager->ConstructEntity(newEn);
} }

View File

@@ -13,14 +13,12 @@ void PetDigBuild::OnQuickBuildComplete(Entity* self, Entity* target) {
info.pos = pos; info.pos = pos;
info.rot = self->GetRotation(); info.rot = self->GetRotation();
info.spawnerID = self->GetSpawnerID(); info.spawnerID = self->GetSpawnerID();
info.settings = { info.settings.Insert<LWOOBJID>(u"builder", target->GetObjectID());
new LDFData<LWOOBJID>(u"builder", target->GetObjectID()), info.settings.Insert<LWOOBJID>(u"X", self->GetObjectID());
new LDFData<LWOOBJID>(u"X", self->GetObjectID())
};
if (!flagNumber.empty()) { if (!flagNumber.empty()) {
info.lot = 7410; // Normal GF treasure info.lot = 7410; // Normal GF treasure
info.settings.push_back(new LDFData<std::u16string>(u"groupID", u"Flag" + flagNumber)); info.settings.Insert<std::u16string>(u"groupID", u"Flag" + flagNumber);
} else { } else {
auto* missionComponent = target->GetComponent<MissionComponent>(); auto* missionComponent = target->GetComponent<MissionComponent>();
if (missionComponent != nullptr && missionComponent->GetMissionState(746) == eMissionState::ACTIVE) { if (missionComponent != nullptr && missionComponent->GetMissionState(746) == eMissionState::ACTIVE) {

View File

@@ -261,15 +261,13 @@ void SGCannon::DoSpawnTimerFunc(Entity* self, const std::string& name) {
info.spawnerID = self->GetObjectID(); info.spawnerID = self->GetObjectID();
info.pos = path->pathWaypoints[0].position; info.pos = path->pathWaypoints[0].position;
info.settings = { info.settings.Insert<SGEnemy>(u"SpawnData", toSpawn);
new LDFData<SGEnemy>(u"SpawnData", toSpawn), info.settings.Insert<std::string>(u"custom_script_server", "scripts/ai/ACT/SG_TARGET.lua"); // this script is never loaded;
new LDFData<std::string>(u"custom_script_server", "scripts/ai/ACT/SG_TARGET.lua"), // this script is never loaded info.settings.Insert<std::string>(u"custom_script_client", "scripts/client/ai/SG_TARGET_CLIENT.lua");
new LDFData<std::string>(u"custom_script_client", "scripts/client/ai/SG_TARGET_CLIENT.lua"), info.settings.Insert<std::string>(u"attached_path", path->pathName);
new LDFData<std::string>(u"attached_path", path->pathName), info.settings.Insert<uint32_t>(u"attached_path_start", 0);
new LDFData<uint32_t>(u"attached_path_start", 0), info.settings.Insert<std::u16string>(u"groupID", u"SGEnemy");
new LDFData<std::u16string>(u"groupID", u"SGEnemy"), info.settings.Insert<uint32_t>(u"wave", self->GetVar<uint32_t>(ThisWaveVariable));
new LDFData<uint32_t>(u"wave", self->GetVar<uint32_t>(ThisWaveVariable)),
};
auto* enemy = Game::entityManager->CreateEntity(info, nullptr, self); auto* enemy = Game::entityManager->CreateEntity(info, nullptr, self);
@@ -621,10 +619,11 @@ void SGCannon::OnActivityNotify(Entity* self, GameMessages::ActivityNotify& noti
if (!self->GetVar<bool>(GameStartedVariable)) return; if (!self->GetVar<bool>(GameStartedVariable)) return;
const auto& params = notify.notification; const auto& params = notify.notification;
if (params.empty()) return; const auto itr = params.values.find(u"shot_done");
if (itr == params.values.end()) return;
const auto& param = params[0]; const auto& param = itr->second;
if (param->GetValueType() != LDF_TYPE_S32 || param->GetKey() != u"shot_done") return; if (param->GetValueType() != LDF_TYPE_S32) return;
const auto superChargeShotDone = static_cast<LDFData<int32_t>*>(param.get())->GetValue() == GetConstants().cannonSuperChargeSkill; const auto superChargeShotDone = static_cast<LDFData<int32_t>*>(param.get())->GetValue() == GetConstants().cannonSuperChargeSkill;

View File

@@ -6,13 +6,11 @@
void RockHydrantSmashable::OnDie(Entity* self, Entity* killer) { void RockHydrantSmashable::OnDie(Entity* self, Entity* killer) {
const auto hydrantName = self->GetVar<std::u16string>(u"hydrant"); const auto hydrantName = self->GetVar<std::u16string>(u"hydrant");
LDFBaseData* data = new LDFData<std::string>(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName));
EntityInfo info{}; EntityInfo info{};
info.lot = ROCK_HYDRANT_BROKEN; info.lot = ROCK_HYDRANT_BROKEN;
info.pos = self->GetPosition(); info.pos = self->GetPosition();
info.rot = self->GetRotation(); info.rot = self->GetRotation();
info.settings = { data }; info.settings.Insert<std::string>(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName));
info.spawnerID = self->GetSpawnerID(); info.spawnerID = self->GetSpawnerID();
auto* hydrant = Game::entityManager->CreateEntity(info); auto* hydrant = Game::entityManager->CreateEntity(info);

View File

@@ -6,13 +6,11 @@
void HydrantSmashable::OnDie(Entity* self, Entity* killer) { void HydrantSmashable::OnDie(Entity* self, Entity* killer) {
const auto hydrantName = self->GetVar<std::u16string>(u"hydrant"); const auto hydrantName = self->GetVar<std::u16string>(u"hydrant");
LDFBaseData* data = new LDFData<std::string>(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName));
EntityInfo info{}; EntityInfo info{};
info.lot = HYDRANT_BROKEN; info.lot = HYDRANT_BROKEN;
info.pos = self->GetPosition(); info.pos = self->GetPosition();
info.rot = self->GetRotation(); info.rot = self->GetRotation();
info.settings = { data }; info.settings.Insert<std::string>(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName));
info.spawnerID = self->GetSpawnerID(); info.spawnerID = self->GetSpawnerID();
auto* hydrant = Game::entityManager->CreateEntity(info); auto* hydrant = Game::entityManager->CreateEntity(info);

View File

@@ -10,46 +10,42 @@ void FvRaceServer::OnStartup(Entity* self) {
GameMessages::ConfigureRacingControl config; GameMessages::ConfigureRacingControl config;
auto& raceSet = config.racingSettings; auto& raceSet = config.racingSettings;
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"GameType", u"Racing")); raceSet.Insert<std::u16string>(u"GameType", u"Racing");
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"GameState", u"Starting")); raceSet.Insert<std::u16string>(u"GameState", u"Starting");
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_Of_PlayersPerTeam", 6)); raceSet.Insert<int32_t>(u"Number_Of_PlayersPerTeam", 6);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Minimum_Players_to_Start", 2)); raceSet.Insert<int32_t>(u"Minimum_Players_to_Start", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Minimum_Players_for_Group_Achievements", 2)); raceSet.Insert<int32_t>(u"Minimum_Players_for_Group_Achievements", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Car_Object", 7703)); raceSet.Insert<int32_t>(u"Car_Object", 7703);
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"Race_PathName", u"MainPath")); raceSet.Insert<std::u16string>(u"Race_PathName", u"MainPath");
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Current_Lap", 1)); raceSet.Insert<int32_t>(u"Current_Lap", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_of_Laps", 3)); raceSet.Insert<int32_t>(u"Number_of_Laps", 3);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"activityID", 54)); raceSet.Insert<int32_t>(u"activityID", 54);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_1", 100)); raceSet.Insert<int32_t>(u"Place_1", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_2", 90)); raceSet.Insert<int32_t>(u"Place_2", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_3", 80)); raceSet.Insert<int32_t>(u"Place_3", 80);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_4", 70)); raceSet.Insert<int32_t>(u"Place_4", 70);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_5", 60)); raceSet.Insert<int32_t>(u"Place_5", 60);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_6", 50)); raceSet.Insert<int32_t>(u"Place_6", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_1", 15)); raceSet.Insert<int32_t>(u"Num_of_Players_1", 15);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_2", 25)); raceSet.Insert<int32_t>(u"Num_of_Players_2", 25);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_3", 50)); raceSet.Insert<int32_t>(u"Num_of_Players_3", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_4", 85)); raceSet.Insert<int32_t>(u"Num_of_Players_4", 85);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_5", 90)); raceSet.Insert<int32_t>(u"Num_of_Players_5", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_6", 100)); raceSet.Insert<int32_t>(u"Num_of_Players_6", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_of_Spawn_Groups", 1)); raceSet.Insert<int32_t>(u"Number_of_Spawn_Groups", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Spawners", 4847)); raceSet.Insert<int32_t>(u"Red_Spawners", 4847);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Spawners", 4848)); raceSet.Insert<int32_t>(u"Blue_Spawners", 4848);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Flag", 4850)); raceSet.Insert<int32_t>(u"Blue_Flag", 4850);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Flag", 4851)); raceSet.Insert<int32_t>(u"Red_Flag", 4851);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Point", 4846)); raceSet.Insert<int32_t>(u"Red_Point", 4846);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Point", 4845)); raceSet.Insert<int32_t>(u"Blue_Point", 4845);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Mark", 4844)); raceSet.Insert<int32_t>(u"Red_Mark", 4844);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Mark", 4843)); raceSet.Insert<int32_t>(u"Blue_Mark", 4843);
const std::vector<Entity*> racingControllers = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::RACING_CONTROL); config.Send(self->GetObjectID());
for (auto* const racingController : racingControllers) {
auto* racingComponent = racingController->GetComponent<RacingControlComponent>();
if (racingComponent) racingComponent->MsgConfigureRacingControl(config);
}
} }

View File

@@ -10,46 +10,42 @@ void GfRaceServer::OnStartup(Entity* self) {
GameMessages::ConfigureRacingControl config; GameMessages::ConfigureRacingControl config;
auto& raceSet = config.racingSettings; auto& raceSet = config.racingSettings;
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"GameType", u"Racing")); raceSet.Insert<std::u16string>(u"GameType", u"Racing");
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"GameState", u"Starting")); raceSet.Insert<std::u16string>(u"GameState", u"Starting");
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_Of_PlayersPerTeam", 6)); raceSet.Insert<int32_t>(u"Number_Of_PlayersPerTeam", 6);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Minimum_Players_to_Start", 2)); raceSet.Insert<int32_t>(u"Minimum_Players_to_Start", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Minimum_Players_for_Group_Achievements", 2)); raceSet.Insert<int32_t>(u"Minimum_Players_for_Group_Achievements", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Car_Object", 7703)); raceSet.Insert<int32_t>(u"Car_Object", 7703);
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"Race_PathName", u"MainPath")); raceSet.Insert<std::u16string>(u"Race_PathName", u"MainPath");
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Current_Lap", 1)); raceSet.Insert<int32_t>(u"Current_Lap", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_of_Laps", 3)); raceSet.Insert<int32_t>(u"Number_of_Laps", 3);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"activityID", 39)); raceSet.Insert<int32_t>(u"activityID", 39);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_1", 100)); raceSet.Insert<int32_t>(u"Place_1", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_2", 90)); raceSet.Insert<int32_t>(u"Place_2", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_3", 80)); raceSet.Insert<int32_t>(u"Place_3", 80);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_4", 70)); raceSet.Insert<int32_t>(u"Place_4", 70);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_5", 60)); raceSet.Insert<int32_t>(u"Place_5", 60);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_6", 50)); raceSet.Insert<int32_t>(u"Place_6", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_1", 15)); raceSet.Insert<int32_t>(u"Num_of_Players_1", 15);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_2", 25)); raceSet.Insert<int32_t>(u"Num_of_Players_2", 25);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_3", 50)); raceSet.Insert<int32_t>(u"Num_of_Players_3", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_4", 85)); raceSet.Insert<int32_t>(u"Num_of_Players_4", 85);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_5", 90)); raceSet.Insert<int32_t>(u"Num_of_Players_5", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_6", 100)); raceSet.Insert<int32_t>(u"Num_of_Players_6", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_of_Spawn_Groups", 1)); raceSet.Insert<int32_t>(u"Number_of_Spawn_Groups", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Spawners", 4847)); raceSet.Insert<int32_t>(u"Red_Spawners", 4847);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Spawners", 4848)); raceSet.Insert<int32_t>(u"Blue_Spawners", 4848);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Flag", 4850)); raceSet.Insert<int32_t>(u"Blue_Flag", 4850);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Flag", 4851)); raceSet.Insert<int32_t>(u"Red_Flag", 4851);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Point", 4846)); raceSet.Insert<int32_t>(u"Red_Point", 4846);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Point", 4845)); raceSet.Insert<int32_t>(u"Blue_Point", 4845);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Mark", 4844)); raceSet.Insert<int32_t>(u"Red_Mark", 4844);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Mark", 4843)); raceSet.Insert<int32_t>(u"Blue_Mark", 4843);
const std::vector<Entity*> racingControllers = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::RACING_CONTROL); config.Send(self->GetObjectID());
for (auto* const racingController : racingControllers) {
auto* racingComponent = racingController->GetComponent<RacingControlComponent>();
if (racingComponent) racingComponent->MsgConfigureRacingControl(config);
}
} }

View File

@@ -10,45 +10,41 @@ void NsRaceServer::OnStartup(Entity* self) {
GameMessages::ConfigureRacingControl config; GameMessages::ConfigureRacingControl config;
auto& raceSet = config.racingSettings; auto& raceSet = config.racingSettings;
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"GameType", u"Racing")); raceSet.Insert<std::u16string>(u"GameType", u"Racing");
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"GameState", u"Starting")); raceSet.Insert<std::u16string>(u"GameState", u"Starting");
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_Of_PlayersPerTeam", 6)); raceSet.Insert<int32_t>(u"Number_Of_PlayersPerTeam", 6);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Minimum_Players_to_Start", 2)); raceSet.Insert<int32_t>(u"Minimum_Players_to_Start", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Minimum_Players_for_Group_Achievements", 2)); raceSet.Insert<int32_t>(u"Minimum_Players_for_Group_Achievements", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Car_Object", 7703)); raceSet.Insert<int32_t>(u"Car_Object", 7703);
raceSet.push_back(make_unique<LDFData<std::u16string>>(u"Race_PathName", u"MainPath")); raceSet.Insert<std::u16string>(u"Race_PathName", u"MainPath");
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Current_Lap", 1)); raceSet.Insert<int32_t>(u"Current_Lap", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_of_Laps", 3)); raceSet.Insert<int32_t>(u"Number_of_Laps", 3);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"activityID", 42)); raceSet.Insert<int32_t>(u"activityID", 42);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_1", 100)); raceSet.Insert<int32_t>(u"Place_1", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_2", 90)); raceSet.Insert<int32_t>(u"Place_2", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_3", 80)); raceSet.Insert<int32_t>(u"Place_3", 80);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_4", 70)); raceSet.Insert<int32_t>(u"Place_4", 70);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_5", 60)); raceSet.Insert<int32_t>(u"Place_5", 60);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Place_6", 50)); raceSet.Insert<int32_t>(u"Place_6", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_1", 15)); raceSet.Insert<int32_t>(u"Num_of_Players_1", 15);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_2", 25)); raceSet.Insert<int32_t>(u"Num_of_Players_2", 25);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_3", 50)); raceSet.Insert<int32_t>(u"Num_of_Players_3", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_4", 85)); raceSet.Insert<int32_t>(u"Num_of_Players_4", 85);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_5", 90)); raceSet.Insert<int32_t>(u"Num_of_Players_5", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Num_of_Players_6", 100)); raceSet.Insert<int32_t>(u"Num_of_Players_6", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Number_of_Spawn_Groups", 1)); raceSet.Insert<int32_t>(u"Number_of_Spawn_Groups", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Spawners", 4847)); raceSet.Insert<int32_t>(u"Red_Spawners", 4847);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Spawners", 4848)); raceSet.Insert<int32_t>(u"Blue_Spawners", 4848);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Flag", 4850)); raceSet.Insert<int32_t>(u"Blue_Flag", 4850);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Flag", 4851)); raceSet.Insert<int32_t>(u"Red_Flag", 4851);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Point", 4846)); raceSet.Insert<int32_t>(u"Red_Point", 4846);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Point", 4845)); raceSet.Insert<int32_t>(u"Blue_Point", 4845);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Red_Mark", 4844)); raceSet.Insert<int32_t>(u"Red_Mark", 4844);
raceSet.push_back(make_unique<LDFData<int32_t>>(u"Blue_Mark", 4843)); raceSet.Insert<int32_t>(u"Blue_Mark", 4843);
std::vector<Entity*> racingControllers = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::RACING_CONTROL); config.Send(self->GetObjectID());
for (auto* const racingController : racingControllers) {
auto* racingComponent = racingController->GetComponent<RacingControlComponent>();
if (racingComponent) racingComponent->MsgConfigureRacingControl(config);
}
} }

View File

@@ -9,45 +9,41 @@ void NsWinterRaceServer::OnStartup(Entity* self) {
GameMessages::ConfigureRacingControl config; GameMessages::ConfigureRacingControl config;
auto& raceSet = config.racingSettings; auto& raceSet = config.racingSettings;
raceSet.push_back(make_unique<LDFData<std::u16string>>("GameType", u"Racing")); raceSet.Insert<std::u16string>("GameType", u"Racing");
raceSet.push_back(make_unique<LDFData<std::u16string>>("GameState", u"Starting")); raceSet.Insert<std::u16string>("GameState", u"Starting");
raceSet.push_back(make_unique<LDFData<int32_t>>("Number_Of_PlayersPerTeam", 6)); raceSet.Insert<int32_t>("Number_Of_PlayersPerTeam", 6);
raceSet.push_back(make_unique<LDFData<int32_t>>("Minimum_Players_to_Start", 2)); raceSet.Insert<int32_t>("Minimum_Players_to_Start", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>("Minimum_Players_for_Group_Achievments", 2)); raceSet.Insert<int32_t>("Minimum_Players_for_Group_Achievments", 2);
raceSet.push_back(make_unique<LDFData<int32_t>>("Car_Object", 7703)); raceSet.Insert<int32_t>("Car_Object", 7703);
raceSet.push_back(make_unique<LDFData<std::u16string>>("Race_PathName", u"MainPath")); raceSet.Insert<std::u16string>("Race_PathName", u"MainPath");
raceSet.push_back(make_unique<LDFData<int32_t>>("Current_Lap", 1)); raceSet.Insert<int32_t>("Current_Lap", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>("Number_of_Laps", 3)); raceSet.Insert<int32_t>("Number_of_Laps", 3);
raceSet.push_back(make_unique<LDFData<int32_t>>("activityID", 60)); raceSet.Insert<int32_t>("activityID", 60);
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_1", 100)); raceSet.Insert<int32_t>("Place_1", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_2", 90)); raceSet.Insert<int32_t>("Place_2", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_3", 80)); raceSet.Insert<int32_t>("Place_3", 80);
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_4", 70)); raceSet.Insert<int32_t>("Place_4", 70);
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_5", 60)); raceSet.Insert<int32_t>("Place_5", 60);
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_6", 50)); raceSet.Insert<int32_t>("Place_6", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_1", 15)); raceSet.Insert<int32_t>("Num_of_Players_1", 15);
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_2", 25)); raceSet.Insert<int32_t>("Num_of_Players_2", 25);
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_3", 50)); raceSet.Insert<int32_t>("Num_of_Players_3", 50);
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_4", 85)); raceSet.Insert<int32_t>("Num_of_Players_4", 85);
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_5", 90)); raceSet.Insert<int32_t>("Num_of_Players_5", 90);
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_6", 100)); raceSet.Insert<int32_t>("Num_of_Players_6", 100);
raceSet.push_back(make_unique<LDFData<int32_t>>("Number_of_Spawn_Groups", 1)); raceSet.Insert<int32_t>("Number_of_Spawn_Groups", 1);
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Spawners", 4847)); raceSet.Insert<int32_t>("Red_Spawners", 4847);
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Spawners", 4848)); raceSet.Insert<int32_t>("Blue_Spawners", 4848);
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Flag", 4850)); raceSet.Insert<int32_t>("Blue_Flag", 4850);
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Flag", 4851)); raceSet.Insert<int32_t>("Red_Flag", 4851);
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Point", 4846)); raceSet.Insert<int32_t>("Red_Point", 4846);
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Point", 4845)); raceSet.Insert<int32_t>("Blue_Point", 4845);
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Mark", 4844)); raceSet.Insert<int32_t>("Red_Mark", 4844);
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Mark", 4843)); raceSet.Insert<int32_t>("Blue_Mark", 4843);
const auto racingControllers = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::RACING_CONTROL); config.Send(self->GetObjectID());
for (auto* const racingController : racingControllers) {
auto* const racingComponent = racingController->GetComponent<RacingControlComponent>();
if (racingComponent) racingComponent->MsgConfigureRacingControl(config);
}
} }

View File

@@ -16,6 +16,7 @@
#include "AssetManager.h" #include "AssetManager.h"
#include "ClientVersion.h" #include "ClientVersion.h"
#include "dConfig.h" #include "dConfig.h"
#include <ranges>
Level::Level(Zone* parentZone, const std::string& filepath) { Level::Level(Zone* parentZone, const std::string& filepath) {
m_ParentZone = parentZone; m_ParentZone = parentZone;
@@ -30,7 +31,7 @@ Level::Level(Zone* parentZone, const std::string& filepath) {
ReadChunks(stream); ReadChunks(stream);
} }
void Level::MakeSpawner(SceneObject obj) { void Level::MakeSpawner(const SceneObject& obj) {
SpawnerInfo spawnInfo = SpawnerInfo(); SpawnerInfo spawnInfo = SpawnerInfo();
SpawnerNode* node = new SpawnerNode(); SpawnerNode* node = new SpawnerNode();
spawnInfo.templateID = obj.lot; spawnInfo.templateID = obj.lot;
@@ -40,7 +41,7 @@ void Level::MakeSpawner(SceneObject obj) {
node->rotation = obj.rotation; node->rotation = obj.rotation;
node->config = obj.settings; node->config = obj.settings;
spawnInfo.nodes.push_back(node); spawnInfo.nodes.push_back(node);
for (LDFBaseData* data : obj.settings) { for (const auto& data : obj.settings.values | std::views::values) {
if (!data) continue; if (!data) continue;
if (data->GetKey() == u"spawntemplate") { if (data->GetKey() == u"spawntemplate") {
spawnInfo.templateID = GeneralUtils::TryParse(data->GetValueAsString(), 0); spawnInfo.templateID = GeneralUtils::TryParse(data->GetValueAsString(), 0);
@@ -70,7 +71,7 @@ void Level::MakeSpawner(SceneObject obj) {
if (data->GetValueType() == eLDFType::LDF_TYPE_FLOAT) // Floats are in seconds if (data->GetValueType() == eLDFType::LDF_TYPE_FLOAT) // Floats are in seconds
{ {
spawnInfo.respawnTime = GeneralUtils::TryParse(data->GetValueAsString(), 0.0f); spawnInfo.respawnTime = GeneralUtils::TryParse(data->GetValueAsString(), 0.0f);
} else if (data->GetValueType() == eLDFType::LDF_TYPE_U32) // Ints are in ms? } else if (data->GetValueType() == eLDFType::LDF_TYPE_U32) // Ints are in ms
{ {
spawnInfo.respawnTime = GeneralUtils::TryParse(data->GetValueAsString(), 0) / 1000; spawnInfo.respawnTime = GeneralUtils::TryParse(data->GetValueAsString(), 0) / 1000;
} }
@@ -86,13 +87,13 @@ void Level::MakeSpawner(SceneObject obj) {
if (spawnInfo.groups.back().empty()) spawnInfo.groups.erase(spawnInfo.groups.end() - 1); if (spawnInfo.groups.back().empty()) spawnInfo.groups.erase(spawnInfo.groups.end() - 1);
} }
if (data->GetKey() == u"no_auto_spawn") { if (data->GetKey() == u"no_auto_spawn") {
spawnInfo.noAutoSpawn = static_cast<LDFData<bool>*>(data)->GetValue(); spawnInfo.noAutoSpawn = GeneralUtils::TryParse(data->GetValueAsString(), false);
} }
if (data->GetKey() == u"no_timed_spawn") { if (data->GetKey() == u"no_timed_spawn") {
spawnInfo.noTimedSpawn = static_cast<LDFData<bool>*>(data)->GetValue(); spawnInfo.noTimedSpawn = GeneralUtils::TryParse(data->GetValueAsString(), false);
} }
if (data->GetKey() == u"spawnActivator") { if (data->GetKey() == u"spawnActivator") {
spawnInfo.spawnActivator = static_cast<LDFData<bool>*>(data)->GetValue(); spawnInfo.spawnActivator = GeneralUtils::TryParse(data->GetValueAsString(), false);
} }
} }
@@ -257,20 +258,14 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
Game::zoneManager->GetZoneMut()->SetSpawnRot(obj.rotation); Game::zoneManager->GetZoneMut()->SetSpawnRot(obj.rotation);
} }
std::string sData = GeneralUtils::UTF16ToWTF8(ldfString); for (const auto& token : GeneralUtils::SplitString(GeneralUtils::UTF16ToWTF8(ldfString), '\n')) {
std::stringstream ssData(sData); obj.settings.ParseInsert(token);
std::string token;
char deliminator = '\n';
while (std::getline(ssData, token, deliminator)) {
LDFBaseData* ldfData = LDFBaseData::DataFromString(token);
obj.settings.push_back(ldfData);
} }
// We should never have more than 1 zone control object // We should never have more than 1 zone control object
bool skipLoadingObject = obj.lot == zoneControlObject->GetLOT(); bool skipLoadingObject = obj.lot == zoneControlObject->GetLOT();
for (LDFBaseData* data : obj.settings) { for (const auto& data : obj.settings | std::views::values) {
if (!data) continue; if (!data) continue;
if (data->GetKey() == u"gatingOnFeature") { if (data->GetKey() == u"gatingOnFeature") {
gating.featureName = data->GetValueAsString(); gating.featureName = data->GetValueAsString();
@@ -296,11 +291,6 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
} }
if (skipLoadingObject) { if (skipLoadingObject) {
for (auto* setting : obj.settings) {
delete setting;
setting = nullptr;
}
continue; continue;
} }

View File

@@ -40,7 +40,7 @@ public:
public: public:
Level(Zone* parentZone, const std::string& filepath); Level(Zone* parentZone, const std::string& filepath);
static void MakeSpawner(SceneObject obj); static void MakeSpawner(const SceneObject& obj);
std::map<uint32_t, Header> m_ChunkHeaders; std::map<uint32_t, Header> m_ChunkHeaders;
private: private:

View File

@@ -17,7 +17,7 @@ struct SpawnerNode {
uint32_t nodeID = 0; uint32_t nodeID = 0;
uint32_t nodeMax = 1; uint32_t nodeMax = 1;
std::vector<LWOOBJID> entities; std::vector<LWOOBJID> entities;
std::vector<LDFBaseData*> config; LwoNameValue config;
}; };
struct SpawnerInfo { struct SpawnerInfo {

View File

@@ -111,7 +111,7 @@ void Zone::LoadZoneIntoMemory() {
node->nodeID = 0; node->nodeID = 0;
node->config = waypoint.config; node->config = waypoint.config;
for (LDFBaseData* data : waypoint.config) { for (const auto& data : waypoint.config | std::views::values) {
if (!data) continue; if (!data) continue;
if (data->GetKey() == u"spawner_node_id") { if (data->GetKey() == u"spawner_node_id") {
@@ -465,7 +465,7 @@ void Zone::LoadPath(std::istream& file) {
command.data = value; command.data = value;
} else LOG("Tried to load invalid waypoint command '%s'", parameter.c_str()); } else LOG("Tried to load invalid waypoint command '%s'", parameter.c_str());
} else { } else {
waypoint.config.emplace_back(LDFBaseData::DataFromString(parameter + "=" + value)); waypoint.config.ParseInsert(parameter + "=" + value);
} }
} }

View File

@@ -76,7 +76,7 @@ struct PathWaypoint {
CameraPathWaypoint camera; CameraPathWaypoint camera;
RacingPathWaypoint racing; RacingPathWaypoint racing;
float speed{}; float speed{};
std::vector<LDFBaseData*> config; LwoNameValue config;
std::vector<WaypointCommand> commands; std::vector<WaypointCommand> commands;
}; };

View File

@@ -13,9 +13,8 @@ struct SceneObject {
NiPoint3 position; NiPoint3 position;
NiQuaternion rotation = QuatUtils::IDENTITY; NiQuaternion rotation = QuatUtils::IDENTITY;
float scale = 1.0f; float scale = 1.0f;
//std::string settings;
uint32_t value3; uint32_t value3;
std::vector<LDFBaseData*> settings; LwoNameValue settings;
}; };
#define LOT_MARKER_PLAYER_START 1931 #define LOT_MARKER_PLAYER_START 1931

View File

@@ -70,7 +70,7 @@ endif()
FetchContent_Declare( FetchContent_Declare(
glm glm
GIT_REPOSITORY https://github.com/g-truc/glm.git GIT_REPOSITORY https://github.com/g-truc/glm.git
GIT_TAG bf71a834948186f4097caa076cd2663c69a10e1e #refs/tags/1.0.1 GIT_TAG 8d1fd52e5ab5590e2c81768ace50c72bae28f2ed #refs/tags/1.0.3
GIT_PROGRESS TRUE GIT_PROGRESS TRUE
GIT_SHALLOW 1 GIT_SHALLOW 1
) )