Skip to content

Conversation

@Saereth
Copy link

@Saereth Saereth commented Dec 11, 2025

What

The Root Cause was MachineRenderState relying on identity-based lookups (IdentityHashMap in model rendering, IdMapper in network sync).

However, StateHolder.setValue() only returns interned instances when called on an already-interned state. When non-interned states entered the system via deserialization or network sync, identity lookups failed, causing blocks to render nothing.

Implementation Details

  • MachineRenderState - Added intern() method that looks up the canonical state instance from StateDefinition.getPossibleStates(), and wired it into the CODEC via xmap() so deserialized states are always interned
    • MetaMachineBlockEntity - setRenderState() now validates the state belongs to the correct definition and interns it; onLoad() also validates since @persisted bypasses the setter.
    • MachineRenderStatePayload - Interns state before registry ID lookup during network write
    • MultiblockControllerMachine - onPartUnload() now immediately invalidates the structure when a part is removed, ensuring all remaining parts have their render state updated to unformed
    • MachineModel - Added fallback rendering that searches by property values when identity lookup fails, preventing invisible blocks if a non-interned state slips through and is mostly a failsafe

Outcome

  • Multiblock renders are now consistent across reloads and break/replace operations with no more invisible blocks due to invalid states.

Saereth and others added 3 commits December 11, 2025 06:32
Fixes GregTechCEu#4276
Addresses an issue where multiblocks sometimes fail to render correctly after initial chunk loading due to the block entity not being fully initialized when the chunk is first rendered.

Forces a model data refresh on the client side when a block entity finishes loading to ensure correct rendering of multiblocks, especially in cases where the chunk was rendered before the block entity was fully available. Also, it avoids returning null model render types, which could cause the block to be invisible, by instead returning the render types of the default model.
…ck parts

The Root Cause was MachineRenderState relying on identity-based lookups (IdentityHashMap in model rendering, IdMapper in network sync).

However, StateHolder.setValue() only returns interned instances when called on an already-interned state. When non-interned  states entered the system via deserialization or network sync, identity lookups failed, causing blocks to render nothing.

The Fix:
- MachineRenderState - Added intern() method that looks up the canonical state instance from StateDefinition.getPossibleStates(), and wired it into the CODEC via xmap() so deserialized states are always interned
  - MetaMachineBlockEntity - setRenderState() now validates the state belongs to the correct definition and interns it; onLoad() also validates since @persisted bypasses the setter.
  - MachineRenderStatePayload - Interns state before registry ID lookup during network write
  - MultiblockControllerMachine - onPartUnload() now immediately invalidates the structure when a part is removed, ensuring all remaining parts have their render state updated to unformed
  - MachineModel - Added fallback rendering that searches by property values when identity lookup fails, preventing invisible blocks if a non-interned state slips through and is mostly a failsafe
@Saereth Saereth requested a review from a team as a code owner December 11, 2025 21:47
@github-actions github-actions bot added the 1.21 label Dec 11, 2025
Fixes dedicated server crash caused by client-side class loading. MachineRenderState was in client/model/machine but used by server-side code (MetaMachineBlockEntity, MachineRenderStatePayload, etc.). When the dedicated server loaded these classes, it triggered  loading of other client-only classes in that package, causing LDLRegisterClient and GuiGraphics class loading errors.
Saereth and others added 4 commits December 12, 2025 11:03
-  Added @persisted to controllerPositions in MultiblockPartMachine so controller references are available immediately on load
- Add onLoad() to rebuild controllers from persisted positions and
  clear IS_FORMED if controllers can't be resolved (prevents inconsistent visual state with overlays but no texture overrides)
- Fix MetaMachineBlockEntity.onLoad() to always intern() the render state after NBT load, ensuring it matches modelsByState keys
@jurrejelle jurrejelle added type: bugfix General bug fixes 1.20.1 Release: Patch - 0.0.X Smaller changes that either are bug fixes or very minor tweaks. and removed 1.20.1 labels Dec 14, 2025
@TechLord22 TechLord22 deleted the branch GregTechCEu:re/1.21-with-love December 23, 2025 03:30
@TechLord22 TechLord22 closed this Dec 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.21 Release: Patch - 0.0.X Smaller changes that either are bug fixes or very minor tweaks. type: bugfix General bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants