Update storage system to use hashmap for partitioning
This commit is contained in:
parent
a7d11dae3f
commit
6819866c48
@ -1,8 +1,6 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity
|
package ru.dbotthepony.mc.otm.block.entity
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
|
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 it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
@ -72,7 +70,7 @@ private class ItemHandlerComponent(private val parent: IItemHandler) : IStorageC
|
|||||||
|
|
||||||
private var scanned = arrayOfNulls<ItemStack>(0)
|
private var scanned = arrayOfNulls<ItemStack>(0)
|
||||||
private var scannedMap = arrayOfNulls<TrackedTuple>(0)
|
private var scannedMap = arrayOfNulls<TrackedTuple>(0)
|
||||||
private val partitioned = Long2ObjectAVLTreeMap<ArrayList<TrackedTuple>>()
|
private val tuples = HashMap<ItemStackWrapper, TrackedTuple>()
|
||||||
private val index = Object2ObjectAVLTreeMap<UUID, TrackedTuple>()
|
private val index = Object2ObjectAVLTreeMap<UUID, TrackedTuple>()
|
||||||
|
|
||||||
private fun removeTracked(slot: Int) {
|
private fun removeTracked(slot: Int) {
|
||||||
@ -96,15 +94,8 @@ private class ItemHandlerComponent(private val parent: IItemHandler) : IStorageC
|
|||||||
|
|
||||||
index.remove(scannedMap.id)
|
index.remove(scannedMap.id)
|
||||||
|
|
||||||
val listing = partitioned[scannedMap.stack.longHashCode] ?: throw IllegalStateException("Item listing is not present for ${scannedMap.stack}")
|
val key = scannedMap.stack.key()
|
||||||
|
tuples.remove(key) ?: throw IllegalStateException("Item tuple is not present for slot $slot at ${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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,24 +115,16 @@ private class ItemHandlerComponent(private val parent: IItemHandler) : IStorageC
|
|||||||
private fun addTracked(slot: Int, stack: ItemStack) {
|
private fun addTracked(slot: Int, stack: ItemStack) {
|
||||||
check(scannedMap[slot] == null) { "Already tracking slot $slot" }
|
check(scannedMap[slot] == null) { "Already tracking slot $slot" }
|
||||||
|
|
||||||
val listing = partitioned.computeIfAbsent(ItemStackWrapper.longHashCode(stack.item), Long2ObjectFunction { ArrayList() })
|
val storageStack = ItemStackWrapper(stack)
|
||||||
var tuple: TrackedTuple? = null
|
val key = storageStack.key()
|
||||||
|
var tuple: TrackedTuple? = tuples[key]
|
||||||
for (storedTuple in listing) {
|
|
||||||
if (storedTuple.stack.sameItem(stack)) {
|
|
||||||
tuple = storedTuple
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val added = tuple == null
|
val added = tuple == null
|
||||||
var oldCount = ImpreciseFraction.ZERO
|
var oldCount = ImpreciseFraction.ZERO
|
||||||
|
|
||||||
if (added) {
|
if (added) {
|
||||||
val storageStack = ItemStackWrapper(stack)
|
|
||||||
tuple = TrackedTuple(storageStack, UUID.randomUUID())
|
tuple = TrackedTuple(storageStack, UUID.randomUUID())
|
||||||
index[tuple.id] = tuple
|
index[tuple.id] = tuple
|
||||||
listing.add(tuple)
|
tuples[key] = tuple
|
||||||
} else {
|
} else {
|
||||||
oldCount = tuple!!.stack.count
|
oldCount = tuple!!.stack.count
|
||||||
tuple.stack.count += stack.count
|
tuple.stack.count += stack.count
|
||||||
|
@ -20,9 +20,9 @@ interface IItemMatteryDrive : IMatteryDrive<ItemStackWrapper> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param stack
|
* @param stack
|
||||||
* @return all items that match this itemstack
|
* @return [ItemStack] that match specified [stack] (item type, nbt tag)
|
||||||
*/
|
*/
|
||||||
fun findItems(stack: ItemStack): Collection<IStorageTuple<ItemStackWrapper>>
|
fun findItems(stack: ItemStack): IStorageTuple<ItemStackWrapper>?
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IItemViewListener {
|
interface IItemViewListener {
|
||||||
|
@ -12,7 +12,9 @@ import ru.dbotthepony.mc.otm.set
|
|||||||
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
import ru.dbotthepony.mc.otm.storage.StorageStackType
|
import ru.dbotthepony.mc.otm.storage.StorageStackType
|
||||||
|
import ru.dbotthepony.mc.otm.storage.key
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
|
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
|
||||||
constructor(capacity: ImpreciseFraction, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks)
|
constructor(capacity: ImpreciseFraction, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks)
|
||||||
@ -56,22 +58,19 @@ class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDri
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun findItems(item: Item): List<IStorageTuple<ItemStackWrapper>> {
|
override fun findItems(item: Item): List<IStorageTuple<ItemStackWrapper>> {
|
||||||
val list = tuples[ItemStackWrapper.longHashCode(item)]
|
val list = ArrayList<IStorageTuple<ItemStackWrapper>>()
|
||||||
return if (list != null) java.util.List.copyOf(list) else emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findItems(stack: ItemStack): List<IStorageTuple<ItemStackWrapper>> {
|
for ((key, value) in tuples.entries) {
|
||||||
val list = tuples[ItemStackWrapper.longHashCode(stack.item)] ?: return emptyList()
|
if (key.item.item === item) {
|
||||||
|
list.add(value)
|
||||||
val buildList = ArrayList<IStorageTuple<ItemStackWrapper>>()
|
|
||||||
|
|
||||||
for (_stack in list) {
|
|
||||||
if (_stack.stack.sameItem(stack)) {
|
|
||||||
buildList.add(_stack)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildList
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findItems(stack: ItemStack): IStorageTuple<ItemStackWrapper>? {
|
||||||
|
return tuples[ItemStackWrapper(stack).key()]
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -4,6 +4,7 @@ import net.minecraft.world.item.Item
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
import net.minecraftforge.registries.ForgeRegistry
|
import net.minecraftforge.registries.ForgeRegistry
|
||||||
|
import org.jetbrains.annotations.ApiStatus
|
||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,6 +16,7 @@ class ItemStackWrapper : IStorageStack {
|
|||||||
*
|
*
|
||||||
* In most cases you want to use [stack] instead.
|
* In most cases you want to use [stack] instead.
|
||||||
*/
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
val item: ItemStack
|
val item: ItemStack
|
||||||
val registryName get() = item.item.registryName!!
|
val registryName get() = item.item.registryName!!
|
||||||
private val hash: Int
|
private val hash: Int
|
||||||
@ -22,10 +24,24 @@ class ItemStackWrapper : IStorageStack {
|
|||||||
override var count: ImpreciseFraction
|
override var count: ImpreciseFraction
|
||||||
set(value) { field = value.floor() }
|
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.count = ImpreciseFraction(item.count)
|
||||||
this.item.count = 1
|
|
||||||
|
if (copy) {
|
||||||
|
this.item.count = 1
|
||||||
|
}
|
||||||
|
|
||||||
this.hash = item.tag.hashCode() xor item.item.hashCode()
|
this.hash = item.tag.hashCode() xor item.item.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +56,8 @@ class ItemStackWrapper : IStorageStack {
|
|||||||
return ItemStackWrapper(this)
|
return ItemStackWrapper(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sameItem(other: ItemStack) = ItemStack.isSameItemSameTags(item, other)
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other === this)
|
if (other === this)
|
||||||
return true
|
return true
|
||||||
|
Loading…
Reference in New Issue
Block a user