From 6819866c48ea20c64ae181941eda1557baa2b4e1 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 26 Apr 2022 15:16:25 +0700 Subject: [PATCH] Update storage system to use hashmap for partitioning --- .../otm/block/entity/StorageBusBlockEntity.kt | 31 +++++-------------- .../mc/otm/capability/drive/API.kt | 4 +-- .../otm/capability/drive/ItemMatteryDrive.kt | 23 +++++++------- .../mc/otm/storage/ItemStackWrapper.kt | 24 ++++++++++++-- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageBusBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageBusBlockEntity.kt index 63bf10e22..b2109e623 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageBusBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageBusBlockEntity.kt @@ -1,8 +1,6 @@ package ru.dbotthepony.mc.otm.block.entity import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap -import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap -import it.unimi.dsi.fastutil.longs.Long2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap import net.minecraft.core.BlockPos import net.minecraft.core.Direction @@ -72,7 +70,7 @@ private class ItemHandlerComponent(private val parent: IItemHandler) : IStorageC private var scanned = arrayOfNulls(0) private var scannedMap = arrayOfNulls(0) - private val partitioned = Long2ObjectAVLTreeMap>() + private val tuples = HashMap() private val index = Object2ObjectAVLTreeMap() private fun removeTracked(slot: Int) { @@ -96,15 +94,8 @@ private class ItemHandlerComponent(private val parent: IItemHandler) : IStorageC index.remove(scannedMap.id) - val listing = partitioned[scannedMap.stack.longHashCode] ?: throw IllegalStateException("Item listing is not present for ${scannedMap.stack}") - - if (listing.remove(scannedMap)) { - if (listing.isEmpty()) { - partitioned.remove(scannedMap.stack.longHashCode) - } - } else { - throw IllegalStateException("Item listing for ${scannedMap.stack} did not contain $scannedMap") - } + val key = scannedMap.stack.key() + tuples.remove(key) ?: throw IllegalStateException("Item tuple is not present for slot $slot at ${scannedMap.stack}") } } @@ -124,24 +115,16 @@ private class ItemHandlerComponent(private val parent: IItemHandler) : IStorageC private fun addTracked(slot: Int, stack: ItemStack) { check(scannedMap[slot] == null) { "Already tracking slot $slot" } - val listing = partitioned.computeIfAbsent(ItemStackWrapper.longHashCode(stack.item), Long2ObjectFunction { ArrayList() }) - var tuple: TrackedTuple? = null - - for (storedTuple in listing) { - if (storedTuple.stack.sameItem(stack)) { - tuple = storedTuple - break - } - } - + val storageStack = ItemStackWrapper(stack) + val key = storageStack.key() + var tuple: TrackedTuple? = tuples[key] val added = tuple == null var oldCount = ImpreciseFraction.ZERO if (added) { - val storageStack = ItemStackWrapper(stack) tuple = TrackedTuple(storageStack, UUID.randomUUID()) index[tuple.id] = tuple - listing.add(tuple) + tuples[key] = tuple } else { oldCount = tuple!!.stack.count tuple.stack.count += stack.count diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/API.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/API.kt index 65d4042f2..2e2027d7e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/API.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/API.kt @@ -20,9 +20,9 @@ interface IItemMatteryDrive : IMatteryDrive { /** * @param stack - * @return all items that match this itemstack + * @return [ItemStack] that match specified [stack] (item type, nbt tag) */ - fun findItems(stack: ItemStack): Collection> + fun findItems(stack: ItemStack): IStorageTuple? } interface IItemViewListener { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt index e379fba5b..a4e3eba92 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt @@ -12,7 +12,9 @@ import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.storage.IStorageTuple import ru.dbotthepony.mc.otm.storage.ItemStackWrapper import ru.dbotthepony.mc.otm.storage.StorageStackType +import ru.dbotthepony.mc.otm.storage.key import java.util.* +import kotlin.collections.ArrayList class ItemMatteryDrive : AbstractMatteryDrive, IItemMatteryDrive { constructor(capacity: ImpreciseFraction, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks) @@ -56,22 +58,19 @@ class ItemMatteryDrive : AbstractMatteryDrive, IItemMatteryDri } override fun findItems(item: Item): List> { - val list = tuples[ItemStackWrapper.longHashCode(item)] - return if (list != null) java.util.List.copyOf(list) else emptyList() - } + val list = ArrayList>() - override fun findItems(stack: ItemStack): List> { - val list = tuples[ItemStackWrapper.longHashCode(stack.item)] ?: return emptyList() - - val buildList = ArrayList>() - - for (_stack in list) { - if (_stack.stack.sameItem(stack)) { - buildList.add(_stack) + for ((key, value) in tuples.entries) { + if (key.item.item === item) { + list.add(value) } } - return buildList + return list + } + + override fun findItems(stack: ItemStack): IStorageTuple? { + return tuples[ItemStackWrapper(stack).key()] } companion object { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt index acff4ae69..0015aeecf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt @@ -4,6 +4,7 @@ import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistry +import org.jetbrains.annotations.ApiStatus import ru.dbotthepony.mc.otm.core.ImpreciseFraction /** @@ -15,6 +16,7 @@ class ItemStackWrapper : IStorageStack { * * In most cases you want to use [stack] instead. */ + @ApiStatus.Internal val item: ItemStack val registryName get() = item.item.registryName!! private val hash: Int @@ -22,10 +24,24 @@ class ItemStackWrapper : IStorageStack { override var count: ImpreciseFraction set(value) { field = value.floor() } - constructor(item: ItemStack) { - this.item = item.copy() + /** + * [copy] as false is used internally for fast index construction, do not specify + * it unless you know what you are doing! + */ + @JvmOverloads + constructor(item: ItemStack, copy: Boolean = true) { + if (copy) { + this.item = item.copy() + } else { + this.item = item + } + this.count = ImpreciseFraction(item.count) - this.item.count = 1 + + if (copy) { + this.item.count = 1 + } + this.hash = item.tag.hashCode() xor item.item.hashCode() } @@ -40,6 +56,8 @@ class ItemStackWrapper : IStorageStack { return ItemStackWrapper(this) } + fun sameItem(other: ItemStack) = ItemStack.isSameItemSameTags(item, other) + override fun equals(other: Any?): Boolean { if (other === this) return true