From 70c5382e9d7a62580690bdc246e33d36c0eb0375 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 14 Mar 2025 19:45:28 +0700 Subject: [PATCH] Always use slotted addItem implementation in containers --- .../mc/otm/container/IEnhancedContainer.kt | 111 +++++++++----- .../mc/otm/container/ISlottedContainer.kt | 145 +----------------- .../mc/otm/player/ExopackContainer.kt | 3 + 3 files changed, 80 insertions(+), 179 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IEnhancedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IEnhancedContainer.kt index d42d54a9b..2eb1774fe 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IEnhancedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IEnhancedContainer.kt @@ -1,7 +1,6 @@ package ru.dbotthepony.mc.otm.container import it.unimi.dsi.fastutil.ints.IntCollection -import it.unimi.dsi.fastutil.ints.IntSet import net.minecraft.world.Container import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.StackedContents @@ -253,60 +252,102 @@ interface IEnhancedContainer : Container, RecipeInput, I return list } - fun addItem(stack: ItemStack, simulate: Boolean, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null): ItemStack { + private fun addItem(stack: ItemStack, simulate: Boolean, filterPass: Boolean, slots: IntCollection, onlyIntoExisting: Boolean, popTime: Int?, ignoreFilters: Boolean): ItemStack { if (stack.isEmpty || slots.isEmpty()) return stack - val copy = stack.copy() - // двигаем в одинаковые слоты - for (slot in slotWithItemIterator(stack.item, slots)) { - if (ItemStack.isSameItemSameComponents(this[slot], copy)) { - val slotStack = this[slot] - val slotLimit = getMaxStackSize(slot, slotStack) + for (i in slotWithItemIterator(stack.item, slots)) { + val slot = containerSlot(i) - if (slotStack.count < slotLimit) { - val newCount = (slotStack.count + copy.count).coerceAtMost(slotLimit) - val diff = newCount - slotStack.count + val condition: Boolean + + if (slot is IFilteredContainerSlot) { + condition = (ignoreFilters || !slot.isForbiddenForAutomation) && + ItemStack.isSameItemSameComponents(slot.item, stack) && + (ignoreFilters || !filterPass && !slot.hasFilter || filterPass && slot.hasFilter && slot.testSlotFilter(stack)) + } else { + condition = (ignoreFilters || !filterPass) && ItemStack.isSameItemSameComponents(slot.item, stack) + } + + if (condition) { + val slotLimit = slot.maxStackSize(slot.item) + + if (slot.item.count < slotLimit) { + val newCount = (slot.item.count + stack.count).coerceAtMost(slotLimit) + val diff = newCount - slot.item.count if (!simulate) { - slotStack.count = newCount - setChanged(slot) + slot.item.count = newCount + slot.setChanged() if (popTime != null) { - slotStack.popTime = popTime + slot.item.popTime = popTime } } - copy.shrink(diff) + stack.shrink(diff) - if (copy.isEmpty) { + if (stack.isEmpty) return ItemStack.EMPTY - } } } } if (!onlyIntoExisting) { - // двигаем в пустые слоты - for (slot in emptySlotIndexIterator(slots)) { - val diff = copy.count.coerceAtMost(getMaxStackSize(slot, stack)) + for (i in emptySlotIndexIterator(slots)) { + val slot = containerSlot(i) - if (!simulate) { - val copyToPut = copy.copy() - copyToPut.count = diff - this[slot] = copyToPut - setChanged() + val condition: Boolean + + if (slot is IFilteredContainerSlot) { + condition = (ignoreFilters || !slot.isForbiddenForAutomation) && + (ignoreFilters || !filterPass && !slot.hasFilter || filterPass && slot.hasFilter && slot.testSlotFilter(stack)) + } else { + condition = ignoreFilters || !filterPass } - copy.shrink(diff) + if (condition) { + val diff = stack.count.coerceAtMost(slot.maxStackSize(stack)) - if (copy.isEmpty) - return ItemStack.EMPTY + if (!simulate) { + val copyToPut = stack.copy() + copyToPut.count = diff + slot.item = copyToPut + + if (popTime != null) { + copyToPut.popTime = popTime + } + } + + stack.shrink(diff) + + if (stack.isEmpty) + return ItemStack.EMPTY + } } } - return copy + return stack + } + + /** + * Hint used internally by [IEnhancedContainer] to potentially speed up default method implementations + */ + val hasFilterableSlots: Boolean + get() = false + + fun addItem(stack: ItemStack, simulate: Boolean, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null, ignoreFilters: Boolean = false): ItemStack { + if (stack.isEmpty || slots.isEmpty()) + return stack + + if (ignoreFilters || !hasFilterableSlots) { + return addItem(stack.copy(), simulate, filterPass = true, slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = true) + } else { + var copy = addItem(stack.copy(), simulate, filterPass = true, slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = false) + copy = addItem(copy, simulate, filterPass = false, slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = false) + return copy + } } /** @@ -314,20 +355,20 @@ interface IEnhancedContainer : Container, RecipeInput, I * * @return Whenever [stack] was modified */ - fun consumeItem(stack: ItemStack, simulate: Boolean, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null): Boolean { - if (stack.isEmpty || slots.isEmpty()) + fun consumeItem(stack: ItemStack, simulate: Boolean, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null, ignoreFilters: Boolean = false): Boolean { + if (stack.isEmpty) return false - val result = addItem(stack, simulate, slots, onlyIntoExisting, popTime) + val result = addItem(stack, simulate = simulate, slots = slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = ignoreFilters) if (!simulate) stack.count = result.count return result.count != stack.count } - fun fullyAddItem(stack: ItemStack, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null): Boolean { - if (!addItem(stack, true, slots, onlyIntoExisting, popTime).isEmpty) + fun fullyAddItem(stack: ItemStack, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null, ignoreFilters: Boolean = false): Boolean { + if (!addItem(stack, simulate = true, slots = slots, popTime = popTime, onlyIntoExisting = onlyIntoExisting, ignoreFilters = ignoreFilters).isEmpty) return false - return addItem(stack, false, slots, onlyIntoExisting, popTime).isEmpty + return addItem(stack, simulate = false, slots = slots, popTime = popTime, onlyIntoExisting = onlyIntoExisting, ignoreFilters = ignoreFilters).isEmpty } fun stream(): Stream { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainer.kt index 59307ad96..5a39fbd8a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainer.kt @@ -1,7 +1,5 @@ package ru.dbotthepony.mc.otm.container -import it.unimi.dsi.fastutil.ints.IntCollection -import it.unimi.dsi.fastutil.ints.IntSet import net.minecraft.world.item.ItemStack import ru.dbotthepony.kommons.collect.any @@ -33,147 +31,6 @@ interface ISlottedContainer : IEnhancedContainer { containerSlot(slot).item = itemStack } - private fun addItem(stack: ItemStack, simulate: Boolean, filterPass: Boolean, slots: IntCollection, onlyIntoExisting: Boolean, popTime: Int?, ignoreFilters: Boolean): ItemStack { - if (stack.isEmpty || slots.isEmpty()) - return stack - - // двигаем в одинаковые слоты - for (i in slotWithItemIterator(stack.item, slots)) { - val slot = containerSlot(i) - - val condition: Boolean - - if (slot is IFilteredContainerSlot) { - condition = (ignoreFilters || !slot.isForbiddenForAutomation) && - ItemStack.isSameItemSameComponents(slot.item, stack) && - (ignoreFilters || !filterPass && !slot.hasFilter || filterPass && slot.hasFilter && slot.testSlotFilter(stack)) - } else { - condition = (ignoreFilters || !filterPass) && ItemStack.isSameItemSameComponents(slot.item, stack) - } - - if (condition) { - val slotLimit = slot.maxStackSize(slot.item) - - if (slot.item.count < slotLimit) { - val newCount = (slot.item.count + stack.count).coerceAtMost(slotLimit) - val diff = newCount - slot.item.count - - if (!simulate) { - slot.item.count = newCount - slot.setChanged() - - if (popTime != null) { - slot.item.popTime = popTime - } - } - - stack.shrink(diff) - - if (stack.isEmpty) - return ItemStack.EMPTY - } - } - } - - if (!onlyIntoExisting) { - for (i in emptySlotIndexIterator(slots)) { - val slot = containerSlot(i) - - val condition: Boolean - - if (slot is IFilteredContainerSlot) { - condition = (ignoreFilters || !slot.isForbiddenForAutomation) && - (ignoreFilters || !filterPass && !slot.hasFilter || filterPass && slot.hasFilter && slot.testSlotFilter(stack)) - } else { - condition = ignoreFilters || !filterPass - } - - if (condition) { - val diff = stack.count.coerceAtMost(slot.maxStackSize(stack)) - - if (!simulate) { - val copyToPut = stack.copy() - copyToPut.count = diff - slot.item = copyToPut - - if (popTime != null) { - copyToPut.popTime = popTime - } - } - - stack.shrink(diff) - - if (stack.isEmpty) - return ItemStack.EMPTY - } - } - } - - return stack - } - - /** - * Hint used internally by [ISlottedContainer] to potentially speed up default method implementations - */ - val hasFilterableSlots: Boolean + override val hasFilterableSlots: Boolean get() = slotIterator().any { it is IFilteredContainerSlot } - - fun addItem(stack: ItemStack, simulate: Boolean, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null, ignoreFilters: Boolean): ItemStack { - if (stack.isEmpty || slots.isEmpty()) - return stack - - if (ignoreFilters || !hasFilterableSlots) { - return addItem(stack.copy(), simulate, filterPass = true, slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = true) - } else { - var copy = addItem(stack.copy(), simulate, filterPass = true, slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = false) - copy = addItem(copy, simulate, filterPass = false, slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = false) - return copy - } - } - - - /** - * Unlike [addItem], modifies original [stack] - * - * @return Whenever [stack] was modified - */ - fun consumeItem(stack: ItemStack, simulate: Boolean, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null, ignoreFilters: Boolean): Boolean { - if (stack.isEmpty) - return false - - val result = addItem(stack, simulate = simulate, slots = slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = ignoreFilters) - if (!simulate) stack.count = result.count - return result.count != stack.count - } - - fun fullyAddItem(stack: ItemStack, slots: IntCollection = slotRange, onlyIntoExisting: Boolean = false, popTime: Int? = null, ignoreFilters: Boolean): Boolean { - if (!addItem(stack, simulate = true, slots = slots, popTime = popTime, onlyIntoExisting = onlyIntoExisting, ignoreFilters = ignoreFilters).isEmpty) - return false - - return addItem(stack, simulate = false, slots = slots, popTime = popTime, onlyIntoExisting = onlyIntoExisting, ignoreFilters = ignoreFilters).isEmpty - } - - override fun addItem( - stack: ItemStack, - simulate: Boolean, - slots: IntCollection, - onlyIntoExisting: Boolean, - popTime: Int? - ): ItemStack { - return addItem(stack, simulate = simulate, slots = slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = false) - } - - override fun consumeItem( - stack: ItemStack, - simulate: Boolean, - slots: IntCollection, - onlyIntoExisting: Boolean, - popTime: Int? - ): Boolean { - return consumeItem(stack, simulate = simulate, slots = slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = false) - } - - override fun fullyAddItem(stack: ItemStack, slots: IntCollection, onlyIntoExisting: Boolean, popTime: Int?): Boolean { - return fullyAddItem(stack, slots = slots, onlyIntoExisting = onlyIntoExisting, popTime = popTime, ignoreFilters = false) - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/player/ExopackContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/player/ExopackContainer.kt index c3b7c9f9d..f7c86e5b2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/player/ExopackContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/player/ExopackContainer.kt @@ -19,4 +19,7 @@ class ExopackContainer(size: Int, val player: MatteryPlayer) : EnhancedContainer override fun containerSlot(slot: Int): IPlayerInventorySlot { return Slot(slot) } + + override val hasFilterableSlots: Boolean + get() = true }