Skip to content

Give Click Slot the three clicks a player actually makes - #81

Closed
Gaetarra wants to merge 1 commit into
soymods:mainfrom
Gaetarra:feature/click-slot-modes
Closed

Give Click Slot the three clicks a player actually makes#81
Gaetarra wants to merge 1 commit into
soymods:mainfrom
Gaetarra:feature/click-slot-modes

Conversation

@Gaetarra

@Gaetarra Gaetarra commented Aug 29, 2026

Copy link
Copy Markdown

What This Changes

Based directly on main, not stacked on #78 or #79. Supersedes #80, which I
opened prematurely and closed — same branch, but the write-in parameter
discussed below has since been removed and the commit rewritten.

Click Slot always sent ClickType.PICKUP. Shift-clicking a stack into the other
container, or swapping it to the offhand with F, had to be built out of
Move Item or the raw packet fabricator in UI Utils. Both are more work than
the click they stand in for, and neither matches what the server sees from a
real player.

  • CLICK_SLOT gains modes, each sending what the vanilla screen sends for
    the same input:

    Mode Click sent
    Left Click (default) PICKUP, button 0
    Shift Click QUICK_MOVE, button 0
    F SWAP, button 40 — the offhand's button index in AbstractContainerScreen
  • Click Slot is tagged RENDER_INLINE_PARAMETERS. NodeGraph.rendersInline Parameters gates the parameter strip and the mode selector is drawn inside
    it, so without the tag the modes would exist but not be selectable.

  • The click_slot_index write-in parameter is removed and the parameter slot
    is relabelled Selection -> Slot.
    The node had two ways to name a slot and
    only one of them could ever win; see below.

Verification

Check Status
./gradlew :common:test -Pmc_version=1.21.11 Not run locally. Relying on CI. NodeClickSlotTest is added but has never been executed.
verifyCompatibilityManifest verifyCompatibilityStructure verifyBuildGenerationRouting Not run locally. Relying on CI.
Compiles on 1.21 / 1.21.8 / 1.21.10 / 1.21.11 Not run locally. Relying on CI.
Compiles on 26.1 / 26.2 (-p mc26, both loaders) Fabric passes on both. NeoForge passes on 26.1.2. NeoForge on 26.2 fails with Could not find net.neoforged:neoforge:unsupported — pre-existing, same as #78 and #79.
Clicked through the affected UI in a dev client Yes. The mode selector opens and reads in English, and all three modes produce the right click against an open container. Removing the write-in initially broke execution — see below — and the node was re-run after the fix.

Only common is touched, so nothing here is version-sensitive on its face — but
the compile matrix is the check that would catch it if that assumption is wrong.

Notes For Review

Removing the write-in is not a behaviour change, and this is the part most
worth a second pair of eyes.
The reasoning:

  • parameterHost(NodeType.CLICK_SLOT, ...) uses the (type, label, traits)
    overload, which passes required = true. NodeExecutionCoordinator fails any
    Click Slot with nothing attached before the executor runs, so every Click
    Slot that has ever executed had a Slot node attached.
  • On each run, preprocessAttachedParameter exports that node's values and
    applyParameterValuesFromMap copies Slot over the host's own parameter.
    adjustParameterValuesForSlot is identity for CLICK_SLOT.
  • So the write-in's value was overwritten before it was read, every time. It was
    redundant by construction, not merely duplicated.

With no host parameter left to copy into, resolveClickSlotIndex reads the index
straight off the attachment, applying resolveVariableSelectionParameterNode
first so a Variable in the slot resolves the same way it already does for the
selection type.

That same copy is how a slot gets marked handled, which is the sharp edge
here.
preprocessParameterNode treats the boolean returned by
applyParameterValuesFromMap as "this attachment was consumed", and a host with
no parameters of its own can never return true from it. Dropping the write-in
therefore made every Click Slot run report its own required Slot node as an
incompatible parameter. NodeRuntimeParameterResolver now claims the slot
explicitly when the owner is CLICK_SLOT and the attachment provides
INVENTORY_SLOT, in the same shape as the existing MOVE_ITEM and BREAK
clauses beside it. Worth knowing generally: a parameter host that keeps no
parameters of its own needs one of these claims, or attachment-time compatibility
and run-time compatibility disagree.

Saved presets. Nothing migrates. The removed parameter never held a value the
attached node did not already supply, and it was never editable — before this
branch, Click Slot rendered no field for it, so the only way to name a slot was
the attachment. The mode is absent from old saves and falls back to the
constructor default CLICK_SLOT_LEFT, which is the click those presets were
already sending. I have not loaded a pre-existing preset in a client to confirm
this end to end; the reasoning above is the argument, and NodeClickSlotTest
pins the null-mode fallback.

Why the field existed at all in this branch. The first draft kept
click_slot_index as a mode parameter on all three modes, on the theory that a
node with modes reads mode parameters instead of type parameters
(NodeCatalog.initializeParameters) and dropping it would lose saved values.
That was true of the mechanism but wrong about this node — the value was never
the write-in's to lose. Testing surfaced it as a visibly redundant second field
next to the slot.

Lang keys. NodeMode.getDisplayName ignores the display strings in the enum
constructor and builds pathmind.node.mode.<name> as a translation key, so all
three modes have en_us.json entries plus .desc.

Click Slot always sent ClickType.PICKUP, so shift-clicking a stack into the
other container or swapping it to the offhand with F had to be built out of
Move Item or the raw packet fabricator in UI Utils. Both are more work than the
click they stand in for, and neither matches what the server sees from a real
player.

Click Slot gains three modes, mapping to what the vanilla screen sends for the
same input: Left Click is PICKUP and stays the default, Shift Click is
QUICK_MOVE, and F is SWAP on button 40, the offhand's button index in
AbstractContainerScreen.

Two supporting changes:

- Click Slot is tagged RENDER_INLINE_PARAMETERS. NodeGraph.rendersInline
  Parameters gates the parameter strip and the mode selector is drawn inside it,
  so without the tag the modes would exist but not be selectable.

- The click_slot_index write-in parameter is removed, and the parameter slot is
  relabelled from Selection to Slot. The node had two ways to name a slot and
  only one of them ever won: the parameter slot is required, so every Click Slot
  has a Slot node attached, and that node's value was copied over the write-in
  on every run by applyParameterValuesFromMap. The field was redundant by
  construction. With no host parameter to copy into, the executor now reads the
  index straight off the attachment, resolving variable indirection the same way
  the selection type already does. Parameter preprocessing needs the same claim:
  it marks a slot handled by writing the attached node's value into one of the
  host's own parameters, and a host with none left would have reported its own
  Slot node as an incompatible parameter.

Saved presets are unaffected. The removed parameter never held a value the
attached node did not already supply, and it was not editable before this change
either, since Click Slot rendered no field for it.

Mode display names get lang entries, since NodeMode.getDisplayName ignores the
strings in the enum constructor and builds "pathmind.node.mode.<name>" as a
translation key.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Gaetarra
Gaetarra force-pushed the feature/click-slot-modes branch from 4dfc7e8 to 288aff3 Compare August 30, 2026 23:49
@ryduzz1

ryduzz1 commented Sep 1, 2026

Copy link
Copy Markdown
Member

Implemented and tested in c2d40d3, thanks!

@ryduzz1 ryduzz1 closed this Sep 1, 2026
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