From 8fb12119ef8434c8ade4ddf7b16deab73f32a6d0 Mon Sep 17 00:00:00 2001 From: Neeve Date: Wed, 20 Dec 2023 13:52:07 +1100 Subject: [PATCH] Fix oversized slot weirdness (#331) --- .../appeng/container/AEBaseContainer.java | 67 +++++++++++++------ .../implementations/ContainerInterface.java | 18 ----- .../appeng/container/slot/AppEngSlot.java | 18 +++++ .../inventory/AppEngInternalInventory.java | 6 -- .../AppEngInternalOversizedInventory.java | 2 - 5 files changed, 64 insertions(+), 47 deletions(-) diff --git a/src/main/java/appeng/container/AEBaseContainer.java b/src/main/java/appeng/container/AEBaseContainer.java index a9a16c92c..78fac9392 100644 --- a/src/main/java/appeng/container/AEBaseContainer.java +++ b/src/main/java/appeng/container/AEBaseContainer.java @@ -39,15 +39,7 @@ import appeng.client.me.SlotME; import appeng.container.guisync.GuiSync; import appeng.container.guisync.SyncData; import appeng.container.implementations.ContainerInterface; -import appeng.container.slot.AppEngSlot; -import appeng.container.slot.SlotCraftingMatrix; -import appeng.container.slot.SlotCraftingTerm; -import appeng.container.slot.SlotDisabled; -import appeng.container.slot.SlotFake; -import appeng.container.slot.SlotInaccessible; -import appeng.container.slot.SlotPlayerHotBar; -import appeng.container.slot.SlotPlayerInv; -import appeng.container.slot.SlotRestrictedInput; +import appeng.container.slot.*; import appeng.container.slot.SlotRestrictedInput.PlacableItemType; import appeng.core.AELog; import appeng.core.sync.network.NetworkHandler; @@ -65,14 +57,12 @@ import appeng.util.item.AEItemStack; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.Container; -import net.minecraft.inventory.IContainerListener; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.Slot; +import net.minecraft.inventory.*; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.wrapper.PlayerInvWrapper; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.lang.reflect.Field; @@ -409,10 +399,7 @@ public abstract class AEBaseContainer extends Container { return ItemStack.EMPTY; // don't insert duplicate encoded patterns to interfaces } - int maxSize = t.getMaxStackSize(); - if (maxSize > d.getSlotStackLimit()) { - maxSize = d.getSlotStackLimit(); - } + int maxSize = Math.max(tis.getMaxStackSize(), d.getSlotStackLimit()); int placeAble = maxSize - t.getCount(); @@ -448,10 +435,7 @@ public abstract class AEBaseContainer extends Container { if (d.isItemValid(tis)) { if (!d.getHasStack()) { - int maxSize = tis.getMaxStackSize(); - if (maxSize > d.getSlotStackLimit()) { - maxSize = d.getSlotStackLimit(); - } + int maxSize = Math.max(tis.getMaxStackSize(), d.getSlotStackLimit()); final ItemStack tmp = tis.copy(); if (tmp.getCount() > maxSize) { @@ -967,6 +951,47 @@ public abstract class AEBaseContainer extends Container { b.putStack(testB); } + @Override + public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, @NotNull EntityPlayer player) { + if (slotId >= 0 && clickTypeIn == ClickType.PICKUP) { + final var slot = this.getSlot(slotId); + if (slot instanceof AppEngSlot appEngSlot) { + var slotStack = slot.getStack(); + var draggedStack = this.invPlayer.getItemStack(); + + // The default vanilla behavior assumes that slots can't hold more items than the default stack size. + // Thus, it's possible to underflow the vanilla code when clicking non-empty slots with an item stack. + if (!draggedStack.isEmpty()) { + if (appEngSlot.isItemValid(draggedStack)) { + if (slotStack.getItem() == draggedStack.getItem() && slotStack.getMetadata() == draggedStack.getMetadata() && ItemStack.areItemStackTagsEqual(slotStack, draggedStack)) { + var maxSize = Math.max(appEngSlot.getSlotStackLimit(), draggedStack.getMaxStackSize()); + var maxInsertable = Math.min(draggedStack.getCount(), maxSize - appEngSlot.getStack().getCount()); + var toInsert = Math.min(maxInsertable, dragType == 0 ? maxInsertable : 1); + + draggedStack.shrink(toInsert); + slotStack.grow(toInsert); + + slot.onSlotChanged(); + return ItemStack.EMPTY; + } + } + } + // Fixes taking and halving issues from oversized slots. + else if (dragType == 0 || dragType == 1) { + if (slot.canTakeStack(player) && !slotStack.isEmpty()) { + var toTake = Math.min(slotStack.getCount(), slotStack.getMaxStackSize()); + this.invPlayer.setItemStack(slot.decrStackSize(dragType == 0 ? toTake : (toTake + 1) / 2)); + + slot.onTake(player, invPlayer.getItemStack()); + return ItemStack.EMPTY; + } + } + + } + } + return super.slotClick(slotId, dragType, clickTypeIn, player); + } + public void onUpdate(final String field, final Object oldValue, final Object newValue) { } diff --git a/src/main/java/appeng/container/implementations/ContainerInterface.java b/src/main/java/appeng/container/implementations/ContainerInterface.java index 4086cb1f7..68fda38a5 100644 --- a/src/main/java/appeng/container/implementations/ContainerInterface.java +++ b/src/main/java/appeng/container/implementations/ContainerInterface.java @@ -28,13 +28,8 @@ import appeng.container.guisync.GuiSync; import appeng.container.slot.*; import appeng.helpers.DualityInterface; import appeng.helpers.IInterfaceHost; -import appeng.tile.inventory.AppEngInternalInventory; -import appeng.tile.inventory.AppEngInternalOversizedInventory; import appeng.util.Platform; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.ClickType; -import net.minecraft.item.ItemStack; public class ContainerInterface extends ContainerUpgradeable implements IOptionalSlotHost { @@ -71,19 +66,6 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona } } - @Override - public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player) { - if (slotId >= 0 && slotId < this.inventorySlots.size()) { - if (this.inventorySlots.get(slotId) instanceof SlotOversized) { - ((AppEngInternalOversizedInventory) ((SlotOversized) this.inventorySlots.get(slotId)).getItemHandler()).limitExtraction(true); - ItemStack ret = super.slotClick(slotId, dragType, clickTypeIn, player); - ((AppEngInternalOversizedInventory) ((SlotOversized) this.inventorySlots.get(slotId)).getItemHandler()).limitExtraction(false); - return ret; - } - } - return super.slotClick(slotId, dragType, clickTypeIn, player); - } - @Override protected int getHeight() { return 256; diff --git a/src/main/java/appeng/container/slot/AppEngSlot.java b/src/main/java/appeng/container/slot/AppEngSlot.java index 11dea9afa..4c91ee8b9 100644 --- a/src/main/java/appeng/container/slot/AppEngSlot.java +++ b/src/main/java/appeng/container/slot/AppEngSlot.java @@ -158,6 +158,24 @@ public class AppEngSlot extends Slot { @Override public boolean canTakeStack(final EntityPlayer par1EntityPlayer) { + if (this.isSlotEnabled()) { + var draggedStack = par1EntityPlayer.inventory.getItemStack(); + ItemStack slotStack = this.getStack(); + + + if (!draggedStack.isEmpty()) { + if (draggedStack.isItemEqual(slotStack)) { + if (draggedStack.getCount() >= draggedStack.getMaxStackSize()) { + // Prevent over-pulling. + return false; + } + } else if (slotStack.getCount() > slotStack.getMaxStackSize()) { + // Prevent swapping when clicking slots that hold more items than the max stack size. + return false; + } + } + } + if (this.isSlotEnabled()) { return !this.itemHandler.extractItem(this.index, Integer.MAX_VALUE, true).isEmpty(); } diff --git a/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java b/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java index 41dc66dbb..a88bc1ed7 100644 --- a/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java +++ b/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java @@ -27,7 +27,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.Constants; -import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; import javax.annotation.Nonnull; @@ -46,7 +45,6 @@ public class AppEngInternalInventory extends ItemStackHandler implements Iterabl protected ItemStack previousStack = ItemStack.EMPTY; protected IAEItemFilter filter; protected boolean dirtyFlag = false; - protected boolean limitExtraction; public AppEngInternalInventory(final IAEAppEngInventory inventory, final int size, final int maxStack, IAEItemFilter filter) { super(size); @@ -221,8 +219,4 @@ public class AppEngInternalInventory extends ItemStackHandler implements Iterabl public void setTileEntity(final IAEAppEngInventory te) { this.te = te; } - - public void limitExtraction(boolean limitExtraction) { - this.limitExtraction = limitExtraction; - } } diff --git a/src/main/java/appeng/tile/inventory/AppEngInternalOversizedInventory.java b/src/main/java/appeng/tile/inventory/AppEngInternalOversizedInventory.java index 119d09c7a..7c47fbeca 100644 --- a/src/main/java/appeng/tile/inventory/AppEngInternalOversizedInventory.java +++ b/src/main/java/appeng/tile/inventory/AppEngInternalOversizedInventory.java @@ -77,8 +77,6 @@ public class AppEngInternalOversizedInventory extends AppEngInternalInventory { this.previousStack = this.getStackInSlot(slot).copy(); } - if (limitExtraction) - return super.extractItem(slot, amount, simulate); if (amount == 0) return ItemStack.EMPTY;