Skip to content

Allow aspect settings to be determined by variables - #1707

Merged
rubensworks merged 4 commits into
master-1.21-ltsfrom
claude/aspect-settings-variable-slots-fdjwp3
Aug 30, 2026
Merged

Allow aspect settings to be determined by variables#1707
rubensworks merged 4 commits into
master-1.21-ltsfrom
claude/aspect-settings-variable-slots-fdjwp3

Conversation

@rubensworks

@rubensworks rubensworks commented Aug 25, 2026

Copy link
Copy Markdown
Member

Closes CyclopsMC/IntegratedTunnels#278

Aspect settings (aspect properties) could only hold static values before.
Every aspect setting now gets an optional variable slot in the aspect settings gui, just like the variable slots that the part offset gui got.
When a variable is present in that slot, its value overrides the statically configured value of that setting.

This is generic over all aspect properties, so add-ons such as IntegratedTunnels get it for free for their settings (channel, slot, exact match, ...).

Gui

  • The aspect settings gui gets one variable slot per setting. Since the gui already pages through settings with the < / > buttons, only the slot of the setting that is currently being configured is visible; the gui informs the server which setting is active through AbstractContainerMenu#clickMenuButton.
  • An ok/error signal is drawn next to the slot when it holds a variable, with the error (or an explanation that the setting is variable-driven) as tooltip.
  • The manual input field is disabled while the setting is driven by a variable, and shows the value that its variable currently produces, refreshed continuously, so that players can inspect what a variable evaluates to.
  • The aspect properties tooltip of the part gui (added in Show modified aspect property values in tooltip #1706) now also shows variable-driven values, refreshed continuously. Values that are driven by a variable are always listed there, even when they happen to equal the default, since they can change at any moment.
  • The gui and its texture are 24px taller to make room for the slot row.

Behaviour

  • Variables are stored in a named inventory per aspect (aspectVariables_<aspect name>) inside the part state, so they are persisted with the part and dropped when the part is broken.
  • PartStateAspectVariablesHandler evaluates them on each part update tick and reloads a slot when its variable is invalidated, mirroring PartStateOffsetHandler.
  • The statically configured value is left untouched, and remains the fallback when the slot is empty, the variable errors, its value type does not match the setting, or the value does not pass the setting's validator.

API

All additive, with defaults, so existing implementations keep working:

  • IAspect#getStaticProperties: the configured properties without variable-driven overrides. IAspect#getProperties now returns the variable-driven values where present.
  • IPartState#updateAspectVariables, #markAspectVariablesChanged, #markAspectPropertiesChanged, #getAspectVariableError, #getAspectVariableValue, #getAspectPropertiesVariableDriven
  • IPartType#onAspectVariablesChanged
  • IPartState#loadInventoryNamed now bounds-checks against the target inventory size, so a shrunken property list can not cause an out-of-bounds crash.
  • ContainerMultipartAspects#getModifiedAspectPropertyValues became public.

Tests

New GameTestsAspectVariables covers:

  • the default and statically configured value being used when no variable is present,
  • a constant variable overriding the static value, without modifying it,
  • a variable whose value changes over time being picked up,
  • removing a variable falling back to the static value,
  • a wrong value type and a value rejected by the setting's validator both producing an error and falling back to the static value,
  • variable-driven settings on the redstone writer: strong power true (a wire on top of a solid block only lights up under strong power), strong power false, a variable-driven pulse length, a variable-driven pulse emit value, and strong power driven by a redstone clock so that it keeps toggling,
  • a variable that is resolved through the network (variable store) instead of a constant,
  • the variables surviving a part state serialization round-trip,
  • the variables being dropped when the part is broken,
  • the aspect settings container storing the variable in the part state, and only exposing/accepting the slot of the active setting,
  • the value shown in the aspect settings gui following its variable (including a dynamically changing one) and falling back to the static value after removal,
  • the part gui properties tooltip showing the variable-driven value, and showing it even when it equals the default.

./gradlew build and ./gradlew runGameTestServer (916 tests) pass.

Note on an existing test helper

GameTestHelpersIntegratedDynamics#setAspectProperty mutated the aspect's shared default properties object whenever a part had no properties stored yet, which leaked configuration across game tests. It now clones instead. Two redstone pulse tests relied on that leak and set their pulse length on the wrong part/aspect; they now set it on the writer part itself.


Generated by Claude Code

@coveralls

coveralls commented Aug 25, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 46.799% (+1.3%) from 45.463% — claude/aspect-settings-variable-slots-fdjwp3 into master-1.21-lts

claude added 2 commits August 28, 2026 18:37
Every aspect setting now has an optional variable slot in the aspect
settings gui, similar to the variable slots of the part offset gui.
When a variable is present, its value overrides the statically
configured value of that setting.

Closes CyclopsMC/IntegratedTunnels#278

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEB2eDBd8VaFgqeJRwaSyk
The value shown for a variable-driven aspect setting is now the value
that its variable currently produces, so that players can inspect what a
variable evaluates to. The same values are shown in the aspect properties
tooltip of the part gui, and both are refreshed continuously.

Also center the variable slot in the aspect settings gui.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEB2eDBd8VaFgqeJRwaSyk
@rubensworks
rubensworks force-pushed the claude/aspect-settings-variable-slots-fdjwp3 branch from 1045e6d to c0671c1 Compare August 28, 2026 18:42
claude added 2 commits August 29, 2026 13:04
The tooltip only used the property values that the server syncs.
The statically configured values can be determined client-side as well,
as they are part of the part state that is synced anyway,
so they are now determined locally, with the synced values layered on top
for the values that only the server knows, being those driven by variables.

Also show the value of a setting whose variable is erroring in red,
as the shown value is then its statically configured fallback value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEB2eDBd8VaFgqeJRwaSyk
The values that are shown in the aspect properties tooltip of the part gui
were fully determined by the values that the server syncs to the container.
They are now also determined client-side, from the part state, which is
known on both sides:

* Properties that hold a variable in their setting slot are always shown,
  as the part state contains the variable slots of all aspects.
  The value that the variable produces is layered on top of this
  as soon as the server syncs it.
* The errors of aspect setting variables are now stored inside the part state,
  just like the offset variable errors already were,
  so that the tooltip can render erroring values in red without any syncing.
  An update is sent to the client whenever such an error appears or disappears.

Determining the shown values also no longer fails when the part
disappears while its gui is open.

Adds game tests for the full server-to-client path of these values:
the server-side container broadcasting them, the value ids they are
synced under being identical on both sides, the client-side container
showing them, and the fallbacks when nothing was synced (yet).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEB2eDBd8VaFgqeJRwaSyk
@rubensworks
rubensworks merged commit 9212527 into master-1.21-lts Aug 30, 2026
7 checks passed
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