World-format trust + generalization: lossless round-trips, unknown-field warnings, applyWorldEnvironment, world-format.md, world-viewer example#104
Conversation
…fields serializePrefab dropped schemaVersion and bounds from every prefab it ever wrote — the version was silently backfilled by migration on reload (hiding the loss) and bounds came back undefined. Now both serialize; migratePrefabData backfills degenerate bounds for pre-fix files; createEmptyPrefab stamps the current schema version instead of a hardcoded 1. New listUnknownWorldFields / listUnknownPrefabFields walk every schema level of a parsed document and return dotted paths for fields the schema-explicit saver would drop. loadWorld/loadPrefab console.error each one at load time — the sanctioned extension points that DO round-trip are metadata, userData, and tags. Verified by the editor's self-test suite (129 pass), including real load->save->deep-compare round-trips of both shooter arenas. Claude-Session: https://claude.ai/code/session_01PmL9WgNMkAgvpYSHEZga8K
|
Warning Review limit reached
Next review available in: 19 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughWorld and prefab schema handling now reports unknown fields and preserves prefab metadata and bounds. A world-viewer example loads, instantiates, and renders worlds with applied environment settings. Render-texture conversion and Windows mouse coordinate handling now use compatible runtime representations. ChangesWorld schema and prefab persistence
World viewer runtime
Render and Windows input compatibility
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant loadWorld
participant instantiateWorld
participant applyWorldEnvironment
participant Renderer
CLI->>loadWorld: load the world path
CLI->>instantiateWorld: provide model lookup and prefab registry
instantiateWorld-->>CLI: return instantiation warnings
CLI->>applyWorldEnvironment: apply environment each frame
applyWorldEnvironment->>Renderer: set lights and fog
CLI->>Renderer: render the camera view and HUD
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…e-0.5 { id }
Texture renamed its field to handle in v0.5; this function was never
migrated. Every draw call reads texture.handle, so drawing a render texture
passed undefined into a native f64 parameter — nobody had drawn one until
the editor's asset thumbnails (PLAN §G).
Claude-Session: https://claude.ai/code/session_01PmL9WgNMkAgvpYSHEZga8K
…ct doc, world-viewer example - applyWorldEnvironment(world) in world/render.ts: per-frame ambient + sun + point lights + fog, the call every instantiateWorld consumer needs (the renderer clears lighting in begin_frame — instantiateWorld alone lights exactly one frame). The editor's syncEnvironment and the new example both use it, so the editor's lighting preview is the same code path games run. - docs/world-format.md: the adoption contract — schema summary, extension points that round-trip vs fields that get dropped (with the load-time warning), the full editor.project.json key table incl. kindColors, the --world play-in-editor convention, both runtime consumption shapes, and versioning promises. A third game can adopt from this doc alone. - examples/world-viewer: the FIRST consumer of instantiateWorld. Loads any world, fly camera, warnings surfaced. Verified live against shooter's arena_02 (terrain, models, water, rivers, lights spawn; sentinel-model entities warn-and-skip as documented). Claude-Session: https://claude.ai/code/session_01PmL9WgNMkAgvpYSHEZga8K
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/world-format.md`:
- Around line 66-80: Make the editor.project.json example valid JSON by removing
all inline // comments from the fenced json block in the documentation. Preserve
the existing property names and example values without introducing JSONC syntax
or loader changes.
In `@examples/world-viewer/main.ts`:
- Around line 149-154: Update the background color setup in the world-viewer
initialization flow to handle an undefined world.environment before accessing
skyColor. Reuse the same safe fallback behavior established by
applyWorldEnvironment in render.ts, while preserving the current skyColor-based
values when environment is present.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7fabf17e-56eb-47a3-a2e2-1ee32d59a2fe
⛔ Files ignored due to path filters (1)
examples/world-viewer/world-viewer.exeis excluded by!**/*.exe
📒 Files selected for processing (6)
docs/world-format.mdexamples/world-viewer/README.mdexamples/world-viewer/main.tsexamples/world-viewer/package.jsonsrc/textures/index.tssrc/world/render.ts
| ```json | ||
| { | ||
| "name": "My Game", // ("Untitled Project") window title | ||
| "gameId": "mygame", // ("") shown in the title bar | ||
| "modelsDir": "assets/models", // (that) flat dir of .glb/.gltf | ||
| "prefabsDir": "assets/prefabs", // (that) *.prefab.json | ||
| "worldsDir": "assets/worlds", // (that) | ||
| "texturesDir": "assets/textures", // (that) splat-layer sources, listed not loaded | ||
| "defaultWorld": "level1.world.json", // ("") opened at launch | ||
| "playCommand": "main.exe", // ("") enables the Play button — see §4 | ||
| "kindColors": { // (none) placeholder colors for YOUR kinds | ||
| "spawn_point": "90, 220, 120" // "r, g, b" 0-255 | ||
| } | ||
| } | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the editor.project.json example valid JSON.
This block is labeled json, but // comments make it invalid JSON. A user who copies it into editor.project.json will get a parse error. Remove the inline comments, or explicitly document a JSONC format and ensure the loader supports it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/world-format.md` around lines 66 - 80, Make the editor.project.json
example valid JSON by removing all inline // comments from the fenced json block
in the documentation. Preserve the existing property names and example values
without introducing JSONC syntax or loader changes.
| clearBackground({ | ||
| r: Math.floor(world.environment.skyColor[0] * 255), | ||
| g: Math.floor(world.environment.skyColor[1] * 255), | ||
| b: Math.floor(world.environment.skyColor[2] * 255), | ||
| a: 255, | ||
| }); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Prevent potential crash if world.environment is undefined.
applyWorldEnvironment in render.ts safely guards against world.environment being undefined. If older worlds or prefabs can lack this field, accessing world.environment.skyColor here will result in a runtime crash. Consider adding a defensive fallback to ensure the reference viewer remains stable.
🛡️ Proposed defensive fix
- clearBackground({
- r: Math.floor(world.environment.skyColor[0] * 255),
- g: Math.floor(world.environment.skyColor[1] * 255),
- b: Math.floor(world.environment.skyColor[2] * 255),
- a: 255,
- });
+ const env = world.environment;
+ clearBackground(env ? {
+ r: Math.floor(env.skyColor[0] * 255),
+ g: Math.floor(env.skyColor[1] * 255),
+ b: Math.floor(env.skyColor[2] * 255),
+ a: 255,
+ } : { r: 0, g: 0, b: 0, a: 255 });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| clearBackground({ | |
| r: Math.floor(world.environment.skyColor[0] * 255), | |
| g: Math.floor(world.environment.skyColor[1] * 255), | |
| b: Math.floor(world.environment.skyColor[2] * 255), | |
| a: 255, | |
| }); | |
| const env = world.environment; | |
| clearBackground(env ? { | |
| r: Math.floor(env.skyColor[0] * 255), | |
| g: Math.floor(env.skyColor[1] * 255), | |
| b: Math.floor(env.skyColor[2] * 255), | |
| a: 255, | |
| } : { r: 0, g: 0, b: 0, a: 255 }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/world-viewer/main.ts` around lines 149 - 154, Update the background
color setup in the world-viewer initialization flow to handle an undefined
world.environment before accessing skyColor. Reuse the same safe fallback
behavior established by applyWorldEnvironment in render.ts, while preserving the
current skyColor-based values when environment is present.
…sts were off by the DPI scale WM_MOUSEMOVE stored raw physical client pixels while everything else on Windows speaks logical units (WM_SIZE derives logical = physical / dpi_scale precisely so 'the rest of the engine sees the same logical/physical split macOS does'). On a 125%/150% display every hover and click landed scale-x away from the pointer, worse with distance from the top-left — the editor's UI was unusable at 150%. Both window procs (standalone + attached-view) now divide by dpi_scale before set_mouse_position. The FPS-capture path keeps its centre math and SetCursorPos in physical (those APIs are physical) and converts only the delta handed to the engine, so look sensitivity matches macOS point-deltas. Claude-Session: https://claude.ai/code/session_01PmL9WgNMkAgvpYSHEZga8K
The rule was examples/**/main.exe | main | main.app, which assumed every example compiles to `main`. The world-viewer compiles to world-viewer.exe, so it matched nothing, got committed at 26 MB, and was one merge away from being in main's history forever (where deleting it later would not have removed it -- the blob stays reachable). Match by extension instead. The .exe itself is dropped from this branch's commits in the same push, so the blob never reaches main.
6f30bc3 to
a60838e
Compare
Engine-side half of the editor's "any world, any game" push (editor PLAN.md Part 4). Grew beyond the original file-trust scope as the work surfaced more:
File trust (original scope)
serializePrefabdroppedschemaVersion+boundsfrom every prefab ever saved — both now serialize;migratePrefabDatabackfills degenerate bounds for old files;createEmptyPrefabstamps the current version.listUnknownWorldFields/listUnknownPrefabFieldswalk every schema level;loadWorld/loadPrefabwarn per field at load. Sanctioned extension points:metadata/userData/tags.Generalization (added)
3.
applyWorldEnvironment(world)inworld/render.ts— per-frame ambient+sun+lights+fog. The renderer clears lighting in begin_frame, soinstantiateWorldalone lights exactly one frame; every consumer needed this and none existed. The editor's lighting preview now runs this exact code path.4.
docs/world-format.md— the adoption contract: schema, extension points + strip-warning behavior, fulleditor.project.jsonkey table (incl. newkindColors), the--worldplay-in-editor convention, both runtime consumption shapes, versioning promises.5.
examples/world-viewer— the FIRST consumer ofinstantiateWorld, verified live against shooter's arena_02.6.
getRenderTextureTexturereturned the pre-0.5{ id }Texture shape — drawing any render texture fedundefinedinto a native f64 param (surfaced by editor thumbnails).Verified by the editor suite (148 self-tests incl. real-world round-trips) + live runs of the viewer and editor.
https://claude.ai/code/session_01PmL9WgNMkAgvpYSHEZga8K
Summary by CodeRabbit
Bug Fixes
boundsnow load with safe default bounds.New Features
applyWorldEnvironmentAPI to refresh ambient/directional lighting and fog each frame.world-viewerexample and expanded the Bloom world format specification.Improvements
bounds; new prefabs use the current schema version.