Repository navigation
feat: Raw reading on zone load and scene tools - #1910
aronwk-aaron wants to merge 11 commits into
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR implements raw terrain file reading on zone load to enable scene identification from player positions. Key changes include parsing .raw terrain files, building a scene adjacency graph from scene transitions, and adding developer commands for scene debugging and visualization.
- Adds comprehensive RAW terrain file parsing with scene map support
- Implements scene ID lookup from world positions and scene adjacency graph construction
- Adds developer commands for scene debugging and visualization with OBJ export capability
Reviewed Changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| resources/worldconfig.ini | Adds config option to export terrain meshes to OBJ files for debugging |
| dZoneManager/dZoneManager.h | Declares scene position lookup, adjacency list access, and scene graph building methods |
| dZoneManager/dZoneManager.cpp | Implements scene position queries, scene graph construction from transitions, and global scene connectivity |
| dZoneManager/Zone.h | Adds Raw terrain data storage and scene lookup methods |
| dZoneManager/Zone.cpp | Implements zone file version checking, Raw file loading, and optional OBJ export |
| dZoneManager/Raw.h | Defines complete terrain chunk structures, scene vertex data, and mesh generation/export functions |
| dZoneManager/Raw.cpp | Implements RAW file parsing, terrain mesh generation with scene IDs, and OBJ export with scene colors |
| dZoneManager/CMakeLists.txt | Adds Raw.cpp to build and includes SceneColor.h path |
| dNavigation/dTerrain/* | Removes old unused terrain parsing code |
| dNavigation/dNavMesh.cpp | Removes unused RawFile.h include |
| dNavigation/CMakeLists.txt | Removes dTerrain subdirectory from build |
| dGame/dUtilities/SlashCommands/DEVGMCommands.h | Declares four new scene debugging commands |
| dGame/dUtilities/SlashCommands/DEVGMCommands.cpp | Implements GetScene, GetAdjacentScenes, SpawnScenePoints, and SpawnAllScenePoints commands |
| dGame/dUtilities/SlashCommandHandler.cpp | Registers the four new scene debugging commands |
| dCommon/dClient/SceneColor.h | Defines color palette for visualizing scene IDs in OBJ exports |
| dCommon/NiColor.h | Adds RGB color structure with grayscale conversion |
Comments suppressed due to low confidence (1)
dZoneManager/Raw.cpp:1
- Potential division by zero in GetSceneIDFromPosition if chunk dimensions are 1. Similar to the issue in GenerateTerrainMesh, if chunk.width or chunk.height equals 1, this will cause division by zero. Add validation before these calculations.
#include "Raw.h"
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (1)
dZoneManager/dZoneManager.cpp:18
- This file uses
std::clamp,std::min, andstd::findbut doesn’t include<algorithm>directly. Relying on transitive includes can break builds when include order changes; add the proper standard header and drop unused<cmath>if it’s no longer needed.
#include "WorldConfig.h"
#include "CDZoneTableTable.h"
#include <chrono>
#include <cmath>
#include "eObjectBits.h"
#include "CDZoneTableTable.h"
#include "AssetManager.h"
#include <ranges>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.
Comments suppressed due to low confidence (1)
dZoneManager/dZoneManager.cpp:18
- This file now uses std::clamp/std::min/std::find and std::set, but the includes only add . Please add the required standard headers (at least for clamp/min/find and for std::set) to avoid relying on transitive includes and potential build breaks on other toolchains.
#include "WorldConfig.h"
#include "CDZoneTableTable.h"
#include <chrono>
#include <cmath>
#include "eObjectBits.h"
#include "CDZoneTableTable.h"
#include "AssetManager.h"
#include <ranges>
e1b8924 to
7dd918d
Compare
729b2ae to
0eeb5b0
Compare
e07cc1b to
9c20622
Compare
Replace old dNavigation/dTerrain raw parser with new Raw module in dZoneManager. Parse heightmaps, color maps, and scene maps from .raw files to determine which scene a position belongs to. Build scene adjacency graph from terrain data and scene transitions. Adds NiColor type, SceneColor lookup table, eSceneType enum, terrain mesh generation with OBJ export, and debug slash commands for scene visualization. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add IsValidForSceneLookup(), GetSceneIDAtGrid(), and GridToWorldPos() to Raw::Chunk. Use them in GenerateTerrainMesh, GetSceneIDFromPosition, SpawnScenePoints, and SpawnAllScenePoints instead of duplicated inline math. Remove unnecessary static_cast in LoadSceneTransitionInfo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The parser was only correct for v32 files. For v<32: - colorMapResolution is width-1, not width - Color map reads width*width*4 bytes (BGRA per-pixel), not colorMapRes^2*4 - No DDS lightmap - No texture settings byte or blend DDS - Scene map: v31 reads (colorMapRes+1)^2 cells with border skip, v<31 skips 1 byte - No mesh data Verified against all 309 .raw files across multiple client versions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Log a clear message and throw if the zone uses a legacy raw format (LUZ version < 30) since no known maps use it. Remove ReadLegacyRaw and the mapVersion parameter from ReadRaw. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These fields are skipped by the client in every known build (ptr += 12 and ptr += 4). No client ever reads them into a struct. Keep the original unknown1/unknown2 names from main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ing or unreadable Log at debug when it parses; build the terrain mesh only for the OBJ export; read the zone name and description only for version 31 and later, as the client does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…time Chunk bounds span (width - 1) * scale; the nearest scene map cell is used and the far edge is kept one cell inside. Chunks are indexed by grid cell when they form a grid. Skipping reads instead of seeking, so a cut-off file can't seek past the end. Terrain mesh indices follow the vertex order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ickIDTable Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6df22db to
36d6245
Compare
…dows Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
got opus 5.5 agent to look oer this again, it found several things that could cause crashes |
| // A different LEGO brick per scene so the scenes can be told apart, from the BrickIDTable (every brick's LOT) | ||
| static LOT GetScenePointLot(uint8_t sceneID) { | ||
| static const std::vector<LOT> brickLots = [] { | ||
| std::vector<LOT> lots; | ||
| for (const auto& brick : CDClientManager::GetTable<CDBrickIDTableTable>()->Query([](const CDBrickIDTable&) { return true; })) { | ||
| lots.push_back(brick.NDObjectID); | ||
| } | ||
| std::ranges::sort(lots); | ||
| return lots; | ||
| }(); | ||
| return brickLots.empty() ? LOT_NULL : brickLots[sceneID % brickLots.size()]; | ||
| } |
EmosewaMC
left a comment
There was a problem hiding this comment.
remove all the em dashes
| ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); | ||
| return; | ||
| } | ||
|
|
||
| // Build the feedback message with current scene | ||
| std::ostringstream feedback; | ||
| feedback << "Current Scene: " << sceneID.GetSceneID() << " (" << currentSceneName << ")"; | ||
| ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); | ||
|
|
||
| // List all adjacent scenes | ||
| feedback.str(""); | ||
| feedback << "Adjacent Scenes (" << adjacentSceneIDs.size() << "):"; | ||
| ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); | ||
|
|
||
| for (const auto& adjSceneID : adjacentSceneIDs) { | ||
| feedback.str(""); | ||
| feedback << " - Scene ID: " << adjSceneID.GetSceneID(); | ||
| feedback << " (Layer: " << adjSceneID.GetLayerID() << ")"; | ||
|
|
||
| // Get the scene name if available | ||
| const auto* sceneRef = zone->GetScene(adjSceneID); | ||
| if (sceneRef && !sceneRef->name.empty()) { | ||
| feedback << " - " << sceneRef->name; | ||
| } | ||
|
|
||
| ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); | ||
| } |
There was a problem hiding this comment.
why are we unable to send this as one packet?
| BinaryIO::BinaryRead(stream, flair.colorR); | ||
| BinaryIO::BinaryRead(stream, flair.colorG); | ||
| BinaryIO::BinaryRead(stream, flair.colorB); | ||
| BinaryIO::BinaryRead(stream, flair.colorA); |
There was a problem hiding this comment.
https://docs.lu-dev.net/en/latest/file-structures/raw.html#raw-types-flair_attributes-seq
i dont see an alpha documented here, is this correct?
| } | ||
|
|
||
| const size_t heightMapSize = width * height; | ||
| const size_t elementSize = sizeof(chunk.heightMap[0]); |
There was a problem hiding this comment.
uh, sizeof is a compile time operation, not a runtime one, but it seems to be used here as a runtime one? Replace this with a constant if so or use the sizeof the actual struct being queried rather than the result of a operator[].
| } | ||
| } | ||
|
|
||
| bool WriteTerrainMeshToOBJ(const TerrainMesh& mesh, const std::string& path) { |
There was a problem hiding this comment.
was this tested? it wasnt called in the original code and i want to make sure this still works
| } | ||
|
|
||
| //Read generic zone info: | ||
| BinaryIO::ReadString<uint8_t>(file, m_ZonePath, BinaryIO::ReadType::String); |
There was a problem hiding this comment.
Where did this go? why is this not necessary anymore?
Uh oh!
There was an error while loading. Please reload this page.