Skip to content

feat(runtime): scroll, right click, and a dialog text prompt on the full-screen surface - #126

Open
oglassdev wants to merge 8 commits into
feat/fullscreen-sessionfrom
feat/fullscreen-input
Open

oglassdev wants to merge 8 commits into
feat/fullscreen-sessionfrom
feat/fullscreen-input

Conversation

@oglassdev

@oglassdev oglassdev commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Closes #121
Part of #115

Adds scroll, right click, and a native dialog text prompt to full-screen windows. The other open sub-issues stay separate: this PR changes no Rust, codegen, or render/composition code.

API

  • FullscreenScope.scroll { steps -> }: each held-slot change becomes a signed step count, floorMod(slot - last + 4, 9) - 4, so it goes the shortest way around the hotbar. Positive means the selection moved right, which is what scrolling down does by default. The KDoc covers the limits: the client sends at most one change per tick, so notches scrolled within one tick arrive together (more than 4 read as a scroll the other way), and number keys look the same as scrolling.
  • FullscreenScope.rightClick { click -> }: a right click at the cursor, as a FullscreenClick.
  • FullscreenView.promptText(title, initial, onDone): opens a dialog over the canvas with one text field and Confirm and Cancel buttons. onDone gets the text on Confirm and null on Cancel. To prompt on a click, call it from the control's click handler (the KDoc has the pattern); there is no new authoring element.
  • Host contract additions (new members only): FullscreenListener.onRightClick and onScroll, and OpenFullscreen.promptText.

Behaviour

  • Scroll: the held-slot packet is cancelled, so the server's player never changes slot and other listeners never see it. The host tracks the client's slot from incoming changes and from the server's own HeldItemChangePackets, so each step is measured from the right slot. The held slot is still restored on close.
  • Right click: 26.2 client bytecode shows that Interaction.interact returns CONSUME on the client and startUseItem returns after the first hand. So one press sends exactly one main-hand ServerboundInteractPacket. Off-hand interactions are dropped as a safeguard. Like left clicks, right clicks are reported at the end of the tick, after that tick's rotation. Holding the use key repeats every 4 ticks (vanilla rightClickDelay); this is documented.
  • Text prompt: a Dialog.MultiAction with a text input (up to 256 characters; initial is cut to fit) and two buttons in the dialog body, sent in a ShowDialogPacket. Each prompt gets its own custom action ids (window:prompt/<n>/confirm and /cancel), so a response to an earlier or foreign dialog is ignored. The client closes the dialog when a button is pressed (DialogAfterAction.CLOSE) and the canvas is back. onDone runs exactly once: Confirm delivers the text; Cancel, a new prompt replacing the old one, and the window ending (disconnect, close(), sneaking) deliver null. The window ending also sends a ClearDialogPacket. Canvas input (look, clicks, scroll) is ignored while a prompt is open, so the cursor stays where it was.
  • Escape: canCloseWithEscape is false, so a prompt always ends through a button. The 26.2 client runs the dialog's cancel action on Escape (DialogScreen.onClose runs Dialog.onCancel(): the exit action of a multi-action dialog, the No button of a confirmation dialog), so Escape could be reported. But both of those sit in the dialog's footer, inside the bottom strip the pack's shader clips while the HUD is hidden, so a footer button would draw without its background. The buttons are in the body instead, which the client centres vertically on the screen.
  • HUD: a dialog is a client screen rather than a server container, so no OpenWindowPacket arrives and the world age and blank hotbar are left alone; the HUD stays hidden behind it.

Checks

  • just gradle :runtime:test --tests '*Fullscreen*': pass (FullscreenSessionTest has 11 tests, 2 new)
  • just gradle :minestom:test --tests '*Fullscreen*': pass (MinestomFullscreenTest has 14 tests, 6 new)
  • just fmt-check-jvm: pass

Not yet checked in a real client

  • Scroll steps and number keys under fake survival with the hotbar slot left wherever the player scrolled it.
  • One right click per press and the 4-tick repeat (taken from bytecode, not observed).
  • The dialog flow end to end: that the buttons clear the clipped HUD strip at the player's GUI scale, that the canvas looks right behind the dialog's blurred background, and that no stray input arrives after it closes. The client behaviour above (Shift in the text field does not reach the sneak key, a replaced dialog returns to the right screen, the dialog opens and closes without a container packet) is from 26.2 client bytecode.

…screen windows

Held-slot changes become signed steps the shortest way around the hotbar,
main-hand interactions with the click entity become right clicks, and
promptText opens an anvil over the canvas whose rename field is reported,
reopening a fresh anvil each time the 50-character field fills.
…s click resyncs

The prompt anvil is the window's own UI, so it no longer hands the client
the real world age and hotbar. Its paper takes the blank item model and
carries no enchantments, so the client computes no result or cost label,
and the repair cost is sent as 0. Click resyncs ride a ping like opens do,
and text typed before one reached the client is kept. Taking the result
resyncs the player's experience.

Generated full-screen classes bind scroll and right click to open
onScroll and onRightClick hooks.
…guised anvil

promptText(title, initial, onDone) now shows a dialog with one text field and
Confirm and Cancel buttons. Each prompt has its own custom action ids, so stale
or foreign responses are ignored, and onDone runs once: Confirm delivers the
text, and Cancel, a replacing prompt, or the window ending deliver null. Escape
does not dismiss the dialog. Canvas input is ignored while a prompt is open.

Removes the anvil prompt: blank paper seed, repair cost and XP resyncs, the
50-character reopen, rename echo gating, and the anvil branch of container
handoff.
@oglassdev oglassdev changed the title feat(runtime): scroll, right click, and anvil text input on the full-screen surface feat(runtime): scroll, right click, and a dialog text prompt on the full-screen surface Oct 15, 2026
… the state it reports

The host alone holds the pending prompt and the session derives whether canvas input counts from it. Every ending
(answer, replacement, container takeover, window end) clears the prompt before calling its callback. A container
opening over the dialog cancels the prompt on the player's next tick, and a window ending restores the player first,
then cancels the prompt, then calls onClose, even if the callback throws.
@oglassdev
oglassdev marked this pull request as ready for review October 16, 2026 00:08
@oglassdev
oglassdev added this pull request to stack #130 October 16, 2026 00:26
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.

1 participant