From 6747d5f471dc6b9cca378b64a07070a106e1e3f3 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 27 Feb 2025 23:40:29 +0700 Subject: [PATCH] Further split ISlottedContainer into IAutomatedContainer --- .../mc/otm/container/CombinedContainer.kt | 100 ++++++++---------- .../mc/otm/container/ContainerSlot.kt | 4 +- .../mc/otm/container/IAutomatedContainer.kt | 40 +++++++ ...inerSlot.kt => IAutomatedContainerSlot.kt} | 2 +- .../mc/otm/container/IEnhancedContainer.kt | 6 ++ ....kt => IFilteredAutomatedContainerSlot.kt} | 2 +- .../mc/otm/container/ISlottedContainer.kt | 38 +------ .../mc/otm/container/SlottedContainer.kt | 5 +- 8 files changed, 98 insertions(+), 99 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainer.kt rename src/main/kotlin/ru/dbotthepony/mc/otm/container/{ISlottedContainerSlot.kt => IAutomatedContainerSlot.kt} (97%) rename src/main/kotlin/ru/dbotthepony/mc/otm/container/{IFilteredSlottedContainerSlot.kt => IFilteredAutomatedContainerSlot.kt} (71%) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt index 542ebb252..3eb596d83 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt @@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableMap import com.google.common.collect.ImmutableSet import it.unimi.dsi.fastutil.ints.IntAVLTreeSet import it.unimi.dsi.fastutil.ints.IntArrayList +import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.ints.IntSet import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap @@ -22,39 +23,36 @@ import ru.dbotthepony.mc.otm.core.isNotEmpty import ru.dbotthepony.mc.otm.core.stream import java.util.stream.Stream -class CombinedContainer(containers: Stream>>) : IMatteryContainer { - constructor(vararg containers: Container) : this(containers.stream().map { it to (0 until it.containerSize) }) - constructor(containers: Collection) : this(containers.stream().map { it to (0 until it.containerSize) }) +class CombinedContainer(containers: Stream>>) : ISlottedContainer { + constructor(vararg containers: IEnhancedContainer) : this(containers.stream().map { it to (0 until it.containerSize) }) + constructor(containers: Collection) : this(containers.stream().map { it to (0 until it.containerSize) }) - private inner class Slot(override val slot: Int, val outer: IContainerSlot) : IContainerSlot by outer { - override val container: Container - get() = this@CombinedContainer - } - - private val slots: ImmutableList + private val slots: ImmutableList private val slotsMap: ImmutableMap> private val containers: ImmutableSet private val fullCoverage: ImmutableList private val notFullCoverage: ImmutableMap> init { - val list = ImmutableList.Builder() - var i = 0 + val list = ImmutableList.Builder() val validationMap = Reference2ObjectOpenHashMap() val slotsMap = Reference2ObjectOpenHashMap>() + var i = 0 for ((container, slots) in containers) { - val validator = validationMap.computeIfAbsent(container, Object2ObjectFunction { IntAVLTreeSet() }) + val validator = validationMap.computeIfAbsent(container, Object2ObjectFunction { IntOpenHashSet() }) val slotList = slotsMap.computeIfAbsent(container, Object2ObjectFunction { ArrayList() }) for (slot in slots) { if (validator.add(slot)) { val slotObj = container.containerSlot(slot) - list.add(Slot(i++, slotObj)) + list.add(slotObj) slotList.add(slotObj) } else { throw IllegalArgumentException("Duplicate mapping for $container at $i for slot $slot") } + + i++ } } @@ -85,20 +83,7 @@ class CombinedContainer(containers: Stream>>) : IM for (slots in notFullCoverage.values) { for (slot in slots) { - slot.item = ItemStack.EMPTY - } - } - } - - override fun clearSlotFilters() { - for (container in fullCoverage) { - if (container is IMatteryContainer) - container.clearSlotFilters() - } - - for (slots in notFullCoverage.values) { - for (slot in slots) { - slot.setFilter() + slot.remove() } } } @@ -127,16 +112,6 @@ class CombinedContainer(containers: Stream>>) : IM return slots.getOrNull(slot)?.item ?: ItemStack.EMPTY } - override fun removeItem(slot: Int, amount: Int): ItemStack { - val data = slots.getOrNull(slot) ?: return ItemStack.EMPTY - return data.outer.container.removeItem(data.outer.slot, amount) - } - - override fun removeItemNoUpdate(slot: Int): ItemStack { - val data = slots.getOrNull(slot) ?: return ItemStack.EMPTY - return data.outer.container.removeItemNoUpdate(data.outer.slot) - } - override fun setItem(slot: Int, itemStack: ItemStack) { slots.getOrNull(slot)?.item = itemStack } @@ -155,20 +130,17 @@ class CombinedContainer(containers: Stream>>) : IM return true } - override fun iterator(nonEmpty: Boolean): Iterator { + override fun iterator(): Iterator { if (notFullCoverage.isEmpty()) - return fullCoverage.iterator().flatMap { it.iterator(nonEmpty) } + return fullCoverage.iterator().flatMap { it.iterator() } return concatIterators( - fullCoverage.iterator().flatMap { it.iterator(nonEmpty) }, - notFullCoverage.values.iterator().flatMap { it.iterator() }.map { it.item }.let { if (nonEmpty) it.filter { it.isNotEmpty } else it } + fullCoverage.iterator().flatMap { it.iterator() }, + notFullCoverage.values.iterator().flatMap { it.iterator() }.map { it.item }.filter { it.isNotEmpty } ) } - override fun slotIterator(nonEmpty: Boolean): Iterator { - if (nonEmpty) - return slots.iterator().filter { it.isNotEmpty } - + override fun slotIterator(): Iterator { return slots.iterator() } @@ -176,42 +148,54 @@ class CombinedContainer(containers: Stream>>) : IM return slots[slot] } - override fun getSlotFilter(slot: Int): Item? { - return slots[slot].getFilter() - } - override fun setChanged(slot: Int) { slots[slot].setChanged() } - override fun setSlotFilter(slot: Int, filter: Item?): Boolean { - return slots[slot].setFilter(filter) - } - class Builder { - private val values = ArrayList>>() + private val values = ArrayList>>() fun add(container: Container): Builder { + return add(IEnhancedContainer.wrap(container)) + } + + fun add(container: Container, slots: Iterator): Builder { + return add(IEnhancedContainer.wrap(container), slots) + } + + fun add(container: Container, slot: Int): Builder { + return add(IEnhancedContainer.wrap(container), slot) + } + + fun add(container: Container, from: Int, to: Int): Builder { + return add(IEnhancedContainer.wrap(container), from, to) + } + + fun add(container: Container, slots: Iterable): Builder { + return add(IEnhancedContainer.wrap(container), slots) + } + + fun add(container: IEnhancedContainer): Builder { values.add(container to container.slotRange) return this } - fun add(container: Container, slots: Iterator): Builder { + fun add(container: IEnhancedContainer, slots: Iterator): Builder { values.add(container to IntArrayList(slots)) return this } - fun add(container: Container, slot: Int): Builder { + fun add(container: IEnhancedContainer, slot: Int): Builder { values.add(container to intArrayOf(slot).asIterable()) return this } - fun add(container: Container, from: Int, to: Int): Builder { + fun add(container: IEnhancedContainer, from: Int, to: Int): Builder { values.add(container to (from .. to)) return this } - fun add(container: Container, slots: Iterable): Builder { + fun add(container: IEnhancedContainer, slots: Iterable): Builder { values.add(container to slots) return this } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerSlot.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerSlot.kt index 2106682a5..2ab6e6119 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerSlot.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerSlot.kt @@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.data.getOrNull open class ContainerSlot( protected val container: SlottedContainer, protected val slot: Int -) : ISlottedContainerSlot, INBTSerializable { +) : IAutomatedContainerSlot, INBTSerializable { private var _item: ItemStack = ItemStack.EMPTY final override var item: ItemStack @@ -130,7 +130,7 @@ open class ContainerSlot( listener: (new: ItemStack, old: ItemStack) -> Unit, maxStackSize: Int = Item.DEFAULT_MAX_STACK_SIZE, ) : Simple(listener, maxStackSize) { - protected open inner class Instance(container: SlottedContainer, slot: Int) : Simple.Instance(container, slot), IFilteredSlottedContainerSlot { + protected open inner class Instance(container: SlottedContainer, slot: Int) : Simple.Instance(container, slot), IFilteredAutomatedContainerSlot { override var filter: Item? = null set(value) { if (field !== value) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainer.kt new file mode 100644 index 000000000..644b30b3e --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainer.kt @@ -0,0 +1,40 @@ +package ru.dbotthepony.mc.otm.container + +import net.minecraft.world.Container +import net.minecraft.world.item.ItemStack +import net.neoforged.neoforge.items.IItemHandler + +/** + * Reinforced [ISlottedContainer] which slots are [IAutomatedContainerSlot]s, which + * subsequently allow this container to implement [IItemHandler] + */ +interface IAutomatedContainer : ISlottedContainer, IItemHandler { + override fun containerSlot(slot: Int): IAutomatedContainerSlot + + override fun canPlaceItem(slot: Int, itemStack: ItemStack): Boolean { + return containerSlot(slot).canAutomationPlaceItem(itemStack) + } + + override fun canTakeItem(container: Container, slot: Int, itemStack: ItemStack): Boolean { + return containerSlot(slot).canAutomationTakeItem() + } + + override fun getSlots() = containerSize + override fun getStackInSlot(slot: Int) = containerSlot(slot).item + + override fun insertItem(slot: Int, stack: ItemStack, simulate: Boolean): ItemStack { + return containerSlot(slot).insertItem(stack, simulate) + } + + override fun extractItem(slot: Int, amount: Int, simulate: Boolean): ItemStack { + return containerSlot(slot).extractItem(amount, simulate) + } + + override fun getSlotLimit(slot: Int): Int { + return containerSlot(slot).maxStackSize + } + + override fun isItemValid(slot: Int, stack: ItemStack): Boolean { + return canPlaceItem(slot, stack) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainerSlot.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainerSlot.kt similarity index 97% rename from src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainerSlot.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainerSlot.kt index 9da3d32da..16ca182f2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainerSlot.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainerSlot.kt @@ -6,7 +6,7 @@ import net.neoforged.neoforge.items.IItemHandler /** * Slot of [ISlottedContainer], with additional methods to implement interaction behavior for both for players and mechanisms */ -interface ISlottedContainerSlot : IContainerSlot { +interface IAutomatedContainerSlot : IContainerSlot { fun canAutomationPlaceItem(itemStack: ItemStack): Boolean { return true } 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 f61bc6b86..34a1ddd75 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IEnhancedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IEnhancedContainer.kt @@ -24,6 +24,9 @@ interface IEnhancedContainer : IContainer, RecipeInput, Iterable { return IContainerSlot.Simple(slot, this) } + /** + * Returns iterator over **all** slots this container has + */ fun slotIterator(): Iterator { return (0 until containerSize).iterator().map { containerSlot(it) } } @@ -122,6 +125,9 @@ interface IEnhancedContainer : IContainer, RecipeInput, Iterable { return maxStackSize } + /** + * Returns iterator over **non-empty** [ItemStack]s inside this container + */ override fun iterator(): Iterator { return (0 until containerSize).iterator().map { this[it] }.filter { it.isNotEmpty } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredSlottedContainerSlot.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredAutomatedContainerSlot.kt similarity index 71% rename from src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredSlottedContainerSlot.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredAutomatedContainerSlot.kt index 91f1d9da2..b61234064 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredSlottedContainerSlot.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredAutomatedContainerSlot.kt @@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.container import net.minecraft.world.item.ItemStack -interface IFilteredSlottedContainerSlot : IFilteredContainerSlot, ISlottedContainerSlot { +interface IFilteredAutomatedContainerSlot : IFilteredContainerSlot, IAutomatedContainerSlot { override fun canAutomationPlaceItem(itemStack: ItemStack): Boolean { return super.canAutomationPlaceItem(itemStack) && testSlotFilter(itemStack) } 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 dfccd28e0..c6cdb88ad 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ISlottedContainer.kt @@ -9,17 +9,14 @@ import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.map /** - * Container which revolve around embedding slot objects rather than providing direct item access, - * and subsequently fully implement [IItemHandler] + * Container which revolve around embedding slot objects rather than providing direct item access */ -interface ISlottedContainer : IEnhancedContainer, IItemHandler { - override fun containerSlot(slot: Int): ISlottedContainerSlot - - override fun slotIterator(): Iterator { +interface ISlottedContainer : IEnhancedContainer { + override fun slotIterator(): Iterator { return (0 until containerSize).iterator().map { containerSlot(it) } } - override fun nonEmptySlotIterator(): Iterator { + override fun nonEmptySlotIterator(): Iterator { return (0 until containerSize).iterator().map { containerSlot(it) }.filter { it.isNotEmpty } } @@ -47,33 +44,6 @@ interface ISlottedContainer : IEnhancedContainer, IItemHandler { containerSlot(slot).item = itemStack } - override fun canPlaceItem(slot: Int, itemStack: ItemStack): Boolean { - return containerSlot(slot).canAutomationPlaceItem(itemStack) - } - - override fun canTakeItem(container: Container, slot: Int, itemStack: ItemStack): Boolean { - return containerSlot(slot).canAutomationTakeItem() - } - - override fun getSlots() = containerSize - override fun getStackInSlot(slot: Int) = containerSlot(slot).item - - override fun insertItem(slot: Int, stack: ItemStack, simulate: Boolean): ItemStack { - return containerSlot(slot).insertItem(stack, simulate) - } - - override fun extractItem(slot: Int, amount: Int, simulate: Boolean): ItemStack { - return containerSlot(slot).extractItem(amount, simulate) - } - - override fun getSlotLimit(slot: Int): Int { - return containerSlot(slot).maxStackSize - } - - override fun isItemValid(slot: Int, stack: ItemStack): Boolean { - return canPlaceItem(slot, stack) - } - private fun addItem(stack: ItemStack, simulate: Boolean, filterPass: Boolean, slots: IntSet, onlyIntoExisting: Boolean, popTime: Int?, ignoreFilters: Boolean): ItemStack { if (stack.isEmpty || slots.isEmpty()) return stack diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt index d978031c2..18dde606f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt @@ -15,7 +15,6 @@ import net.minecraft.world.item.ItemStack import net.neoforged.neoforge.common.util.INBTSerializable import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.core.isNotEmpty -import ru.dbotthepony.mc.otm.core.math.set import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.data.codec.minRange import java.util.function.Predicate @@ -24,7 +23,7 @@ class SlottedContainer( slots: Collection, private val stillValid: Predicate, private val globalChangeListeners: Array -) : ISlottedContainer, INBTSerializable { +) : IAutomatedContainer, INBTSerializable { private val slots: Array init { @@ -46,7 +45,7 @@ class SlottedContainer( } } - override fun containerSlot(slot: Int): ISlottedContainerSlot { + override fun containerSlot(slot: Int): IAutomatedContainerSlot { return slots[slot] }