Pattern Repeater add to interface terminal support (#1278)

Co-authored-by: Martin Robertz <dream-master@gmx.net>
Co-authored-by: Kogepan229 <73163994+Kogepan229@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-05-25 12:35:50 +02:00
1 parent 232223897e
commit 25a6dff3d6
2 files changed
+123 -89

No files matched your search

@@ -49,6 +49,7 @@ import appeng.helpers.IInterfaceHost;
import appeng.helpers.InventoryAction;
import appeng.items.misc.ItemEncodedPattern;
import appeng.parts.AEBasePart;
import appeng.parts.misc.PartPatternRepeater;
import appeng.parts.p2p.PartP2PTunnel;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
@@ -286,6 +287,27 @@ public final class ContainerInterfaceTerminal extends AEBaseContainer implements
return playerInv.addItems(stack);
}
private void fletchRepeaters(final IGrid grid, final Set<IGrid> gridSet) {
for (IGridNode node : grid.getMachines(PartPatternRepeater.class)) {
final PartPatternRepeater rep = (PartPatternRepeater) node.getMachine();
if (!rep.isProvider() || rep.getPair() == null || !node.isActive() || rep.getPair().isProvider()) continue;
final IGridNode n = rep.getPair().getGridNode();
if (n == null || !n.isActive()) continue;
final IGrid currentGrid = n.getGrid();
if (!gridSet.contains(currentGrid)) {
gridSet.add(currentGrid);
this.fletchRepeaters(currentGrid, gridSet);
}
}
}
private Set<IGrid> collectReachableGrids() {
final Set<IGrid> gridSet = new HashSet<>();
gridSet.add(this.grid);
this.fletchRepeaters(this.grid, gridSet);
return gridSet;
}
/**
* Finds out whether any updates are needed, and if so, incrementally updates the list.
*/
@@ -294,86 +316,88 @@ public final class ContainerInterfaceTerminal extends AEBaseContainer implements
var supported = AEApi.instance().registries().interfaceTerminal().getSupportedClasses();
Set<IInterfaceViewable> visited = new HashSet<>();
for (Class<? extends IInterfaceViewable> c : supported) {
for (IGridNode node : grid.getMachines(c)) {
IInterfaceViewable machine = (IInterfaceViewable) node.getMachine();
/* First check if we are already tracking this node */
if (tracked.containsKey(machine)) {
/* Check for updates */
InvTracker known = tracked.get(machine);
for (final IGrid currentGrid : this.collectReachableGrids()) {
for (Class<? extends IInterfaceViewable> c : supported) {
for (IGridNode node : currentGrid.getMachines(c)) {
IInterfaceViewable machine = (IInterfaceViewable) node.getMachine();
/* First check if we are already tracking this node */
if (tracked.containsKey(machine)) {
/* Check for updates */
InvTracker known = tracked.get(machine);
/* Name changed? */
String rawName = machine.getRawName();
String suffix = machine.getNameSuffix();
/* Name changed? */
String rawName = machine.getRawName();
String suffix = machine.getNameSuffix();
if (!Objects.equals(known.name, rawName) || !Objects.equals(known.suffix, suffix)) {
if (!Objects.equals(known.name, rawName) || !Objects.equals(known.suffix, suffix)) {
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addRenamedEntry(known.id, rawName, suffix);
known.name = rawName;
known.suffix = suffix;
}
/* Status changed? */
boolean isActive = node.isActive();
if (!known.online && isActive) {
/* Node offline -> online */
known.online = true;
if (update == null) update = new PacketInterfaceTerminalUpdate();
known.updateNBT();
update.addOverwriteEntry(known.id).setOnline(true).setItems(new int[0], known.invNbt);
} else if (known.online && !isActive) {
/* Node online -> offline */
known.online = false;
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setOnline(false);
}
// visibility changed?
final boolean machineShouldDisplay = getTerminalVisibility(machine);
if (known.shouldDisplay != machineShouldDisplay) {
known.shouldDisplay = machineShouldDisplay;
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setTerminalVisible(machineShouldDisplay);
}
// If the size changed, we need to do a full update of inventory
if (known.rows != machine.rows() || known.rowSize != machine.rowSize()
|| known.numSlots != machine.numSlots()) {
known.rows = machine.rows();
known.rowSize = machine.rowSize();
known.numSlots = machine.numSlots();
known.updateNBT();
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setItems(new int[0], known.invNbt)
.setSize(known.rows, known.rowSize, known.numSlots);
}
int priority = machine.getPriority();
if (known.priority != priority) {
known.priority = priority;
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setPriority(priority);
}
visited.add(machine);
} else {
/* Add a new entry (always, including hidden ones) */
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addRenamedEntry(known.id, rawName, suffix);
known.name = rawName;
known.suffix = suffix;
InvTracker entry = new InvTracker(nextId++, machine, node.isActive());
update.addNewEntry(entry.id, entry.name, entry.online).setSuffix(entry.suffix)
.setLoc(entry.x, entry.y, entry.z, entry.dim, entry.side.ordinal())
.setItems(entry.rows, entry.rowSize, entry.numSlots, entry.invNbt)
.setReps(machine.getSelfRep(), machine.getDisplayRep())
.setP2POutput(machine instanceof PartP2PTunnel<?>p2pTunnel && p2pTunnel.isOutput())
.setSupportedStackTypes(entry.supportedStackTypes).setPriority(entry.priority)
.setTerminalVisible(entry.shouldDisplay);
// Ensure the client applies the correct visibility even if PacketAdd state gets corrupted
// client-side. PacketOverwrite handling is known to work reliably.
update.addOverwriteEntry(entry.id).setTerminalVisible(entry.shouldDisplay);
tracked.put(machine, entry);
trackedById.put(entry.id, entry);
visited.add(machine);
}
/* Status changed? */
boolean isActive = node.isActive();
if (!known.online && isActive) {
/* Node offline -> online */
known.online = true;
if (update == null) update = new PacketInterfaceTerminalUpdate();
known.updateNBT();
update.addOverwriteEntry(known.id).setOnline(true).setItems(new int[0], known.invNbt);
} else if (known.online && !isActive) {
/* Node online -> offline */
known.online = false;
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setOnline(false);
}
// visibility changed?
final boolean machineShouldDisplay = getTerminalVisibility(machine);
if (known.shouldDisplay != machineShouldDisplay) {
known.shouldDisplay = machineShouldDisplay;
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setTerminalVisible(machineShouldDisplay);
}
// If the size changed, we need to do a full update of inventory
if (known.rows != machine.rows() || known.rowSize != machine.rowSize()
|| known.numSlots != machine.numSlots()) {
known.rows = machine.rows();
known.rowSize = machine.rowSize();
known.numSlots = machine.numSlots();
known.updateNBT();
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setItems(new int[0], known.invNbt)
.setSize(known.rows, known.rowSize, known.numSlots);
}
int priority = machine.getPriority();
if (known.priority != priority) {
known.priority = priority;
if (update == null) update = new PacketInterfaceTerminalUpdate();
update.addOverwriteEntry(known.id).setPriority(priority);
}
visited.add(machine);
} else {
/* Add a new entry (always, including hidden ones) */
if (update == null) update = new PacketInterfaceTerminalUpdate();
InvTracker entry = new InvTracker(nextId++, machine, node.isActive());
update.addNewEntry(entry.id, entry.name, entry.online).setSuffix(entry.suffix)
.setLoc(entry.x, entry.y, entry.z, entry.dim, entry.side.ordinal())
.setItems(entry.rows, entry.rowSize, entry.numSlots, entry.invNbt)
.setReps(machine.getSelfRep(), machine.getDisplayRep())
.setP2POutput(machine instanceof PartP2PTunnel<?>p2pTunnel && p2pTunnel.isOutput())
.setSupportedStackTypes(entry.supportedStackTypes).setPriority(entry.priority)
.setTerminalVisible(entry.shouldDisplay);
// Ensure the client applies the correct visibility even if PacketAdd state gets corrupted
// client-side. PacketOverwrite handling is known to work reliably.
update.addOverwriteEntry(entry.id).setTerminalVisible(entry.shouldDisplay);
tracked.put(machine, entry);
trackedById.put(entry.id, entry);
visited.add(machine);
}
}
}
@@ -14,10 +14,12 @@ import static appeng.util.Platform.readAEStackListNBT;
import static appeng.util.Platform.writeAEStackListNBT;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.entity.player.EntityPlayer;
@@ -74,7 +76,7 @@ import cpw.mods.fml.relauncher.SideOnly;
public class PartPatternRepeater extends PartBasicState
implements ICraftingProvider, IStorageInterceptor, ICraftingPostPatternChangeListener {
private final List<ICraftingPatternDetails> craftingList = new ArrayList<>();
private final Set<ICraftingPatternDetails> craftingList = new HashSet<>();
private IItemList<IAEStack<?>> waitingStacks = AEApi.instance().storage().createAEStackList();
private CraftingGridCache targetCraftingGrid = null;
private CraftingGridCache currentCraftingGrid = null;
@@ -259,7 +261,10 @@ public class PartPatternRepeater extends PartBasicState
}
}
private boolean duringFletchPatterns = false;
public void init() {
if (this.duringFletchPatterns) return;
this.craftingList.clear();
this.targetCraftingGrid = null;
this.targetNetworkProxy = null;
@@ -277,27 +282,28 @@ public class PartPatternRepeater extends PartBasicState
this.pairPatternRepeater = ppr;
this.targetNetworkProxy = ppr.getProxy();
if (this.provider && !ppr.provider) {
if (this.provider) {
if (ppr.provider) return;
final IGridNode gn = tcb.getGridNode(ForgeDirection.UNKNOWN);
if (gn == null) return;
this.duringFletchPatterns = true;
this.targetCraftingGrid = gn.getGrid().getCache(ICraftingGrid.class);
final ImmutableSet<Entry<IAEStack<?>, ImmutableList<ICraftingPatternDetails>>> tempPatterns = this.targetCraftingGrid
.getCraftingMultiPatterns().entrySet();
for (Entry<IAEStack<?>, ImmutableList<ICraftingPatternDetails>> entry : tempPatterns) {
this.craftingList.addAll(entry.getValue());
tempPatterns.forEach((entry) -> this.craftingList.addAll(entry.getValue()));
try {
this.getProxy().getGrid()
.postEvent(new MENetworkCraftingPatternChange(this, this.getProxy().getNode()));
} catch (final GridAccessException e) {
// :P
}
if (!this.craftingList.isEmpty()) {
try {
this.getProxy().getGrid()
.postEvent(new MENetworkCraftingPatternChange(this, this.getProxy().getNode()));
} catch (final GridAccessException e) {
// :P
}
}
this.duringFletchPatterns = false;
} else {
final IGridNode gn = this.getGridNode(ForgeDirection.UNKNOWN);
if (gn == null) return;
@@ -405,7 +411,7 @@ public class PartPatternRepeater extends PartBasicState
@Override
public void onPostPatternChange() {
if (!this.provider && pairPatternRepeater != null) pairPatternRepeater.init();
if (!this.provider && this.pairPatternRepeater != null) this.pairPatternRepeater.init();
}
@Override
@@ -430,4 +436,8 @@ public class PartPatternRepeater extends PartBasicState
public IItemList<IAEStack<?>> getWaitingStacks() {
return this.waitingStacks;
}
public PartPatternRepeater getPair() {
return this.pairPatternRepeater;
}
}