Allow Phantom Slots to use Sync Handler (#1317)

Co-authored-by: Martin Robertz <dream-master@gmx.net>
Co-authored-by: lc-1337 <62835225+lc-1337@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-05-25 12:00:41 +02:00
1 parent a49fcb3a48
commit 232223897e
11 files changed
+82 -182

No files matched your search

@@ -708,9 +708,7 @@ public abstract class AEBaseGui extends GuiContainer implements IGuiTooltipHandl
@Override
public void updateScreen() {
super.updateScreen();
if (this.inventorySlots instanceof AEBaseContainer container) {
container.tickClientSync();
}
this.flushPendingSync();
}
protected void closeGui() {
@@ -718,9 +716,9 @@ public abstract class AEBaseGui extends GuiContainer implements IGuiTooltipHandl
this.mc.thePlayer.closeScreen();
}
private void flushPendingSync() {
protected final void flushPendingSync() {
if (this.inventorySlots instanceof AEBaseContainer container) {
container.getSyncManager().flushClient();
container.getSyncManager().flushSync();
}
}
@@ -154,7 +154,7 @@ public class GuiCellRestriction extends GuiSub {
protected void keyTyped(final char character, final int key) {
if (key == Keyboard.KEY_RETURN || key == Keyboard.KEY_NUMPADENTER) {
this.cellRestriction.cellRestrictionDataSync.set(filterCellRestriction());
this.cellRestriction.tickClientSync();
this.flushPendingSync();
NetworkHandler.instance.sendToServer(new PacketSwitchGuis());
} else
if (!(this.amountField.textboxKeyTyped(character, key) || this.typesField.textboxKeyTyped(character, key)))
@@ -33,7 +33,6 @@ import appeng.core.sync.GuiBridge;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketValueConfig;
import appeng.tile.inventory.IAEStackInventory;
import appeng.util.Platform;
public class GuiCellWorkbench extends GuiUpgradeable {
@@ -174,7 +173,6 @@ public class GuiCellWorkbench extends GuiUpgradeable {
private void initVirtualSlots() {
this.configSlots = new VirtualMEPhantomSlot[63];
final IAEStackInventory inputInv = this.workbench.getConfig();
final int xo = 8;
final int yo = -133;
@@ -183,7 +181,7 @@ public class GuiCellWorkbench extends GuiUpgradeable {
VirtualMEPhantomSlot slot = new VirtualMEPhantomSlot(
xo + x * 18,
yo + y * 18 + 9 * 18,
inputInv,
this.workbench.configSync,
x + y * 9,
this::acceptType);
this.configSlots[x + y * 9] = slot;
@@ -194,7 +192,7 @@ public class GuiCellWorkbench extends GuiUpgradeable {
@Override
protected void handleButtonVisibility() {
this.copyMode.setState(this.workbench.getCopyMode() == CopyMode.CLEAR_ON_REMOVE);
this.copyMode.setState(this.workbench.copyModeSync.get() == CopyMode.CLEAR_ON_REMOVE);
final boolean hasFuzzy = this.cvb.getUpgradeable().getInstalledUpgrades(Upgrades.FUZZY) != 0;
final boolean hasOreFilter = this.cvb.getUpgradeable().getInstalledUpgrades(Upgrades.ORE_FILTER) != 0;
@@ -225,11 +223,11 @@ public class GuiCellWorkbench extends GuiUpgradeable {
protected void actionPerformed(final GuiButton btn) {
try {
if (btn == this.copyMode) {
NetworkHandler.instance.sendToServer(new PacketValueConfig("CellWorkbench.Action", "CopyMode"));
this.workbench.copyModeSync.rotate(false);
} else if (btn == this.partition) {
NetworkHandler.instance.sendToServer(new PacketValueConfig("CellWorkbench.Action", "Partition"));
this.workbench.partitionAction.send();
} else if (btn == this.clear) {
NetworkHandler.instance.sendToServer(new PacketValueConfig("CellWorkbench.Action", "Clear"));
this.workbench.clearAction.send();
} else if (btn == this.fuzzyMode) {
final boolean backwards = Mouse.isButtonDown(1);
@@ -80,12 +80,7 @@ public class GuiLevelEmitter extends GuiUpgradeable {
this.container.setTextField(this.amountTextField);
this.validateText();
this.config = new VirtualMEPhantomSlot(
17,
42,
GuiLevelEmitter::acceptType,
this.container::getConfigStack,
this.container::setConfigStack);
this.config = new VirtualMEPhantomSlot(17, 42, this.container.configSync, 0, GuiLevelEmitter::acceptType);
this.registerVirtualSlots(this.config);
}
@@ -17,6 +17,8 @@ import appeng.api.storage.StorageName;
import appeng.api.storage.data.AEStackTypeRegistry;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IAEStackType;
import appeng.container.sync.deltas.AEStackInventoryDelta;
import appeng.container.sync.handlers.AEStackInventorySyncHandler;
import appeng.core.AEConfig;
import appeng.core.localization.ButtonToolTips;
import appeng.core.sync.network.NetworkHandler;
@@ -35,60 +37,40 @@ public class VirtualMEPhantomSlot extends VirtualMESlot {
boolean test(VirtualMEPhantomSlot slot, IAEStackType<?> type, int mouseButton);
}
@FunctionalInterface
public interface StackGetter {
@Nullable
IAEStack<?> get();
}
@FunctionalInterface
public interface StackSetter {
void set(@Nullable IAEStack<?> stack);
}
@Nullable
private final IAEStackInventory inventory;
private final TypeAcceptPredicate acceptType;
@Nullable
private final StackGetter stackGetter;
@Nullable
private final StackSetter stackSetter;
private final AEStackInventorySyncHandler syncHandler;
public VirtualMEPhantomSlot(int x, int y, IAEStackInventory inventory, int slotIndex,
TypeAcceptPredicate acceptType) {
this(x, y, inventory, slotIndex, acceptType, null, null);
this(x, y, inventory, slotIndex, acceptType, null);
}
public VirtualMEPhantomSlot(int x, int y, TypeAcceptPredicate acceptType, StackGetter stackGetter,
StackSetter stackSetter) {
this(x, y, null, 0, acceptType, stackGetter, stackSetter);
public VirtualMEPhantomSlot(int x, int y, AEStackInventorySyncHandler syncHandler, int slotIndex,
TypeAcceptPredicate acceptType) {
this(x, y, syncHandler.get(), slotIndex, acceptType, syncHandler);
}
private VirtualMEPhantomSlot(int x, int y, @Nullable IAEStackInventory inventory, int slotIndex,
TypeAcceptPredicate acceptType, @Nullable StackGetter stackGetter, @Nullable StackSetter stackSetter) {
TypeAcceptPredicate acceptType, @Nullable AEStackInventorySyncHandler syncHandler) {
super(x, y, slotIndex);
this.inventory = inventory;
this.showAmount = false;
this.acceptType = acceptType;
this.stackGetter = stackGetter;
this.stackSetter = stackSetter;
this.syncHandler = syncHandler;
}
@Nullable
@Override
public IAEStack<?> getAEStack() {
if (this.stackGetter != null) {
return this.stackGetter.get();
}
return this.getInventory().getAEStackInSlot(this.getSlotIndex());
}
protected void setAEStack(@Nullable final IAEStack<?> stack) {
if (this.stackSetter != null) {
this.stackSetter.set(stack);
if (this.syncHandler != null) {
this.syncHandler.applyAndQueueDelta(new AEStackInventoryDelta(this.getSlotIndex(), stack));
return;
}
@@ -386,10 +386,6 @@ public abstract class AEBaseContainer extends Container {
this.syncManager.readIncoming(remoteEndpoint, buf);
}
public final void tickClientSync() {
this.syncManager.tickClient();
}
protected void bindPlayerInventory(final InventoryPlayer inventoryPlayer, final int offsetX, final int offsetY) {
// bind player inventory
for (int i = 0; i < 3; i++) {
@@ -441,7 +437,7 @@ public abstract class AEBaseContainer extends Container {
NetworkHandler.instance.sendTo(new PacketGuiDataSync(this.dataSync::writeChanges), playerMP);
}
this.syncManager.tickServer();
this.syncManager.flushSync();
}
portableSourceTick();
@@ -10,8 +10,6 @@
package appeng.container.implementations;
import static appeng.util.Platform.isServer;
import java.util.Iterator;
import net.minecraft.entity.player.EntityPlayer;
@@ -35,34 +33,44 @@ import appeng.api.storage.StorageName;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IAEStackType;
import appeng.api.storage.data.IItemList;
import appeng.container.guisync.GuiSync;
import appeng.container.interfaces.IVirtualSlotHolder;
import appeng.container.slot.OptionalSlotRestrictedInput;
import appeng.container.slot.SlotRestrictedInput;
import appeng.container.sync.ActionHandler;
import appeng.container.sync.SyncDirection;
import appeng.container.sync.SyncRegistrar;
import appeng.container.sync.handlers.AEStackInventorySyncHandler;
import appeng.container.sync.handlers.ConfigEnumSyncHandler;
import appeng.helpers.ICellRestriction;
import appeng.tile.inventory.AppEngNullInventory;
import appeng.tile.inventory.IAEStackInventory;
import appeng.util.IterationCounter;
import appeng.util.Platform;
import appeng.util.inv.IUpgradeInventory;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
public class ContainerCellWorkbench extends ContainerUpgradeable implements IVirtualSlotHolder {
public class ContainerCellWorkbench extends ContainerUpgradeable {
private final ICellWorkbench workBench;
private final AppEngNullInventory nullInventory = new AppEngNullInventory();
@GuiSync(2)
public CopyMode copyMode = CopyMode.CLEAR_ON_REMOVE;
private ItemStack prevStack = null;
private int lastUpgrades = 0;
private final IAEStack<?>[] configClientSlot = new IAEStack[63];
public final ConfigEnumSyncHandler<CopyMode> copyModeSync;
public final AEStackInventorySyncHandler configSync;
public final ActionHandler<Void> clearAction;
public final ActionHandler<Void> partitionAction;
public ContainerCellWorkbench(final InventoryPlayer ip, final ICellWorkbench te) {
super(ip, te);
this.workBench = te;
SyncRegistrar sync = this.syncRegistrar();
this.copyModeSync = sync.configEnum("copyMode", Settings.COPY_MODE, CopyMode.class, te.getConfigManager());
this.configSync = sync.aeStackInventory("config", te.getAEInventoryByName(StorageName.CONFIG))
.setDiffCheckInterval(2, SyncDirection.SERVER_TO_CLIENT);
this.clearAction = sync.actionC2S("clear").onServerAction(this::clear);
this.partitionAction = sync.actionC2S("partition").onServerAction(this::partition);
}
public void setFuzzy(final FuzzyMode valueOf) {
@@ -72,15 +80,6 @@ public class ContainerCellWorkbench extends ContainerUpgradeable implements IVir
}
}
public void nextWorkBenchCopyMode() {
this.workBench.getConfigManager()
.putSetting(Settings.COPY_MODE, Platform.nextEnum(this.getWorkBenchCopyMode()));
}
private CopyMode getWorkBenchCopyMode() {
return (CopyMode) this.workBench.getConfigManager().getSetting(Settings.COPY_MODE);
}
@Override
protected int getHeight() {
return 251;
@@ -149,13 +148,8 @@ public class ContainerCellWorkbench extends ContainerUpgradeable implements IVir
}
}
this.setCopyMode(this.getWorkBenchCopyMode());
this.copyModeSync.syncFromConfig();
this.setFuzzyMode(this.getWorkBenchFuzzyMode());
this.updateVirtualSlots(
StorageName.NONE,
this.workBench.getAEInventoryByName(StorageName.NONE),
this.configClientSlot);
}
this.prevStack = is;
@@ -181,21 +175,13 @@ public class ContainerCellWorkbench extends ContainerUpgradeable implements IVir
return haveCell() && this.workBench.getCell() instanceof ICellRestriction;
}
@Override
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("copyMode")) {
this.workBench.getConfigManager().putSetting(Settings.COPY_MODE, this.getCopyMode());
}
super.onUpdate(field, oldValue, newValue);
}
public void clear() {
private void clear() {
final IAEStackInventory inv = this.workBench.getAEInventoryByName(StorageName.NONE);
for (int x = 0; x < inv.getSizeInventory(); x++) {
inv.putAEStackInSlot(x, null);
}
this.detectAndSendChanges();
this.configSync.markDirty();
this.getSyncManager().flushSync();
}
private FuzzyMode getWorkBenchFuzzyMode() {
@@ -207,7 +193,7 @@ public class ContainerCellWorkbench extends ContainerUpgradeable implements IVir
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void partition() {
private void partition() {
final IAEStackInventory inv = this.workBench.getAEInventoryByName(StorageName.NONE);
final ItemStack is = this.getUpgradeable().getInventoryByName("cell").getStackInSlot(0);
@@ -231,27 +217,8 @@ public class ContainerCellWorkbench extends ContainerUpgradeable implements IVir
}
}
this.detectAndSendChanges();
}
public CopyMode getCopyMode() {
return this.copyMode;
}
private void setCopyMode(final CopyMode copyMode) {
this.copyMode = copyMode;
}
@Override
public void receiveSlotStacks(StorageName invName, Int2ObjectMap<IAEStack<?>> slotStacks) {
final IAEStackInventory config = this.workBench.getAEInventoryByName(StorageName.NONE);
for (var entry : slotStacks.int2ObjectEntrySet()) {
config.putAEStackInSlot(entry.getIntKey(), entry.getValue());
}
if (isServer()) {
this.updateVirtualSlots(StorageName.NONE, config, this.configClientSlot);
}
this.configSync.markDirty();
this.getSyncManager().flushSync();
}
@Nullable
@@ -17,7 +17,6 @@ import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import appeng.api.config.FuzzyMode;
import appeng.api.config.LevelType;
@@ -27,7 +26,6 @@ import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.api.parts.ILevelEmitter;
import appeng.api.storage.StorageName;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IAEStackType;
import appeng.client.gui.IGuiSub;
import appeng.client.gui.implementations.GuiLevelEmitter;
@@ -36,14 +34,13 @@ import appeng.container.PrimaryGui;
import appeng.container.interfaces.IContainerSubGui;
import appeng.container.slot.SlotInaccessible;
import appeng.container.slot.SlotRestrictedInput;
import appeng.container.sync.SyncCodecs;
import appeng.container.sync.SyncRegistrar;
import appeng.container.sync.codecs.AEStackTypeFilterSyncCodec;
import appeng.container.sync.deltas.TypeFilterDelta;
import appeng.container.sync.handlers.AEStackInventorySyncHandler;
import appeng.container.sync.handlers.ConfigEnumSyncHandler;
import appeng.container.sync.handlers.DeltaObjectSyncHandler;
import appeng.container.sync.handlers.LongSyncHandler;
import appeng.container.sync.handlers.ObjectSyncHandler;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.AEStackTypeFilter;
import appeng.util.Platform;
@@ -61,7 +58,7 @@ public class ContainerLevelEmitter extends ContainerUpgradeable implements ICont
private final DeltaObjectSyncHandler<@NotNull AEStackTypeFilter, TypeFilterDelta> typeFiltersSync;
private final ConfigEnumSyncHandler<@NotNull LevelType> levelModeSync;
private final ConfigEnumSyncHandler<@NotNull YesNo> craftingModeSync;
private final ObjectSyncHandler<@Nullable IAEStack<?>> configStackSync;
public final AEStackInventorySyncHandler configSync;
public ContainerLevelEmitter(final InventoryPlayer ip, final ILevelEmitter te) {
super(ip, te);
@@ -100,15 +97,7 @@ public class ContainerLevelEmitter extends ContainerUpgradeable implements ICont
Settings.CRAFT_VIA_REDSTONE,
YesNo.class,
this.getUpgradeable().getConfigManager());
this.configStackSync = sync
.object(
"configStack",
SyncCodecs.aeStack(),
this.lvlEmitter.getAEInventoryByName(StorageName.CONFIG).getAEStackInSlot(0))
.onServerChange((oldValue, newValue) -> {
final IAEStack<?> stack = newValue == null ? null : newValue.copy();
this.lvlEmitter.getAEInventoryByName(StorageName.CONFIG).putAEStackInSlot(0, stack);
});
this.configSync = sync.aeStackInventory("config", this.lvlEmitter.getAEInventoryByName(StorageName.CONFIG));
// sub gui copy paste
this.primaryGuiButtonIcon = new SlotInaccessible(new AppEngInternalInventory(null, 1), 0, 0, -9000);
@@ -187,7 +176,6 @@ public class ContainerLevelEmitter extends ContainerUpgradeable implements ICont
this.setFuzzyMode((FuzzyMode) this.getUpgradeable().getConfigManager().getSetting(Settings.FUZZY_MODE));
this.setRedStoneMode(
(RedstoneMode) this.getUpgradeable().getConfigManager().getSetting(Settings.REDSTONE_EMITTER));
this.configStackSync.set(this.lvlEmitter.getAEInventoryByName(StorageName.CONFIG).getAEStackInSlot(0));
}
this.standardDetectAndSendChanges();
@@ -232,18 +220,6 @@ public class ContainerLevelEmitter extends ContainerUpgradeable implements ICont
this.typeFiltersSync.applyAndQueueDelta(TypeFilterDelta.toggle(type));
}
public ILevelEmitter getLvlEmitter() {
return this.lvlEmitter;
}
public @Nullable IAEStack<?> getConfigStack() {
return this.configStackSync.get();
}
public void setConfigStack(@Nullable final IAEStack<?> stack) {
this.configStackSync.set(stack);
}
// for level terminal
// sub gui copypaste
private final Slot primaryGuiButtonIcon;
@@ -80,37 +80,18 @@ public final class SyncManager {
this.frozen = true;
}
public void tickServer() {
if (!Platform.isServer()) {
return;
}
public void flushSync() {
this.freezeLayout();
if (!this.initialServerSyncSent) {
this.sendUpdates(SyncEndpoint.SERVER, true);
this.initialServerSyncSent = true;
if (Platform.isServer()) {
if (!this.initialServerSyncSent) {
this.sendUpdates(SyncEndpoint.SERVER, true);
this.initialServerSyncSent = true;
}
this.sendUpdates(SyncEndpoint.SERVER, false);
} else {
this.sendUpdates(SyncEndpoint.CLIENT, false);
}
this.sendUpdates(SyncEndpoint.SERVER, false);
}
public void tickClient() {
if (!Platform.isClient()) {
return;
}
this.freezeLayout();
this.sendUpdates(SyncEndpoint.CLIENT, false);
}
public void flushClient() {
if (!Platform.isClient()) {
return;
}
this.freezeLayout();
this.sendUpdates(SyncEndpoint.CLIENT, false);
}
public void readIncoming(final SyncEndpoint remoteEndpoint, final ByteBuf buf) {
@@ -230,6 +211,7 @@ public final class SyncManager {
}
this.freezeLayout();
this.sendUpdates(localEndpoint, false);
final ByteBuf data = Unpooled.buffer();
data.writeInt(this.layoutHash);
@@ -166,13 +166,7 @@ public class PacketValueConfig extends AppEngPacket {
}
}
} else if (this.Name.startsWith("CellWorkbench.") && c instanceof final ContainerCellWorkbench ccw) {
if (this.Name.equals("CellWorkbench.Action")) {
switch (this.Value) {
case "CopyMode" -> ccw.nextWorkBenchCopyMode();
case "Partition" -> ccw.partition();
case "Clear" -> ccw.clear();
}
} else if (this.Name.equals("CellWorkbench.Fuzzy")) {
if (this.Name.equals("CellWorkbench.Fuzzy")) {
ccw.setFuzzy(FuzzyMode.valueOf(this.Value));
}
} else if (c instanceof ContainerNetworkTool) {
@@ -38,6 +38,7 @@ import appeng.tile.inventory.AppEngInternalInventory;
import appeng.tile.inventory.IAEStackInventory;
import appeng.tile.inventory.InvOperation;
import appeng.util.ConfigManager;
import appeng.util.Platform;
public class TileCellWorkbench extends AEBaseTile implements ICellWorkbench, IPrimaryGuiIconProvider {
@@ -138,10 +139,14 @@ public class TileCellWorkbench extends AEBaseTile implements ICellWorkbench, IPr
}
if (inv == this.cell && !this.locked) {
this.locked = true;
this.cacheUpgrades = null;
this.cacheConfig = null;
if (Platform.isClient()) {
this.updateStackTypeFromCell();
return;
}
this.locked = true;
ItemStack is = this.cell.getStackInSlot(0);
if (this.manager.getSetting(Settings.COPY_MODE) == CopyMode.KEEP_ON_REMOVE) {
@@ -149,13 +154,11 @@ public class TileCellWorkbench extends AEBaseTile implements ICellWorkbench, IPr
icr.setCellRestriction(is, new CellRestrictionData(cellRestrictTypes, cellRestrictAmount));
}
if (is != null && is.getItem() instanceof ICellWorkbenchItem wi) {
if (wi.getStackType() != this.type) {
this.type = wi.getStackType();
for (int x = 0; x < this.config.getSizeInventory(); x++) {
this.config.putAEStackInSlot(x, null);
}
final IAEStackType<?> oldType = this.type;
this.updateStackTypeFromCell();
if (this.type != null && this.type != oldType) {
for (int x = 0; x < this.config.getSizeInventory(); x++) {
this.config.putAEStackInSlot(x, null);
}
}
@@ -216,6 +219,15 @@ public class TileCellWorkbench extends AEBaseTile implements ICellWorkbench, IPr
return this.cacheConfig;
}
private void updateStackTypeFromCell() {
final ItemStack is = this.cell.getStackInSlot(0);
if (is != null && is.getItem() instanceof ICellWorkbenchItem wi) {
this.type = wi.getStackType();
} else {
this.type = null;
}
}
@Override
public void getDrops(final World w, final int x, final int y, final int z, final List<ItemStack> drops) {
super.getDrops(w, x, y, z, drops);