Migrate storage system to use bigintegers
since there are zero known real cases of storage units which use fractions and are not singleton units (e.g. energy) fluid is still millibuckets despite having cauldrons and etc
This commit is contained in:
parent
4682d8116d
commit
cb5cb44848
@ -103,7 +103,7 @@ public final class OverdriveThatMatters {
|
||||
|
||||
private void setup(final FMLCommonSetupEvent event) {
|
||||
MatteryNetworking.register();
|
||||
ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125"), false);
|
||||
ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125"));
|
||||
|
||||
if (ModList.get().isLoaded("mekanism")) {
|
||||
MinecraftForge.EVENT_BUS.register(QIOKt.class);
|
||||
|
@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
@ -26,6 +25,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
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.plus
|
||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||
import ru.dbotthepony.mc.otm.graph.GraphNodeListener
|
||||
@ -36,7 +36,9 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.storage.*
|
||||
import java.lang.ref.WeakReference
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
@ -186,9 +188,9 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
override val storageType: StorageStackType<ItemStackWrapper>
|
||||
get() = OverdriveThatMatters.INSTANCE.ITEM_STORAGE()
|
||||
|
||||
private val listeners = ArrayList<IStorageListener<ItemStackWrapper>>()
|
||||
private val listeners = ArrayList<IStorageEventConsumer<ItemStackWrapper>>()
|
||||
|
||||
override fun addListener(listener: IStorageListener<ItemStackWrapper>): Boolean {
|
||||
override fun addListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
|
||||
if (!listeners.contains(listener)) {
|
||||
listeners.add(listener)
|
||||
return true
|
||||
@ -197,7 +199,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
return false
|
||||
}
|
||||
|
||||
override fun removeListener(listener: IStorageListener<ItemStackWrapper>): Boolean {
|
||||
override fun removeListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
|
||||
return listeners.remove(listener)
|
||||
}
|
||||
|
||||
@ -214,7 +216,7 @@ 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
|
||||
scannedMap.stack.count -= item.stack.count.toBigInteger()
|
||||
|
||||
if (scannedMap.stack.count.isPositive) {
|
||||
for (listener in listeners) {
|
||||
@ -238,7 +240,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
|
||||
val oldCount = scannedMap.stack.count
|
||||
item.stack.count += diff
|
||||
scannedMap.stack.count += diff
|
||||
scannedMap.stack.count += diff.toBigInteger()
|
||||
|
||||
for (listener in listeners) {
|
||||
listener.changeStack(scannedMap.stack, scannedMap.id, oldCount)
|
||||
@ -252,7 +254,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
val key = storageStack.key()
|
||||
var tuple: TrackedTuple? = tuples[key]
|
||||
val added = tuple == null
|
||||
var oldCount = ImpreciseFraction.ZERO
|
||||
var oldCount = BigInteger.ZERO
|
||||
|
||||
if (added) {
|
||||
tuple = TrackedTuple(storageStack, UUID.randomUUID())
|
||||
@ -260,7 +262,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
tuples[key] = tuple
|
||||
} else {
|
||||
oldCount = tuple!!.stack.count
|
||||
tuple.stack.count += stack.count
|
||||
tuple.stack.count += stack.count.toBigInteger()
|
||||
}
|
||||
|
||||
tuple.children[slot] = SlotTuple(slot, stack.copy())
|
||||
@ -343,7 +345,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
if (energy.batteryLevel.isZero || !filter.match(stack.item))
|
||||
return stack
|
||||
|
||||
val maxPossibleDemand = stack.count * ITEM_STORAGE.energyPerOperation
|
||||
val maxPossibleDemand = ITEM_STORAGE.energyPerOperation * stack.count
|
||||
val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true)
|
||||
|
||||
var leftover: ItemStackWrapper
|
||||
@ -352,7 +354,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
leftover = stack.copy()
|
||||
} else {
|
||||
leftover = stack.copy().also {
|
||||
it.count = (maxExtractEnergy / ITEM_STORAGE.energyPerOperation).floor()
|
||||
it.count = (maxExtractEnergy / ITEM_STORAGE.energyPerOperation).whole
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,7 +363,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
leftover = ItemStackWrapper(parent.insertItem(slot, leftover.stack, simulate))
|
||||
|
||||
if (oldCount != leftover.count && !simulate) {
|
||||
energy.extractEnergyInner((oldCount - leftover.count) * ITEM_STORAGE.energyPerOperation, false)
|
||||
energy.extractEnergyInner(ITEM_STORAGE.energyPerOperation * (oldCount - leftover.count), false)
|
||||
scan(slot)
|
||||
}
|
||||
|
||||
@ -373,22 +375,22 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
return leftover
|
||||
}
|
||||
|
||||
override fun getStack(id: UUID): ItemStackWrapper {
|
||||
override fun get(id: UUID): ItemStackWrapper {
|
||||
return index[id]?.stack ?: ItemStackWrapper.EMPTY
|
||||
}
|
||||
|
||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): ItemStackWrapper {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
var amount = amount.floor()
|
||||
|
||||
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): ItemStackWrapper {
|
||||
if (!amount.isPositive)
|
||||
return ItemStackWrapper.EMPTY
|
||||
|
||||
val maxPossibleDemand = amount * OverdriveThatMatters.INSTANCE.ITEM_STORAGE().energyPerOperation
|
||||
val maxPossibleDemand = ITEM_STORAGE.energyPerOperation * amount
|
||||
val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true)
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
var amount = amount
|
||||
|
||||
if (maxPossibleDemand != maxExtractEnergy) {
|
||||
amount = (maxExtractEnergy / OverdriveThatMatters.INSTANCE.ITEM_STORAGE().energyPerOperation).floor()
|
||||
amount = (maxExtractEnergy / ITEM_STORAGE.energyPerOperation).whole
|
||||
}
|
||||
|
||||
val intAmount = amount.toLong()
|
||||
@ -433,18 +435,18 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
return ItemStackWrapper.EMPTY
|
||||
}
|
||||
|
||||
copy.count = ImpreciseFraction(totalExtracted)
|
||||
copy.count = totalExtracted.toBigInteger()
|
||||
return copy
|
||||
}
|
||||
|
||||
override fun getStacks(): Collection<IStorageTuple<ItemStackWrapper>> {
|
||||
override val stacks: Stream<IStorageTuple<ItemStackWrapper>> get() {
|
||||
val listing = ArrayList<IStorageTuple<ItemStackWrapper>>(index.size)
|
||||
|
||||
for (tuple in index.values) {
|
||||
listing.add(StorageTuple(tuple.id, tuple.stack))
|
||||
}
|
||||
|
||||
return listing
|
||||
return listing.stream()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.block.entity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
@ -36,9 +35,9 @@ import ru.dbotthepony.mc.otm.menu.StorageImporterMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.storage.*
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
abstract class AbstractStorageImportExport<T>(
|
||||
@ -190,17 +189,17 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
return stack
|
||||
|
||||
val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return stack
|
||||
val maxMove = energy.extractStepInner(ITEM_STORAGE.energyPerOperation, stack.count, true)
|
||||
val maxMove = energy.extractStepInnerBi(ITEM_STORAGE.energyPerOperation, stack.count, true)
|
||||
|
||||
if (maxMove == 0)
|
||||
if (maxMove == BigInteger.ZERO)
|
||||
return stack
|
||||
|
||||
val leftover = view.insertStack(ItemStackWrapper(stack).also { it.count = maxMove.toImpreciseFraction() }, simulate)
|
||||
val leftover = view.insertStack(ItemStackWrapper(stack).also { it.count = maxMove }, simulate)
|
||||
|
||||
if (simulate)
|
||||
return leftover.stack
|
||||
|
||||
energy.extractStepInner(ITEM_STORAGE.energyPerOperation, maxMove - leftover.count.toInt(), false)
|
||||
energy.extractStepInner(ITEM_STORAGE.energyPerOperation, maxMove - leftover.count, false)
|
||||
return leftover.stack
|
||||
}
|
||||
|
||||
@ -265,7 +264,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
|
||||
class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_EXPORTER, blockPos, blockState),
|
||||
IStorageListener<ItemStackWrapper> {
|
||||
IStorageEventConsumer<ItemStackWrapper> {
|
||||
override val defaultDisplayName: Component
|
||||
get() = MACHINE_NAME
|
||||
|
||||
@ -275,7 +274,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
|
||||
private val relevantTuples = HashSet<UUID>()
|
||||
|
||||
override fun addStack(stack: ItemStackWrapper, id: UUID, provider: IStorageView<ItemStackWrapper>) {
|
||||
override fun addStack(stack: ItemStackWrapper, id: UUID, provider: IStorageProvider<ItemStackWrapper>) {
|
||||
if (!filter.match(stack.item)) {
|
||||
return
|
||||
}
|
||||
@ -283,7 +282,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
relevantTuples.add(id)
|
||||
}
|
||||
|
||||
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: ImpreciseFraction) {
|
||||
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: BigInteger) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@ -296,7 +295,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
|
||||
val component = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return@ItemFilter
|
||||
|
||||
for (tuple in component.getStacks()) {
|
||||
for (tuple in component.stacks) {
|
||||
addStack(tuple, component)
|
||||
}
|
||||
|
||||
@ -315,7 +314,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
private val exportStacks: Stream<Pair<UUID, ItemStackWrapper>>
|
||||
get() {
|
||||
val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return Stream.empty()
|
||||
return relevantTuples.stream().map { it to view.getStack(it) }
|
||||
return relevantTuples.stream().map { it to view[it] }
|
||||
}
|
||||
|
||||
override fun saveAdditional(nbt: CompoundTag) {
|
||||
@ -353,9 +352,9 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
continue
|
||||
}
|
||||
|
||||
val exportAmountA = items.extractStack(stack.first, stack.second.count.toInt().coerceAtMost(MAX_MOVE_PER_OPERATION).toImpreciseFraction(), true).count.toInt()
|
||||
val exportAmountA = items.extractStack(stack.first, stack.second.count.coerceAtMost(MAX_MOVE_PER_OPERATION), true).count
|
||||
|
||||
if (exportAmountA == 0) {
|
||||
if (exportAmountA == BigInteger.ZERO) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -369,7 +368,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
|
||||
if (leftover.count != exportAmount) {
|
||||
hit = true
|
||||
exportAmount = items.extractStack(stack.first, ImpreciseFraction(exportAmount - leftover.count), false).count.toInt()
|
||||
exportAmount = items.extractStack(stack.first, (exportAmount - leftover.count).toBigInteger(), false).count.toInt()
|
||||
resolved.insertItem(lastSlot, stack.second.stack.also { it.count = exportAmount }, false)
|
||||
energy.extractStepInner(ITEM_STORAGE.energyPerOperation, exportAmount, false)
|
||||
break
|
||||
@ -387,7 +386,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAX_MOVE_PER_OPERATION = 4
|
||||
val MAX_MOVE_PER_OPERATION: BigInteger = BigInteger.valueOf(4L)
|
||||
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_EXPORTER}")
|
||||
private const val INTERVAL = 5
|
||||
const val MAX_FILTERS = 6 * 3
|
||||
|
@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import net.minecraftforge.energy.IEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import java.math.BigInteger
|
||||
|
||||
// IEnergyStorage for direct compat with Forge Energy
|
||||
interface IMatteryEnergyStorage : IEnergyStorage {
|
||||
@ -212,3 +213,27 @@ fun IMatteryEnergyStorage.extractStepInner(base: ImpreciseFraction, multiplier:
|
||||
fun IMatteryEnergyStorage.extractStepOuter(base: ImpreciseFraction, multiplier: Int, simulate: Boolean): Int {
|
||||
return (extractEnergyOuter(base * multiplier, simulate) / base).toInt()
|
||||
}
|
||||
|
||||
fun IMatteryEnergyStorage.extractStepInnerBi(base: ImpreciseFraction, multiplier: Int, simulate: Boolean): BigInteger {
|
||||
return (extractEnergyInner(base * multiplier, simulate) / base).whole
|
||||
}
|
||||
|
||||
fun IMatteryEnergyStorage.extractStepOuterBi(base: ImpreciseFraction, multiplier: Int, simulate: Boolean): BigInteger {
|
||||
return (extractEnergyOuter(base * multiplier, simulate) / base).whole
|
||||
}
|
||||
|
||||
fun IMatteryEnergyStorage.extractStepInner(base: ImpreciseFraction, multiplier: BigInteger, simulate: Boolean): Int {
|
||||
return (extractEnergyInner(base * multiplier, simulate) / base).toInt()
|
||||
}
|
||||
|
||||
fun IMatteryEnergyStorage.extractStepOuter(base: ImpreciseFraction, multiplier: BigInteger, simulate: Boolean): Int {
|
||||
return (extractEnergyOuter(base * multiplier, simulate) / base).toInt()
|
||||
}
|
||||
|
||||
fun IMatteryEnergyStorage.extractStepInnerBi(base: ImpreciseFraction, multiplier: BigInteger, simulate: Boolean): BigInteger {
|
||||
return (extractEnergyInner(base * multiplier, simulate) / base).whole
|
||||
}
|
||||
|
||||
fun IMatteryEnergyStorage.extractStepOuterBi(base: ImpreciseFraction, multiplier: BigInteger, simulate: Boolean): BigInteger {
|
||||
return (extractEnergyOuter(base * multiplier, simulate) / base).whole
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.storage.IStorageComponent
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageStack
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
|
||||
interface IItemMatteryDrive : IMatteryDrive<ItemStackWrapper> {
|
||||
@ -25,19 +26,13 @@ interface IItemMatteryDrive : IMatteryDrive<ItemStackWrapper> {
|
||||
fun findItems(stack: ItemStack): IStorageTuple<ItemStackWrapper>?
|
||||
}
|
||||
|
||||
interface IItemViewListener {
|
||||
fun addViewItem(stack: ItemStack, id_upstream: UUID)
|
||||
fun changeViewItem(id_upstream: UUID, new_count: Int)
|
||||
fun removeViewItem(id_upstream: UUID)
|
||||
}
|
||||
|
||||
interface IMatteryDrive<T : IStorageStack> : IStorageComponent<T> {
|
||||
val uuid: UUID
|
||||
|
||||
var isDirty: Boolean
|
||||
|
||||
val storedCount: ImpreciseFraction
|
||||
val driveCapacity: ImpreciseFraction
|
||||
val storedCount: BigInteger
|
||||
val driveCapacity: BigInteger
|
||||
|
||||
// not extending INBTSerializable to avoid serializing it as forgecaps
|
||||
fun serializeNBT(): CompoundTag
|
||||
|
@ -1,21 +1,26 @@
|
||||
package ru.dbotthepony.mc.otm.capability.drive
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import kotlin.jvm.JvmOverloads
|
||||
import java.util.UUID
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import ru.dbotthepony.mc.otm.core.BigInteger
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.isPositive
|
||||
import ru.dbotthepony.mc.otm.core.serializeNBT
|
||||
import ru.dbotthepony.mc.otm.ifHas
|
||||
import ru.dbotthepony.mc.otm.set
|
||||
import ru.dbotthepony.mc.otm.storage.*
|
||||
import java.math.BigInteger
|
||||
import java.util.ArrayList
|
||||
import java.util.HashSet
|
||||
import java.util.stream.Stream
|
||||
|
||||
abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor(
|
||||
override var driveCapacity: ImpreciseFraction,
|
||||
override var driveCapacity: BigInteger,
|
||||
override val uuid: UUID = UUID.randomUUID(),
|
||||
var maxDifferentStacks: Int = 0xFFFF
|
||||
) : IMatteryDrive<T> {
|
||||
@ -34,13 +39,13 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
||||
var storedDifferentStacks = 0
|
||||
protected set
|
||||
|
||||
override var storedCount = ImpreciseFraction.ZERO
|
||||
override var storedCount: BigInteger = BigInteger.ZERO
|
||||
protected set
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
override fun insertStack(stack: T, simulate: Boolean): T {
|
||||
val maxInsert = driveCapacity.minus(storedCount).coerceAtMost(stack.count)
|
||||
if (maxInsert <= ImpreciseFraction.ZERO) return stack
|
||||
if (maxInsert <= BigInteger.ZERO) return stack
|
||||
|
||||
val key = stack.key()
|
||||
val tuple = tuples[key]
|
||||
@ -91,20 +96,18 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
||||
}
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
var amount = amount
|
||||
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T {
|
||||
val get = tuplesByID[id] ?: return storageType.empty
|
||||
|
||||
if (!storageType.fractional)
|
||||
amount = amount.floor()
|
||||
@Suppress("NAME_SHADOWING")
|
||||
var amount = amount
|
||||
|
||||
if (!amount.isPositive)
|
||||
amount = get.stack.maxStackSize ?: get.stack.count
|
||||
|
||||
amount = amount.coerceAtMost(get.stack.count)
|
||||
|
||||
if (amount <= ImpreciseFraction.ZERO)
|
||||
if (amount <= BigInteger.ZERO)
|
||||
return storageType.empty
|
||||
|
||||
val copy = get.stack.copy() as T
|
||||
@ -165,11 +168,11 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
tuples.clear()
|
||||
tuplesByID.clear()
|
||||
storedCount = ImpreciseFraction.ZERO
|
||||
storedCount = BigInteger.ZERO
|
||||
storedDifferentStacks = 0
|
||||
|
||||
nbt.ifHas("capacity") {
|
||||
driveCapacity = ImpreciseFraction.deserializeNBT(it)
|
||||
driveCapacity = BigInteger(it)
|
||||
}
|
||||
|
||||
maxDifferentStacks = nbt.getInt("max_different_stacks")
|
||||
@ -191,21 +194,21 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStack(id: UUID): T {
|
||||
override fun get(id: UUID): T {
|
||||
return tuplesByID[id]?.stack ?: storageType.empty
|
||||
}
|
||||
|
||||
override fun getStacks(): List<IStorageTuple<T>> {
|
||||
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }
|
||||
override val stacks: Stream<IStorageTuple<T>> get() {
|
||||
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }.stream()
|
||||
}
|
||||
|
||||
protected val listeners = HashSet<IStorageListener<T>>()
|
||||
protected val listeners = ObjectArraySet<IStorageEventConsumer<T>>()
|
||||
|
||||
override fun addListener(listener: IStorageListener<T>): Boolean {
|
||||
override fun addListener(listener: IStorageEventConsumer<T>): Boolean {
|
||||
return listeners.add(listener)
|
||||
}
|
||||
|
||||
override fun removeListener(listener: IStorageListener<T>): Boolean {
|
||||
override fun removeListener(listener: IStorageEventConsumer<T>): Boolean {
|
||||
return listeners.remove(listener)
|
||||
}
|
||||
}
|
@ -28,13 +28,15 @@ import java.util.ArrayList
|
||||
* Why?
|
||||
*
|
||||
* There are several reasons:
|
||||
* 0. This data can get very large very quickly, even when playing singleplayer (and much quicker and bigger when hosting a dedicated server)
|
||||
* 1. This data can not be stored inside ItemStack.ForgeCaps due to it's size
|
||||
* 2. This data can not be stored inside unshared (server only) nbt tag because, again, mods prone to use and interact with
|
||||
* 1. This data can get very large very quickly, even when playing singleplayer (and much quicker and bigger when hosting a dedicated server)
|
||||
* 2. This data can not be stored inside ItemStack.ForgeCaps due to it's size
|
||||
* 3. This data can not be stored inside unshared (server only) nbt tag because, again, mods prone to use and interact with
|
||||
* it wrong, causing loss of stored data or mods exposing full content of a drive inside their own tag (which cause very real "NBT size too large"
|
||||
* network kicks, often locking players out of server/singleplayer worlds
|
||||
* 3. net.minecraft.world.level.saveddata.SaveData is for storing everything inside one dat file, which
|
||||
* 4. net.minecraft.world.level.saveddata.SaveData is for storing everything inside one dat file, which
|
||||
* is performance tanking, because we have to write *entire* NBT on each save, not the data of Drives that are dirty
|
||||
* 5. Mods which check items for being stack-able even with stack size of 1 gonna compare nbt tag,
|
||||
* which will be performance tanking due to clause 1.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
object DrivePool {
|
||||
|
@ -8,20 +8,23 @@ import net.minecraft.world.item.Items
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.RegistryManager
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.BigInteger
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.serializeNBT
|
||||
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.math.BigInteger
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
|
||||
constructor(capacity: ImpreciseFraction, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks)
|
||||
constructor(capacity: ImpreciseFraction, uuid: UUID, max_different_stacks: Int) : super(capacity, uuid, max_different_stacks)
|
||||
constructor(capacity: ImpreciseFraction, uuid: UUID) : super(capacity, uuid)
|
||||
constructor(capacity: ImpreciseFraction) : super(capacity)
|
||||
constructor(capacity: BigInteger, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks)
|
||||
constructor(capacity: BigInteger, uuid: UUID, max_different_stacks: Int) : super(capacity, uuid, max_different_stacks)
|
||||
constructor(capacity: BigInteger, uuid: UUID) : super(capacity, uuid)
|
||||
constructor(capacity: BigInteger) : super(capacity)
|
||||
|
||||
override val storageType: StorageStackType<ItemStackWrapper> = OverdriveThatMatters.INSTANCE.ITEM_STORAGE()
|
||||
|
||||
@ -49,7 +52,7 @@ class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDri
|
||||
val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(tag.getString("item")))
|
||||
|
||||
if (item != null && item !== Items.AIR) {
|
||||
val count = ImpreciseFraction.deserializeNBT(tag["count"])
|
||||
val count = BigInteger(tag["count"])
|
||||
val itemstack = ItemStack(item, 1)
|
||||
itemstack.tag = tag["data"] as? CompoundTag
|
||||
return ItemStackWrapper(itemstack, copy = false).also { it.count = count }
|
||||
@ -76,6 +79,6 @@ class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDri
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val DUMMY = ItemMatteryDrive(ImpreciseFraction(0), UUID(0L, 0L), 0)
|
||||
val DUMMY = ItemMatteryDrive(BigInteger.ZERO, UUID(0L, 0L), 0)
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.compat.mekanism
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import mekanism.api.math.MathUtils
|
||||
import mekanism.common.content.qio.QIOFrequency
|
||||
import mekanism.common.content.qio.QIOFrequency.QIOItemTypeData
|
||||
import mekanism.common.lib.frequency.Frequency
|
||||
@ -23,11 +22,14 @@ import ru.dbotthepony.mc.otm.addPostServerTickerOnce
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.isPositive
|
||||
import ru.dbotthepony.mc.otm.core.toImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
||||
import ru.dbotthepony.mc.otm.storage.*
|
||||
import java.math.BigInteger
|
||||
import java.util.UUID
|
||||
import java.util.stream.Stream
|
||||
|
||||
private val QIO_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, "item_storage")
|
||||
|
||||
@ -46,14 +48,14 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
||||
|
||||
private val index = Object2ObjectAVLTreeMap<UUID, QIOTuple>()
|
||||
private val tracked = HashMap<HashedItem, QIOTuple>()
|
||||
private val listeners = ArrayList<IStorageListener<ItemStackWrapper>>()
|
||||
private val listeners = ArrayList<IStorageEventConsumer<ItemStackWrapper>>()
|
||||
|
||||
override fun getStack(id: UUID): ItemStackWrapper {
|
||||
override fun get(id: UUID): ItemStackWrapper {
|
||||
return index[id]?.stack ?: ItemStackWrapper.EMPTY
|
||||
}
|
||||
|
||||
override fun getStacks(): Collection<IStorageTuple<ItemStackWrapper>> {
|
||||
return ArrayList<IStorageTuple<ItemStackWrapper>>(index.size).also { it.addAll(index.values) }
|
||||
override val stacks: Stream<IStorageTuple<ItemStackWrapper>> get() {
|
||||
return ArrayList<IStorageTuple<ItemStackWrapper>>(index.size).also { it.addAll(index.values) }.stream()
|
||||
}
|
||||
|
||||
override fun insertStack(stack: ItemStackWrapper, simulate: Boolean): ItemStackWrapper {
|
||||
@ -81,11 +83,11 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
||||
}
|
||||
|
||||
val inserted = stack.copy()
|
||||
inserted.count = (parent.totalItemCountCapacity - parent.totalItemCount).toImpreciseFraction().coerceAtMost(stack.count)
|
||||
inserted.count = (parent.totalItemCountCapacity - parent.totalItemCount).toBigInteger().coerceAtMost(stack.count)
|
||||
return inserted
|
||||
}
|
||||
|
||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): ItemStackWrapper {
|
||||
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): ItemStackWrapper {
|
||||
// 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.
|
||||
|
||||
@ -128,7 +130,7 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
||||
return copy
|
||||
}
|
||||
|
||||
override fun addListener(listener: IStorageListener<ItemStackWrapper>): Boolean {
|
||||
override fun addListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
|
||||
if (!listeners.contains(listener)) {
|
||||
listeners.add(listener)
|
||||
return true
|
||||
@ -137,7 +139,7 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
||||
return false
|
||||
}
|
||||
|
||||
override fun removeListener(listener: IStorageListener<ItemStackWrapper>): Boolean {
|
||||
override fun removeListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
|
||||
return listeners.remove(listener)
|
||||
}
|
||||
|
||||
@ -149,14 +151,14 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
||||
|
||||
if (local.stack.count.toLong() != value.count) {
|
||||
val oldCount = local.stack.count
|
||||
local.stack.count = value.count.toImpreciseFraction()
|
||||
local.stack.count = value.count.toBigInteger()
|
||||
|
||||
for (listener in listeners) {
|
||||
listener.changeStack(local, oldCount)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val tuple = QIOTuple(at, ItemStackWrapper(at.stack).also { it.count = value.count.toImpreciseFraction() }, UUID.randomUUID(), mark)
|
||||
val tuple = QIOTuple(at, ItemStackWrapper(at.stack).also { it.count = value.count.toBigInteger() }, UUID.randomUUID(), mark)
|
||||
index[tuple.id] = tuple
|
||||
|
||||
for (listener in listeners) {
|
||||
|
@ -318,6 +318,11 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
|
||||
operator fun times(other: Long): ImpreciseFraction = times(ImpreciseFraction(other))
|
||||
operator fun div(other: Long): ImpreciseFraction = div(ImpreciseFraction(other))
|
||||
|
||||
operator fun plus(other: BigInteger): ImpreciseFraction = plus(ImpreciseFraction(other))
|
||||
operator fun minus(other: BigInteger): ImpreciseFraction = minus(ImpreciseFraction(other))
|
||||
operator fun times(other: BigInteger): ImpreciseFraction = times(ImpreciseFraction(other))
|
||||
operator fun div(other: BigInteger): ImpreciseFraction = div(ImpreciseFraction(other))
|
||||
|
||||
operator fun unaryMinus(): ImpreciseFraction {
|
||||
return ImpreciseFraction(-whole, -decimal)
|
||||
}
|
||||
|
20
src/main/kotlin/ru/dbotthepony/mc/otm/core/Math.kt
Normal file
20
src/main/kotlin/ru/dbotthepony/mc/otm/core/Math.kt
Normal file
@ -0,0 +1,20 @@
|
||||
package ru.dbotthepony.mc.otm.core
|
||||
|
||||
import net.minecraft.nbt.ByteArrayTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import java.math.BigInteger
|
||||
|
||||
inline val BigInteger.isZero get() = this == BigInteger.ZERO
|
||||
inline val BigInteger.isPositive get() = this > BigInteger.ZERO
|
||||
inline val BigInteger.isNegative get() = this < BigInteger.ZERO
|
||||
|
||||
fun BigInteger.serializeNBT(): ByteArrayTag {
|
||||
return ByteArrayTag(toByteArray())
|
||||
}
|
||||
|
||||
fun BigInteger(tag: Tag?): BigInteger {
|
||||
if (tag !is ByteArrayTag)
|
||||
return BigInteger.ZERO
|
||||
|
||||
return BigInteger(tag.asByteArray)
|
||||
}
|
@ -5,7 +5,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import ru.dbotthepony.mc.otm.addPreServerTicker
|
||||
import ru.dbotthepony.mc.otm.addPreWorldTicker
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
|
@ -28,15 +28,12 @@ import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.ifHas
|
||||
import ru.dbotthepony.mc.otm.set
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
|
||||
class PortableCondensationDriveItem(capacity: Int) :
|
||||
Item(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
|
||||
val capacity: ImpreciseFraction
|
||||
|
||||
init {
|
||||
this.capacity = ImpreciseFraction(capacity)
|
||||
}
|
||||
val capacity: BigInteger = capacity.toBigInteger()
|
||||
|
||||
private inner class DriveCapability(private val stack: ItemStack) : ICapabilityProvider {
|
||||
private var uuid: UUID? = null
|
||||
@ -48,10 +45,10 @@ class PortableCondensationDriveItem(capacity: Int) :
|
||||
|
||||
val uuid = uuid
|
||||
|
||||
DrivePool.get(uuid!!, { tag: CompoundTag? ->
|
||||
return@of DrivePool.get(uuid!!, { tag: CompoundTag? ->
|
||||
val drive = ItemMatteryDrive(capacity, uuid)
|
||||
drive.deserializeNBT(tag!!)
|
||||
drive
|
||||
return@get drive
|
||||
}, { ItemMatteryDrive(capacity, uuid) })
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,14 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.isZero
|
||||
import ru.dbotthepony.mc.otm.core.readImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.writeImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.menu.FormattingHelper
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||
import ru.dbotthepony.mc.otm.orNull
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||
import java.math.BigInteger
|
||||
import java.util.function.Supplier
|
||||
|
||||
internal var building = false
|
||||
@ -174,7 +176,7 @@ fun canDecompose(stack: ItemStack): Boolean {
|
||||
|
||||
return canDecompose(stack.item) &&
|
||||
(stack.getCapability(MatteryCapability.MATTER).orNull()?.storedMatter ?: ImpreciseFraction.ZERO).isZero &&
|
||||
(stack.getCapability(MatteryCapability.DRIVE).orNull()?.storedCount ?: ImpreciseFraction.ZERO).isZero
|
||||
(stack.getCapability(MatteryCapability.DRIVE).orNull()?.storedCount ?: BigInteger.ZERO).isZero
|
||||
}
|
||||
|
||||
private const val MAX_NESTING = 100
|
||||
@ -203,7 +205,7 @@ private fun getMatterValue(stack: ItemStack, level: Int): MatterTuple {
|
||||
val drive = stack.getCapability(MatteryCapability.DRIVE).orNull()
|
||||
|
||||
if (drive != null && drive.storageType === OverdriveThatMatters.INSTANCE.ITEM_STORAGE()) {
|
||||
for (item in (drive as IMatteryDrive<ItemStackWrapper>).getStacks()) {
|
||||
for (item in (drive as IMatteryDrive<ItemStackWrapper>).stacks) {
|
||||
val tuple = getMatterValue(item.stack.stack, level + 1)
|
||||
|
||||
if (!tuple.isZero) {
|
||||
|
@ -18,9 +18,10 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||
import ru.dbotthepony.mc.otm.network.SetCarriedPacket
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageComponent
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageListener
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageView
|
||||
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.util.*
|
||||
import java.util.function.Supplier
|
||||
|
||||
@ -155,7 +156,7 @@ class StackRemovePacket(val id: Int, val stackID: Int) {
|
||||
/**
|
||||
* Creates a virtual, slotless container for Player to interaction with.
|
||||
*/
|
||||
open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote: Boolean) : IStorageListener<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)
|
||||
|
||||
protected var nextStackID = 0
|
||||
@ -230,8 +231,8 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
|
||||
return localState.values.size
|
||||
}
|
||||
|
||||
override fun addStack(stack: ItemStackWrapper, id: UUID, provider: IStorageView<ItemStackWrapper>) = addObject(stack.stack, id)
|
||||
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: ImpreciseFraction) = changeObject(id, stack.count.toInt())
|
||||
override fun addStack(stack: ItemStackWrapper, id: UUID, provider: IStorageProvider<ItemStackWrapper>) = addObject(stack.stack, id)
|
||||
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: BigInteger) = changeObject(id, stack.count.toInt())
|
||||
|
||||
protected fun network(fn: () -> Any) {
|
||||
if (!remote) {
|
||||
@ -310,13 +311,13 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
|
||||
else
|
||||
Math.max(1, state.stack.maxStackSize / 2)
|
||||
|
||||
val extracted = provider.extractStack(state.upstreamId!!, amount, true)
|
||||
val extracted = provider.extractStack(state.upstreamId!!, amount.toBigInteger(), true)
|
||||
|
||||
if (!extracted.isEmpty) {
|
||||
val (_, remaining) = menu.quickMoveToInventory(extracted.stack, false)
|
||||
|
||||
if (remaining.count != extracted.count.toInt()) {
|
||||
provider.extractStack(state.upstreamId, extracted.count.toInt() - remaining.count, false)
|
||||
provider.extractStack(state.upstreamId, (extracted.count.toInt() - remaining.count).toBigInteger(), false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +355,7 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
|
||||
else
|
||||
(state.stack.count / 2).coerceAtMost(state.stack.maxStackSize / 2).coerceAtLeast(1)
|
||||
|
||||
val extracted = provider.extractStack(state.upstreamId!!, amount, false)
|
||||
val extracted = provider.extractStack(state.upstreamId!!, amount.toBigInteger(), false)
|
||||
menu.carried = extracted.stack
|
||||
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
|
||||
menu.setRemoteCarried(menu.carried.copy())
|
||||
|
@ -1,7 +1,9 @@
|
||||
package ru.dbotthepony.mc.otm.storage
|
||||
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
|
||||
/**
|
||||
* Represents a stack in storage system.
|
||||
@ -19,51 +21,36 @@ interface IStorageStack {
|
||||
fun copy(): IStorageStack
|
||||
|
||||
/**
|
||||
* Despite count being [ImpreciseFraction], far not all items can be "fraction"
|
||||
* into pieces (e.g. ItemStacks).
|
||||
* Size of this storage stack
|
||||
*
|
||||
* Consult [StorageStackType.fractional] to see if item has actual fractions.
|
||||
*
|
||||
* Implementation MUST [ImpreciseFraction.floor] received value if fractions
|
||||
* are not supported, and NOT throw any errors. Writing fractional value is a correct
|
||||
* behavior, and is used in base mod.
|
||||
*
|
||||
* Behavior of writing negative value is undefined.
|
||||
* This is overriden in subclasses
|
||||
*/
|
||||
var count: ImpreciseFraction
|
||||
var count: BigInteger
|
||||
val isEmpty: Boolean
|
||||
|
||||
/**
|
||||
* @return max stack size for this stack object,
|
||||
* null if unlimited (default)
|
||||
*/
|
||||
val maxStackSize: ImpreciseFraction? get() = null
|
||||
val maxStackSize: BigInteger? get() = null
|
||||
|
||||
/**
|
||||
* Increase [count] by [amount]
|
||||
*/
|
||||
fun grow(amount: ImpreciseFraction) {
|
||||
fun grow(amount: BigInteger) {
|
||||
count += amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease [count] by [amount]
|
||||
*/
|
||||
fun shrink(amount: ImpreciseFraction) {
|
||||
fun shrink(amount: BigInteger) {
|
||||
count -= amount
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (Supposedly shallow) Copies this object and sets it's count to 1 for use as map key.
|
||||
*
|
||||
* Equals to next code:
|
||||
* ```kotlin
|
||||
* this.copy().also { it.count = ImpreciseFraction.ONE }
|
||||
* ```
|
||||
*/
|
||||
fun <T : IStorageStack> T.key(): T {
|
||||
return copy().also { it.count = ImpreciseFraction.ONE } as T
|
||||
return copy().also { it.count = BigInteger.ONE } as T
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,19 +63,42 @@ interface IStorage<T : IStorageStack> {
|
||||
val storageType: StorageStackType<T>
|
||||
}
|
||||
|
||||
interface IStorageTrigger<T : IStorageStack> : IStorage<T> {
|
||||
/**
|
||||
* Generates events for [IStorageEventConsumer]
|
||||
*/
|
||||
interface IStorageEventProducer<T : IStorageStack> : IStorage<T> {
|
||||
/**
|
||||
* [listener] is [IStorageListener] which want to subscribe to our events
|
||||
* [listener] is [IStorageEventConsumer] which want to subscribe to our events
|
||||
*/
|
||||
fun addListener(listener: IStorageListener<T>): Boolean
|
||||
fun addListener(listener: IStorageEventConsumer<T>): Boolean
|
||||
|
||||
/**
|
||||
* [listener] is [IStorageListener] which want to unsubscribe from our events
|
||||
* [listener] is [IStorageEventConsumer] which want to unsubscribe from our events
|
||||
*/
|
||||
fun removeListener(listener: IStorageListener<T>): Boolean
|
||||
fun removeListener(listener: IStorageEventConsumer<T>): Boolean
|
||||
}
|
||||
|
||||
interface IStorageConsumer<T : IStorageStack> : IStorage<T> {
|
||||
/**
|
||||
* Consumes events produced by [IStorageEventConsumer]
|
||||
*/
|
||||
interface IStorageEventConsumer<T : IStorageStack> {
|
||||
/**
|
||||
* Fired on whenever an object is added (to listener) we subscribed to
|
||||
*/
|
||||
fun addStack(stack: T, id: UUID, provider: IStorageProvider<T>)
|
||||
|
||||
/**
|
||||
* Fired on whenever an object is changes on listener we subscribed to
|
||||
*/
|
||||
fun changeStack(stack: T, id: UUID, oldCount: BigInteger)
|
||||
|
||||
/**
|
||||
* Fired on whenever an object is removed from listener we subscribed to
|
||||
*/
|
||||
fun removeStack(stack: T, id: UUID)
|
||||
}
|
||||
|
||||
interface IStorageAcceptor<T : IStorageStack> : IStorage<T> {
|
||||
/**
|
||||
* Inserts an item into system.
|
||||
* @return leftover, might equal to [stack] if no items were inserted
|
||||
@ -96,12 +106,14 @@ interface IStorageConsumer<T : IStorageStack> : IStorage<T> {
|
||||
fun insertStack(stack: T, simulate: Boolean): T
|
||||
}
|
||||
|
||||
interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
||||
interface IStorageProvider<T : IStorageStack> : IStorageEventProducer<T> {
|
||||
/**
|
||||
* @param id identifier of stack
|
||||
* @return stored object (not a copy). Do not edit it.
|
||||
*/
|
||||
fun getStack(id: UUID): T
|
||||
operator fun get(id: UUID): T
|
||||
|
||||
val stacks: Stream<IStorageTuple<T>>
|
||||
|
||||
/**
|
||||
* If tuple does not exist, returns empty stack
|
||||
@ -111,31 +123,11 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
||||
* @param simulate whenever to simulate the action or not
|
||||
* @return copy of object, with amount of units actually extracted
|
||||
*/
|
||||
fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T
|
||||
fun extractStack(id: UUID, amount: Int, simulate: Boolean): T = extractStack(id, ImpreciseFraction(amount), simulate)
|
||||
fun extractStack(id: UUID, amount: Long, simulate: Boolean): T = extractStack(id, ImpreciseFraction(amount), simulate)
|
||||
fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T
|
||||
|
||||
/**
|
||||
* Designed for views, for extraction with less computation overhead caused by
|
||||
* copying stack extracted
|
||||
*
|
||||
* @param id identifier of stack to extract
|
||||
* @param amount desired amount to extract
|
||||
* @param simulate whenever to simulate the action or not
|
||||
* @return amount extracted
|
||||
*/
|
||||
fun extractStackCount(id: UUID, amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
||||
return extractStack(id, amount, simulate).count
|
||||
}
|
||||
|
||||
fun extractStackCount(id: UUID, amount: Int, simulate: Boolean): ImpreciseFraction = extractStackCount(id, ImpreciseFraction(amount), simulate)
|
||||
fun extractStackCount(id: UUID, amount: Long, simulate: Boolean): ImpreciseFraction = extractStackCount(id, ImpreciseFraction(amount), simulate)
|
||||
|
||||
fun getStacks(): Collection<IStorageTuple<T>>
|
||||
|
||||
fun addListenerAuto(listener: IStorageListener<T>): Boolean {
|
||||
fun addListenerAuto(listener: IStorageEventConsumer<T>): Boolean {
|
||||
if (addListener(listener)) {
|
||||
for (stack in getStacks()) {
|
||||
for (stack in stacks) {
|
||||
listener.addStack(stack.stack, stack.id, this)
|
||||
}
|
||||
|
||||
@ -145,9 +137,9 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
||||
return false
|
||||
}
|
||||
|
||||
fun removeListenerAuto(listener: IStorageListener<T>): Boolean {
|
||||
fun removeListenerAuto(listener: IStorageEventConsumer<T>): Boolean {
|
||||
if (removeListener(listener)) {
|
||||
for (stack in getStacks()) {
|
||||
for (stack in stacks) {
|
||||
listener.removeStack(stack.stack, stack.id)
|
||||
}
|
||||
|
||||
@ -158,33 +150,16 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
||||
}
|
||||
}
|
||||
|
||||
interface IStorageListener<T : IStorageStack> {
|
||||
/**
|
||||
* Fired on whenever an object is added (to listener) we subscribed to
|
||||
*/
|
||||
fun addStack(stack: T, id: UUID, provider: IStorageView<T>)
|
||||
fun <T : IStorageStack> IStorageEventConsumer<T>.changeStack(tuple: IStorageTuple<T>, oldCount: BigInteger) {
|
||||
changeStack(tuple.stack, tuple.id, oldCount)
|
||||
}
|
||||
|
||||
fun addStack(tuple: IStorageTuple<T>, provider: IStorageView<T>) {
|
||||
addStack(tuple.stack, tuple.id, provider)
|
||||
}
|
||||
fun <T : IStorageStack> IStorageEventConsumer<T>.addStack(tuple: IStorageTuple<T>, provider: IStorageProvider<T>) {
|
||||
addStack(tuple.stack, tuple.id, provider)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired on whenever an object is changes on listener we subscribed to
|
||||
*/
|
||||
fun changeStack(stack: T, id: UUID, oldCount: ImpreciseFraction)
|
||||
|
||||
fun changeStack(tuple: IStorageTuple<T>, oldCount: ImpreciseFraction) {
|
||||
changeStack(tuple.stack, tuple.id, oldCount)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired on whenever an object is removed from listener we subscribed to
|
||||
*/
|
||||
fun removeStack(stack: T, id: UUID)
|
||||
|
||||
fun removeStack(tuple: IStorageTuple<T>) {
|
||||
removeStack(tuple.stack, tuple.id)
|
||||
}
|
||||
fun <T : IStorageStack> IStorageEventConsumer<T>.removeStack(tuple: IStorageTuple<T>) {
|
||||
removeStack(tuple.stack, tuple.id)
|
||||
}
|
||||
|
||||
interface IStorageTuple<T : IStorageStack> {
|
||||
@ -193,12 +168,13 @@ interface IStorageTuple<T : IStorageStack> {
|
||||
}
|
||||
|
||||
class StorageTuple<T : IStorageStack>(override val id: UUID, override val stack: T) : IStorageTuple<T>
|
||||
interface IStorageComponent<T : IStorageStack> : IStorageView<T>, IStorageConsumer<T>
|
||||
|
||||
interface IStorageComponent<T : IStorageStack> : IStorageProvider<T>, IStorageAcceptor<T>
|
||||
|
||||
/**
|
||||
* Component which (most time) proxy other components (combine their contents into single view)
|
||||
*/
|
||||
interface IVirtualStorageComponent<T : IStorageStack> : IStorageComponent<T>, IStorageListener<T> {
|
||||
interface IVirtualStorageComponent<T : IStorageStack> : IStorageComponent<T>, IStorageEventConsumer<T> {
|
||||
fun add(identity: IStorage<T>)
|
||||
fun remove(identity: IStorage<T>)
|
||||
fun contains(identity: IStorage<T>): Boolean
|
||||
|
@ -6,6 +6,8 @@ import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.ForgeRegistry
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.isPositive
|
||||
import java.math.BigInteger
|
||||
|
||||
/**
|
||||
* constructors always copy its input.
|
||||
@ -21,8 +23,7 @@ class ItemStackWrapper : IStorageStack {
|
||||
val registryName get() = item.item.registryName!!
|
||||
private val hash: Int
|
||||
|
||||
override var count: ImpreciseFraction
|
||||
set(value) { field = value.floor() }
|
||||
override var count: BigInteger
|
||||
|
||||
/**
|
||||
* [copy] as false is used internally for fast index construction, do not specify
|
||||
@ -36,7 +37,7 @@ class ItemStackWrapper : IStorageStack {
|
||||
this.item = item
|
||||
}
|
||||
|
||||
this.count = ImpreciseFraction(item.count)
|
||||
this.count = BigInteger.valueOf(item.count.toLong())
|
||||
|
||||
if (copy) {
|
||||
this.item.count = 1
|
||||
@ -72,7 +73,7 @@ class ItemStackWrapper : IStorageStack {
|
||||
return hash * 31 + count.hashCode()
|
||||
}
|
||||
|
||||
override val maxStackSize get() = ImpreciseFraction(item.maxStackSize)
|
||||
override val maxStackSize: BigInteger get() = BigInteger.valueOf(item.maxStackSize.toLong())
|
||||
|
||||
override val isEmpty: Boolean get() = item.isEmpty || !count.isPositive
|
||||
|
||||
|
@ -13,24 +13,9 @@ open class StorageStackType<T : IStorageStack>(
|
||||
* Speculated energy required per operation on stack with size of 1
|
||||
*/
|
||||
open val energyPerOperation: ImpreciseFraction,
|
||||
|
||||
/**
|
||||
* Whenever is this stack supports fractional part (e.g. 0.5).
|
||||
*
|
||||
* Keep in mind fractions are imprecise and can lead to rounding errors.
|
||||
* [ImpreciseFraction] class attempts to negate most of the issues
|
||||
* (e.g. 0.1 + 0.2 eventually getting its 0....4 part into whole part),
|
||||
* but that is about it.
|
||||
*
|
||||
* On design side note, storage system could have been using [Fraction], but there is an issue:
|
||||
* they are **precise**. Under precise, means that anything that continuously divide/multiply them
|
||||
* they become more and more "irrational", greatly slowing down operations. Worst case scenario:
|
||||
* value is getting divided by [Long.MAX_VALUE] again and again, creating insanely huge divisor.
|
||||
*/
|
||||
open val fractional: Boolean
|
||||
) {
|
||||
open fun energyPerOperation(stack: T): ImpreciseFraction {
|
||||
return stack.count * energyPerOperation
|
||||
return energyPerOperation * stack.count
|
||||
}
|
||||
|
||||
open fun energyPerStorage(stack: T) = energyPerOperation(stack)
|
||||
@ -56,10 +41,9 @@ object StorageRegistry {
|
||||
fun <T : IStorageStack> register(
|
||||
identity: Class<T>,
|
||||
empty: T,
|
||||
energyPerOperation: ImpreciseFraction,
|
||||
fractional: Boolean
|
||||
energyPerOperation: ImpreciseFraction
|
||||
): StorageStackType<T> {
|
||||
return register(StorageStackType(identity, empty, energyPerOperation, fractional)) as StorageStackType<T>
|
||||
return register(StorageStackType(identity, empty, energyPerOperation)) as StorageStackType<T>
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
@ -1,29 +1,31 @@
|
||||
package ru.dbotthepony.mc.otm.storage
|
||||
|
||||
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.ObjectArraySet
|
||||
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.isZero
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
class RemoteTuple<T : IStorageStack>(val obj: T, val remote_id: UUID, val provider: IStorageView<T>, val local: LocalTuple<T>) {
|
||||
fun extract(amount: ImpreciseFraction, simulate: Boolean): T {
|
||||
return provider.extractStack(remote_id, amount, simulate)
|
||||
}
|
||||
|
||||
fun extractCount(amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
||||
return provider.extractStackCount(remote_id, amount, simulate)
|
||||
class RemoteTuple<T : IStorageStack>(
|
||||
override val stack: T,
|
||||
override val id: UUID,
|
||||
val provider: IStorageProvider<T>,
|
||||
val local: LocalTuple<T>
|
||||
) : IStorageTuple<T> {
|
||||
fun extract(amount: BigInteger, simulate: Boolean): T {
|
||||
return provider.extractStack(id, amount, simulate)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is RemoteTuple<*> && other.remote_id == remote_id || other is UUID && other == remote_id
|
||||
return other is RemoteTuple<*> && other.id == id || other is UUID && other == id
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return remote_id.hashCode()
|
||||
return id.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,31 +37,31 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
override val storageType: StorageStackType<T> = type
|
||||
|
||||
// удаленный UUID -> Кортеж
|
||||
protected val remoteByUUID = HashMap<UUID, RemoteTuple<T>>()
|
||||
protected val remoteByUUID: MutableMap<UUID, RemoteTuple<T>> = HashMap()
|
||||
|
||||
// локальный UUID -> Локальный кортеж
|
||||
protected val localByUUID = HashMap<UUID, LocalTuple<T>>()
|
||||
protected val localByUUID: MutableMap<UUID, LocalTuple<T>> = HashMap()
|
||||
|
||||
// Стак -> Локальный кортеж стака
|
||||
protected val tuples = HashMap<T, LocalTuple<T>>()
|
||||
protected val tuples: MutableMap<T, LocalTuple<T>> = HashMap()
|
||||
|
||||
// ArrayList для скорости работы
|
||||
protected val listeners = ArrayList<IStorageListener<T>>()
|
||||
protected val set = ObjectArraySet<Any>()
|
||||
protected val consumers = ArrayList<IStorageConsumer<T>>()
|
||||
protected val listeners: MutableSet<IStorageEventConsumer<T>> = ObjectArraySet()
|
||||
protected val set: MutableSet<IStorage<T>> = ObjectArraySet()
|
||||
protected val consumers: MutableSet<IStorageAcceptor<T>> = ObjectArraySet()
|
||||
|
||||
protected open fun onAdd(identity: IStorage<T>) {}
|
||||
protected open fun onRemove(identity: IStorage<T>) {}
|
||||
|
||||
override fun add(identity: IStorage<T>) {
|
||||
if (set.add(identity)) {
|
||||
if (identity is IStorageView<T>) {
|
||||
if (identity is IStorageProvider<T>) {
|
||||
identity.addListenerAuto(this)
|
||||
} else if (identity is IStorageTrigger<T>) {
|
||||
} else if (identity is IStorageEventProducer<T>) {
|
||||
identity.addListener(this)
|
||||
}
|
||||
|
||||
if (identity is IStorageConsumer<T>) {
|
||||
if (identity is IStorageAcceptor<T>) {
|
||||
consumers.add(identity)
|
||||
}
|
||||
|
||||
@ -69,13 +71,13 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
|
||||
override fun remove(identity: IStorage<T>) {
|
||||
if (set.remove(identity)) {
|
||||
if (identity is IStorageView<T>) {
|
||||
if (identity is IStorageProvider<T>) {
|
||||
identity.removeListenerAuto(this)
|
||||
} else if (identity is IStorageTrigger<T>) {
|
||||
} else if (identity is IStorageEventProducer<T>) {
|
||||
identity.removeListener(this)
|
||||
}
|
||||
|
||||
if (identity is IStorageConsumer<T>) {
|
||||
if (identity is IStorageAcceptor<T>) {
|
||||
consumers.remove(identity)
|
||||
}
|
||||
|
||||
@ -87,7 +89,7 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
return set.contains(identity)
|
||||
}
|
||||
|
||||
override fun addListener(listener: IStorageListener<T>): Boolean {
|
||||
override fun addListener(listener: IStorageEventConsumer<T>): Boolean {
|
||||
if (!listeners.contains(listener)) {
|
||||
listeners.add(listener)
|
||||
return true
|
||||
@ -96,31 +98,31 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
return false
|
||||
}
|
||||
|
||||
override fun removeListener(listener: IStorageListener<T>): Boolean {
|
||||
override fun removeListener(listener: IStorageEventConsumer<T>): Boolean {
|
||||
return listeners.remove(listener)
|
||||
}
|
||||
|
||||
override fun getStack(id: UUID): T {
|
||||
override fun get(id: UUID): T {
|
||||
return localByUUID[id]?.stack ?: this.storageType.empty
|
||||
}
|
||||
|
||||
override fun getStacks(): List<IStorageTuple<T>> {
|
||||
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }
|
||||
override val stacks: Stream<IStorageTuple<T>> get() {
|
||||
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }.stream()
|
||||
}
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
override fun addStack(stack: T, id: UUID, provider: IStorageView<T>) {
|
||||
override fun addStack(stack: T, id: UUID, provider: IStorageProvider<T>) {
|
||||
check(!remoteByUUID.containsKey(id)) { "Already tracking tuple with id $id" }
|
||||
|
||||
val key = stack.key()
|
||||
var local: LocalTuple<T>? = tuples[key]
|
||||
var oldCount = ImpreciseFraction.ZERO
|
||||
var oldCount = BigInteger.ZERO
|
||||
val added = local == null
|
||||
|
||||
if (local == null) {
|
||||
local = LocalTuple(stack.copy() as T, UUID.randomUUID(), ArrayList<RemoteTuple<T>>(1))
|
||||
localByUUID[local.id] = local
|
||||
tuples[key as T] = local
|
||||
tuples[key] = local
|
||||
} else {
|
||||
oldCount = local.stack.count
|
||||
local.stack.grow(stack.count)
|
||||
@ -141,12 +143,12 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeStack(stack: T, id: UUID, oldCount: ImpreciseFraction) {
|
||||
override fun changeStack(stack: T, id: UUID, oldCount: BigInteger) {
|
||||
require(stack.count.isPositive)
|
||||
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id")
|
||||
|
||||
val diff = stack.count - tuple.obj.count
|
||||
tuple.obj.count = stack.count
|
||||
val diff = stack.count - tuple.stack.count
|
||||
tuple.stack.count = stack.count
|
||||
|
||||
@Suppress("NAME_SHADOWING") val oldCount = tuple.local.stack.count
|
||||
tuple.local.stack.grow(diff)
|
||||
@ -159,12 +161,12 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
override fun removeStack(stack: T, id: UUID) {
|
||||
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id")
|
||||
|
||||
tuple.local.stack.shrink(tuple.obj.count)
|
||||
tuple.local.stack.shrink(tuple.stack.count)
|
||||
tuple.local.tuples.remove(tuple)
|
||||
|
||||
remoteByUUID.remove(id)
|
||||
|
||||
val a = tuple.local.stack.count <= ImpreciseFraction.ZERO
|
||||
val a = tuple.local.stack.count <= BigInteger.ZERO
|
||||
val b = tuple.local.tuples.size == 0
|
||||
|
||||
if (a || b) {
|
||||
@ -194,8 +196,8 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
}
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
|
||||
if (amount.isZero)
|
||||
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T {
|
||||
if (!amount.isPositive)
|
||||
return this.storageType.empty
|
||||
|
||||
@Suppress("name_shadowing")
|
||||
@ -205,18 +207,16 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
||||
if (tuple == null || amount.isZero)
|
||||
return this.storageType.empty
|
||||
|
||||
if (!storageType.fractional)
|
||||
amount = amount.floor()
|
||||
|
||||
if (!amount.isPositive)
|
||||
amount = tuple.stack.maxStackSize ?: tuple.stack.count
|
||||
|
||||
val toExtract = tuple.stack.count.coerceAtMost(amount)
|
||||
var extracted = ImpreciseFraction.ZERO
|
||||
var extracted = BigInteger.ZERO
|
||||
val copy = tuple.stack.copy() as T
|
||||
|
||||
for (remote_tuple in tuple.tuples.let { Array(it.size) { i -> it[i] } }) {
|
||||
extracted += remote_tuple.extractCount(toExtract - extracted, simulate)
|
||||
val extractedStack = remote_tuple.extract(toExtract - extracted, simulate)
|
||||
extracted += extractedStack.count
|
||||
|
||||
if (extracted >= toExtract)
|
||||
break
|
||||
@ -238,8 +238,8 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
||||
override val storageType: StorageStackType<T>
|
||||
get() = parent.storageType
|
||||
|
||||
override fun addListener(listener: IStorageListener<T>) = parent.addListener(listener)
|
||||
override fun removeListener(listener: IStorageListener<T>) = parent.removeListener(listener)
|
||||
override fun addListener(listener: IStorageEventConsumer<T>) = parent.addListener(listener)
|
||||
override fun removeListener(listener: IStorageEventConsumer<T>) = parent.removeListener(listener)
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
override fun insertStack(stack: T, simulate: Boolean): T {
|
||||
@ -273,7 +273,7 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
||||
@Suppress("name_shadowing")
|
||||
val stack = stack.copy() as T
|
||||
val oldCount = stack.count
|
||||
stack.count = extracted / storageType.energyPerOperation
|
||||
stack.count = (extracted / storageType.energyPerOperation).whole
|
||||
val diff = oldCount - stack.count
|
||||
val newRequired = storageType.energyPerOperation * stack.count
|
||||
val newExtracted = energy.extractEnergyInner(newRequired, true)
|
||||
@ -291,7 +291,7 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
||||
}
|
||||
|
||||
if (!simulate) {
|
||||
val requiredNew = (stack.count - leftover.count) * storageType.energyPerOperation
|
||||
val requiredNew = storageType.energyPerOperation * (stack.count - leftover.count)
|
||||
energy.extractEnergyInner(requiredNew, false)
|
||||
}
|
||||
|
||||
@ -302,9 +302,9 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
||||
return stack
|
||||
}
|
||||
|
||||
override fun getStack(id: UUID) = parent.getStack(id)
|
||||
override fun get(id: UUID) = parent[id]
|
||||
|
||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
|
||||
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T {
|
||||
val required = storageType.energyPerOperation * amount
|
||||
val energy = energyProvider.invoke()
|
||||
val extracted = energy.extractEnergyInner(required, true)
|
||||
@ -324,7 +324,7 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
||||
if (extractedStack.count == amount) {
|
||||
energy.extractEnergyInner(required, false)
|
||||
} else {
|
||||
energy.extractEnergyInner(extractedStack.count * storageType.energyPerOperation, false)
|
||||
energy.extractEnergyInner(storageType.energyPerOperation * extractedStack.count, false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,7 +332,7 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
||||
}
|
||||
|
||||
@Suppress("name_shadowing")
|
||||
val amount = required / storageType.energyPerOperation
|
||||
val amount = (required / storageType.energyPerOperation).whole
|
||||
val extractedStack = parent.extractStack(id, amount, simulate)
|
||||
|
||||
if (extractedStack.isEmpty) {
|
||||
@ -340,13 +340,13 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
||||
}
|
||||
|
||||
if (!simulate) {
|
||||
energy.extractEnergyInner(extractedStack.count * storageType.energyPerOperation, false)
|
||||
energy.extractEnergyInner(storageType.energyPerOperation * extractedStack.count, false)
|
||||
}
|
||||
|
||||
return extractedStack
|
||||
}
|
||||
|
||||
override fun getStacks() = parent.getStacks()
|
||||
override val stacks get() = parent.stacks
|
||||
}
|
||||
|
||||
/**
|
||||
@ -358,8 +358,8 @@ open class PoweredVirtualComponent<T : IStorageStack>(override val parent: IVirt
|
||||
constructor(parent: Class<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: IStorageView<T>) = parent.addStack(stack, id, provider)
|
||||
override fun changeStack(stack: T, id: UUID, oldCount: ImpreciseFraction) = parent.changeStack(stack, id, oldCount)
|
||||
override fun addStack(stack: T, id: UUID, provider: IStorageProvider<T>) = parent.addStack(stack, id, provider)
|
||||
override fun changeStack(stack: T, id: UUID, oldCount: BigInteger) = parent.changeStack(stack, id, oldCount)
|
||||
override fun removeStack(stack: T, id: UUID) = parent.removeStack(stack, id)
|
||||
|
||||
override fun add(identity: IStorage<T>) = parent.add(identity)
|
||||
|
Loading…
Reference in New Issue
Block a user