mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-23 15:14:20 +00:00
feat: add eSceneType enum, filter scene graph to general scenes, zone parsing improvements
- Add eSceneType enum (General, Audio) replacing raw uint32_t in SceneRef - Filter BuildSceneGraph to only include General scenes - Skip transitions referencing non-general scenes in adjacency graph - Rename SceneRef unknown fields to scenePosition/sceneRadius - Zone parsing and Level improvements Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -107,7 +107,7 @@ void Level::ReadChunks(std::istream& file) {
|
||||
uint32_t initPos = uint32_t(file.tellg());
|
||||
uint32_t header = 0;
|
||||
BinaryIO::BinaryRead(file, header);
|
||||
if (header == CHNK_HEADER) { //Make sure we're reading a valid CHNK
|
||||
if (header == CHNK_HEADER) {
|
||||
Header header;
|
||||
BinaryIO::BinaryRead(file, header.id);
|
||||
BinaryIO::BinaryRead(file, header.chunkVersion);
|
||||
@@ -118,83 +118,39 @@ void Level::ReadChunks(std::istream& file) {
|
||||
uint32_t target = initPos + header.size;
|
||||
file.seekg(header.startPosition);
|
||||
|
||||
//We're currently not loading env or particle data
|
||||
if (header.id == ChunkTypeID::FileInfo) {
|
||||
ReadFileInfoChunk(file, header);
|
||||
} else if (header.id == ChunkTypeID::SceneEnviroment) {
|
||||
ReadEnvironmentChunk(file, header);
|
||||
} else if (header.id == ChunkTypeID::SceneObjectData) {
|
||||
ReadSceneObjectDataChunk(file, header);
|
||||
} else if (header.id == ChunkTypeID::SceneParticleData) {
|
||||
ReadParticleChunk(file, header);
|
||||
}
|
||||
|
||||
m_ChunkHeaders.insert(std::make_pair(header.id, header));
|
||||
file.seekg(target);
|
||||
} else {
|
||||
if (initPos == std::streamoff(0)) { //Really old chunk version
|
||||
if (initPos == std::streamoff(0)) {
|
||||
// Old LVL format without CHNK headers — environment + objects inline
|
||||
file.seekg(0);
|
||||
Header header;
|
||||
header.id = ChunkTypeID::FileInfo;
|
||||
BinaryIO::BinaryRead(file, header.chunkVersion);
|
||||
BinaryIO::BinaryRead(file, header.chunkType);
|
||||
uint8_t important = 0;
|
||||
BinaryIO::BinaryRead(file, important);
|
||||
// file.ignore(1); //probably used
|
||||
uint8_t hasEditorData = 0;
|
||||
BinaryIO::BinaryRead(file, hasEditorData);
|
||||
if (header.chunkVersion > 36) {
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.revision);
|
||||
}
|
||||
// HARDCODED 3
|
||||
if (header.chunkVersion >= 45) file.ignore(4);
|
||||
file.ignore(4 * (4 * 3));
|
||||
|
||||
if (header.chunkVersion >= 31) {
|
||||
if (header.chunkVersion >= 39) {
|
||||
file.ignore(12 * 4);
|
||||
|
||||
if (header.chunkVersion >= 40) {
|
||||
uint32_t s = 0;
|
||||
BinaryIO::BinaryRead(file, s);
|
||||
for (uint32_t i = 0; i < s; ++i) {
|
||||
file.ignore(4 * 3); //a uint and two floats
|
||||
}
|
||||
}
|
||||
} else {
|
||||
file.ignore(8);
|
||||
}
|
||||
|
||||
file.ignore(3 * 4);
|
||||
}
|
||||
|
||||
if (header.chunkVersion >= 36) {
|
||||
file.ignore(3 * 4);
|
||||
}
|
||||
|
||||
if (header.chunkVersion < 42) {
|
||||
file.ignore(3 * 4);
|
||||
|
||||
if (header.chunkVersion >= 33) {
|
||||
file.ignore(4 * 4);
|
||||
}
|
||||
}
|
||||
|
||||
// skydome info
|
||||
uint32_t count = 0;
|
||||
BinaryIO::BinaryRead(file, count);
|
||||
file.ignore(count);
|
||||
|
||||
if (header.chunkVersion >= 33) {
|
||||
for (uint32_t i = 0; i < 5; ++i) {
|
||||
uint32_t count = 0;
|
||||
BinaryIO::BinaryRead(file, count);
|
||||
file.ignore(count);
|
||||
}
|
||||
}
|
||||
// editor settings
|
||||
if (!important && header.chunkVersion >= 37){
|
||||
file.ignore(4);
|
||||
|
||||
uint32_t count = 0;
|
||||
BinaryIO::BinaryRead(file, count);
|
||||
file.ignore(count * 12);
|
||||
|
||||
// Read environment data inline (no absolute offsets in old format)
|
||||
ReadLighting(file, header.chunkVersion);
|
||||
ReadSkydome(file, header.chunkVersion);
|
||||
if (!hasEditorData && header.chunkVersion >= 37) {
|
||||
ReadEditor(file);
|
||||
}
|
||||
m_HasEnvironment = true;
|
||||
|
||||
header.id = ChunkTypeID::SceneObjectData;
|
||||
header.fileInfo.version = header.chunkVersion;
|
||||
@@ -213,6 +169,157 @@ void Level::ReadFileInfoChunk(std::istream& file, Header& header) {
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.particleChunkStart);
|
||||
}
|
||||
|
||||
void Level::ReadLighting(std::istream& file, uint32_t version) {
|
||||
auto& li = m_Environment.lighting;
|
||||
if (version >= 45) BinaryIO::BinaryRead(file, li.blendTime);
|
||||
for (float& f : li.ambient) BinaryIO::BinaryRead(file, f);
|
||||
for (float& f : li.specular) BinaryIO::BinaryRead(file, f);
|
||||
for (float& f : li.upperHemi) BinaryIO::BinaryRead(file, f);
|
||||
BinaryIO::BinaryRead(file, li.position);
|
||||
|
||||
if (version >= 39) {
|
||||
li.hasDrawDistances = true;
|
||||
auto readDD = [&](LvlDrawDistances& dd) {
|
||||
BinaryIO::BinaryRead(file, dd.fogNear);
|
||||
BinaryIO::BinaryRead(file, dd.fogFar);
|
||||
BinaryIO::BinaryRead(file, dd.postFogSolid);
|
||||
BinaryIO::BinaryRead(file, dd.postFogFade);
|
||||
BinaryIO::BinaryRead(file, dd.staticObjDistance);
|
||||
BinaryIO::BinaryRead(file, dd.dynamicObjDistance);
|
||||
};
|
||||
readDD(li.minDraw);
|
||||
readDD(li.maxDraw);
|
||||
}
|
||||
if (version >= 40) {
|
||||
uint32_t numCull = 0;
|
||||
BinaryIO::BinaryRead(file, numCull);
|
||||
li.cullVals.reserve(numCull);
|
||||
for (uint32_t i = 0; i < numCull; ++i) {
|
||||
LvlCullVal cv;
|
||||
BinaryIO::BinaryRead(file, cv.groupID);
|
||||
BinaryIO::BinaryRead(file, cv.min);
|
||||
BinaryIO::BinaryRead(file, cv.max);
|
||||
li.cullVals.push_back(cv);
|
||||
}
|
||||
}
|
||||
if (version >= 31 && version < 39) {
|
||||
BinaryIO::BinaryRead(file, li.fogNear);
|
||||
BinaryIO::BinaryRead(file, li.fogFar);
|
||||
}
|
||||
if (version >= 31) {
|
||||
for (float& f : li.fogColor) BinaryIO::BinaryRead(file, f);
|
||||
}
|
||||
if (version >= 36) {
|
||||
for (float& f : li.dirLight) BinaryIO::BinaryRead(file, f);
|
||||
}
|
||||
if (version < 42) {
|
||||
li.hasSpawn = true;
|
||||
BinaryIO::BinaryRead(file, li.startPosition);
|
||||
if (version >= 33) {
|
||||
BinaryIO::BinaryRead(file, li.startRotation.w);
|
||||
BinaryIO::BinaryRead(file, li.startRotation.x);
|
||||
BinaryIO::BinaryRead(file, li.startRotation.y);
|
||||
BinaryIO::BinaryRead(file, li.startRotation.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Level::ReadSkydome(std::istream& file, uint32_t version) {
|
||||
auto& si = m_Environment.skydome;
|
||||
BinaryIO::ReadString<uint32_t>(file, si.filename, BinaryIO::ReadType::String);
|
||||
if (version >= 34) {
|
||||
BinaryIO::ReadString<uint32_t>(file, si.skyLayerFilename, BinaryIO::ReadType::String);
|
||||
for (auto& rl : si.ringLayer) {
|
||||
BinaryIO::ReadString<uint32_t>(file, rl, BinaryIO::ReadType::String);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Level::ReadEditor(std::istream& file) {
|
||||
auto& ed = m_Environment.editor;
|
||||
uint32_t blockSize = 0;
|
||||
BinaryIO::BinaryRead(file, blockSize);
|
||||
uint32_t numColors = 0;
|
||||
BinaryIO::BinaryRead(file, numColors);
|
||||
ed.savedColors.reserve(numColors);
|
||||
for (uint32_t i = 0; i < numColors; ++i) {
|
||||
LvlEditorColor c;
|
||||
BinaryIO::BinaryRead(file, c.r);
|
||||
BinaryIO::BinaryRead(file, c.g);
|
||||
BinaryIO::BinaryRead(file, c.b);
|
||||
ed.savedColors.push_back(c);
|
||||
}
|
||||
m_Environment.hasEditor = true;
|
||||
}
|
||||
|
||||
void Level::ReadEnvironmentChunk(std::istream& file, Header& header) {
|
||||
uint32_t version = 0;
|
||||
// Find the version from the fib chunk if we've already read it
|
||||
auto fibIt = m_ChunkHeaders.find(ChunkTypeID::FileInfo);
|
||||
if (fibIt != m_ChunkHeaders.end()) {
|
||||
version = fibIt->second.fileInfo.version;
|
||||
}
|
||||
|
||||
// Environment chunk payload: 3 absolute u32 offsets
|
||||
uint32_t ofsLighting, ofsSkydome, ofsEditor;
|
||||
BinaryIO::BinaryRead(file, ofsLighting);
|
||||
BinaryIO::BinaryRead(file, ofsSkydome);
|
||||
BinaryIO::BinaryRead(file, ofsEditor);
|
||||
|
||||
if (ofsLighting > 0) {
|
||||
file.seekg(ofsLighting);
|
||||
ReadLighting(file, version);
|
||||
}
|
||||
if (ofsSkydome > 0) {
|
||||
file.seekg(ofsSkydome);
|
||||
ReadSkydome(file, version);
|
||||
}
|
||||
if (version >= 37 && ofsEditor > 0) {
|
||||
file.seekg(ofsEditor);
|
||||
ReadEditor(file);
|
||||
}
|
||||
m_HasEnvironment = true;
|
||||
}
|
||||
|
||||
void Level::ReadParticleChunk(std::istream& file, Header& header) {
|
||||
uint32_t version = 0;
|
||||
auto fibIt = m_ChunkHeaders.find(ChunkTypeID::FileInfo);
|
||||
if (fibIt != m_ChunkHeaders.end()) {
|
||||
version = fibIt->second.fileInfo.version;
|
||||
}
|
||||
|
||||
uint32_t count = 0;
|
||||
BinaryIO::BinaryRead(file, count);
|
||||
m_Particles.reserve(count);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
LvlParticle p;
|
||||
if (version >= 43) BinaryIO::BinaryRead(file, p.priority);
|
||||
BinaryIO::BinaryRead(file, p.position);
|
||||
BinaryIO::BinaryRead(file, p.rotation.w);
|
||||
BinaryIO::BinaryRead(file, p.rotation.x);
|
||||
BinaryIO::BinaryRead(file, p.rotation.y);
|
||||
BinaryIO::BinaryRead(file, p.rotation.z);
|
||||
|
||||
// effect_names: u4_wstr
|
||||
BinaryIO::ReadString<uint32_t>(file, p.effectNames, BinaryIO::ReadType::WideString);
|
||||
|
||||
// null terminator (version < 46)
|
||||
if (version < 46) {
|
||||
uint16_t null_term;
|
||||
BinaryIO::BinaryRead(file, null_term);
|
||||
}
|
||||
|
||||
// config: u4_wstr parsed as LDF
|
||||
std::string configStr;
|
||||
BinaryIO::ReadString<uint32_t>(file, configStr, BinaryIO::ReadType::WideString);
|
||||
for (const auto& token : GeneralUtils::SplitString(configStr, '\n')) {
|
||||
p.config.ParseInsert(token);
|
||||
}
|
||||
|
||||
m_Particles.push_back(std::move(p));
|
||||
}
|
||||
}
|
||||
|
||||
void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
||||
uint32_t objectsCount = 0;
|
||||
BinaryIO::BinaryRead(file, objectsCount);
|
||||
@@ -236,9 +343,9 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
||||
BinaryIO::BinaryRead(file, obj.lot);
|
||||
|
||||
if (header.fileInfo.version >= 38) {
|
||||
int32_t tmp = 1;
|
||||
BinaryIO::BinaryRead(file, tmp);
|
||||
if (tmp > -1 && tmp < 11) obj.nodeType = tmp;
|
||||
uint32_t nodeType;
|
||||
BinaryIO::BinaryRead(file, nodeType);
|
||||
obj.nodeType = (nodeType <= 15) ? nodeType : 1;
|
||||
}
|
||||
|
||||
if (header.fileInfo.version >= 32) {
|
||||
@@ -249,7 +356,29 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
||||
BinaryIO::BinaryRead(file, obj.rotation);
|
||||
BinaryIO::BinaryRead(file, obj.scale);
|
||||
BinaryIO::ReadString<uint32_t>(file, ldfString);
|
||||
BinaryIO::BinaryRead(file, obj.value3);
|
||||
|
||||
if (header.fileInfo.version >= 7) {
|
||||
uint32_t numRenderAttrs = 0;
|
||||
BinaryIO::BinaryRead(file, numRenderAttrs);
|
||||
if (numRenderAttrs > 0) {
|
||||
char nameBuf[64]{};
|
||||
file.read(nameBuf, 64);
|
||||
obj.renderTechnique.name.assign(nameBuf, strnlen(nameBuf, 64));
|
||||
|
||||
obj.renderTechnique.attrs.resize(numRenderAttrs);
|
||||
for (uint32_t a = 0; a < numRenderAttrs; ++a) {
|
||||
auto& attr = obj.renderTechnique.attrs[a];
|
||||
char attrName[64]{};
|
||||
file.read(attrName, 64);
|
||||
attr.name.assign(attrName, strnlen(attrName, 64));
|
||||
BinaryIO::BinaryRead(file, attr.numFloats);
|
||||
uint8_t isColor = 0;
|
||||
BinaryIO::BinaryRead(file, isColor);
|
||||
attr.isColor = isColor != 0;
|
||||
for (float& f : attr.values) BinaryIO::BinaryRead(file, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This is a little bit of a bodge, but because the alpha client (HF) doesn't store the
|
||||
//spawn position / rotation like the later versions do, we need to check the LOT for the spawn pos & set it.
|
||||
|
||||
Reference in New Issue
Block a user