fix(level): split a scene object's config as the client does

LDF_FROM_STRING (1.10.64, 0x010fa220) splits an object's config at
every comma and line break, leaves out empty entries and entries with
no '=', and sets each key=value it finds. The reader split at line
breaks only and parsed every piece, so an object with no config got an
empty entry of unknown type, and a value with a comma would have stayed
whole.

Live scene files are unchanged; objects in older client files with an
empty config no longer get the empty entry.

Check in game: every world spawns its objects as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 07:44:06 -05:00
parent 272fafc886
commit f73f4da0e4
2 changed files with 31 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
#include "LevelFile.h"
#include <algorithm>
#include <istream>
#include <stdexcept>
@@ -198,8 +199,15 @@ void LevelFile::ReadSceneObjectDataChunk(std::istream& file, uint32_t version) {
}
if (file.fail()) throw std::runtime_error("Failed to read from istream.");
for (const auto& token : GeneralUtils::SplitString(GeneralUtils::UTF16ToWTF8(ldfString), '\n')) {
obj.settings.ParseInsert(token);
// LDF_FROM_STRING (0x010fa220): entries are split at every comma and line break, empty ones and ones without a
// '=' are left out
const auto config = GeneralUtils::UTF16ToWTF8(ldfString);
size_t start = 0;
while (start <= config.size()) {
const auto end = std::min(config.find_first_of(",\n", start), config.size());
const auto entry = config.substr(start, end - start);
if (entry.find('=') != std::string::npos) obj.settings.ParseInsert(entry);
start = end + 1;
}
ApplyClientConfigFixups(obj, version);