Skip to content

Predict slot rules on the client's machine menu - #85

Merged
dshadowwolf merged 1 commit into
master-2.0-1.21.1-neofrom
client-menu-handler
Nov 2, 2026
Merged

dshadowwolf merged 1 commit into
master-2.0-1.21.1-neofrom
client-menu-handler

Conversation

@faceofcat

@faceofcat faceofcat commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

What this is

A small fix to how the client predicts clicks in machine menus, and the first step towards the reservations design on #83. It has no reservations in it and doesn't need the processor.

The problem. The client's MachineMenu backs its slots with a blank new ItemStackHandler(count), which accepts anything up to a full stack. From the code, it predicts placing items in output slots, past slot limits and against filters, and the server then corrects it. I haven't watched that flicker happen in a running game.

The fix. ClientMenuItems is the new client handler:

  • Contents still come from vanilla's menu sync, in the handler's own stacks.
  • Rules (isItemValid, getSlotLimit) come from the client block entity's own screenItems(), which has the same roles, filters and limits on any ScreenHost. Its contents aren't read or changed.
  • Ghost slots can take the menu's slot count past the end of the storage. Those indexes are refused rather than thrown, since no real slot uses them.

The server still decides. A filter that depends on server-only state can still mispredict, and the server corrects it as it does today.

Review notes

  • New requirement: screenItems() must now work on the client. ScreenHost and docs/gui-screens.md say so. The default screenDestinations already relied on it, but a host that overrides that and has no client storage would now fail when the menu asks about a slot.
  • Test machine: Counter gets an output slot, a filter and a limit, because it had none, so the GUI smoke test can check them.
  • Separate from Move the builder checks to JUnit #84: nothing here depends on it, and the two don't touch the same files, apart from both being based on the merged Machine recipe types: datapack loading, lookup, datagen and JEI #83.

Testing

  • ./gradlew check passes locally, including all 19 game tests. clientMenuItems is new and checks the handler against a real ItemStorage.
  • The GUI smoke test now checks a real client menu: the input slot's limit and filter, and that an output slot refuses a placement.
  • I didn't run the GUI smoke test locally, so the CI job on this PR is its only run, and I haven't seen those client checks fail against the old handler.

🤖 Generated with Claude Code

The client's menu backed its slots with a blank ItemStackHandler, which
accepts anything up to a full stack. So it predicted placing items in output
slots, past slot limits and against filters, until the server corrected it.

ClientMenuItems keeps the same contents, filled by vanilla's menu sync, but
takes isItemValid and getSlotLimit from the client block entity's own
screenItems(), which has the same roles, filters and limits on any
ScreenHost. Its contents aren't read or changed. The server still decides,
so a filter that depends on server-only state can still mispredict.

screenItems() must now work on the client, which ScreenHost and the docs
now say. The default screenDestinations already relied on it.

The test machine gets an output slot, a filter and a limit, and the GUI smoke
test checks them through a real client menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018zpP6ZrFjaGe477FvWAZKo
@dshadowwolf

dshadowwolf commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

No comments -- waiting on CI, this is an excellent PR

@dshadowwolf
dshadowwolf merged commit 28410a7 into master-2.0-1.21.1-neo Nov 2, 2026
3 checks passed
@faceofcat
faceofcat deleted the client-menu-handler branch November 2, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants