Move around and update container apis

This commit is contained in:
DBotThePony 2023-08-19 19:51:19 +07:00
parent 9d79e52c43
commit 67f97dfba6
Signed by: DBot
GPG Key ID: DCC23B5715498507
34 changed files with 343 additions and 250 deletions

View File

@ -10,7 +10,6 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import net.minecraft.world.Container
import net.minecraft.world.Containers
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
@ -20,7 +19,6 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.gameevent.GameEvent
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.LootParams
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.parameters.LootContextParams

View File

@ -105,15 +105,13 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
override fun tick() {
super.tick()
val i = dyeInput.iterator()
for (item in i) {
val dye = DyeColor.entries.firstOrNull { item.`is`(it.tag) } ?: continue
for (slot in dyeInput.slotIterator()) {
val dye = DyeColor.entries.firstOrNull { slot.item.`is`(it.tag) } ?: continue
val stored = dyeStored(dye)
if (stored + HUE_PER_ITEM <= MAX_STORAGE) {
item.shrink(1)
i.setChanged()
slot.item.shrink(1)
slot.setChanged()
dyeStored[dye] = stored + HUE_PER_ITEM
}
}

View File

@ -183,13 +183,13 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
if (isBottling) {
var any = false
var idle = false
val iterator = bottling.iterator()
for (item in iterator) {
for (slot in bottling.slotIterator()) {
val item = slot.item
item.getCapability(MatteryCapability.MATTER).ifPresentK {
if (!it.missingMatter.isPositive) {
unbottling.consumeItem(item, false)
iterator.setChanged()
slot.setChanged()
} else {
any = true
initialCapacity = initialCapacity ?: it.storedMatter
@ -215,7 +215,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
if (spitItemsWhenCantWork) {
unbottling.consumeItem(item, false)
iterator.setChanged()
slot.setChanged()
}
}
}
@ -237,11 +237,9 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
if (!matter.missingMatter.isPositive) {
if (spitItemsWhenCantWork) {
val iterator = unbottling.iterator()
for (item in iterator) {
bottling.consumeItem(item, false)
iterator.setChanged()
for (slot in unbottling.slotIterator()) {
bottling.consumeItem(slot.item, false)
slot.setChanged()
}
}
@ -251,12 +249,13 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
var any = false
val iterator = unbottling.iterator()
for (item in iterator) {
for (slot in unbottling.slotIterator()) {
val item = slot.item
item.getCapability(MatteryCapability.MATTER).ifPresentK {
if (!it.storedMatter.isPositive) {
bottling.consumeItem(item, false)
iterator.setChanged()
slot.setChanged()
} else {
any = true
initialCapacity = initialCapacity ?: it.storedMatter

View File

@ -1,6 +1,5 @@
package ru.dbotthepony.mc.otm.block.entity.matter
import com.google.common.collect.Streams
import javax.annotation.ParametersAreNonnullByDefault
import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.state.BlockState
@ -18,8 +17,6 @@ import net.minecraft.world.level.block.Block
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.core.collect.filterNotNull
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.filterNotNull

View File

@ -44,7 +44,8 @@ import kotlin.collections.HashMap
import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.container.CombinedContainer
import ru.dbotthepony.mc.otm.container.addItem
import ru.dbotthepony.mc.otm.container.fullIterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.container.util.slotIterator
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.collect.toList
import ru.dbotthepony.mc.otm.core.isNotEmpty
@ -58,13 +59,15 @@ interface IItemMonitorPlayerSettings {
var ascendingSort: Boolean
}
private fun takeOne(inventory: CombinedContainer?, item: ItemStack): Boolean {
val iterator = inventory?.optimizedIterator() ?: return false
private fun takeOne(inventory: Container?, item: ItemStack): Boolean {
val iterator = inventory?.slotIterator() ?: return false
for (slot in iterator) {
val stack = slot.item
for (stack in iterator) {
if (stack.equals(item, false)) {
stack.shrink(1)
inventory.setChanged()
slot.setChanged()
return true
}
}
@ -343,7 +346,7 @@ class ItemMonitorBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
check(residue.size == craftingGrid.containerSize) { "Container and residue list sizes mismatch: ${residue.size} != ${craftingGrid.containerSize}" }
val combinedInventory = craftingPlayer.matteryPlayer?.combinedInventory
val copy = craftingGrid.fullIterator().map { it.copy() }.toList()
val copy = craftingGrid.iterator(true).map { it.copy() }.toList()
// удаляем по одному предмету из сетки крафта
for (slot in 0 until craftingGrid.containerSize) {

View File

@ -26,9 +26,9 @@ import ru.dbotthepony.mc.otm.compat.curios.curiosStream
import ru.dbotthepony.mc.otm.compat.curios.isCuriosLoaded
import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided
import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy
import ru.dbotthepony.mc.otm.container.awareStream
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.container.util.awareStream
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
import ru.dbotthepony.mc.otm.core.collect.ContainerItemStackEntry
import ru.dbotthepony.mc.otm.core.collect.concatIterators
@ -38,7 +38,6 @@ import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
import java.util.IdentityHashMap
import java.util.stream.Stream
private val LOGGER = LogManager.getLogger()

View File

@ -1,8 +1,9 @@
package ru.dbotthepony.mc.otm.container
package ru.dbotthepony.mc.otm.capability
import it.unimi.dsi.fastutil.objects.ObjectIterators.AbstractIndexBasedIterator
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.fluids.capability.IFluidHandler
import ru.dbotthepony.mc.otm.container.get
class FluidHandlerIterator(private val handler: IFluidHandler, initialPosition: Int = 0) : AbstractIndexBasedIterator<FluidStack>(0, initialPosition) {
init {

View File

@ -1,9 +1,10 @@
package ru.dbotthepony.mc.otm.container
package ru.dbotthepony.mc.otm.capability
import it.unimi.dsi.fastutil.objects.ObjectSpliterator
import it.unimi.dsi.fastutil.objects.ObjectSpliterators.AbstractIndexBasedSpliterator
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.fluids.capability.IFluidHandler
import ru.dbotthepony.mc.otm.container.get
import java.util.Spliterator
import java.util.stream.Stream
import java.util.stream.StreamSupport

View File

@ -82,8 +82,8 @@ import ru.dbotthepony.mc.otm.config.ExopackConfig
import ru.dbotthepony.mc.otm.container.CombinedContainer
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.slotIterator
import ru.dbotthepony.mc.otm.container.vanishCursedItems
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.collect.UUIDIntModifiersMap
@ -130,13 +130,9 @@ import kotlin.collections.ArrayDeque
import kotlin.reflect.KMutableProperty1
private fun Player.dropContainer(container: Container, spill: Boolean = true, setThrower: Boolean = false) {
val iterator = container.iterator()
for (item in iterator) {
if (item.isNotEmpty) {
drop(item, spill, setThrower)
iterator.remove()
}
for (slot in container.slotIterator()) {
drop(slot.item, spill, setThrower)
slot.remove()
}
}

View File

@ -23,9 +23,9 @@ import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.RectangleButtonPanel
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_ACTIVE
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_INACTIVE
import ru.dbotthepony.mc.otm.container.awareStream
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.container.util.awareStream
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
import ru.dbotthepony.mc.otm.core.collect.emptyIterator
import ru.dbotthepony.mc.otm.menu.MatterySlot

View File

@ -4,15 +4,14 @@ import com.google.common.collect.Streams
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.ItemStack
import net.minecraftforge.api.distmarker.Dist
import net.minecraftforge.fml.ModList
import net.minecraftforge.fml.loading.FMLEnvironment
import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.container.awareStream
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.container.util.awareStream
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
import ru.dbotthepony.mc.otm.core.collect.concatIterators
import ru.dbotthepony.mc.otm.core.collect.emptyIterator

View File

@ -4,13 +4,16 @@ import com.google.common.collect.ImmutableList
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.IntOpenHashSet
import it.unimi.dsi.fastutil.ints.IntSet
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
import net.minecraft.world.Container
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.container.util.ContainerSlot
import ru.dbotthepony.mc.otm.container.util.IContainerSlot
import ru.dbotthepony.mc.otm.container.util.IIterableContainer
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.collect.concatIterators
import ru.dbotthepony.mc.otm.core.collect.filter
@ -21,26 +24,10 @@ import ru.dbotthepony.mc.otm.core.stream
import java.util.LinkedList
import java.util.stream.Stream
class CombinedContainer(containers: Stream<Pair<Container, Iterator<Int>>>) : Container {
class CombinedContainer(containers: Stream<Pair<Container, Iterator<Int>>>) : Container, IIterableContainer {
constructor(vararg containers: Container) : this(containers.stream().map { it to (0 until it.containerSize).iterator() })
constructor(containers: Collection<Container>) : this(containers.stream().map { it to (0 until it.containerSize).iterator() })
class ContainerSlot(val container: Container, val containerIndex: Int) : GetterSetter<ItemStack> {
var item: ItemStack
get() = container[containerIndex]
set(value) { container[containerIndex] = value }
override fun get(): ItemStack {
return item
}
override fun accept(t: ItemStack) {
item = t
}
val isEmpty: Boolean get() = item.isEmpty
}
private val slots: List<ContainerSlot>
private val slotsMap: Map<Container, List<ContainerSlot>>
private val containers: Set<Container>
@ -60,7 +47,7 @@ class CombinedContainer(containers: Stream<Pair<Container, Iterator<Int>>>) : Co
for (slot in slots) {
if (validator.add(slot)) {
i++
val slotObj = ContainerSlot(container, slot)
val slotObj = ContainerSlot(slot, container)
list.add(slotObj)
slotList.add(slotObj)
} else {
@ -131,12 +118,12 @@ class CombinedContainer(containers: Stream<Pair<Container, Iterator<Int>>>) : Co
override fun removeItem(index: Int, count: Int): ItemStack {
val data = slots.getOrNull(index) ?: return ItemStack.EMPTY
return data.container.removeItem(data.containerIndex, count)
return data.container.removeItem(data.slot, count)
}
override fun removeItemNoUpdate(index: Int): ItemStack {
val data = slots.getOrNull(index) ?: return ItemStack.EMPTY
return data.container.removeItemNoUpdate(data.containerIndex)
return data.container.removeItemNoUpdate(data.slot)
}
override fun setItem(index: Int, value: ItemStack) {
@ -153,7 +140,7 @@ class CombinedContainer(containers: Stream<Pair<Container, Iterator<Int>>>) : Co
val data = slots.getOrNull(index) ?: return
if (data.container is MatteryContainer) {
data.container.setChanged(data.containerIndex)
data.container.setChanged(data.slot)
} else {
data.container.setChanged()
}
@ -167,13 +154,20 @@ class CombinedContainer(containers: Stream<Pair<Container, Iterator<Int>>>) : Co
return true
}
fun optimizedIterator(): Iterator<ItemStack> {
override fun iterator(nonEmpty: Boolean): Iterator<ItemStack> {
return concatIterators(
fullCoverage.iterator().flatMap { it.iterator() },
notFullCoverage.values.iterator().flatMap { it.iterator() }.map { it.item }.filter { it.isNotEmpty }
fullCoverage.iterator().flatMap { it.iterator(nonEmpty) },
notFullCoverage.values.iterator().flatMap { it.iterator() }.map { it.item }.let { if (nonEmpty) it.filter { it.isNotEmpty } else it }
)
}
override fun slotIterator(nonEmpty: Boolean): Iterator<IContainerSlot> {
if (nonEmpty)
return slots.iterator().filter { it.isNotEmpty }
return slots.iterator()
}
class Builder {
private var built = false
private val values = LinkedList<Pair<Container, Iterator<Int>>>()

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.container
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.items.IItemHandler
class ContainerHandler @JvmOverloads internal constructor(

View File

@ -11,8 +11,11 @@ import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.enchantment.EnchantmentHelper.hasVanishingCurse
import net.minecraftforge.fluids.capability.IFluidHandler
import ru.dbotthepony.mc.otm.container.util.ItemStackHashStrategy
import ru.dbotthepony.mc.otm.container.util.slotIterator
import ru.dbotthepony.mc.otm.core.addAll
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.util.ItemStackSorter
import kotlin.math.roundToInt
@Suppress("nothing_to_inline")
@ -87,11 +90,9 @@ fun Container.addItem(stack: ItemStack, range: IntRange, simulate: Boolean = fal
fun Container.addItem(stack: ItemStack, simulate: Boolean): ItemStack = addItem(stack, 0 until containerSize, simulate)
fun Container.vanishCursedItems() {
val iterator = iterator()
for (item in iterator) {
if (item.isNotEmpty && hasVanishingCurse(item)) {
iterator.remove()
for (slot in slotIterator()) {
if (hasVanishingCurse(slot.item)) {
slot.remove()
}
}
}

View File

@ -1,82 +0,0 @@
package ru.dbotthepony.mc.otm.container
import it.unimi.dsi.fastutil.objects.ObjectIterators
import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.isNotEmpty
class ContainerIterator(private val container: Container) : IContainerIterator {
private var index = 0
private var lastIndex = -1
override fun hasNext(): Boolean {
while (index < container.containerSize) {
if (container[index].isNotEmpty) {
return true
}
index++
}
return false
}
override fun next(): ItemStack {
if (!hasNext()) {
throw NoSuchElementException()
}
lastIndex = index
return container[index++]
}
override fun remove() {
if (lastIndex == -1) {
throw NoSuchElementException()
}
container[lastIndex] = ItemStack.EMPTY
lastIndex = -1
}
override fun setChanged() {
container.setChanged()
}
}
fun Container.iterator(): IContainerIterator {
return if (this is MatteryContainer) {
iterator()
} else {
ContainerIterator(this)
}
}
class FullContainerIterator(val container: Container, initialPos: Int = 0) : MutableIterator<ItemStack>, ObjectIterators.AbstractIndexBasedListIterator<ItemStack>(0, initialPos), IContainerIterator {
override fun remove(location: Int) {
pos++
container[location] = ItemStack.EMPTY
}
override fun get(location: Int): ItemStack {
return container[location]
}
override fun getMaxPos(): Int {
return container.containerSize
}
override fun add(location: Int, k: ItemStack?) {
throw UnsupportedOperationException()
}
override fun set(location: Int, k: ItemStack) {
container[location] = k
}
override fun setChanged() {
container.setChanged()
}
}
fun Container.fullIterator() = FullContainerIterator(this)

View File

@ -4,7 +4,7 @@ import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.ForgeHooks
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.capability.stream
import ru.dbotthepony.mc.otm.core.isNotEmpty
interface HandlerFilter {

View File

@ -0,0 +1,84 @@
package ru.dbotthepony.mc.otm.container
import net.minecraft.world.Container
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import java.util.function.Predicate
// passthrough all default methods to fix Kotlin bug related to implementation delegation not properly working on Java interfaces
// https://youtrack.jetbrains.com/issue/KT-55080/Change-the-behavior-of-inheritance-delegation-to-delegates-implementing-Java-interfaces-with-default-methods
interface IContainer : Container {
override fun getMaxStackSize(): Int {
return super.getMaxStackSize()
}
override fun startOpen(player: Player) {
super.startOpen(player)
}
override fun stopOpen(player: Player) {
super.stopOpen(player)
}
override fun canPlaceItem(slot: Int, itemStack: ItemStack): Boolean {
return super.canPlaceItem(slot, itemStack)
}
override fun canTakeItem(container: Container, slot: Int, itemStack: ItemStack): Boolean {
return super.canTakeItem(container, slot, itemStack)
}
override fun countItem(item: Item): Int {
return super.countItem(item)
}
override fun hasAnyOf(items: Set<Item>): Boolean {
return super.hasAnyOf(items)
}
override fun hasAnyMatching(predicate: Predicate<ItemStack>): Boolean {
return super.hasAnyMatching(predicate)
}
companion object {
fun wrap(container: Container): IContainer {
if (container is IContainer)
return container
else
return object : IContainer, Container by container {
override fun getMaxStackSize(): Int {
return container.getMaxStackSize()
}
override fun startOpen(player: Player) {
container.startOpen(player)
}
override fun stopOpen(player: Player) {
container.stopOpen(player)
}
override fun canPlaceItem(slot: Int, itemStack: ItemStack): Boolean {
return container.canPlaceItem(slot, itemStack)
}
override fun canTakeItem(container: Container, slot: Int, itemStack: ItemStack): Boolean {
return container.canTakeItem(container, slot, itemStack)
}
override fun countItem(item: Item): Int {
return container.countItem(item)
}
override fun hasAnyOf(items: Set<Item>): Boolean {
return container.hasAnyOf(items)
}
override fun hasAnyMatching(predicate: Predicate<ItemStack>): Boolean {
return container.hasAnyMatching(predicate)
}
}
}
}
}

View File

@ -1,12 +0,0 @@
package ru.dbotthepony.mc.otm.container
import net.minecraft.world.item.ItemStack
interface IContainerIterator : MutableIterator<ItemStack> {
/**
* Notifies underlying container that last returned [ItemStack] was modified
*
* @throws NoSuchElementException
*/
fun setChanged()
}

View File

@ -11,7 +11,6 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.Container
import kotlin.jvm.JvmOverloads
import net.minecraft.world.entity.player.Player
import net.minecraft.world.entity.player.StackedContents
@ -20,10 +19,15 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.Items
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.container.util.ContainerSlot
import ru.dbotthepony.mc.otm.container.util.IContainerSlot
import ru.dbotthepony.mc.otm.container.util.IIterableContainer
import ru.dbotthepony.mc.otm.core.addSorted
import ru.dbotthepony.mc.otm.core.collect.any
import ru.dbotthepony.mc.otm.core.collect.count
import ru.dbotthepony.mc.otm.core.collect.emptyIterator
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set
@ -39,11 +43,11 @@ import java.util.function.Predicate
import java.util.function.Supplier
import java.util.stream.Stream
import java.util.stream.StreamSupport
import kotlin.NoSuchElementException
import kotlin.collections.ArrayList
import kotlin.collections.Iterator
@Suppress("UNUSED")
open class MatteryContainer(protected val watcher: Runnable, private val size: Int) : Container, Iterable<ItemStack>, INBTSerializable<Tag?>, StackedContentsCompatible {
open class MatteryContainer(protected val watcher: Runnable, private val size: Int) : IContainer, IIterableContainer, Iterable<ItemStack>, INBTSerializable<Tag?>, StackedContentsCompatible {
constructor(size: Int) : this({}, size)
init {
@ -553,7 +557,7 @@ open class MatteryContainer(protected val watcher: Runnable, private val size: I
}
}
private inner class Iterator : IContainerIterator {
private inner class Iterator : kotlin.collections.Iterator<ItemStack> {
init {
indicesReferenced = true
}
@ -569,24 +573,6 @@ open class MatteryContainer(protected val watcher: Runnable, private val size: I
lastIndex = parent.nextInt()
return getItem(lastIndex)
}
override fun remove() {
if (lastIndex == -1) {
throw NoSuchElementException()
}
parent.remove()
setItem(lastIndex, ItemStack.EMPTY)
lastIndex = -1
}
override fun setChanged() {
if (lastIndex == -1) {
throw NoSuchElementException()
}
setChanged(lastIndex)
}
}
private inner class Spliterator(private val parent: IntSpliterator) : java.util.Spliterator<ItemStack> {
@ -609,38 +595,46 @@ open class MatteryContainer(protected val watcher: Runnable, private val size: I
}
}
private object EmptyIterator : IContainerIterator {
override fun hasNext(): Boolean {
return false
}
override fun next(): ItemStack {
throw NoSuchElementException()
}
override fun remove() {
throw NoSuchElementException()
}
override fun setChanged() {
throw NoSuchElementException()
}
}
final override fun iterator(): IContainerIterator {
final override fun iterator(): kotlin.collections.Iterator<ItemStack> {
if (isEmpty) {
return EmptyIterator
return emptyIterator()
}
return Iterator()
}
final override fun iterator(nonEmpty: Boolean): kotlin.collections.Iterator<ItemStack> {
if (!nonEmpty) {
return (0 until size).iterator().map { slots[it] }
} else if (isEmpty) {
return emptyIterator()
} else {
return Iterator()
}
}
final override fun slotIterator(): kotlin.collections.Iterator<IContainerSlot> {
indicesReferenced = true
return nonEmptyIndices.iterator().map { ContainerSlot(it, this) }
}
final override fun slotIterator(nonEmpty: Boolean): kotlin.collections.Iterator<IContainerSlot> {
if (!nonEmpty) {
return (0 until size).iterator().map { ContainerSlot(it, this) }
} else if (isEmpty) {
return emptyIterator()
} else {
indicesReferenced = true
return nonEmptyIndices.iterator().map { ContainerSlot(it, this) }
}
}
final override fun countItem(item: Item): Int {
return iterator().filter { it.item == item }.count().toInt()
}
final override fun hasAnyOf(set: Set<Item>): Boolean {
return iterator().any { it.item in set }
final override fun hasAnyOf(items: Set<Item>): Boolean {
return iterator().any { it.item in items }
}
final override fun hasAnyMatching(predicate: Predicate<ItemStack>): Boolean {

View File

@ -3,9 +3,8 @@ package ru.dbotthepony.mc.otm.container
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap
import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack
import java.util.Arrays
class ShadowContainer(private val parent: Container) : Container by parent {
class ShadowContainer(private val parent: Container) : IContainer by IContainer.wrap(parent) {
private val shadowed = Int2ObjectArrayMap<ItemStack>(0)
override fun clearContent() {

View File

@ -1,12 +1,12 @@
package ru.dbotthepony.mc.otm.container
import net.minecraft.world.Container
import net.minecraft.world.entity.player.StackedContents
import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.collect.toList
class ShadowCraftingContainer(private val parent: CraftingContainer) : Container by ShadowContainer(parent), CraftingContainer {
class ShadowCraftingContainer(private val parent: CraftingContainer) : IContainer by ShadowContainer(parent), CraftingContainer {
override fun fillStackedContents(contents: StackedContents) {
for (item in iterator()) {
contents.accountStack(item)

View File

@ -1,9 +1,10 @@
package ru.dbotthepony.mc.otm.container
package ru.dbotthepony.mc.otm.container.util
import it.unimi.dsi.fastutil.objects.ObjectSpliterator
import it.unimi.dsi.fastutil.objects.ObjectSpliterators
import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
import ru.dbotthepony.mc.otm.core.collect.ContainerItemStackEntry
import java.util.stream.Stream

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.container
package ru.dbotthepony.mc.otm.container.util
import it.unimi.dsi.fastutil.objects.ObjectSpliterator
import it.unimi.dsi.fastutil.objects.ObjectSpliterators

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.container
package ru.dbotthepony.mc.otm.container.util
import it.unimi.dsi.fastutil.Hash
import net.minecraft.world.item.ItemStack

View File

@ -0,0 +1,123 @@
package ru.dbotthepony.mc.otm.container.util
import net.minecraft.world.Container
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.isNotEmpty
interface IContainerSlot : GetterSetter<ItemStack> {
val slot: Int
val container: Container
operator fun component1() = slot
operator fun component2() = item
val isForbiddenForAutomation: Boolean get() {
val container = container
if (container is MatteryContainer) {
return container.isSlotForbiddenForAutomation(slot)
} else {
return false
}
}
val filter: Item? get() {
val container = container
if (container is MatteryContainer) {
return container.getSlotFilter(slot)
} else {
return null
}
}
val hasFilter: Boolean
get() = filter != null
fun remove() {
container[slot] = ItemStack.EMPTY
}
override fun get(): ItemStack {
return container[slot]
}
override fun accept(t: ItemStack) {
container[slot] = t
}
fun setChanged() {
val container = container
if (container is MatteryContainer) {
container.setChanged(slot)
} else {
container.setChanged()
}
}
var item: ItemStack
get() = container[slot]
set(value) { container[slot] = value }
val isEmpty: Boolean
get() = container[slot].isEmpty
val isNotEmpty: Boolean
get() = container[slot].isNotEmpty
}
class ContainerSlot(override val slot: Int, override val container: Container) : IContainerSlot {
init {
require(slot in 0 until container.containerSize) { "Slot out of bounds: $slot (container: $container with size ${container.containerSize})" }
}
}
interface IIterableContainer : Iterable<ItemStack> {
/**
* Iterates over non-empty itemstacks of this container
*/
override fun iterator(): Iterator<ItemStack> {
return iterator(true)
}
fun iterator(nonEmpty: Boolean): Iterator<ItemStack>
/**
* Iterates non-empty slots of this container
*/
fun slotIterator(): Iterator<IContainerSlot> {
return slotIterator(true)
}
fun slotIterator(nonEmpty: Boolean): Iterator<IContainerSlot>
}
operator fun Container.iterator() = iterator(true)
fun Container.iterator(nonEmpty: Boolean): Iterator<ItemStack> {
if (this is IIterableContainer) {
return iterator(nonEmpty)
} else if (nonEmpty) {
return (0 until containerSize).iterator().map { this[it] }.filter { it.isNotEmpty }
} else {
return (0 until containerSize).iterator().map { this[it] }
}
}
fun Container.slotIterator(nonEmpty: Boolean = true): Iterator<IContainerSlot> {
if (this is IIterableContainer) {
return slotIterator(nonEmpty)
} else if (nonEmpty) {
return (0 until containerSize).iterator().filter { this[it].isNotEmpty }.map { ContainerSlot(it, this) }
} else {
return (0 until containerSize).iterator().map { ContainerSlot(it, this) }
}
}

View File

@ -34,10 +34,12 @@ import net.minecraftforge.fluids.FluidUtil
import net.minecraftforge.fluids.capability.IFluidHandler
import ru.dbotthepony.mc.otm.capability.fluid.ItemMatteryFluidHandler
import ru.dbotthepony.mc.otm.capability.fluidLevel
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.capability.moveFluid
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.container.util.stream
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.collect.any
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.immutableMap
@ -223,7 +225,7 @@ class FluidCapsuleItem(val capacity: IntSupplier) : Item(Properties().stacksTo(6
override fun canInteract(item: ItemStack, player: Player, context: Context): Boolean {
val target = player.level().getBlockEntity(context.blockPos)?.getCapability(ForgeCapabilities.FLUID_HANDLER, context.side)?.orNull() ?: return false
val cap = item.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull() ?: return false
return target.stream().anyMatch { !it.isEmpty } || cap.stream().anyMatch { !it.isEmpty }
return target.iterator().any { !it.isEmpty } || cap.iterator().any { !it.isEmpty }
}
override fun interact(item: ItemStack, player: Player, context: Context): InteractionResult {

View File

@ -71,7 +71,7 @@ import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
import ru.dbotthepony.mc.otm.client.isShiftDown
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.container.util.stream
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent

View File

@ -11,7 +11,9 @@ import net.minecraft.world.inventory.*
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.container.util.slotIterator
import ru.dbotthepony.mc.otm.menu.input.InstantBooleanInput
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.network.ExopackCarriedPacket
@ -164,16 +166,14 @@ class ExopackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
craftingResultContainer.clearContent()
if (!player.level().isClientSide) {
val iterator = craftingGrid.iterator()
for (itemStack in iterator) {
val leftover = moveItemStackToSlots(itemStack, playerInventorySlots)
for (slot in craftingGrid.slotIterator()) {
val leftover = moveItemStackToSlots(slot.item, playerInventorySlots)
if (!leftover.isEmpty) {
player.drop(leftover, true)
}
iterator.remove()
slot.remove()
}
}
}

View File

@ -16,8 +16,9 @@ import net.minecraft.world.item.crafting.ShapedRecipe
import net.minecraft.world.level.Level
import net.minecraftforge.common.crafting.IShapedRecipe
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.container.util.stream
import ru.dbotthepony.mc.otm.core.filterNotNull
class EnergyContainerRecipe(val parent: ShapedRecipe) : CraftingRecipe, IShapedRecipe<CraftingContainer> by parent {
@ -84,7 +85,7 @@ class EnergyContainerRecipe(val parent: ShapedRecipe) : CraftingRecipe, IShapedR
if (itemStack.isEnchantable) {
for (it in container.iterator()) {
if (!it.isEmpty && it.isEnchanted) {
if (it.isEnchanted) {
for ((key, value) in it.allEnchantments) {
itemStack.enchant(key, value)
}

View File

@ -15,7 +15,7 @@ import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.level.Level
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.container.util.stream
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.set

View File

@ -8,7 +8,7 @@ import net.minecraft.world.item.crafting.Recipe
import net.minecraft.world.item.crafting.RecipeSerializer
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
// overrides all methods to fix Kotlin bug related to implementation delegation (to allow easy optics)
// passthrough all default methods to fix Kotlin bug related to implementation delegation not properly working on Java interfaces
// https://youtrack.jetbrains.com/issue/KT-55080/Change-the-behavior-of-inheritance-delegation-to-delegates-implementing-Java-interfaces-with-default-methods
interface IMatteryRecipe<C : Container> : Recipe<C> {
override fun getRemainingItems(p_44004_: C): NonNullList<ItemStack> {

View File

@ -10,16 +10,14 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.Recipe
import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.matter.matter
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.collect.filterNotNull
import ru.dbotthepony.mc.otm.core.collect.forEach
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.nbt.set

View File

@ -19,7 +19,7 @@ import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.item.crafting.ShapedRecipe
import net.minecraft.world.level.Level
import net.minecraftforge.common.crafting.IShapedRecipe
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.container.util.stream
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set

View File

@ -23,7 +23,8 @@ import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.container.CombinedContainer
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.capability.iterator
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.collect.flatMap
import ru.dbotthepony.mc.otm.core.collect.toList
import ru.dbotthepony.mc.otm.core.isNotEmpty
@ -178,9 +179,8 @@ object MatteryInventoryChangeTrigger : CriterionTrigger<InventoryChangeTrigger.T
} else if (this.predicates.size > 1) {
val unsatisfied = ObjectArrayList(this.predicates)
unsatisfied.removeIf { it.matches(ItemStack.EMPTY) }
val iterator = if (inventory is CombinedContainer) inventory.optimizedIterator() else inventory.iterator()
for (inventoryItem in iterator) {
for (inventoryItem in inventory) {
unsatisfied.removeIf { it.matches(inventoryItem) }
if (unsatisfied.isEmpty) break
}