From eedad7646731ce1f49f6b71577332e8b7512a807 Mon Sep 17 00:00:00 2001 From: Sara Freimer Date: Thu, 8 Jun 2023 11:51:09 -0500 Subject: [PATCH] Fix configurator empty mode ignoring stack size (#7798) and also only allow emptying creative bins if the player is in creative --- .../common/item/ItemConfigurator.java | 14 +++++- .../mekanism/common/util/InventoryUtils.java | 49 ++++++++++++------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/main/java/mekanism/common/item/ItemConfigurator.java b/src/main/java/mekanism/common/item/ItemConfigurator.java index 2f17f5b281c..f5aed4bc9cb 100644 --- a/src/main/java/mekanism/common/item/ItemConfigurator.java +++ b/src/main/java/mekanism/common/item/ItemConfigurator.java @@ -32,11 +32,14 @@ import mekanism.common.item.interfaces.IItemHUDProvider; import mekanism.common.lib.radial.IRadialEnumModeItem; import mekanism.common.lib.transmitter.TransmissionType; +import mekanism.common.tier.BinTier; +import mekanism.common.tile.TileEntityBin; import mekanism.common.tile.base.TileEntityMekanism; import mekanism.common.tile.component.config.ConfigInfo; import mekanism.common.tile.component.config.DataType; import mekanism.common.tile.interfaces.ISideConfiguration; import mekanism.common.util.CapabilityUtils; +import mekanism.common.util.InventoryUtils; import mekanism.common.util.MekanismUtils; import mekanism.common.util.MekanismUtils.ResourceType; import mekanism.common.util.StorageUtils; @@ -141,6 +144,15 @@ public InteractionResult useOn(UseOnContext context) { return InteractionResult.FAIL; } boolean creative = player.isCreative(); + if (tile instanceof TileEntityBin bin && bin.getTier() == BinTier.CREATIVE) { + //If the tile is a creative bin only allow clearing it if the player is in creative + // and don't bother popping the stack out + if (creative) { + bin.getBinSlot().setEmpty(); + return InteractionResult.SUCCESS; + } + return InteractionResult.FAIL; + } IEnergyContainer energyContainer = creative ? null : StorageUtils.getEnergyContainer(stack, 0); if (!creative && energyContainer == null) { return InteractionResult.FAIL; @@ -155,7 +167,7 @@ public InteractionResult useOn(UseOnContext context) { } energyContainer.extract(energyPerItemDump, Action.EXECUTE, AutomationType.MANUAL); } - Block.popResource(world, pos, inventorySlot.getStack().copy()); + InventoryUtils.dropStack(inventorySlot.getStack().copy(), slotStack -> Block.popResourceFromFace(world, pos, side, slotStack)); inventorySlot.setEmpty(); } } diff --git a/src/main/java/mekanism/common/util/InventoryUtils.java b/src/main/java/mekanism/common/util/InventoryUtils.java index 518e9f2f9bc..43001c45476 100644 --- a/src/main/java/mekanism/common/util/InventoryUtils.java +++ b/src/main/java/mekanism/common/util/InventoryUtils.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.function.Consumer; import mekanism.api.Action; import mekanism.api.AutomationType; import mekanism.api.MekanismAPI; @@ -51,31 +52,41 @@ public static void dropItemContents(ItemEntity entity, DamageSource source) { ListTag storedContents = sustainedInventory.getInventory(stack); for (IInventorySlot slot : ItemRecipeData.readContents(storedContents)) { if (!slot.isEmpty()) { - ItemStack slotStack = slot.getStack(); - int count = slotStack.getCount(); - int max = slotStack.getMaxStackSize(); - if (count > max) { - //If we have more than a stack of the item (such as we are a bin) or some other thing that allows for compressing - // stack counts, drop as many stacks as we need at their max size - while (count > max) { - entity.level.addFreshEntity(new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), StackUtils.size(slotStack, max))); - count -= max; - } - if (count > 0) { - //If we have anything left to drop afterward, do so - entity.level.addFreshEntity(new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), StackUtils.size(slotStack, count))); - } - } else { - //If we have a valid stack, we can just directly drop that instead without requiring any copies - // as while IInventorySlot#getStack says to not mutate the stack, our slot is a dummy slot - entity.level.addFreshEntity(new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), slotStack)); - } + //Pass the stack directly as while IInventorySlot#getStack says to not mutate the stack, our slot is a dummy slot + // so even if we end up adding the entity using the source stack it is fine + dropStack(slot.getStack(), slotStack -> entity.level.addFreshEntity(new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), slotStack))); } } } } } + /** + * Helper to drop a stack that may potentially be oversized. + * + * @param stack Item Stack to drop, may be passed directly to the dropper. + * @param dropper Called to drop the item. + */ + public static void dropStack(ItemStack stack, Consumer dropper) { + int count = stack.getCount(); + int max = stack.getMaxStackSize(); + if (count > max) { + //If we have more than a stack of the item (such as we are a bin) or some other thing that allows for compressing + // stack counts, drop as many stacks as we need at their max size + while (count > max) { + dropper.accept(StackUtils.size(stack, max)); + count -= max; + } + if (count > 0) { + //If we have anything left to drop afterward, do so + dropper.accept(StackUtils.size(stack, count)); + } + } else { + //If we have a valid stack, we can just directly drop that instead without requiring any copies + dropper.accept(stack); + } + } + /** * Like {@link ItemHandlerHelper#canItemStacksStack(ItemStack, ItemStack)} but empty stacks mean equal (either param). Thiakil: not sure why. *