From 7c0c43dbb48e2df436cb6e2e05b4d5005f7add46 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 8 Jun 2022 19:27:29 +0700 Subject: [PATCH] Snapshot change events on each frame, to avoid event spam when attached inventory reconstruct slot list (hi Ender Rift) --- .../entity/storage/StorageBusBlockEntity.kt | 113 +++++++++++++++--- 1 file changed, 95 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt index 2450f8e6f..74be93aa3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt @@ -28,6 +28,7 @@ import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.isPositive +import ru.dbotthepony.mc.otm.core.isZero import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.GraphNodeListener @@ -186,6 +187,55 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter } private inner class ItemHandlerComponent(private val parent: IItemHandler) : IStorageComponent { + private inner class EventsSnapshot { + val index = Long2ObjectAVLTreeMap() + + fun change(key: Long, diff: BigInteger) { + if (diff.isZero) + return + + val value = index[key] + + if (value == null) { + index[key] = diff + } else { + val newvalue = value + diff + + if (newvalue.isZero) { + index.remove(key) + } else { + index[key] = newvalue + } + } + } + + fun apply() { + for ((key, value) in index) { + val tuple = checkNotNull(this@ItemHandlerComponent.index[key]) { "Tuple with ID $key is missing!" } + + val count = tuple.stack.count + tuple.stack.count += value + + if (tuple.stack.count.isPositive) { + for (listener in listeners) { + listener.changeStack(tuple, count) + } + } else { + for (listener in listeners) { + listener.removeStack(tuple) + } + + this@ItemHandlerComponent.index.remove(tuple.id) + + val tuplekey = tuple.stack.key() + tuples.remove(tuplekey) ?: throw IllegalStateException("Cross-reference integrity check failed for $tuple") + } + } + } + } + + private var snapshot: EventsSnapshot? = null + override val storageType: StorageStackType get() = ITEM_STORAGE @@ -219,21 +269,28 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter val item = scannedMap.children[slot] ?: throw IllegalStateException("${scannedMap.id} does not track $slot") scannedMap.children.remove(slot) val count = scannedMap.stack.count - scannedMap.stack.count -= item.stack.count.toBigInteger() - if (scannedMap.stack.count.isPositive) { - for (listener in listeners) { - listener.changeStack(scannedMap, count) - } + val snapshot = snapshot + + if (snapshot != null) { + snapshot.change(scannedMap.id, -item.stack.count.toBigInteger()) } else { - for (listener in listeners) { - listener.removeStack(scannedMap) + scannedMap.stack.count -= item.stack.count.toBigInteger() + + if (scannedMap.stack.count.isPositive) { + for (listener in listeners) { + listener.changeStack(scannedMap, count) + } + } else { + for (listener in listeners) { + listener.removeStack(scannedMap) + } + + index.remove(scannedMap.id) + + val key = scannedMap.stack.key() + tuples.remove(key) ?: throw IllegalStateException("Item tuple is not present for slot $slot at ${scannedMap.stack}") } - - index.remove(scannedMap.id) - - val key = scannedMap.stack.key() - tuples.remove(key) ?: throw IllegalStateException("Item tuple is not present for slot $slot at ${scannedMap.stack}") } } @@ -243,10 +300,17 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter val oldCount = scannedMap.stack.count item.stack.count += diff - scannedMap.stack.count += diff.toBigInteger() - for (listener in listeners) { - listener.changeStack(scannedMap.stack, scannedMap.id, oldCount) + val snapshot = snapshot + + if (snapshot != null) { + snapshot.change(scannedMap.id, diff.toBigInteger()) + } else { + scannedMap.stack.count += diff.toBigInteger() + + for (listener in listeners) { + listener.changeStack(scannedMap.stack, scannedMap.id, oldCount) + } } } @@ -265,7 +329,9 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter tuples[key] = tuple } else { oldCount = tuple!!.stack.count - tuple.stack.count += stack.count.toBigInteger() + + if (snapshot == null) + tuple.stack.count += stack.count.toBigInteger() } tuple.children[slot] = SlotTuple(slot, stack.copy()) @@ -277,8 +343,14 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter listener.addStack(tuple.stack, tuple.id, this) } } else { - for (listener in listeners) { - listener.changeStack(tuple.stack, tuple.id, oldCount) + val snapshot = snapshot + + if (snapshot != null) { + snapshot.change(tuple.id, stack.count.toBigInteger()) + } else { + for (listener in listeners) { + listener.changeStack(tuple.stack, tuple.id, oldCount) + } } } } @@ -339,9 +411,14 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter fun scan() { sizeScan() + snapshot = EventsSnapshot() + for (slot in 0 until parent.slots) { scan(slot) } + + snapshot!!.apply() + snapshot = null } override fun insertStack(stack: ItemStackWrapper, simulate: Boolean): ItemStackWrapper {