Skip to content

Commit 849223e

Browse files
committed
Fix multiblock parts not showing formed textures on world load
- 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
1 parent 8784aa0 commit 849223e

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

src/main/java/com/gregtechceu/gtceu/api/blockentity/MetaMachineBlockEntity.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,15 @@ public void setRemoved() {
176176
@Override
177177
public void onLoad() {
178178
super.onLoad();
179-
// Validate render state after NBT load - @Persisted writes directly to field via reflection,
180-
// bypassing setRenderState(), so we need to validate here as well
181-
if (renderState != null && !renderState.is(getDefinition())) {
182-
this.renderState = correctRenderStateDefinition(renderState);
179+
// Validate and intern render state after NBT load - @Persisted writes directly to field via reflection,
180+
// bypassing setRenderState(), so we need to validate and intern here as well
181+
if (renderState != null) {
182+
if (!renderState.is(getDefinition())) {
183+
this.renderState = correctRenderStateDefinition(renderState).intern();
184+
} else {
185+
// Ensure the state is properly interned even if definition is correct
186+
this.renderState = renderState.intern();
187+
}
183188
}
184189
metaMachine.onLoad();
185190
}

src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/MultiblockPartMachine.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList;
1313

1414
import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced;
15+
import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted;
1516
import com.lowdragmc.lowdraglib.syncdata.annotation.RequireRerender;
1617
import com.lowdragmc.lowdraglib.syncdata.annotation.UpdateListener;
1718
import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder;
@@ -38,6 +39,7 @@ public class MultiblockPartMachine extends MetaMachine implements IMultiPart {
3839
protected static final ManagedFieldHolder MANAGED_FIELD_HOLDER = new ManagedFieldHolder(MultiblockPartMachine.class,
3940
MetaMachine.MANAGED_FIELD_HOLDER);
4041

42+
@Persisted
4143
@DescSynced
4244
@RequireRerender
4345
@UpdateListener(methodName = "onControllersUpdated")
@@ -114,6 +116,26 @@ protected RecipeHandlerList getHandlerList() {
114116
return handlerList;
115117
}
116118

119+
@Override
120+
public void onLoad() {
121+
super.onLoad();
122+
// Rebuild controllers from persisted positions on load
123+
// @UpdateListener only fires on sync updates, not on NBT load
124+
if (!controllerPositions.isEmpty()) {
125+
onControllersUpdated(controllerPositions, Collections.emptySet());
126+
// If we couldn't resolve controllers (loading order or cross-chunk),
127+
// clear the formed state to avoid inconsistent visuals (overlays without texture overrides).
128+
// The async multiblock validation will restore formed state properly when ready.
129+
if (controllers.isEmpty()) {
130+
MachineRenderState renderState = getRenderState();
131+
if (renderState.hasProperty(GTMachineModelProperties.IS_FORMED) &&
132+
renderState.getValue(GTMachineModelProperties.IS_FORMED)) {
133+
setRenderState(renderState.setValue(GTMachineModelProperties.IS_FORMED, false));
134+
}
135+
}
136+
}
137+
}
138+
117139
@Override
118140
public void onUnload() {
119141
super.onUnload();

0 commit comments

Comments
 (0)