Skip to content

Upmerge expressions in the Logic Programmer to 26.3 - #1783

Merged
rubensworks merged 4 commits into
master-26from
feature/expression-cards-26.3
Nov 8, 2026
Merged

rubensworks merged 4 commits into
master-26from
feature/expression-cards-26.3

Conversation

@rubensworks

Copy link
Copy Markdown
Member

Merges master-26-lts into master-26. This brings the Logic Programmer expressions of #1766 and #1781 to Minecraft 26.3. It is a single merge commit.

Conflicts

Porting to 26.3

SDL instead of GLFW

26.3 replaced GLFW with SDL3. Key codes are now SDL scancodes, mouse buttons count from 1, and the modifier masks changed. Most of this compiles either way, so I checked each use rather than relying on the compiler.

  • Key codes and mouse buttons: these now use InputConstants. Mouse buttons are compared only through InputConstants.MOUSE_BUTTON_LEFT and MOUSE_BUTTON_RIGHT. No literal button or key numbers are left in the expression code.
  • Undo and redo: these read KeyEvent.shortcutKey(), the semantic key, against SDLKeycode.SDLK_Z and SDLK_Y. Vanilla does the same for Ctrl+A/C/V/X, so the shortcuts follow the keyboard layout. key() is now the physical key.
  • Ctrl, Cmd and Alt: these come from the key event. Vanilla's edit shortcuts use hasControlDownWithQuirk(), which is Cmd on macOS. On 26.3, Minecraft#hasControlDown() checks only the physical Ctrl keys, where on 26.1 it meant Cmd on macOS. Without this change, Cmd+Left, Cmd+Backspace and the other macOS line keys would have stopped working.
  • Enter: Enter in the text and in the value editor uses KeyEvent.isConfirmation().
  • Text input: SDL only delivers typed characters while text input is started. ExpressionTextField is not an EditBox, so it now calls TextInputManager#onTextInputFocusChange when it gains or loses focus. Without this, typing into the expression text does nothing on 26.3. The value editor and the other fields are EditBoxes, which already do this.

Block literals

In 26.3, the BlockState codec writes id and properties instead of Name and Properties. A block without properties is written as its id alone.

  • Text form: blocks are now written @Block{id: "minecraft:oak_log", properties: {axis: "x"}}. Without properties, a block prints as @Block"minecraft:stone", which matches how entities already print (@Entity"<uuid>").
  • Parser check: the parser rejects a value when writing it back loses something that was typed. That check now accepts a compound holding only an id that is written back as the id alone. Without this, @Block{id: "stone"} was rejected as "value changed".
  • Both forms are read: @Block "stone" and @Block{id: "stone"}.
  • Tests: the block literal integration tests now use the 26.3 keys. TestExpressionValueLiterals.testIsKept covers the new rule, including that {id: "stoen"} written as "minecraft:air" is still rejected.

Other renames

  • MinMaxBounds moved to advancements.predicates.
  • Minecraft#screen is now gui.screen().
  • getGuiLeft() and getGuiTop() are now getLeftPos() and getTopPos().
  • DisplayInfo#getIcon() is now icon().
  • ChatFormatting.getByName is gone. Tooltip wrapping maps a TextColor to its format by name instead.

Testing

  • ./gradlew build: all 1057 unit tests pass.
  • ./gradlew runGameTestServer: all 1097 game tests pass, including the expression integration tests.
  • Visual test in a 26.3 dev client with clientdevbridge, in the 26.1 test world from Upmerge expressions in the Logic Programmer to 26.1 #1781, upgraded by 26.3:
    • World upgrade: the Display Panels holding expression cards still show 14 (2 * 5 + 4) and [20], and the expression advancements stay granted.
    • Text input: clicking the expression text starts SDL text input owned by ExpressionTextField, and Escape stops it. The value editor's field does the same. I read this from TextInputManager, since clientdevbridge may inject characters directly.
    • Typing: typing in the start panel switches the root operator.
    • Keys: I sent real 26.3 KeyEvents (SDL scancode, keycode and modifiers) through eval:
      • Home, End and Ctrl+Right (word).
      • Ctrl+Backspace (word).
      • Enter (new line).
      • Ctrl+Z, Ctrl+Y and Ctrl+Shift+Z.
      • Ctrl+A.
      • Down and Enter in the completion popup ("ab".l to "ab".length()).
    • Mouse: with SDL buttons:
      • Right-clicking a slot clears it.
      • Left-clicking selects it and opens the value editor, and Enter applies the value.
      • Double-clicking opens a nested operator, with the breadcrumbs.
      • Dragging a parameter chip into a slot gives (x: Integer) => x > 1.
    • Blocks: @Block "stone" == @Block{id: "stone"} && @Block{id: "oak_log", properties: {axis: "x"}} != @Block "stone" applies as a Boolean, and Format prints it in the forms above.
    • Cards: writing a card, and its tooltip (n => n > 10, Integer -> Boolean).
    • Copying:
      • In a crafting grid, the card left in the grid gets a new id, and both keep the expression.
      • A Wrench paste of a panel holding an expression card gives a new id and shows 14.
    • Book: the Expressions tutorial (with the advancements and rewards) and the manual's Expressions pages.
  • Not tested: the macOS key behavior, since the client runs on Linux. The Cmd mapping follows vanilla's hasControlDownWithQuirk().

Found, not fixed here

  • Labels are not saved in singleplayer. This also affects master-26-lts.
    • LabelsWorldStorage.Access#get() returns the client-only instance whenever MinecraftHelpers#isClientSide() is true. That checks the physical side, so it is true for the integrated server as well.
    • In singleplayer, labels therefore never reach the saved data and are lost when the world is left. labels.dat stays empty, and #label references in expressions stop resolving after a restart.
    • isClientSideThread() is probably what was meant. This code is not touched by the expressions, so I left it for a separate fix.
  • Book advancement tooltips: descriptions still don't wrap in CyclopsCore's AdvancementButton, as noted in Upmerge expressions in the Logic Programmer to 26.1 #1781.
  • Loading warnings: a 26.3 client shows warnings that CyclopsCore and CommonCapabilities use the deprecated logoFile property. They come from those mods, not from this one.

Generated by Claude Code

rubensworks and others added 4 commits November 8, 2026 16:40
This allows constant values and multiple nested operators
to be combined within a single variable card, without having
to combine multiple variable cards.

These expressions can either be created through the existing
Logic Programmer interface, or they can be written in a text-form
for easy exchange across worlds and players.
Ports the expressions of the Logic Programmer (#1766) to Minecraft 26.1:
- Client-only classes of the expression panel move to core.logicprogrammer.client,
  the typed text is kept by the screen instead of the container, and the card
  facades get client classes for their model overlays.
- Expression trees are written with ValueOutput and ValueInput, so values and
  operators in them are serialized as everywhere else in 26.1.
- Values written with their type in the text leave out the "v" field of the
  serialized value, and items are written as their stack, so the text form is
  the same as in 1.21, such as @item{id: "minecraft:diamond"}.
- Rendering uses GuiGraphicsExtractor, with strata instead of depth for the
  popups and dragged parameters, and input uses the new event types.
- Tests use JUnit 5 and the game test API of 26.1. Unknown items, invalid entity
  ids and non-compound lists can no longer be read at all, so their error is
  bad_value instead of value_changed, and an empty entity is written as @entity{}.
- The icons of the expression advancements are converted to the 26.1 format, and
  an unreadable operator makes an expression card invalid instead of throwing,
  which crashed the book on the Expressions tutorial.
- The expression action packet no longer uses @onlyin, which NeoForge 26.1 warns
  about on every start.

Also fixes the invisible operator symbol in the Logic Programmer, which was drawn
with color 0, fully transparent since 26.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
Upmerge expressions in the Logic Programmer to 26.1
Ports the expressions of the Logic Programmer to Minecraft 26.3:
- Keys and mouse buttons use the SDL codes of InputConstants instead of GLFW.
  Undo and redo read the shortcut key, so they follow the keyboard layout, and
  Ctrl, or Cmd on macOS, comes from the key event, as Minecraft#hasControlDown
  no longer means Cmd on macOS.
- The expression text field starts SDL text input when it gets focus, without
  which no typed characters arrive.
- Blocks without properties are written as their id alone in 26.3, so a typed
  compound with only an id is kept when it is written as that id.
- MinMaxBounds, the screen, the left and top of containers, advancement icons and
  color names follow their 26.3 replacements.

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

Copy link
Copy Markdown

Coverage Status

coverage: 58.683% (+0.3%) from 58.387% — feature/expression-cards-26.3 into master-26

@rubensworks
rubensworks merged commit dc0e944 into master-26 Nov 8, 2026
10 checks passed
@rubensworks
rubensworks deleted the feature/expression-cards-26.3 branch November 8, 2026 19:11
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.

3 participants