review: safe JoinServer handoff, ScreenGrabber visibility, deprecate CoreRegistry constructor#5322
Conversation
Three issues in the client join path: 1. Dead thread was treated as success — if the environment switch threw an exception, the thread died and step() returned true. Now uses FutureTask which surfaces exceptions via get(). 2. Unsafe .stream().findFirst().get() for BeanContext extraction replaced with orElseThrow() and a clear error message. 3. CoreRegistry.setContext() was called from the worker thread. Now the FutureTask returns the Context and the main thread sets CoreRegistry after get() completes successfully. CodeRabbit flagged this on PR MovingBlocks#5299 (outside-diff-range, critical). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comment clarifying that the world seed is carried by the GameManifest from the UI (via GameManifestProvider), with a random fallback if not specified. BSA asked "Where is the seed being set now?" on PR MovingBlocks#5299. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…uctor Mark the old constructor that resolves dependencies via CoreRegistry as @deprecated. The @Inject constructor is the correct DI path. No callers use the old constructor directly — it exists only as a fallback. BSA flagged this on PR MovingBlocks#5299. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ages ScreenGrabber was registered only in WorldRendererImpl's private child context, invisible from the shared game context. ReadWriteStorageManager resolves it via CoreRegistry.get(ScreenGrabber.class) when saving the game preview image, which returned null — resulting in black preview screenshots. Propagate the instance to CoreRegistry after init(). CodeRabbit flagged this on PR MovingBlocks#5299 (outside-diff-range, major). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughFixes and small refactors across engine initialization and persistence: fall back to a generated world seed if missing, replace raw Thread usage with FutureTask for module environment application, deprecate a legacy ReadWriteStorageManager constructor, and register ScreenGrabber into CoreRegistry during renderer init. Changes
Sequence Diagram(s)sequenceDiagram
participant Loader as Load Process (JoinServer)
participant Future as Background Task (FutureTask)
participant ModuleEnv as Module Environment Builder
participant Core as CoreRegistry
participant Network as NetworkSystem
Loader->>Future: submit module-environment task
Future-->>Loader: done
Loader->>Future: get() (may throw ExecutionException / InterruptedException)
alt success
Future--)ModuleEnv: returns ContextImpl
Loader->>Core: CoreRegistry.set(Context)
else ExecutionException
Loader->>Core: CoreRegistry.set(StateMainMenu)
Loader->>Network: shutdown()
else InterruptedException
Loader->>Loader: Thread.currentThread().interrupt()
Loader-->>Loader: abort load (return false)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@engine/src/main/java/org/terasology/engine/core/modes/loadProcesses/JoinServer.java`:
- Around line 72-77: The catch block for ExecutionException in JoinServer (where
you construct StateMainMenu and call
context.get(GameEngine.class).changeState(mainMenu)) should end the current load
step so it isn't re-run; change the final return value to true (matching
InitialiseWorld.step() pattern) after switching to StateMainMenu to signal the
step is complete and avoid re-entering the same catch on the next step, keeping
the existing networkSystem.shutdown() call and logger.error call intact.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 98dd2914-88a4-448d-b75b-080795e0ceab
📒 Files selected for processing (4)
engine/src/main/java/org/terasology/engine/core/modes/loadProcesses/InitialiseWorld.javaengine/src/main/java/org/terasology/engine/core/modes/loadProcesses/JoinServer.javaengine/src/main/java/org/terasology/engine/persistence/internal/ReadWriteStorageManager.javaengine/src/main/java/org/terasology/engine/rendering/world/WorldRendererImpl.java
After changeState(mainMenu) on failure, returning false left the load step active, causing the error path to repeat on the next tick. Return true to end the step, matching the pattern in InitialiseWorld. CodeRabbit review feedback on PR MovingBlocks#5322. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… game context level BSA review: injecting into CoreRegistry is counter to the DI migration. ScreenGrabber is already registered in the game-level ServiceRegistry by LwjglRenderingSubsystemFactory.registerWorldRenderer(), so it should be resolvable from CoreRegistry without manual injection. The black save preview is a separate framebuffer timing issue tracked in MovingBlocks#5321. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Sixth review follow-up to #5299 (gestalt-di migration). The last critical fix, plus cleanup and a partial fix for save previews.
Changes
.stream().findFirst().get()replaced withorElseThrow(). CoreRegistry is now set from the main thread after the task completes, not from the worker.Related
Test Plan
🤖 Generated with Claude Code