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

@@ -16,6 +16,7 @@
#include "AssetManager.h"
#include "ClientVersion.h"
#include "dConfig.h"
#include <ranges>
Level::Level(Zone* parentZone, const std::string& filepath) {
m_ParentZone = parentZone;
@@ -30,7 +31,7 @@ Level::Level(Zone* parentZone, const std::string& filepath) {
ReadChunks(stream);
}
void Level::MakeSpawner(SceneObject obj) {
void Level::MakeSpawner(const SceneObject& obj) {
SpawnerInfo spawnInfo = SpawnerInfo();
SpawnerNode* node = new SpawnerNode();
spawnInfo.templateID = obj.lot;
@@ -40,7 +41,7 @@ void Level::MakeSpawner(SceneObject obj) {
node->rotation = obj.rotation;
node->config = obj.settings;
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->GetKey() == u"spawntemplate") {
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
{
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;
}
@@ -86,13 +87,13 @@ void Level::MakeSpawner(SceneObject obj) {
if (spawnInfo.groups.back().empty()) spawnInfo.groups.erase(spawnInfo.groups.end() - 1);
}
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") {
spawnInfo.noTimedSpawn = static_cast<LDFData<bool>*>(data)->GetValue();
spawnInfo.noTimedSpawn = GeneralUtils::TryParse(data->GetValueAsString(), false);
}
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);
}
std::string sData = GeneralUtils::UTF16ToWTF8(ldfString);
std::stringstream ssData(sData);
std::string token;
char deliminator = '\n';
while (std::getline(ssData, token, deliminator)) {
LDFBaseData* ldfData = LDFBaseData::DataFromString(token);
obj.settings.push_back(ldfData);
for (const auto& token : GeneralUtils::SplitString(GeneralUtils::UTF16ToWTF8(ldfString), '\n')) {
obj.settings.ParseInsert(token);
}
// We should never have more than 1 zone control object
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->GetKey() == u"gatingOnFeature") {
gating.featureName = data->GetValueAsString();
@@ -296,11 +291,6 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
}
if (skipLoadingObject) {
for (auto* setting : obj.settings) {
delete setting;
setting = nullptr;
}
continue;
}

View File

@@ -40,7 +40,7 @@ public:
public:
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;
private:

View File

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

View File

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

View File

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

View File

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