Repository navigation
refactor: split save_load_mixin.zig into save/load modules (behavior-preserving) - #694
Conversation
…preserving) Pure extraction along the SAVE vs LOAD seam. `save_load_mixin.zig` becomes a thin composition barrel re-exporting the same 5 public functions (saveGameState, loadGameState, armPostLoadRenderGate, updatePostLoadRenderGate, releaseLoadAcquired), so game.zig's aliases resolve unchanged. - src/game/save_load/common.zig — entityToU64, isRegistered, collectEntities and SAVE_VERSION (shared by both directions, not duplicated). - src/game/save_load/save.zig — saveGameState + private writeJsonString. - src/game/save_load/load.zig — loadGameState with its Phase 1a/1b/1c → Phase 2 sequence kept together, the post-load render gate, and the load-only JSON accessors. Each is a Mixin(Game) instantiated by the barrel against the same Game (the idiom loop_mixin uses for AtlasMixin/InputEventsMixin). Shared helpers reached via Common.<fn>. No logic or signature changes. zig build / zig build test / zig build spec all green on 0.16.0; zig fmt clean. Claude-Session: https://claude.ai/code/session_017pW3ifKf9wgxNg4viy6okw
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThe monolithic save/load mixin implementation is refactored into three new files under src/game/save_load/: common.zig (shared helpers), save.zig (JSON serialization), and load.zig (JSON deserialization, entity reconstruction, and post-load render gating). save_load_mixin.zig becomes a thin re-export barrel. ChangesSave/Load Module Split
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Game
participant LoadMixin
participant ECS
participant Renderer
participant AtlasManager
Game->>LoadMixin: loadGameState(filename)
LoadMixin->>LoadMixin: parse JSON, validate version
LoadMixin->>ECS: spawn prefab roots, map children, create remaining entities
LoadMixin->>ECS: restore components via id_map
LoadMixin->>ECS: register entities into scene
LoadMixin->>Renderer: re-track visual components
LoadMixin->>LoadMixin: armPostLoadRenderGate(saved_scene)
loop each frame until ready or deadline
Game->>LoadMixin: updatePostLoadRenderGate()
LoadMixin->>AtlasManager: isLoaded()?
AtlasManager-->>LoadMixin: ready/failed status
end
LoadMixin-->>Game: render gate cleared
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request refactors the save/load system by modularizing the monolithic save_load_mixin.zig file. The implementation is split into three new files under src/game/save_load/: common.zig for shared helpers, save.zig for serialization logic, and load.zig for deserialization and post-load render gating. The original save_load_mixin.zig is simplified into a thin composition barrel that re-exports the public API, preserving identical behavior. No review comments were provided, and the refactoring is clean and well-structured.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
…764) * refactor: extract post-load render gate from load.zig into render_gate.zig (#762) Completes the save_load_mixin split into focused modules. PR #694 split the 1156-line monolith by direction (save/load/common); load.zig was left at 977 lines because it still carried two concerns: the rehydration/load seams (loadGameState + its Phase 1a/1b/1c -> Phase 2 sequence) AND the transient post-load render-gate machinery. This extracts the gate machinery -- armPostLoadRenderGate, updatePostLoadRenderGate, releaseLoadAcquired, plus the private armPostLoadRenderGateFromEntry / postLoadGateHasImage helpers and the POST_LOAD_GATE_MAX_FRAMES constant -- verbatim into a new save_load/render_gate.zig Mixin(Game). It is a distinct concern with its own per-frame lifecycle (armed at end of load, ticked from tick, released on next load / teardown) and touches none of the reader's rehydration seams. loadGameState reaches it through self.armPostLoadRenderGate(...), aliased onto Game in game.zig, so no reader<->gate import edge is needed. The four focused modules now map to the issue's vision: serialization walk (save.zig), rehydration/load seams (load.zig, now ~747 lines), transient render-gate machinery (render_gate.zig), and the thin composition barrel (save_load_mixin.zig). Behaviour-preserving: the barrel re-exports the same 5-fn public surface, so game.zig aliases resolve exactly as before. zig build test: no change in results (697/744 tests pass; the 47 failures are pre-existing and unrelated -- asset_catalog compile error + loopback socket tests that the sandbox blocks). save_load_mixin_test, save_load_two_phase_test, and post_load_render_gate_test all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: extract load-only JSON accessors from load.zig into json_read.zig (#762) Second focused extraction for #762. load.zig still mixed two concerns: the rehydration walk (loadGameState + its Phase 1a/1b/1c -> Phase 2 sequence) and a layer of pure, tag-checked JSON shape-guards. The seven accessors (parentFlag, getComponentsObject, getObjectField, getStringField, getU64Field, getSavedId, getNumberField) are std.json-only -- no Game, no Entity, no registry -- so they move verbatim into save_load/json_read.zig as plain pub fns. load.zig re-aliases them at mixin scope, so every call site (getComponentsObject(entry), getObjectField(...), ...) reads exactly as before. This leaves load.zig focused on the rehydration sequence (down to 695 lines from 977 pre-#762) and gives the shape-guards a standalone home. The save_load cluster is now the focused-module split the ticket calls for: * save.zig -- serialization walk (writer) * load.zig -- rehydration/load seams (reader) * json_read.zig -- load-only JSON accessors * render_gate.zig -- transient post-load render-gate machinery * common.zig -- shared helpers + SAVE_VERSION * save_load_mixin.zig -- thin composition root (barrel) Behaviour-preserving: the accessors' malformed-save hardening stays covered by test/save_load_mixin_test.zig + test/save_load_two_phase_test.zig, which drive the full load path. zig build test: 697/744 pass -- identical to baseline (the 47 failures are pre-existing, unrelated: sandbox-blocked loopback-socket tests + pre-existing `expected void found u64` compile errors in unrelated test files). Zero regressions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Pure, behavior-preserving extraction of
src/game/save_load_mixin.zig(~1156 lines) along the SAVE vs LOAD seam. No logic, signature, or public-API changes — code moved verbatim, only shared-helper call sites re-pointed at the common mixin.How it's split
src/game/save_load_mixin.zigsrc/game/save_load/common.zigentityToU64,isRegistered,collectEntities,SAVE_VERSION(shared by both directions, not duplicated)src/game/save_load/save.zigsaveGameState+ privatewriteJsonString(save-only)src/game/save_load/load.zigloadGameState(Phase 1a/1b/1c → Phase 2 kept together), post-load render gate, load-only JSON accessorsEach is a
Mixin(Game)instantiated by the barrel against the sameGame— the exact idiomloop_mixinalready uses forAtlasMixin/InputEventsMixin. Shared helpers are reached viaCommon.<fn>.Public surface (unchanged)
game.zigaliasesSaveLoadMixin.{saveGameState, loadGameState, armPostLoadRenderGate, updatePostLoadRenderGate, releaseLoadAcquired}— all still resolve, so every call site works unchanged. Load's phase sequence stays intact in one file (load-path symmetry preserved).Verification
zig build— compiles on 0.16.0zig build test— green (incl.save_load_mixin_test.zig+save_load_two_phase_test.zig)zig build spec— greenzig fmt --check— clean on all new/changed filesDo not merge without review.
https://claude.ai/code/session_017pW3ifKf9wgxNg4viy6okw