Make P2P Tunnel - ME Interface share storage slot contents between input and outputs (#759)

Co-authored-by: Julia <78276563+Vlamonster@users.noreply.github.com>
Co-authored-by: lordIcocain <62835225+lordIcocain@users.noreply.github.com>
Co-authored-by: boubou19 <miisterunknown@gmail.com>
Co-authored-by: Martin Robertz <dream-master@gmx.net>
Co-authored-by: lordIcocain <lordicocain@gmail.com>
Co-authored-by: lc-1337 <62835225+lc-1337@users.noreply.github.com>
Co-authored-by: Kogepan229 <73163994+Kogepan229@users.noreply.github.com>
Co-authored-by: Maya <10861407+serenibyss@users.noreply.github.com>
Co-authored-by: Alexdoru <57050655+Alexdoru@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2025-06-28 23:36:07 +02:00
1 parent ba7d5abd32
commit 04ea677ac3
6 files changed
+230 -22

No files matched your search

@@ -194,7 +194,7 @@ public class GuiInterface extends GuiUpgradeable {
@Override
protected String getBackground() {
return switch (((ContainerInterface) this.cvb).getPatternCapacityCardsInstalled()) {
case -1 -> "guis/interfacenone.png";
case -1 -> "guis/interfacenonenoconfig.png";
case 1 -> "guis/interface2.png";
case 2 -> "guis/interface3.png";
case 3 -> "guis/interface4.png";
@@ -30,8 +30,8 @@ import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.util.IConfigManager;
import appeng.container.guisync.GuiSync;
import appeng.container.slot.IOptionalSlotHost;
import appeng.container.slot.OptionalSlotFake;
import appeng.container.slot.OptionalSlotRestrictedInput;
import appeng.container.slot.SlotFake;
import appeng.container.slot.SlotNormal;
import appeng.container.slot.SlotRestrictedInput;
import appeng.helpers.DualityInterface;
@@ -74,14 +74,21 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona
@GuiSync(7)
public int patternRows;
@GuiSync(17)
public int configSlots;
@GuiSync(9)
public boolean isEmpty;
@GuiSync(18)
public boolean isConfigEmpty;
public ContainerInterface(final InventoryPlayer ip, final IInterfaceHost te) {
super(ip, te.getInterfaceDuality().getHost());
this.myDuality = te.getInterfaceDuality();
patternRows = getPatternCapacityCardsInstalled();
configSlots = getConfigSlotsEnabled();
for (int row = 0; row < 4; ++row) {
for (int x = 0; x < DualityInterface.NUMBER_OF_PATTERN_SLOTS; x++) {
@@ -99,7 +106,7 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona
}
for (int x = 0; x < DualityInterface.NUMBER_OF_CONFIG_SLOTS; x++) {
this.addSlotToContainer(new SlotFake(this.myDuality.getConfig(), x, 8 + 18 * x, 15));
this.addSlotToContainer(new OptionalSlotFake(this.myDuality.getConfig(), this, x, 8 + 18 * x, 15, 0));
}
for (int x = 0; x < DualityInterface.NUMBER_OF_STORAGE_SLOTS; x++) {
@@ -126,6 +133,7 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
super.onUpdate(field, oldValue, newValue);
if (Platform.isClient() && field.equals("patternRows")) getRemovedPatterns();
if (Platform.isClient() && field.equals("configSlots")) getRemovedConfig();
}
@Override
@@ -137,6 +145,9 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona
if (patternRows != getPatternCapacityCardsInstalled()) patternRows = getPatternCapacityCardsInstalled();
isEmpty = patternRows == -1;
if (configSlots != getConfigSlotsEnabled()) configSlots = getConfigSlotsEnabled();
isConfigEmpty = configSlots == -1;
final ArrayList<ItemStack> drops = getRemovedPatterns();
if (!drops.isEmpty()) {
TileEntity te = myDuality.getHost().getTile();
@@ -162,6 +173,17 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona
return drops;
}
private void getRemovedConfig() {
for (final Object o : this.inventorySlots) {
if (o instanceof OptionalSlotFake fs) {
if (!fs.isEnabled()) {
fs.inventory.setInventorySlotContents(fs.getSlotIndex(), null);
fs.clearStack();
}
}
}
}
@Override
protected void loadSettingsFromHost(final IConfigManager cm) {
this.setBlockingMode((YesNo) cm.getSetting(Settings.BLOCK));
@@ -273,9 +295,14 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona
return myDuality.getInstalledUpgrades(Upgrades.PATTERN_CAPACITY);
}
private int getConfigSlotsEnabled() {
if (Platform.isClient() && isConfigEmpty) return -1;
return myDuality.getConfigSize();
}
@Override
public boolean isSlotEnabled(final int idx) {
if (Platform.isClient() && isEmpty) return false;
if (Platform.isClient() && (isEmpty || isConfigEmpty)) return false;
return myDuality.getInstalledUpgrades(Upgrades.PATTERN_CAPACITY) >= idx;
}
}
@@ -21,6 +21,15 @@ public class OptionalSlotFake extends SlotFake {
private final IOptionalSlotHost host;
private boolean renderDisabled = true;
public OptionalSlotFake(final IInventory inv, final IOptionalSlotHost containerBus, final int idx, final int x,
final int y, final int groupNum) {
super(inv, idx, x, y);
this.srcX = x;
this.srcY = y;
this.groupNum = groupNum;
this.host = containerBus;
}
public OptionalSlotFake(final IInventory inv, final IOptionalSlotHost containerBus, final int idx, final int x,
final int y, final int offX, final int offY, final int groupNum) {
super(inv, idx, x + offX * 18, y + offY * 18);
@@ -117,7 +117,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private static final Collection<Block> BAD_BLOCKS = new HashSet<>(100);
private final int[] sides = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
private final IAEItemStack[] requireWork = { null, null, null, null, null, null, null, null, null };
private final boolean[] hasFuzzyConfig = { false, false, false, false, false, false, false, false, false, };
private final boolean[] hasFuzzyConfig = { false, false, false, false, false, false, false, false, false };
private final MultiCraftingTracker craftingTracker;
protected final AENetworkProxy gridProxy;
private final IInterfaceHost iHost;
@@ -125,9 +125,9 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private final BaseActionSource interfaceRequestSource;
private final ConfigManager cm = new ConfigManager(this);
private final AppEngInternalAEInventory config = new AppEngInternalAEInventory(this, NUMBER_OF_CONFIG_SLOTS);
private final AppEngInternalInventory storage = new AppEngInternalInventory(this, NUMBER_OF_STORAGE_SLOTS);
private AppEngInternalInventory storage = new AppEngInternalInventory(this, NUMBER_OF_STORAGE_SLOTS);
private final AppEngInternalInventory patterns = new AppEngInternalInventory(this, NUMBER_OF_PATTERN_SLOTS * 4);
private final WrapperInvSlot slotInv = new WrapperInvSlot(this.storage);
private WrapperInvSlot slotInv = new WrapperInvSlot(this.storage);
private final MEMonitorPassThrough<IAEItemStack> items = new MEMonitorPassThrough<>(
new NullInventory<IAEItemStack>(),
StorageChannel.ITEMS);
@@ -140,6 +140,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private boolean hasConfig = false;
private int priority;
public List<ICraftingPatternDetails> craftingList = null;
public boolean sharedInventory = false;
private List<ItemStack> waitingToSend = null;
private IMEInventory<IAEItemStack> destination;
private boolean isWorking = false;
@@ -231,7 +232,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
public void writeToNBT(final NBTTagCompound data) {
this.config.writeToNBT(data, "config");
this.patterns.writeToNBT(data, "patterns");
this.storage.writeToNBT(data, "storage");
if (!sharedInventory) this.storage.writeToNBT(data, "storage");
this.upgrades.writeToNBT(data, "upgrades");
this.cm.writeToNBT(data);
this.craftingTracker.writeToNBT(data);
@@ -344,7 +345,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
private void readConfig() {
public void readConfig() {
this.hasConfig = false;
for (final ItemStack p : this.config) {
@@ -417,7 +418,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
private boolean hasWorkToDo() {
protected boolean hasWorkToDo() {
if (this.hasItemsToSend()) {
return true;
} else {
@@ -523,7 +524,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
private boolean hasItemsToSend() {
protected boolean hasItemsToSend() {
return this.waitingToSend != null && !this.waitingToSend.isEmpty();
}
@@ -541,14 +542,37 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
// return after.stackSize != stack.stackSize;
}
public IInventory getConfig() {
public AppEngInternalAEInventory getConfig() {
return this.config;
}
public IInventory getPatterns() {
public AppEngInternalInventory getPatterns() {
return this.patterns;
}
public AppEngInternalInventory getUpgrades() {
return this.upgrades;
}
public AppEngInternalInventory setStorage(final AppEngInternalInventory inv) {
this.storage = inv;
return this.storage;
}
public boolean setHasConfig(final boolean ifHasConfig) {
this.hasConfig = ifHasConfig;
return this.hasConfig;
}
public int getConfigSize() {
return this.config.getSizeInventory();
}
public WrapperInvSlot setSlotInv(final WrapperInvSlot slotInventory) {
this.slotInv = slotInventory;
return this.slotInv;
}
public void gridChanged() {
try {
this.items.setInternal(this.gridProxy.getStorage().getItemInventory());
@@ -615,9 +639,11 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
// To prevent duping in case fuzzy-matched item cannot be merged with stack in storage
// slot...
} else fuzzyItemStack.setStackSize(0);
} else fuzzyItemStack = null;
pe = Platform.poweredExtraction(energy, cell, fuzzyItemStack, src);
if (fuzzyItemStack != null) {
pe = Platform.poweredExtraction(energy, cell, fuzzyItemStack, src);
}
}
return new IAEItemStack[] { pe, fuzzyItemStack };
@@ -875,7 +901,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return this.items;
}
private boolean hasConfig() {
public boolean hasConfig() {
return this.hasConfig;
}
@@ -900,7 +926,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return null;
}
public IInventory getStorage() {
public AppEngInternalInventory getStorage() {
return this.storage;
}
@@ -1,5 +1,7 @@
package appeng.parts.p2p;
import static appeng.helpers.DualityInterface.NUMBER_OF_STORAGE_SLOTS;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
@@ -14,12 +16,14 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraft.util.Vec3;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.event.ForgeEventFactory;
import com.google.common.collect.ImmutableSet;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.Upgrades;
import appeng.api.implementations.items.IMemoryCard;
import appeng.api.implementations.tiles.ITileStorageMonitorable;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingLink;
@@ -51,6 +55,7 @@ import appeng.tile.inventory.IAEAppEngInventory;
import appeng.tile.inventory.InvOperation;
import appeng.util.Platform;
import appeng.util.inv.IInventoryDestination;
import appeng.util.inv.WrapperInvSlot;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@@ -58,6 +63,9 @@ public class PartP2PInterface extends PartP2PTunnelStatic<PartP2PInterface>
implements IGridTickable, IStorageMonitorable, IInventoryDestination, IInterfaceHost, ISidedInventory,
IAEAppEngInventory, ITileStorageMonitorable, IPriorityHost {
boolean needUpdateOnNetworkBooted = false;
boolean lastPowerStart = false;
@Reflected
public PartP2PInterface(ItemStack is) {
super(is);
@@ -78,7 +86,6 @@ public class PartP2PInterface extends PartP2PTunnelStatic<PartP2PInterface>
PartP2PInterface p2p = getInput();
if (p2p != null) {
this.craftingList = p2p.duality.craftingList;
try {
this.gridProxy.getGrid()
.postEvent(new MENetworkCraftingPatternChange(this, this.gridProxy.getNode()));
@@ -89,21 +96,131 @@ public class PartP2PInterface extends PartP2PTunnelStatic<PartP2PInterface>
}
}
@Override
public TickRateModulation tickingRequest(IGridNode node, int ticksSinceLastCall) {
final boolean powerState = proxy.isActive();
if (needUpdateOnNetworkBooted || lastPowerStart != powerState) {
needUpdateOnNetworkBooted = false;
lastPowerStart = powerState;
updateSharingInventory();
}
return super.tickingRequest(node, ticksSinceLastCall);
}
@Override
protected boolean hasWorkToDo() {
if (isOutput()) {
return hasItemsToSend() || hasConfig() || !getStorage().isEmpty();
} else return super.hasWorkToDo();
}
@Override
public void readConfig() {
if (isOutput()) {
PartP2PInterface p2p = getInput();
boolean alertDevice = false;
if (p2p != null) {
this.setHasConfig(p2p.duality.hasConfig());
alertDevice = hasWorkToDo();
} else {
this.setHasConfig(false);
}
if (alertDevice) {
try {
this.gridProxy.getTick().alertDevice(this.gridProxy.getNode());
} catch (final GridAccessException ignored) {}
} else {
try {
this.gridProxy.getTick().sleepDevice(this.gridProxy.getNode());
} catch (final GridAccessException ignored) {}
}
this.notifyNeighbors();
} else {
super.readConfig();
}
}
@Override
public void addDrops(final List<ItemStack> drops) {
if (!isOutput()) {
super.addDrops(drops);
try {
for (PartP2PInterface p2p : getOutputs()) p2p.duality.addDrops(drops);
} catch (GridAccessException ignored) {}
} else {
if (this.getWaitingToSend() != null) {
for (final ItemStack is : this.getWaitingToSend()) {
if (is != null) {
drops.add(is);
}
}
}
for (final ItemStack is : this.getUpgrades()) {
if (is != null) {
drops.add(is);
}
}
for (final ItemStack is : this.getPatterns()) {
if (is != null) {
drops.add(is);
}
}
}
}
@Override
public int getInstalledUpgrades(Upgrades u) {
if (isOutput() && u == Upgrades.PATTERN_CAPACITY) return -1;
return super.getInstalledUpgrades(u);
}
@Override
public int getConfigSize() {
if (isOutput()) return -1;
return super.getConfigSize();
}
};
private void updateSharingInventory() {
if (isOutput()) {
PartP2PInterface p2p = getInput();
if (proxy.isActive() && p2p != null) {
duality.setStorage(p2p.duality.getStorage());
duality.sharedInventory = true;
} else {
duality.setStorage(new AppEngInternalInventory(this, NUMBER_OF_STORAGE_SLOTS));
duality.setSlotInv(new WrapperInvSlot(duality.getStorage()));
duality.sharedInventory = false;
}
} else {
try {
for (PartP2PInterface p2p : getOutputs()) {
p2p.duality.readConfig();
}
} catch (GridAccessException ignored) {}
}
duality.readConfig();
}
@MENetworkEventSubscribe
public void stateChange(final MENetworkChannelsChanged c) {
this.duality.notifyNeighbors();
updateSharingInventory();
needUpdateOnNetworkBooted = true;
}
@MENetworkEventSubscribe
public void stateChange(final MENetworkPowerStatusChange c) {
this.duality.notifyNeighbors();
updateSharingInventory();
needUpdateOnNetworkBooted = true;
}
@Override
@@ -181,12 +298,37 @@ public class PartP2PInterface extends PartP2PTunnelStatic<PartP2PInterface>
@Override
public boolean onPartActivate(final EntityPlayer p, final Vec3 pos) {
AppEngInternalInventory patterns = (AppEngInternalInventory) this.duality.getPatterns();
final boolean wasActive = getProxy().isActive();
if (!isOutput()) {
final ItemStack is = p.inventory.getCurrentItem();
if (is != null && is.getItem() instanceof IMemoryCard mc) {
if (ForgeEventFactory.onItemUseStart(p, is, 1) <= 0) return false;
try {
for (PartP2PInterface p2p : getOutputs()) {
p2p.duality.setStorage(new AppEngInternalInventory(this, NUMBER_OF_STORAGE_SLOTS));
p2p.duality.setSlotInv(new WrapperInvSlot(duality.getStorage()));
p2p.duality.sharedInventory = false;
}
} catch (GridAccessException ignored) {}
}
}
if (super.onPartActivate(p, pos)) {
ArrayList<ItemStack> drops = new ArrayList<>();
for (int i = 0; i < patterns.getSizeInventory(); i++) {
if (patterns.getStackInSlot(i) == null) continue;
drops.add(patterns.getStackInSlot(i));
}
if (!duality.sharedInventory && !wasActive) {
AppEngInternalInventory storageAppEng = this.duality.getStorage();
for (int i = 0; i < NUMBER_OF_STORAGE_SLOTS; i++) {
if (storageAppEng.getStackInSlot(i) == null) continue;
drops.add(storageAppEng.getStackInSlot(i));
}
}
final IPart tile = this.getHost().getPart(this.getSide());
if (tile instanceof PartP2PInterface) {
DualityInterface newDuality = ((PartP2PInterface) tile).duality;
@@ -197,11 +339,15 @@ public class PartP2PInterface extends PartP2PTunnelStatic<PartP2PInterface>
for (int i = 0; i < upgrades.getSizeInventory(); ++i) {
newUpgrade.setInventorySlotContents(i, upgrades.getStackInSlot(i));
}
IInventory storage = duality.getStorage();
IInventory newStorage = newDuality.getStorage();
for (int i = 0; i < storage.getSizeInventory(); ++i) {
newStorage.setInventorySlotContents(i, storage.getStackInSlot(i));
if (!duality.sharedInventory) {
IInventory storage = (IInventory) duality.getStorage();
IInventory newStorage = (IInventory) newDuality.getStorage();
for (int i = 0; i < storage.getSizeInventory(); ++i) {
newStorage.setInventorySlotContents(i, storage.getStackInSlot(i));
}
}
IConfigManager config = duality.getConfigManager();
config.getSettings().forEach(
setting -> newDuality.getConfigManager().putSetting(setting, config.getSetting(setting)));
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB