From 69d9aaab50e1c28170510070524a503902719d27 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 14 Mar 2025 22:14:05 +0700 Subject: [PATCH] Fast implementation of some methods in EnhancedContainer --- .../mc/otm/container/EnhancedContainer.kt | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt index f012f130b..f504d831c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.container +import it.unimi.dsi.fastutil.ints.IntCollection import it.unimi.dsi.fastutil.ints.IntOpenHashSet import net.minecraft.core.HolderLookup.Provider import net.minecraft.nbt.CompoundTag @@ -12,9 +13,14 @@ import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack import net.neoforged.neoforge.common.util.INBTSerializable import org.apache.logging.log4j.LogManager +import ru.dbotthepony.kommons.collect.iterateClearBits +import ru.dbotthepony.kommons.collect.iterateSetBits import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer +import ru.dbotthepony.mc.otm.core.collect.IntRange2Set +import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.isNotEmpty import ru.dbotthepony.mc.otm.core.nbt.set +import java.util.BitSet /** * Flexible base implementation of [IEnhancedContainer], designed to be inherited, or used as-is @@ -26,6 +32,55 @@ import ru.dbotthepony.mc.otm.core.nbt.set abstract class EnhancedContainer(private val size: Int) : IEnhancedContainer, INBTSerializable { private val items = Array(size) { ItemStack.EMPTY } private val observedItems = Array(size) { ItemStack.EMPTY } + private val bitmap = BitSet(size) + + final override fun isEmpty(): Boolean { + return bitmap.isEmpty + } + + final override fun nextEmptySlot(startIndex: Int): Int { + if (startIndex >= size) + return -1 + else if (startIndex < 0) + return bitmap.nextClearBit(0) + else + return bitmap.nextClearBit(startIndex) + } + + final override fun nextNonEmptySlot(startIndex: Int): Int { + if (startIndex >= size) + return -1 + else if (startIndex < 0) + return bitmap.nextSetBit(0) + else + return bitmap.nextSetBit(startIndex) + } + + final override fun iterator(): Iterator { + return bitmap.iterateSetBits(size).map { this[it] } + } + + final override fun nonEmptySlotIndexIterator(): IntIterator { + return bitmap.iterateSetBits(size) + } + + final override fun emptySlotIndexIterator(): IntIterator { + return bitmap.iterateClearBits(size) + } + + final override fun emptySlotIndexIterator(allowedSlots: IntCollection): IntIterator { + if (allowedSlots is IntRange2Set && allowedSlots.isNotEmpty()) + return bitmap.iterateClearBits(allowedSlots.firstInt(), allowedSlots.lastInt() + 1) + + return super.emptySlotIndexIterator(allowedSlots) + } + + final override fun nonEmptySlotIndexIterator(allowedSlots: IntCollection): IntIterator { + if (allowedSlots is IntRange2Set && allowedSlots.isNotEmpty()) + return bitmap.iterateSetBits(allowedSlots.firstInt(), allowedSlots.lastInt() + 1) + + return super.nonEmptySlotIndexIterator(allowedSlots) + } protected open fun notifySlotChanged(slot: Int, old: ItemStack) {} @@ -36,9 +91,11 @@ abstract class EnhancedContainer(private val size: Int) if (items[slot].isEmpty) { items[slot] = ItemStack.EMPTY observedItems[slot] = ItemStack.EMPTY + bitmap[slot] = false } else { notifySlotChanged(slot, observedItems[slot]) observedItems[slot] = items[slot].copy() + bitmap[slot] = true } } } @@ -50,6 +107,7 @@ abstract class EnhancedContainer(private val size: Int) override fun clearContent() { items.fill(ItemStack.EMPTY) observedItems.fill(ItemStack.EMPTY) + bitmap.clear() } override fun setChanged() { @@ -146,6 +204,7 @@ abstract class EnhancedContainer(private val size: Int) val copy = observedItems.copyOf() items.fill(ItemStack.EMPTY) observedItems.fill(ItemStack.EMPTY) + bitmap.clear() val seenSlots = IntOpenHashSet() val ops = provider.createSerializationContext(NbtOps.INSTANCE) @@ -166,6 +225,7 @@ abstract class EnhancedContainer(private val size: Int) if (it.isNotEmpty) { items[slot] = it observedItems[slot] = it.copy() + bitmap[slot] = true if (it.count != copy[slot].count || !ItemStack.isSameItemSameComponents(it, copy[slot])) notifySlotChanged(slot, copy[slot])