Move IDs to Longs again, update storage class hierarchy

maybe use ints? IDK
This commit is contained in:
DBotThePony 2022-06-08 12:42:48 +07:00
parent cb5cb44848
commit 50cac6d1b5
Signed by: DBot
GPG Key ID: DCC23B5715498507
8 changed files with 129 additions and 83 deletions

View File

@ -1,6 +1,7 @@
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 net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
@ -43,7 +44,7 @@ import kotlin.collections.ArrayList
import kotlin.collections.HashMap import kotlin.collections.HashMap
private class SlotTuple(val slot: Int, val stack: ItemStack) private class SlotTuple(val slot: Int, val stack: ItemStack)
private class TrackedTuple(override val stack: ItemStackWrapper, override val id: UUID) : IStorageTuple<ItemStackWrapper> { private class TrackedTuple(override val stack: ItemStackWrapper, override val id: Long) : IStorageTuple<ItemStackWrapper> {
val children = Int2ObjectAVLTreeMap<SlotTuple>() val children = Int2ObjectAVLTreeMap<SlotTuple>()
override fun toString(): String { override fun toString(): String {
@ -186,10 +187,12 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
private inner class ItemHandlerComponent(private val parent: IItemHandler) : IStorageComponent<ItemStackWrapper> { private inner class ItemHandlerComponent(private val parent: IItemHandler) : IStorageComponent<ItemStackWrapper> {
override val storageType: StorageStackType<ItemStackWrapper> override val storageType: StorageStackType<ItemStackWrapper>
get() = OverdriveThatMatters.INSTANCE.ITEM_STORAGE() get() = ITEM_STORAGE
private val listeners = ArrayList<IStorageEventConsumer<ItemStackWrapper>>() private val listeners = ArrayList<IStorageEventConsumer<ItemStackWrapper>>()
private var nextID = 0L
override fun addListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean { override fun addListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
if (!listeners.contains(listener)) { if (!listeners.contains(listener)) {
listeners.add(listener) listeners.add(listener)
@ -206,7 +209,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
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 tuples = HashMap<ItemStackWrapper, TrackedTuple>() private val tuples = HashMap<ItemStackWrapper, TrackedTuple>()
private val index = HashMap<UUID, TrackedTuple>() private val index = Long2ObjectAVLTreeMap<TrackedTuple>()
private fun removeTracked(slot: Int) { private fun removeTracked(slot: Int) {
scanned[slot] = null scanned[slot] = null
@ -257,7 +260,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
var oldCount = BigInteger.ZERO var oldCount = BigInteger.ZERO
if (added) { if (added) {
tuple = TrackedTuple(storageStack, UUID.randomUUID()) tuple = TrackedTuple(storageStack, nextID++)
index[tuple.id] = tuple index[tuple.id] = tuple
tuples[key] = tuple tuples[key] = tuple
} else { } else {
@ -375,11 +378,11 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
return leftover return leftover
} }
override fun get(id: UUID): ItemStackWrapper { override fun get(id: Long): ItemStackWrapper {
return index[id]?.stack ?: ItemStackWrapper.EMPTY return index[id]?.stack ?: ItemStackWrapper.EMPTY
} }
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): ItemStackWrapper { override fun extractStack(id: Long, amount: BigInteger, simulate: Boolean): ItemStackWrapper {
if (!amount.isPositive) if (!amount.isPositive)
return ItemStackWrapper.EMPTY return ItemStackWrapper.EMPTY

View File

@ -1,5 +1,7 @@
package ru.dbotthepony.mc.otm.block.entity package ru.dbotthepony.mc.otm.block.entity
import it.unimi.dsi.fastutil.longs.LongAVLTreeSet
import it.unimi.dsi.fastutil.longs.LongArraySet
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
@ -272,9 +274,16 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
return StorageExporterMenu(containerID, inventory, this) return StorageExporterMenu(containerID, inventory, this)
} }
private val relevantTuples = HashSet<UUID>() private val relevantTuples = LongArraySet()
override fun addStack(stack: ItemStackWrapper, id: UUID, provider: IStorageProvider<ItemStackWrapper>) { override val storageType: StorageStackType<ItemStackWrapper>
get() = ITEM_STORAGE
init {
cell.addStorageComponent(this)
}
override fun addStack(stack: ItemStackWrapper, id: Long, provider: IStorageProvider<ItemStackWrapper>) {
if (!filter.match(stack.item)) { if (!filter.match(stack.item)) {
return return
} }
@ -282,11 +291,11 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
relevantTuples.add(id) relevantTuples.add(id)
} }
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: BigInteger) { override fun changeStack(stack: ItemStackWrapper, id: Long, oldCount: BigInteger) {
// no-op // no-op
} }
override fun removeStack(stack: ItemStackWrapper, id: UUID) { override fun removeStack(stack: ItemStackWrapper, id: Long) {
relevantTuples.remove(id) relevantTuples.remove(id)
} }
@ -311,7 +320,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
override val targetCapability: Capability<IItemHandler> override val targetCapability: Capability<IItemHandler>
get() = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY get() = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY
private val exportStacks: Stream<Pair<UUID, ItemStackWrapper>> private val exportStacks: Stream<Pair<Long, ItemStackWrapper>>
get() { get() {
val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return Stream.empty() val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return Stream.empty()
return relevantTuples.stream().map { it to view[it] } return relevantTuples.stream().map { it to view[it] }

View File

@ -1,12 +1,15 @@
package ru.dbotthepony.mc.otm.capability.drive package ru.dbotthepony.mc.otm.capability.drive
import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmOverloads
import java.util.UUID import java.util.UUID
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag import net.minecraft.nbt.ListTag
import net.minecraft.nbt.LongTag
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.core.BigInteger import ru.dbotthepony.mc.otm.core.BigInteger
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.isPositive import ru.dbotthepony.mc.otm.core.isPositive
@ -16,7 +19,6 @@ import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.storage.* import ru.dbotthepony.mc.otm.storage.*
import java.math.BigInteger import java.math.BigInteger
import java.util.ArrayList import java.util.ArrayList
import java.util.HashSet
import java.util.stream.Stream import java.util.stream.Stream
abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor( abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor(
@ -25,7 +27,7 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
var maxDifferentStacks: Int = 0xFFFF var maxDifferentStacks: Int = 0xFFFF
) : IMatteryDrive<T> { ) : IMatteryDrive<T> {
protected val tuples = HashMap<T, IStorageTuple<T>>() protected val tuples = HashMap<T, IStorageTuple<T>>()
protected val tuplesByID = Object2ObjectAVLTreeMap<UUID, IStorageTuple<T>>() protected val tuplesByID: MutableMap<Long, IStorageTuple<T>> = Long2ObjectAVLTreeMap()
override var isDirty = false override var isDirty = false
set(value) { set(value) {
@ -39,6 +41,8 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
var storedDifferentStacks = 0 var storedDifferentStacks = 0
protected set protected set
protected var nextID = 0L
override var storedCount: BigInteger = BigInteger.ZERO override var storedCount: BigInteger = BigInteger.ZERO
protected set protected set
@ -79,7 +83,7 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
val copy = stack.copy() as T val copy = stack.copy() as T
copy.count = maxInsert copy.count = maxInsert
val state = StorageTuple(UUID.randomUUID(), copy) val state = StorageTuple(nextID++, copy)
tuples[key] = state tuples[key] = state
tuplesByID[state.id] = state tuplesByID[state.id] = state
@ -96,7 +100,7 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
} }
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T { override fun extractStack(id: Long, amount: BigInteger, simulate: Boolean): T {
val get = tuplesByID[id] ?: return storageType.empty val get = tuplesByID[id] ?: return storageType.empty
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
@ -157,7 +161,6 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
val serialized = serializeStack(stack) val serialized = serializeStack(stack)
if (serialized != null) { if (serialized != null) {
serialized["id"] = longArrayOf(stack.id.mostSignificantBits, stack.id.leastSignificantBits)
list.add(serialized) list.add(serialized)
} }
} }
@ -166,10 +169,17 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
} }
override fun deserializeNBT(nbt: CompoundTag) { override fun deserializeNBT(nbt: CompoundTag) {
for (listener in listeners) {
for (get in tuples.values) {
listener.removeStack(get.stack, get.id)
}
}
tuples.clear() tuples.clear()
tuplesByID.clear() tuplesByID.clear()
storedCount = BigInteger.ZERO storedCount = BigInteger.ZERO
storedDifferentStacks = 0 storedDifferentStacks = 0
// nextID = 0L
nbt.ifHas("capacity") { nbt.ifHas("capacity") {
driveCapacity = BigInteger(it) driveCapacity = BigInteger(it)
@ -184,9 +194,7 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
if (stack != null) { if (stack != null) {
storedCount += stack.count storedCount += stack.count
storedDifferentStacks++ storedDifferentStacks++
val tuple = StorageTuple(nextID++, stack)
val id = entry.getLongArray("id")
val tuple = StorageTuple(if (id.size == 2) UUID(id[0], id[1]) else UUID.randomUUID(), stack)
tuples[tuple.stack.key()] = tuple tuples[tuple.stack.key()] = tuple
tuplesByID[tuple.id] = tuple tuplesByID[tuple.id] = tuple
} }
@ -194,7 +202,7 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
} }
} }
override fun get(id: UUID): T { override fun get(id: Long): T {
return tuplesByID[id]?.stack ?: storageType.empty return tuplesByID[id]?.stack ?: storageType.empty
} }
@ -211,4 +219,8 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
override fun removeListener(listener: IStorageEventConsumer<T>): Boolean { override fun removeListener(listener: IStorageEventConsumer<T>): Boolean {
return listeners.remove(listener) return listeners.remove(listener)
} }
companion object {
private val LOGGER = LogManager.getLogger()
}
} }

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.compat.mekanism package ru.dbotthepony.mc.otm.compat.mekanism
import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
@ -36,7 +37,7 @@ private val QIO_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, "item_s
private class QIOTuple( private class QIOTuple(
val mekanismItem: HashedItem, val mekanismItem: HashedItem,
override val stack: ItemStackWrapper, override val stack: ItemStackWrapper,
override val id: UUID, override val id: Long,
var mark: Long var mark: Long
) : IStorageTuple<ItemStackWrapper> ) : IStorageTuple<ItemStackWrapper>
@ -46,11 +47,13 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
override val storageType: StorageStackType<ItemStackWrapper> override val storageType: StorageStackType<ItemStackWrapper>
get() = OverdriveThatMatters.INSTANCE.ITEM_STORAGE() get() = OverdriveThatMatters.INSTANCE.ITEM_STORAGE()
private val index = Object2ObjectAVLTreeMap<UUID, QIOTuple>() private val index = Long2ObjectAVLTreeMap<QIOTuple>()
private val tracked = HashMap<HashedItem, QIOTuple>() private val tracked = HashMap<HashedItem, QIOTuple>()
private val listeners = ArrayList<IStorageEventConsumer<ItemStackWrapper>>() private val listeners = ArrayList<IStorageEventConsumer<ItemStackWrapper>>()
override fun get(id: UUID): ItemStackWrapper { private var nextID = 0L
override fun get(id: Long): ItemStackWrapper {
return index[id]?.stack ?: ItemStackWrapper.EMPTY return index[id]?.stack ?: ItemStackWrapper.EMPTY
} }
@ -87,7 +90,7 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
return inserted return inserted
} }
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): ItemStackWrapper { override fun extractStack(id: Long, amount: BigInteger, simulate: Boolean): ItemStackWrapper {
// Because there is no simulate method on QIO array, we have to simulate it by ourselves. // Because there is no simulate method on QIO array, we have to simulate it by ourselves.
// ASSUMPTION: We can ALWAYS remove items from QIO grid. // ASSUMPTION: We can ALWAYS remove items from QIO grid.
@ -158,7 +161,7 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
} }
} }
} else { } else {
val tuple = QIOTuple(at, ItemStackWrapper(at.stack).also { it.count = value.count.toBigInteger() }, UUID.randomUUID(), mark) val tuple = QIOTuple(at, ItemStackWrapper(at.stack).also { it.count = value.count.toBigInteger() }, nextID++, mark)
index[tuple.id] = tuple index[tuple.id] = tuple
for (listener in listeners) { for (listener in listeners) {

View File

@ -1,10 +1,12 @@
package ru.dbotthepony.mc.otm.graph.storage package ru.dbotthepony.mc.otm.graph.storage
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.storage.IStorage import ru.dbotthepony.mc.otm.storage.IStorage
import ru.dbotthepony.mc.otm.storage.IStorageEventConsumer
import ru.dbotthepony.mc.otm.storage.IStorageStack import ru.dbotthepony.mc.otm.storage.IStorageStack
import ru.dbotthepony.mc.otm.storage.StorageStackType import ru.dbotthepony.mc.otm.storage.StorageStackType
import java.util.* import java.util.*

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.menu.data
import com.mojang.blaze3d.platform.InputConstants import com.mojang.blaze3d.platform.InputConstants
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
@ -17,10 +18,7 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.network.MatteryNetworking import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.SetCarriedPacket import ru.dbotthepony.mc.otm.network.SetCarriedPacket
import ru.dbotthepony.mc.otm.storage.IStorageComponent import ru.dbotthepony.mc.otm.storage.*
import ru.dbotthepony.mc.otm.storage.IStorageEventConsumer
import ru.dbotthepony.mc.otm.storage.IStorageProvider
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
import java.math.BigInteger import java.math.BigInteger
import java.util.* import java.util.*
import java.util.function.Supplier import java.util.function.Supplier
@ -157,7 +155,10 @@ class StackRemovePacket(val id: Int, val stackID: Int) {
* Creates a virtual, slotless container for Player to interaction with. * Creates a virtual, slotless container for Player to interaction with.
*/ */
open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote: Boolean) : IStorageEventConsumer<ItemStackWrapper> { open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote: Boolean) : IStorageEventConsumer<ItemStackWrapper> {
data class NetworkedItem constructor(val id: Int, val stack: ItemStack, val upstreamId: UUID? = null) data class NetworkedItem constructor(val id: Int, val stack: ItemStack, val upstreamId: Long? = null)
override val storageType: StorageStackType<ItemStackWrapper>
get() = ITEM_STORAGE
protected var nextStackID = 0 protected var nextStackID = 0
// this (how client see and interact with) // this (how client see and interact with)
@ -193,7 +194,7 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
} }
// parent (e.g. VirtualComponent) // parent (e.g. VirtualComponent)
protected val upstreamState = HashMap<UUID, NetworkedItem>() protected val upstreamState = Long2ObjectAVLTreeMap<NetworkedItem>()
protected val networkBacklog = ArrayList<Any>() protected val networkBacklog = ArrayList<Any>()
operator fun get(id: Int): NetworkedItem? = localState[id] operator fun get(id: Int): NetworkedItem? = localState[id]
@ -231,8 +232,8 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
return localState.values.size return localState.values.size
} }
override fun addStack(stack: ItemStackWrapper, id: UUID, provider: IStorageProvider<ItemStackWrapper>) = addObject(stack.stack, id) override fun addStack(stack: ItemStackWrapper, id: Long, provider: IStorageProvider<ItemStackWrapper>) = addObject(stack.stack, id)
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: BigInteger) = changeObject(id, stack.count.toInt()) override fun changeStack(stack: ItemStackWrapper, id: Long, oldCount: BigInteger) = changeObject(id, stack.count.toInt())
protected fun network(fn: () -> Any) { protected fun network(fn: () -> Any) {
if (!remote) { if (!remote) {
@ -240,14 +241,14 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
} }
} }
override fun removeStack(stack: ItemStackWrapper, id: UUID) { override fun removeStack(stack: ItemStackWrapper, id: Long) {
val get = upstreamState[id] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id!") val get = upstreamState[id] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id!")
upstreamState.remove(id) upstreamState.remove(id)
localState.remove(get.id) localState.remove(get.id)
network { StackRemovePacket(menu.containerId, get.id) } network { StackRemovePacket(menu.containerId, get.id) }
} }
fun addObject(stack: ItemStack, id_upstream: UUID) { fun addObject(stack: ItemStack, id_upstream: Long) {
check(!upstreamState.containsKey(id_upstream)) { "Already tracking ItemStack with upstream id $id_upstream!" } check(!upstreamState.containsKey(id_upstream)) { "Already tracking ItemStack with upstream id $id_upstream!" }
val state = NetworkedItem(nextStackID++, stack.copy(), id_upstream) val state = NetworkedItem(nextStackID++, stack.copy(), id_upstream)
@ -257,7 +258,7 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
network { StackAddPacket(menu.containerId, state.id, stack) } network { StackAddPacket(menu.containerId, state.id, stack) }
} }
fun changeObject(id_upstream: UUID, new_count: Int) { fun changeObject(id_upstream: Long, new_count: Int) {
val get = upstreamState[id_upstream] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id_upstream!") val get = upstreamState[id_upstream] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id_upstream!")
get.stack.count = new_count get.stack.count = new_count
network { StackChangePacket(menu.containerId, get.id, new_count) } network { StackChangePacket(menu.containerId, get.id, new_count) }

View File

@ -81,21 +81,21 @@ interface IStorageEventProducer<T : IStorageStack> : IStorage<T> {
/** /**
* Consumes events produced by [IStorageEventConsumer] * Consumes events produced by [IStorageEventConsumer]
*/ */
interface IStorageEventConsumer<T : IStorageStack> { interface IStorageEventConsumer<T : IStorageStack> : IStorage<T> {
/** /**
* Fired on whenever an object is added (to listener) we subscribed to * Fired on whenever an object is added (to listener) we subscribed to
*/ */
fun addStack(stack: T, id: UUID, provider: IStorageProvider<T>) fun addStack(stack: T, id: Long, provider: IStorageProvider<T>)
/** /**
* Fired on whenever an object is changes on listener we subscribed to * Fired on whenever an object is changes on listener we subscribed to
*/ */
fun changeStack(stack: T, id: UUID, oldCount: BigInteger) fun changeStack(stack: T, id: Long, oldCount: BigInteger)
/** /**
* Fired on whenever an object is removed from listener we subscribed to * Fired on whenever an object is removed from listener we subscribed to
*/ */
fun removeStack(stack: T, id: UUID) fun removeStack(stack: T, id: Long)
} }
interface IStorageAcceptor<T : IStorageStack> : IStorage<T> { interface IStorageAcceptor<T : IStorageStack> : IStorage<T> {
@ -111,7 +111,7 @@ interface IStorageProvider<T : IStorageStack> : IStorageEventProducer<T> {
* @param id identifier of stack * @param id identifier of stack
* @return stored object (not a copy). Do not edit it. * @return stored object (not a copy). Do not edit it.
*/ */
operator fun get(id: UUID): T operator fun get(id: Long): T
val stacks: Stream<IStorageTuple<T>> val stacks: Stream<IStorageTuple<T>>
@ -123,7 +123,7 @@ interface IStorageProvider<T : IStorageStack> : IStorageEventProducer<T> {
* @param simulate whenever to simulate the action or not * @param simulate whenever to simulate the action or not
* @return copy of object, with amount of units actually extracted * @return copy of object, with amount of units actually extracted
*/ */
fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T fun extractStack(id: Long, amount: BigInteger, simulate: Boolean): T
fun addListenerAuto(listener: IStorageEventConsumer<T>): Boolean { fun addListenerAuto(listener: IStorageEventConsumer<T>): Boolean {
if (addListener(listener)) { if (addListener(listener)) {
@ -150,6 +150,8 @@ interface IStorageProvider<T : IStorageStack> : IStorageEventProducer<T> {
} }
} }
interface IStorageComponent<T : IStorageStack> : IStorageProvider<T>, IStorageAcceptor<T>
fun <T : IStorageStack> IStorageEventConsumer<T>.changeStack(tuple: IStorageTuple<T>, oldCount: BigInteger) { fun <T : IStorageStack> IStorageEventConsumer<T>.changeStack(tuple: IStorageTuple<T>, oldCount: BigInteger) {
changeStack(tuple.stack, tuple.id, oldCount) changeStack(tuple.stack, tuple.id, oldCount)
} }
@ -163,13 +165,11 @@ fun <T : IStorageStack> IStorageEventConsumer<T>.removeStack(tuple: IStorageTupl
} }
interface IStorageTuple<T : IStorageStack> { interface IStorageTuple<T : IStorageStack> {
val id: UUID val id: Long
val stack: T val stack: T
} }
class StorageTuple<T : IStorageStack>(override val id: UUID, override val stack: T) : IStorageTuple<T> class StorageTuple<T : IStorageStack>(override val id: Long, override val stack: T) : IStorageTuple<T>
interface IStorageComponent<T : IStorageStack> : IStorageProvider<T>, IStorageAcceptor<T>
/** /**
* Component which (most time) proxy other components (combine their contents into single view) * Component which (most time) proxy other components (combine their contents into single view)

View File

@ -1,18 +1,19 @@
package ru.dbotthepony.mc.otm.storage package ru.dbotthepony.mc.otm.storage
import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.isPositive import ru.dbotthepony.mc.otm.core.isPositive
import ru.dbotthepony.mc.otm.core.isZero import ru.dbotthepony.mc.otm.core.isZero
import java.math.BigInteger import java.math.BigInteger
import java.util.* import java.util.*
import java.util.stream.Stream import java.util.stream.Stream
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.reflect.full.isSubclassOf
class RemoteTuple<T : IStorageStack>( class RemoteTuple<T : IStorageStack>(
override val stack: T, override val stack: T,
override val id: UUID, override val id: Long,
val provider: IStorageProvider<T>, val provider: IStorageProvider<T>,
val local: LocalTuple<T> val local: LocalTuple<T>
) : IStorageTuple<T> { ) : IStorageTuple<T> {
@ -21,7 +22,7 @@ class RemoteTuple<T : IStorageStack>(
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
return other is RemoteTuple<*> && other.id == id || other is UUID && other == id return other is RemoteTuple<*> && other.id == id
} }
override fun hashCode(): Int { override fun hashCode(): Int {
@ -29,7 +30,7 @@ class RemoteTuple<T : IStorageStack>(
} }
} }
class LocalTuple<T : IStorageStack>(override val stack: T, override val id: UUID, val tuples: ArrayList<RemoteTuple<T>>) : IStorageTuple<T> class LocalTuple<T : IStorageStack>(override val stack: T, override val id: Long, val tuples: ArrayList<RemoteTuple<T>>) : IStorageTuple<T>
open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVirtualStorageComponent<T> { open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVirtualStorageComponent<T> {
constructor(type: Class<T>) : this(StorageRegistry.get(type)) constructor(type: Class<T>) : this(StorageRegistry.get(type))
@ -37,30 +38,39 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
override val storageType: StorageStackType<T> = type override val storageType: StorageStackType<T> = type
// удаленный UUID -> Кортеж // удаленный UUID -> Кортеж
protected val remoteByUUID: MutableMap<UUID, RemoteTuple<T>> = HashMap() protected val remoteTuples = Long2ObjectAVLTreeMap<RemoteTuple<T>>()
// локальный UUID -> Локальный кортеж // локальный UUID -> Локальный кортеж
protected val localByUUID: MutableMap<UUID, LocalTuple<T>> = HashMap() protected val localTuples = Long2ObjectAVLTreeMap<LocalTuple<T>>()
// Стак -> Локальный кортеж стака // Стак -> Локальный кортеж стака
protected val tuples: MutableMap<T, LocalTuple<T>> = HashMap() protected val hashedTuples: MutableMap<T, LocalTuple<T>> = HashMap()
// ArrayList для скорости работы // ArrayList для скорости работы
protected val listeners: MutableSet<IStorageEventConsumer<T>> = ObjectArraySet() protected val listeners: MutableSet<IStorageEventConsumer<T>> = ObjectArraySet()
protected val set: MutableSet<IStorage<T>> = ObjectArraySet() protected val children: MutableSet<IStorage<T>> = ObjectArraySet()
protected val consumers: MutableSet<IStorageAcceptor<T>> = ObjectArraySet() protected val consumers: MutableSet<IStorageAcceptor<T>> = ObjectArraySet()
private var nextID = 0L
protected open fun onAdd(identity: IStorage<T>) {} protected open fun onAdd(identity: IStorage<T>) {}
protected open fun onRemove(identity: IStorage<T>) {} protected open fun onRemove(identity: IStorage<T>) {}
override fun add(identity: IStorage<T>) { override fun add(identity: IStorage<T>) {
if (set.add(identity)) { if (!(identity.storageType::class.isSubclassOf(storageType::class)))
throw ClassCastException("Reified Generics: ${identity.storageType::class.qualifiedName} can not be cast into ${storageType::class.qualifiedName}")
if (children.add(identity)) {
if (identity is IStorageProvider<T>) { if (identity is IStorageProvider<T>) {
identity.addListenerAuto(this) identity.addListenerAuto(this)
} else if (identity is IStorageEventProducer<T>) { } else if (identity is IStorageEventProducer<T>) {
identity.addListener(this) identity.addListener(this)
} }
if (identity is IStorageEventConsumer<T>) {
addListenerAuto(identity)
}
if (identity is IStorageAcceptor<T>) { if (identity is IStorageAcceptor<T>) {
consumers.add(identity) consumers.add(identity)
} }
@ -70,13 +80,20 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
} }
override fun remove(identity: IStorage<T>) { override fun remove(identity: IStorage<T>) {
if (set.remove(identity)) { if (!(identity.storageType::class.isSubclassOf(storageType::class)))
throw ClassCastException("Reified Generics: ${identity.storageType::class.qualifiedName} can not be cast into ${storageType::class.qualifiedName}")
if (children.remove(identity)) {
if (identity is IStorageProvider<T>) { if (identity is IStorageProvider<T>) {
identity.removeListenerAuto(this) identity.removeListenerAuto(this)
} else if (identity is IStorageEventProducer<T>) { } else if (identity is IStorageEventProducer<T>) {
identity.removeListener(this) identity.removeListener(this)
} }
if (identity is IStorageEventConsumer<T>) {
removeListenerAuto(identity)
}
if (identity is IStorageAcceptor<T>) { if (identity is IStorageAcceptor<T>) {
consumers.remove(identity) consumers.remove(identity)
} }
@ -86,12 +103,11 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
} }
override fun contains(identity: IStorage<T>): Boolean { override fun contains(identity: IStorage<T>): Boolean {
return set.contains(identity) return children.contains(identity)
} }
override fun addListener(listener: IStorageEventConsumer<T>): Boolean { override fun addListener(listener: IStorageEventConsumer<T>): Boolean {
if (!listeners.contains(listener)) { if (listeners.add(listener)) {
listeners.add(listener)
return true return true
} }
@ -102,27 +118,27 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
return listeners.remove(listener) return listeners.remove(listener)
} }
override fun get(id: UUID): T { override fun get(id: Long): T {
return localByUUID[id]?.stack ?: this.storageType.empty return localTuples[id]?.stack ?: this.storageType.empty
} }
override val stacks: Stream<IStorageTuple<T>> get() { override val stacks: Stream<IStorageTuple<T>> get() {
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }.stream() return ArrayList<IStorageTuple<T>>(hashedTuples.size).also { it.addAll(hashedTuples.values) }.stream()
} }
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
override fun addStack(stack: T, id: UUID, provider: IStorageProvider<T>) { override fun addStack(stack: T, id: Long, provider: IStorageProvider<T>) {
check(!remoteByUUID.containsKey(id)) { "Already tracking tuple with id $id" } check(!remoteTuples.containsKey(id)) { "Already tracking tuple with id $id" }
val key = stack.key() val key = stack.key()
var local: LocalTuple<T>? = tuples[key] var local: LocalTuple<T>? = hashedTuples[key]
var oldCount = BigInteger.ZERO var oldCount = BigInteger.ZERO
val added = local == null val added = local == null
if (local == null) { if (local == null) {
local = LocalTuple(stack.copy() as T, UUID.randomUUID(), ArrayList<RemoteTuple<T>>(1)) local = LocalTuple(stack.copy() as T, nextID++, ArrayList<RemoteTuple<T>>(1))
localByUUID[local.id] = local localTuples[local.id] = local
tuples[key] = local hashedTuples[key] = local
} else { } else {
oldCount = local.stack.count oldCount = local.stack.count
local.stack.grow(stack.count) local.stack.grow(stack.count)
@ -130,7 +146,7 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
val remote = RemoteTuple(stack.copy() as T, id, provider, local) val remote = RemoteTuple(stack.copy() as T, id, provider, local)
local.tuples.add(remote) local.tuples.add(remote)
remoteByUUID[id] = remote remoteTuples[id] = remote
if (added) { if (added) {
for (listener in listeners) { for (listener in listeners) {
@ -143,9 +159,9 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
} }
} }
override fun changeStack(stack: T, id: UUID, oldCount: BigInteger) { override fun changeStack(stack: T, id: Long, oldCount: BigInteger) {
require(stack.count.isPositive) require(stack.count.isPositive)
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id") val tuple = remoteTuples[id] ?: throw IllegalStateException("No such tuple with id $id")
val diff = stack.count - tuple.stack.count val diff = stack.count - tuple.stack.count
tuple.stack.count = stack.count tuple.stack.count = stack.count
@ -158,22 +174,22 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
} }
} }
override fun removeStack(stack: T, id: UUID) { override fun removeStack(stack: T, id: Long) {
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id") val tuple = remoteTuples[id] ?: throw IllegalStateException("No such tuple with id $id")
tuple.local.stack.shrink(tuple.stack.count) tuple.local.stack.shrink(tuple.stack.count)
tuple.local.tuples.remove(tuple) tuple.local.tuples.remove(tuple)
remoteByUUID.remove(id) remoteTuples.remove(id)
val a = tuple.local.stack.count <= BigInteger.ZERO val a = tuple.local.stack.count <= BigInteger.ZERO
val b = tuple.local.tuples.size == 0 val b = tuple.local.tuples.size == 0
if (a || b) { if (a || b) {
check(a && b) { "View object is empty, but tuple list is not!" } check(a && b) { "View object is empty, but tuple list is not!" }
localByUUID.remove(tuple.local.id) localTuples.remove(tuple.local.id)
val key = stack.key() val key = stack.key()
checkNotNull(tuples.remove(key)) { "No such stack $key" } checkNotNull(hashedTuples.remove(key)) { "No such stack $key" }
for (listener in listeners) { for (listener in listeners) {
listener.removeStack(tuple.local.stack, tuple.local.id) listener.removeStack(tuple.local.stack, tuple.local.id)
@ -196,13 +212,13 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
} }
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T { override fun extractStack(id: Long, amount: BigInteger, simulate: Boolean): T {
if (!amount.isPositive) if (!amount.isPositive)
return this.storageType.empty return this.storageType.empty
@Suppress("name_shadowing") @Suppress("name_shadowing")
var amount = amount var amount = amount
val tuple: LocalTuple<T>? = localByUUID[id] val tuple: LocalTuple<T>? = localTuples[id]
if (tuple == null || amount.isZero) if (tuple == null || amount.isZero)
return this.storageType.empty return this.storageType.empty
@ -302,9 +318,9 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
return stack return stack
} }
override fun get(id: UUID) = parent[id] override fun get(id: Long) = parent[id]
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T { override fun extractStack(id: Long, amount: BigInteger, simulate: Boolean): T {
val required = storageType.energyPerOperation * amount val required = storageType.energyPerOperation * amount
val energy = energyProvider.invoke() val energy = energyProvider.invoke()
val extracted = energy.extractEnergyInner(required, true) val extracted = energy.extractEnergyInner(required, true)
@ -358,9 +374,9 @@ open class PoweredVirtualComponent<T : IStorageStack>(override val parent: IVirt
constructor(parent: Class<T>, energy: IMatteryEnergyStorage) : this(VirtualComponent(parent), { energy }) constructor(parent: Class<T>, energy: IMatteryEnergyStorage) : this(VirtualComponent(parent), { energy })
constructor(parent: StorageStackType<T>, energy: IMatteryEnergyStorage) : this(VirtualComponent(parent), { energy }) constructor(parent: StorageStackType<T>, energy: IMatteryEnergyStorage) : this(VirtualComponent(parent), { energy })
override fun addStack(stack: T, id: UUID, provider: IStorageProvider<T>) = parent.addStack(stack, id, provider) override fun addStack(stack: T, id: Long, provider: IStorageProvider<T>) = parent.addStack(stack, id, provider)
override fun changeStack(stack: T, id: UUID, oldCount: BigInteger) = parent.changeStack(stack, id, oldCount) override fun changeStack(stack: T, id: Long, oldCount: BigInteger) = parent.changeStack(stack, id, oldCount)
override fun removeStack(stack: T, id: UUID) = parent.removeStack(stack, id) override fun removeStack(stack: T, id: Long) = parent.removeStack(stack, id)
override fun add(identity: IStorage<T>) = parent.add(identity) override fun add(identity: IStorage<T>) = parent.add(identity)
override fun remove(identity: IStorage<T>) = parent.remove(identity) override fun remove(identity: IStorage<T>) = parent.remove(identity)