Further split ISlottedContainer into IAutomatedContainer
This commit is contained in:
parent
124a1b3db6
commit
6747d5f471
@ -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<Pair<Container, Iterable<Int>>>) : IMatteryContainer {
|
||||
constructor(vararg containers: Container) : this(containers.stream().map { it to (0 until it.containerSize) })
|
||||
constructor(containers: Collection<Container>) : this(containers.stream().map { it to (0 until it.containerSize) })
|
||||
class CombinedContainer(containers: Stream<Pair<IEnhancedContainer, Iterable<Int>>>) : ISlottedContainer {
|
||||
constructor(vararg containers: IEnhancedContainer) : this(containers.stream().map { it to (0 until it.containerSize) })
|
||||
constructor(containers: Collection<IEnhancedContainer>) : 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<Slot>
|
||||
private val slots: ImmutableList<IContainerSlot>
|
||||
private val slotsMap: ImmutableMap<Container, List<IContainerSlot>>
|
||||
private val containers: ImmutableSet<Container>
|
||||
private val fullCoverage: ImmutableList<Container>
|
||||
private val notFullCoverage: ImmutableMap<Container, List<IContainerSlot>>
|
||||
|
||||
init {
|
||||
val list = ImmutableList.Builder<Slot>()
|
||||
var i = 0
|
||||
val list = ImmutableList.Builder<IContainerSlot>()
|
||||
val validationMap = Reference2ObjectOpenHashMap<Container, IntSet>()
|
||||
val slotsMap = Reference2ObjectOpenHashMap<Container, ArrayList<IContainerSlot>>()
|
||||
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<Pair<Container, Iterable<Int>>>) : 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<Pair<Container, Iterable<Int>>>) : 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<Pair<Container, Iterable<Int>>>) : IM
|
||||
return true
|
||||
}
|
||||
|
||||
override fun iterator(nonEmpty: Boolean): Iterator<ItemStack> {
|
||||
override fun iterator(): Iterator<ItemStack> {
|
||||
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<IContainerSlot> {
|
||||
if (nonEmpty)
|
||||
return slots.iterator().filter { it.isNotEmpty }
|
||||
|
||||
override fun slotIterator(): Iterator<IContainerSlot> {
|
||||
return slots.iterator()
|
||||
}
|
||||
|
||||
@ -176,42 +148,54 @@ class CombinedContainer(containers: Stream<Pair<Container, Iterable<Int>>>) : 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<Pair<Container, Iterable<Int>>>()
|
||||
private val values = ArrayList<Pair<IEnhancedContainer, Iterable<Int>>>()
|
||||
|
||||
fun add(container: Container): Builder {
|
||||
return add(IEnhancedContainer.wrap(container))
|
||||
}
|
||||
|
||||
fun add(container: Container, slots: Iterator<Int>): 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<Int>): 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<Int>): Builder {
|
||||
fun add(container: IEnhancedContainer, slots: Iterator<Int>): 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<Int>): Builder {
|
||||
fun add(container: IEnhancedContainer, slots: Iterable<Int>): Builder {
|
||||
values.add(container to slots)
|
||||
return this
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.data.getOrNull
|
||||
open class ContainerSlot(
|
||||
protected val container: SlottedContainer,
|
||||
protected val slot: Int
|
||||
) : ISlottedContainerSlot, INBTSerializable<CompoundTag> {
|
||||
) : IAutomatedContainerSlot, INBTSerializable<CompoundTag> {
|
||||
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) {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -24,6 +24,9 @@ interface IEnhancedContainer : IContainer, RecipeInput, Iterable<ItemStack> {
|
||||
return IContainerSlot.Simple(slot, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns iterator over **all** slots this container has
|
||||
*/
|
||||
fun slotIterator(): Iterator<IContainerSlot> {
|
||||
return (0 until containerSize).iterator().map { containerSlot(it) }
|
||||
}
|
||||
@ -122,6 +125,9 @@ interface IEnhancedContainer : IContainer, RecipeInput, Iterable<ItemStack> {
|
||||
return maxStackSize
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns iterator over **non-empty** [ItemStack]s inside this container
|
||||
*/
|
||||
override fun iterator(): Iterator<ItemStack> {
|
||||
return (0 until containerSize).iterator().map { this[it] }.filter { it.isNotEmpty }
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
@ -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<ISlottedContainerSlot> {
|
||||
interface ISlottedContainer : IEnhancedContainer {
|
||||
override fun slotIterator(): Iterator<IContainerSlot> {
|
||||
return (0 until containerSize).iterator().map { containerSlot(it) }
|
||||
}
|
||||
|
||||
override fun nonEmptySlotIterator(): Iterator<ISlottedContainerSlot> {
|
||||
override fun nonEmptySlotIterator(): Iterator<IContainerSlot> {
|
||||
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
|
||||
|
@ -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<SlotProvider>,
|
||||
private val stillValid: Predicate<Player>,
|
||||
private val globalChangeListeners: Array<Runnable>
|
||||
) : ISlottedContainer, INBTSerializable<Tag> {
|
||||
) : IAutomatedContainer, INBTSerializable<Tag> {
|
||||
private val slots: Array<ContainerSlot>
|
||||
|
||||
init {
|
||||
@ -46,7 +45,7 @@ class SlottedContainer(
|
||||
}
|
||||
}
|
||||
|
||||
override fun containerSlot(slot: Int): ISlottedContainerSlot {
|
||||
override fun containerSlot(slot: Int): IAutomatedContainerSlot {
|
||||
return slots[slot]
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user