Fix SidedInvWrapper not accounting for vanilla stacking special cases in brewing stands and furnaces (#9189)

This commit is contained in:
Technici4n authored and GitHub committed 2022-12-15 11:40:25 -08:00
1 parent b269f7dbfd
commit f8fdd43552
1 file changed
+29 -2
@@ -8,18 +8,30 @@ package net.minecraftforge.items.wrapper;
import net.minecraft.world.WorldlyContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.Direction;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.IntUnaryOperator;
public class SidedInvWrapper implements IItemHandlerModifiable
{
protected final WorldlyContainer inv;
@Nullable
protected final Direction side;
private final IntUnaryOperator slotLimit;
private final InsertLimit newStackInsertLimit;
private interface InsertLimit
{
int limitInsert(int wrapperSlot, int invSlot, ItemStack stack);
}
@SuppressWarnings("unchecked")
public static LazyOptional<IItemHandlerModifiable>[] create(WorldlyContainer inv, Direction... sides) {
LazyOptional<IItemHandlerModifiable>[] ret = new LazyOptional[sides.length];
@@ -34,6 +46,20 @@ public class SidedInvWrapper implements IItemHandlerModifiable
{
this.inv = inv;
this.side = side;
// A few special cases to account for canPlaceItem implementations attempting to limit specific inputs to 1,
// by returning false if there's already a contained item. This doesn't work with modded inserted sizes > 1.
// - Limit buckets to 1 in furnace fuel inputs.
// - Limit brewing stand "bottle" inputs to 1.
// Done using lambdas to avoid the overhead of instanceof checks in hot code.
if (inv instanceof BrewingStandBlockEntity)
this.slotLimit = wrapperSlot -> getSlot(inv, wrapperSlot, side) < 3 ? 1 : inv.getMaxStackSize();
else
this.slotLimit = wrapperSlot -> inv.getMaxStackSize();
if (inv instanceof AbstractFurnaceBlockEntity)
this.newStackInsertLimit = (wrapperSlot, invSlot, stack) -> invSlot == 1 && stack.is(Items.BUCKET) ? 1 : Math.min(stack.getMaxStackSize(), getSlotLimit(wrapperSlot));
else
this.newStackInsertLimit = (wrapperSlot, invSlot, stack) -> Math.min(stack.getMaxStackSize(), getSlotLimit(wrapperSlot));
}
public static int getSlot(WorldlyContainer inv, int slot, @Nullable Direction side)
@@ -141,7 +167,8 @@ public class SidedInvWrapper implements IItemHandlerModifiable
if (!inv.canPlaceItemThroughFace(slot1, stack, side) || !inv.canPlaceItem(slot1, stack))
return stack;
m = Math.min(stack.getMaxStackSize(), getSlotLimit(slot));
m = newStackInsertLimit.limitInsert(slot, slot1, stack);
if (m < stack.getCount())
{
// copy the stack to not modify the original one
@@ -226,7 +253,7 @@ public class SidedInvWrapper implements IItemHandlerModifiable
@Override
public int getSlotLimit(int slot)
{
return inv.getMaxStackSize();
return slotLimit.applyAsInt(slot);
}
@Override