Always use slotted addItem implementation in containers

This commit is contained in:
DBotThePony 2025-03-14 19:45:28 +07:00
parent 01215d647c
commit 70c5382e9d
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 80 additions and 179 deletions

View File

@ -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<out S : IContainerSlot> : 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<out S : IContainerSlot> : 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<ItemStack> {

View File

@ -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<out S : IContainerSlot> : IEnhancedContainer<S> {
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)
}
}

View File

@ -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
}