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) {
|
private void setup(final FMLCommonSetupEvent event) {
|
||||||
MatteryNetworking.register();
|
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")) {
|
if (ModList.get().isLoaded("mekanism")) {
|
||||||
MinecraftForge.EVENT_BUS.register(QIOKt.class);
|
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.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.TranslatableComponent
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import net.minecraft.server.level.ServerLevel
|
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.capability.WorkerEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.container.ItemFilter
|
import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||||
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.plus
|
import ru.dbotthepony.mc.otm.core.plus
|
||||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||||
import ru.dbotthepony.mc.otm.graph.GraphNodeListener
|
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.registry.MNames
|
||||||
import ru.dbotthepony.mc.otm.storage.*
|
import ru.dbotthepony.mc.otm.storage.*
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.stream.Stream
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
@ -186,9 +188,9 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
override val storageType: StorageStackType<ItemStackWrapper>
|
override val storageType: StorageStackType<ItemStackWrapper>
|
||||||
get() = OverdriveThatMatters.INSTANCE.ITEM_STORAGE()
|
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)) {
|
if (!listeners.contains(listener)) {
|
||||||
listeners.add(listener)
|
listeners.add(listener)
|
||||||
return true
|
return true
|
||||||
@ -197,7 +199,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeListener(listener: IStorageListener<ItemStackWrapper>): Boolean {
|
override fun removeListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
|
||||||
return listeners.remove(listener)
|
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")
|
val item = scannedMap.children[slot] ?: throw IllegalStateException("${scannedMap.id} does not track $slot")
|
||||||
scannedMap.children.remove(slot)
|
scannedMap.children.remove(slot)
|
||||||
val count = scannedMap.stack.count
|
val count = scannedMap.stack.count
|
||||||
scannedMap.stack.count -= item.stack.count
|
scannedMap.stack.count -= item.stack.count.toBigInteger()
|
||||||
|
|
||||||
if (scannedMap.stack.count.isPositive) {
|
if (scannedMap.stack.count.isPositive) {
|
||||||
for (listener in listeners) {
|
for (listener in listeners) {
|
||||||
@ -238,7 +240,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
|
|
||||||
val oldCount = scannedMap.stack.count
|
val oldCount = scannedMap.stack.count
|
||||||
item.stack.count += diff
|
item.stack.count += diff
|
||||||
scannedMap.stack.count += diff
|
scannedMap.stack.count += diff.toBigInteger()
|
||||||
|
|
||||||
for (listener in listeners) {
|
for (listener in listeners) {
|
||||||
listener.changeStack(scannedMap.stack, scannedMap.id, oldCount)
|
listener.changeStack(scannedMap.stack, scannedMap.id, oldCount)
|
||||||
@ -252,7 +254,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
val key = storageStack.key()
|
val key = storageStack.key()
|
||||||
var tuple: TrackedTuple? = tuples[key]
|
var tuple: TrackedTuple? = tuples[key]
|
||||||
val added = tuple == null
|
val added = tuple == null
|
||||||
var oldCount = ImpreciseFraction.ZERO
|
var oldCount = BigInteger.ZERO
|
||||||
|
|
||||||
if (added) {
|
if (added) {
|
||||||
tuple = TrackedTuple(storageStack, UUID.randomUUID())
|
tuple = TrackedTuple(storageStack, UUID.randomUUID())
|
||||||
@ -260,7 +262,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
tuples[key] = tuple
|
tuples[key] = tuple
|
||||||
} else {
|
} else {
|
||||||
oldCount = tuple!!.stack.count
|
oldCount = tuple!!.stack.count
|
||||||
tuple.stack.count += stack.count
|
tuple.stack.count += stack.count.toBigInteger()
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple.children[slot] = SlotTuple(slot, stack.copy())
|
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))
|
if (energy.batteryLevel.isZero || !filter.match(stack.item))
|
||||||
return stack
|
return stack
|
||||||
|
|
||||||
val maxPossibleDemand = stack.count * ITEM_STORAGE.energyPerOperation
|
val maxPossibleDemand = ITEM_STORAGE.energyPerOperation * stack.count
|
||||||
val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true)
|
val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true)
|
||||||
|
|
||||||
var leftover: ItemStackWrapper
|
var leftover: ItemStackWrapper
|
||||||
@ -352,7 +354,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
leftover = stack.copy()
|
leftover = stack.copy()
|
||||||
} else {
|
} else {
|
||||||
leftover = stack.copy().also {
|
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))
|
leftover = ItemStackWrapper(parent.insertItem(slot, leftover.stack, simulate))
|
||||||
|
|
||||||
if (oldCount != leftover.count && !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)
|
scan(slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,22 +375,22 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
return leftover
|
return leftover
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStack(id: UUID): ItemStackWrapper {
|
override fun get(id: UUID): ItemStackWrapper {
|
||||||
return index[id]?.stack ?: ItemStackWrapper.EMPTY
|
return index[id]?.stack ?: ItemStackWrapper.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): ItemStackWrapper {
|
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): ItemStackWrapper {
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
var amount = amount.floor()
|
|
||||||
|
|
||||||
if (!amount.isPositive)
|
if (!amount.isPositive)
|
||||||
return ItemStackWrapper.EMPTY
|
return ItemStackWrapper.EMPTY
|
||||||
|
|
||||||
val maxPossibleDemand = amount * OverdriveThatMatters.INSTANCE.ITEM_STORAGE().energyPerOperation
|
val maxPossibleDemand = ITEM_STORAGE.energyPerOperation * amount
|
||||||
val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true)
|
val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true)
|
||||||
|
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
var amount = amount
|
||||||
|
|
||||||
if (maxPossibleDemand != maxExtractEnergy) {
|
if (maxPossibleDemand != maxExtractEnergy) {
|
||||||
amount = (maxExtractEnergy / OverdriveThatMatters.INSTANCE.ITEM_STORAGE().energyPerOperation).floor()
|
amount = (maxExtractEnergy / ITEM_STORAGE.energyPerOperation).whole
|
||||||
}
|
}
|
||||||
|
|
||||||
val intAmount = amount.toLong()
|
val intAmount = amount.toLong()
|
||||||
@ -433,18 +435,18 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
return ItemStackWrapper.EMPTY
|
return ItemStackWrapper.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
copy.count = ImpreciseFraction(totalExtracted)
|
copy.count = totalExtracted.toBigInteger()
|
||||||
return copy
|
return copy
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStacks(): Collection<IStorageTuple<ItemStackWrapper>> {
|
override val stacks: Stream<IStorageTuple<ItemStackWrapper>> get() {
|
||||||
val listing = ArrayList<IStorageTuple<ItemStackWrapper>>(index.size)
|
val listing = ArrayList<IStorageTuple<ItemStackWrapper>>(index.size)
|
||||||
|
|
||||||
for (tuple in index.values) {
|
for (tuple in index.values) {
|
||||||
listing.add(StorageTuple(tuple.id, tuple.stack))
|
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.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.TranslatableComponent
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import net.minecraft.server.level.ServerLevel
|
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.MBlockEntities
|
||||||
import ru.dbotthepony.mc.otm.registry.MNames
|
import ru.dbotthepony.mc.otm.registry.MNames
|
||||||
import ru.dbotthepony.mc.otm.storage.*
|
import ru.dbotthepony.mc.otm.storage.*
|
||||||
|
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.HashSet
|
import kotlin.collections.HashSet
|
||||||
|
|
||||||
abstract class AbstractStorageImportExport<T>(
|
abstract class AbstractStorageImportExport<T>(
|
||||||
@ -190,17 +189,17 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
return stack
|
return stack
|
||||||
|
|
||||||
val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: 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
|
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)
|
if (simulate)
|
||||||
return leftover.stack
|
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
|
return leftover.stack
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +264,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
|
|
||||||
class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||||
AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_EXPORTER, blockPos, blockState),
|
AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_EXPORTER, blockPos, blockState),
|
||||||
IStorageListener<ItemStackWrapper> {
|
IStorageEventConsumer<ItemStackWrapper> {
|
||||||
override val defaultDisplayName: Component
|
override val defaultDisplayName: Component
|
||||||
get() = MACHINE_NAME
|
get() = MACHINE_NAME
|
||||||
|
|
||||||
@ -275,7 +274,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
|
|
||||||
private val relevantTuples = HashSet<UUID>()
|
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)) {
|
if (!filter.match(stack.item)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -283,7 +282,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
relevantTuples.add(id)
|
relevantTuples.add(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: ImpreciseFraction) {
|
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: BigInteger) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +295,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
|
|
||||||
val component = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return@ItemFilter
|
val component = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return@ItemFilter
|
||||||
|
|
||||||
for (tuple in component.getStacks()) {
|
for (tuple in component.stacks) {
|
||||||
addStack(tuple, component)
|
addStack(tuple, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +314,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
private val exportStacks: Stream<Pair<UUID, ItemStackWrapper>>
|
private val exportStacks: Stream<Pair<UUID, 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.getStack(it) }
|
return relevantTuples.stream().map { it to view[it] }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveAdditional(nbt: CompoundTag) {
|
override fun saveAdditional(nbt: CompoundTag) {
|
||||||
@ -353,9 +352,9 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
continue
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,7 +368,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
|
|
||||||
if (leftover.count != exportAmount) {
|
if (leftover.count != exportAmount) {
|
||||||
hit = true
|
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)
|
resolved.insertItem(lastSlot, stack.second.stack.also { it.count = exportAmount }, false)
|
||||||
energy.extractStepInner(ITEM_STORAGE.energyPerOperation, exportAmount, false)
|
energy.extractStepInner(ITEM_STORAGE.energyPerOperation, exportAmount, false)
|
||||||
break
|
break
|
||||||
@ -387,7 +386,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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 val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_EXPORTER}")
|
||||||
private const val INTERVAL = 5
|
private const val INTERVAL = 5
|
||||||
const val MAX_FILTERS = 6 * 3
|
const val MAX_FILTERS = 6 * 3
|
||||||
|
@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.capability
|
|||||||
|
|
||||||
import net.minecraftforge.energy.IEnergyStorage
|
import net.minecraftforge.energy.IEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
// IEnergyStorage for direct compat with Forge Energy
|
// IEnergyStorage for direct compat with Forge Energy
|
||||||
interface IMatteryEnergyStorage : IEnergyStorage {
|
interface IMatteryEnergyStorage : IEnergyStorage {
|
||||||
@ -212,3 +213,27 @@ fun IMatteryEnergyStorage.extractStepInner(base: ImpreciseFraction, multiplier:
|
|||||||
fun IMatteryEnergyStorage.extractStepOuter(base: ImpreciseFraction, multiplier: Int, simulate: Boolean): Int {
|
fun IMatteryEnergyStorage.extractStepOuter(base: ImpreciseFraction, multiplier: Int, simulate: Boolean): Int {
|
||||||
return (extractEnergyOuter(base * multiplier, simulate) / base).toInt()
|
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.IStorageStack
|
||||||
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface IItemMatteryDrive : IMatteryDrive<ItemStackWrapper> {
|
interface IItemMatteryDrive : IMatteryDrive<ItemStackWrapper> {
|
||||||
@ -25,19 +26,13 @@ interface IItemMatteryDrive : IMatteryDrive<ItemStackWrapper> {
|
|||||||
fun findItems(stack: ItemStack): IStorageTuple<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> {
|
interface IMatteryDrive<T : IStorageStack> : IStorageComponent<T> {
|
||||||
val uuid: UUID
|
val uuid: UUID
|
||||||
|
|
||||||
var isDirty: Boolean
|
var isDirty: Boolean
|
||||||
|
|
||||||
val storedCount: ImpreciseFraction
|
val storedCount: BigInteger
|
||||||
val driveCapacity: ImpreciseFraction
|
val driveCapacity: BigInteger
|
||||||
|
|
||||||
// not extending INBTSerializable to avoid serializing it as forgecaps
|
// not extending INBTSerializable to avoid serializing it as forgecaps
|
||||||
fun serializeNBT(): CompoundTag
|
fun serializeNBT(): CompoundTag
|
||||||
|
@ -1,21 +1,26 @@
|
|||||||
package ru.dbotthepony.mc.otm.capability.drive
|
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.Object2ObjectAVLTreeMap
|
||||||
|
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.Tag
|
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.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.ifHas
|
||||||
import ru.dbotthepony.mc.otm.set
|
import ru.dbotthepony.mc.otm.set
|
||||||
import ru.dbotthepony.mc.otm.storage.*
|
import ru.dbotthepony.mc.otm.storage.*
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
|
import java.util.stream.Stream
|
||||||
|
|
||||||
abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor(
|
abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor(
|
||||||
override var driveCapacity: ImpreciseFraction,
|
override var driveCapacity: BigInteger,
|
||||||
override val uuid: UUID = UUID.randomUUID(),
|
override val uuid: UUID = UUID.randomUUID(),
|
||||||
var maxDifferentStacks: Int = 0xFFFF
|
var maxDifferentStacks: Int = 0xFFFF
|
||||||
) : IMatteryDrive<T> {
|
) : IMatteryDrive<T> {
|
||||||
@ -34,13 +39,13 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
|||||||
var storedDifferentStacks = 0
|
var storedDifferentStacks = 0
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
override var storedCount = ImpreciseFraction.ZERO
|
override var storedCount: BigInteger = BigInteger.ZERO
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
override fun insertStack(stack: T, simulate: Boolean): T {
|
override fun insertStack(stack: T, simulate: Boolean): T {
|
||||||
val maxInsert = driveCapacity.minus(storedCount).coerceAtMost(stack.count)
|
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 key = stack.key()
|
||||||
val tuple = tuples[key]
|
val tuple = tuples[key]
|
||||||
@ -91,20 +96,18 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
|
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T {
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
var amount = amount
|
|
||||||
val get = tuplesByID[id] ?: return storageType.empty
|
val get = tuplesByID[id] ?: return storageType.empty
|
||||||
|
|
||||||
if (!storageType.fractional)
|
@Suppress("NAME_SHADOWING")
|
||||||
amount = amount.floor()
|
var amount = amount
|
||||||
|
|
||||||
if (!amount.isPositive)
|
if (!amount.isPositive)
|
||||||
amount = get.stack.maxStackSize ?: get.stack.count
|
amount = get.stack.maxStackSize ?: get.stack.count
|
||||||
|
|
||||||
amount = amount.coerceAtMost(get.stack.count)
|
amount = amount.coerceAtMost(get.stack.count)
|
||||||
|
|
||||||
if (amount <= ImpreciseFraction.ZERO)
|
if (amount <= BigInteger.ZERO)
|
||||||
return storageType.empty
|
return storageType.empty
|
||||||
|
|
||||||
val copy = get.stack.copy() as T
|
val copy = get.stack.copy() as T
|
||||||
@ -165,11 +168,11 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
|||||||
override fun deserializeNBT(nbt: CompoundTag) {
|
override fun deserializeNBT(nbt: CompoundTag) {
|
||||||
tuples.clear()
|
tuples.clear()
|
||||||
tuplesByID.clear()
|
tuplesByID.clear()
|
||||||
storedCount = ImpreciseFraction.ZERO
|
storedCount = BigInteger.ZERO
|
||||||
storedDifferentStacks = 0
|
storedDifferentStacks = 0
|
||||||
|
|
||||||
nbt.ifHas("capacity") {
|
nbt.ifHas("capacity") {
|
||||||
driveCapacity = ImpreciseFraction.deserializeNBT(it)
|
driveCapacity = BigInteger(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxDifferentStacks = nbt.getInt("max_different_stacks")
|
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
|
return tuplesByID[id]?.stack ?: storageType.empty
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStacks(): List<IStorageTuple<T>> {
|
override val stacks: Stream<IStorageTuple<T>> get() {
|
||||||
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }
|
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)
|
return listeners.add(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeListener(listener: IStorageListener<T>): Boolean {
|
override fun removeListener(listener: IStorageEventConsumer<T>): Boolean {
|
||||||
return listeners.remove(listener)
|
return listeners.remove(listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -28,13 +28,15 @@ import java.util.ArrayList
|
|||||||
* Why?
|
* Why?
|
||||||
*
|
*
|
||||||
* There are several reasons:
|
* 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 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 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
|
* 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"
|
* 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
|
* 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
|
* 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")
|
@Suppress("unused")
|
||||||
object DrivePool {
|
object DrivePool {
|
||||||
|
@ -8,20 +8,23 @@ import net.minecraft.world.item.Items
|
|||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
import net.minecraftforge.registries.RegistryManager
|
import net.minecraftforge.registries.RegistryManager
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
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.ImpreciseFraction
|
||||||
|
import ru.dbotthepony.mc.otm.core.serializeNBT
|
||||||
import ru.dbotthepony.mc.otm.set
|
import ru.dbotthepony.mc.otm.set
|
||||||
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
import ru.dbotthepony.mc.otm.storage.StorageStackType
|
import ru.dbotthepony.mc.otm.storage.StorageStackType
|
||||||
import ru.dbotthepony.mc.otm.storage.key
|
import ru.dbotthepony.mc.otm.storage.key
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
|
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
|
||||||
constructor(capacity: ImpreciseFraction, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks)
|
constructor(capacity: BigInteger, 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: BigInteger, uuid: UUID, max_different_stacks: Int) : super(capacity, uuid, max_different_stacks)
|
||||||
constructor(capacity: ImpreciseFraction, uuid: UUID) : super(capacity, uuid)
|
constructor(capacity: BigInteger, uuid: UUID) : super(capacity, uuid)
|
||||||
constructor(capacity: ImpreciseFraction) : super(capacity)
|
constructor(capacity: BigInteger) : super(capacity)
|
||||||
|
|
||||||
override val storageType: StorageStackType<ItemStackWrapper> = OverdriveThatMatters.INSTANCE.ITEM_STORAGE()
|
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")))
|
val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(tag.getString("item")))
|
||||||
|
|
||||||
if (item != null && item !== Items.AIR) {
|
if (item != null && item !== Items.AIR) {
|
||||||
val count = ImpreciseFraction.deserializeNBT(tag["count"])
|
val count = BigInteger(tag["count"])
|
||||||
val itemstack = ItemStack(item, 1)
|
val itemstack = ItemStack(item, 1)
|
||||||
itemstack.tag = tag["data"] as? CompoundTag
|
itemstack.tag = tag["data"] as? CompoundTag
|
||||||
return ItemStackWrapper(itemstack, copy = false).also { it.count = count }
|
return ItemStackWrapper(itemstack, copy = false).also { it.count = count }
|
||||||
@ -76,6 +79,6 @@ class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDri
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@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.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
|
||||||
import mekanism.api.math.MathUtils
|
|
||||||
import mekanism.common.content.qio.QIOFrequency
|
import mekanism.common.content.qio.QIOFrequency
|
||||||
import mekanism.common.content.qio.QIOFrequency.QIOItemTypeData
|
import mekanism.common.content.qio.QIOFrequency.QIOItemTypeData
|
||||||
import mekanism.common.lib.frequency.Frequency
|
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.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
|
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
|
||||||
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.toImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.toImpreciseFraction
|
||||||
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
|
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
|
||||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
||||||
import ru.dbotthepony.mc.otm.storage.*
|
import ru.dbotthepony.mc.otm.storage.*
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import java.util.stream.Stream
|
||||||
|
|
||||||
private val QIO_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, "item_storage")
|
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 index = Object2ObjectAVLTreeMap<UUID, QIOTuple>()
|
||||||
private val tracked = HashMap<HashedItem, 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
|
return index[id]?.stack ?: ItemStackWrapper.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStacks(): Collection<IStorageTuple<ItemStackWrapper>> {
|
override val stacks: Stream<IStorageTuple<ItemStackWrapper>> get() {
|
||||||
return ArrayList<IStorageTuple<ItemStackWrapper>>(index.size).also { it.addAll(index.values) }
|
return ArrayList<IStorageTuple<ItemStackWrapper>>(index.size).also { it.addAll(index.values) }.stream()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun insertStack(stack: ItemStackWrapper, simulate: Boolean): ItemStackWrapper {
|
override fun insertStack(stack: ItemStackWrapper, simulate: Boolean): ItemStackWrapper {
|
||||||
@ -81,11 +83,11 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
|||||||
}
|
}
|
||||||
|
|
||||||
val inserted = stack.copy()
|
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
|
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.
|
// 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.
|
||||||
|
|
||||||
@ -128,7 +130,7 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
|||||||
return copy
|
return copy
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addListener(listener: IStorageListener<ItemStackWrapper>): Boolean {
|
override fun addListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
|
||||||
if (!listeners.contains(listener)) {
|
if (!listeners.contains(listener)) {
|
||||||
listeners.add(listener)
|
listeners.add(listener)
|
||||||
return true
|
return true
|
||||||
@ -137,7 +139,7 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeListener(listener: IStorageListener<ItemStackWrapper>): Boolean {
|
override fun removeListener(listener: IStorageEventConsumer<ItemStackWrapper>): Boolean {
|
||||||
return listeners.remove(listener)
|
return listeners.remove(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,14 +151,14 @@ private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<I
|
|||||||
|
|
||||||
if (local.stack.count.toLong() != value.count) {
|
if (local.stack.count.toLong() != value.count) {
|
||||||
val oldCount = local.stack.count
|
val oldCount = local.stack.count
|
||||||
local.stack.count = value.count.toImpreciseFraction()
|
local.stack.count = value.count.toBigInteger()
|
||||||
|
|
||||||
for (listener in listeners) {
|
for (listener in listeners) {
|
||||||
listener.changeStack(local, oldCount)
|
listener.changeStack(local, oldCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
index[tuple.id] = tuple
|
||||||
|
|
||||||
for (listener in listeners) {
|
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 times(other: Long): ImpreciseFraction = times(ImpreciseFraction(other))
|
||||||
operator fun div(other: Long): ImpreciseFraction = div(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 {
|
operator fun unaryMinus(): ImpreciseFraction {
|
||||||
return ImpreciseFraction(-whole, -decimal)
|
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.server.level.ServerLevel
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
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.addPreWorldTicker
|
||||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
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.core.ImpreciseFraction
|
||||||
import ru.dbotthepony.mc.otm.ifHas
|
import ru.dbotthepony.mc.otm.ifHas
|
||||||
import ru.dbotthepony.mc.otm.set
|
import ru.dbotthepony.mc.otm.set
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class PortableCondensationDriveItem(capacity: Int) :
|
class PortableCondensationDriveItem(capacity: Int) :
|
||||||
Item(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
|
Item(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
|
||||||
val capacity: ImpreciseFraction
|
val capacity: BigInteger = capacity.toBigInteger()
|
||||||
|
|
||||||
init {
|
|
||||||
this.capacity = ImpreciseFraction(capacity)
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class DriveCapability(private val stack: ItemStack) : ICapabilityProvider {
|
private inner class DriveCapability(private val stack: ItemStack) : ICapabilityProvider {
|
||||||
private var uuid: UUID? = null
|
private var uuid: UUID? = null
|
||||||
@ -48,10 +45,10 @@ class PortableCondensationDriveItem(capacity: Int) :
|
|||||||
|
|
||||||
val uuid = uuid
|
val uuid = uuid
|
||||||
|
|
||||||
DrivePool.get(uuid!!, { tag: CompoundTag? ->
|
return@of DrivePool.get(uuid!!, { tag: CompoundTag? ->
|
||||||
val drive = ItemMatteryDrive(capacity, uuid)
|
val drive = ItemMatteryDrive(capacity, uuid)
|
||||||
drive.deserializeNBT(tag!!)
|
drive.deserializeNBT(tag!!)
|
||||||
drive
|
return@get drive
|
||||||
}, { ItemMatteryDrive(capacity, uuid) })
|
}, { 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.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
|
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
|
||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
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.readImpreciseFraction
|
||||||
import ru.dbotthepony.mc.otm.core.writeImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.writeImpreciseFraction
|
||||||
import ru.dbotthepony.mc.otm.menu.FormattingHelper
|
import ru.dbotthepony.mc.otm.menu.FormattingHelper
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||||
import ru.dbotthepony.mc.otm.orNull
|
import ru.dbotthepony.mc.otm.orNull
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
|
||||||
internal var building = false
|
internal var building = false
|
||||||
@ -174,7 +176,7 @@ fun canDecompose(stack: ItemStack): Boolean {
|
|||||||
|
|
||||||
return canDecompose(stack.item) &&
|
return canDecompose(stack.item) &&
|
||||||
(stack.getCapability(MatteryCapability.MATTER).orNull()?.storedMatter ?: ImpreciseFraction.ZERO).isZero &&
|
(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
|
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()
|
val drive = stack.getCapability(MatteryCapability.DRIVE).orNull()
|
||||||
|
|
||||||
if (drive != null && drive.storageType === OverdriveThatMatters.INSTANCE.ITEM_STORAGE()) {
|
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)
|
val tuple = getMatterValue(item.stack.stack, level + 1)
|
||||||
|
|
||||||
if (!tuple.isZero) {
|
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.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.IStorageComponent
|
||||||
import ru.dbotthepony.mc.otm.storage.IStorageListener
|
import ru.dbotthepony.mc.otm.storage.IStorageEventConsumer
|
||||||
import ru.dbotthepony.mc.otm.storage.IStorageView
|
import ru.dbotthepony.mc.otm.storage.IStorageProvider
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.function.Supplier
|
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.
|
* 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)
|
data class NetworkedItem constructor(val id: Int, val stack: ItemStack, val upstreamId: UUID? = null)
|
||||||
|
|
||||||
protected var nextStackID = 0
|
protected var nextStackID = 0
|
||||||
@ -230,8 +231,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: IStorageView<ItemStackWrapper>) = addObject(stack.stack, id)
|
override fun addStack(stack: ItemStackWrapper, id: UUID, provider: IStorageProvider<ItemStackWrapper>) = addObject(stack.stack, id)
|
||||||
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: ImpreciseFraction) = changeObject(id, stack.count.toInt())
|
override fun changeStack(stack: ItemStackWrapper, id: UUID, oldCount: BigInteger) = changeObject(id, stack.count.toInt())
|
||||||
|
|
||||||
protected fun network(fn: () -> Any) {
|
protected fun network(fn: () -> Any) {
|
||||||
if (!remote) {
|
if (!remote) {
|
||||||
@ -310,13 +311,13 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
|
|||||||
else
|
else
|
||||||
Math.max(1, state.stack.maxStackSize / 2)
|
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) {
|
if (!extracted.isEmpty) {
|
||||||
val (_, remaining) = menu.quickMoveToInventory(extracted.stack, false)
|
val (_, remaining) = menu.quickMoveToInventory(extracted.stack, false)
|
||||||
|
|
||||||
if (remaining.count != extracted.count.toInt()) {
|
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
|
else
|
||||||
(state.stack.count / 2).coerceAtMost(state.stack.maxStackSize / 2).coerceAtLeast(1)
|
(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
|
menu.carried = extracted.stack
|
||||||
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
|
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
|
||||||
menu.setRemoteCarried(menu.carried.copy())
|
menu.setRemoteCarried(menu.carried.copy())
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage
|
package ru.dbotthepony.mc.otm.storage
|
||||||
|
|
||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.stream.Stream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a stack in storage system.
|
* Represents a stack in storage system.
|
||||||
@ -19,51 +21,36 @@ interface IStorageStack {
|
|||||||
fun copy(): IStorageStack
|
fun copy(): IStorageStack
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Despite count being [ImpreciseFraction], far not all items can be "fraction"
|
* Size of this storage stack
|
||||||
* into pieces (e.g. ItemStacks).
|
|
||||||
*
|
*
|
||||||
* Consult [StorageStackType.fractional] to see if item has actual fractions.
|
* This is overriden in subclasses
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
var count: ImpreciseFraction
|
var count: BigInteger
|
||||||
val isEmpty: Boolean
|
val isEmpty: Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return max stack size for this stack object,
|
* @return max stack size for this stack object,
|
||||||
* null if unlimited (default)
|
* null if unlimited (default)
|
||||||
*/
|
*/
|
||||||
val maxStackSize: ImpreciseFraction? get() = null
|
val maxStackSize: BigInteger? get() = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increase [count] by [amount]
|
* Increase [count] by [amount]
|
||||||
*/
|
*/
|
||||||
fun grow(amount: ImpreciseFraction) {
|
fun grow(amount: BigInteger) {
|
||||||
count += amount
|
count += amount
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrease [count] by [amount]
|
* Decrease [count] by [amount]
|
||||||
*/
|
*/
|
||||||
fun shrink(amount: ImpreciseFraction) {
|
fun shrink(amount: BigInteger) {
|
||||||
count -= amount
|
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 {
|
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>
|
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.
|
* Inserts an item into system.
|
||||||
* @return leftover, might equal to [stack] if no items were inserted
|
* @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
|
fun insertStack(stack: T, simulate: Boolean): T
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
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.
|
||||||
*/
|
*/
|
||||||
fun getStack(id: UUID): T
|
operator fun get(id: UUID): T
|
||||||
|
|
||||||
|
val stacks: Stream<IStorageTuple<T>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If tuple does not exist, returns empty stack
|
* 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
|
* @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: ImpreciseFraction, simulate: Boolean): T
|
fun extractStack(id: UUID, amount: BigInteger, 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 addListenerAuto(listener: IStorageEventConsumer<T>): Boolean {
|
||||||
* 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 {
|
|
||||||
if (addListener(listener)) {
|
if (addListener(listener)) {
|
||||||
for (stack in getStacks()) {
|
for (stack in stacks) {
|
||||||
listener.addStack(stack.stack, stack.id, this)
|
listener.addStack(stack.stack, stack.id, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +137,9 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeListenerAuto(listener: IStorageListener<T>): Boolean {
|
fun removeListenerAuto(listener: IStorageEventConsumer<T>): Boolean {
|
||||||
if (removeListener(listener)) {
|
if (removeListener(listener)) {
|
||||||
for (stack in getStacks()) {
|
for (stack in stacks) {
|
||||||
listener.removeStack(stack.stack, stack.id)
|
listener.removeStack(stack.stack, stack.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,33 +150,16 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IStorageListener<T : IStorageStack> {
|
fun <T : IStorageStack> IStorageEventConsumer<T>.changeStack(tuple: IStorageTuple<T>, oldCount: BigInteger) {
|
||||||
/**
|
changeStack(tuple.stack, tuple.id, oldCount)
|
||||||
* Fired on whenever an object is added (to listener) we subscribed to
|
}
|
||||||
*/
|
|
||||||
fun addStack(stack: T, id: UUID, provider: IStorageView<T>)
|
|
||||||
|
|
||||||
fun addStack(tuple: IStorageTuple<T>, provider: IStorageView<T>) {
|
fun <T : IStorageStack> IStorageEventConsumer<T>.addStack(tuple: IStorageTuple<T>, provider: IStorageProvider<T>) {
|
||||||
addStack(tuple.stack, tuple.id, provider)
|
addStack(tuple.stack, tuple.id, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun <T : IStorageStack> IStorageEventConsumer<T>.removeStack(tuple: IStorageTuple<T>) {
|
||||||
* Fired on whenever an object is changes on listener we subscribed to
|
removeStack(tuple.stack, tuple.id)
|
||||||
*/
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IStorageTuple<T : IStorageStack> {
|
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>
|
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)
|
* 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 add(identity: IStorage<T>)
|
||||||
fun remove(identity: IStorage<T>)
|
fun remove(identity: IStorage<T>)
|
||||||
fun contains(identity: IStorage<T>): Boolean
|
fun contains(identity: IStorage<T>): Boolean
|
||||||
|
@ -6,6 +6,8 @@ import net.minecraftforge.registries.ForgeRegistries
|
|||||||
import net.minecraftforge.registries.ForgeRegistry
|
import net.minecraftforge.registries.ForgeRegistry
|
||||||
import org.jetbrains.annotations.ApiStatus
|
import org.jetbrains.annotations.ApiStatus
|
||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
import ru.dbotthepony.mc.otm.core.isPositive
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* constructors always copy its input.
|
* constructors always copy its input.
|
||||||
@ -21,8 +23,7 @@ class ItemStackWrapper : IStorageStack {
|
|||||||
val registryName get() = item.item.registryName!!
|
val registryName get() = item.item.registryName!!
|
||||||
private val hash: Int
|
private val hash: Int
|
||||||
|
|
||||||
override var count: ImpreciseFraction
|
override var count: BigInteger
|
||||||
set(value) { field = value.floor() }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [copy] as false is used internally for fast index construction, do not specify
|
* [copy] as false is used internally for fast index construction, do not specify
|
||||||
@ -36,7 +37,7 @@ class ItemStackWrapper : IStorageStack {
|
|||||||
this.item = item
|
this.item = item
|
||||||
}
|
}
|
||||||
|
|
||||||
this.count = ImpreciseFraction(item.count)
|
this.count = BigInteger.valueOf(item.count.toLong())
|
||||||
|
|
||||||
if (copy) {
|
if (copy) {
|
||||||
this.item.count = 1
|
this.item.count = 1
|
||||||
@ -72,7 +73,7 @@ class ItemStackWrapper : IStorageStack {
|
|||||||
return hash * 31 + count.hashCode()
|
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
|
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
|
* Speculated energy required per operation on stack with size of 1
|
||||||
*/
|
*/
|
||||||
open val energyPerOperation: ImpreciseFraction,
|
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 {
|
open fun energyPerOperation(stack: T): ImpreciseFraction {
|
||||||
return stack.count * energyPerOperation
|
return energyPerOperation * stack.count
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun energyPerStorage(stack: T) = energyPerOperation(stack)
|
open fun energyPerStorage(stack: T) = energyPerOperation(stack)
|
||||||
@ -56,10 +41,9 @@ object StorageRegistry {
|
|||||||
fun <T : IStorageStack> register(
|
fun <T : IStorageStack> register(
|
||||||
identity: Class<T>,
|
identity: Class<T>,
|
||||||
empty: T,
|
empty: T,
|
||||||
energyPerOperation: ImpreciseFraction,
|
energyPerOperation: ImpreciseFraction
|
||||||
fractional: Boolean
|
|
||||||
): StorageStackType<T> {
|
): StorageStackType<T> {
|
||||||
return register(StorageStackType(identity, empty, energyPerOperation, fractional)) as StorageStackType<T>
|
return register(StorageStackType(identity, empty, energyPerOperation)) as StorageStackType<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage
|
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 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.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.*
|
||||||
|
import java.util.stream.Stream
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
class RemoteTuple<T : IStorageStack>(val obj: T, val remote_id: UUID, val provider: IStorageView<T>, val local: LocalTuple<T>) {
|
class RemoteTuple<T : IStorageStack>(
|
||||||
fun extract(amount: ImpreciseFraction, simulate: Boolean): T {
|
override val stack: T,
|
||||||
return provider.extractStack(remote_id, amount, simulate)
|
override val id: UUID,
|
||||||
}
|
val provider: IStorageProvider<T>,
|
||||||
|
val local: LocalTuple<T>
|
||||||
fun extractCount(amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
) : IStorageTuple<T> {
|
||||||
return provider.extractStackCount(remote_id, amount, simulate)
|
fun extract(amount: BigInteger, simulate: Boolean): T {
|
||||||
|
return provider.extractStack(id, amount, simulate)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
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 {
|
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
|
override val storageType: StorageStackType<T> = type
|
||||||
|
|
||||||
// удаленный UUID -> Кортеж
|
// удаленный UUID -> Кортеж
|
||||||
protected val remoteByUUID = HashMap<UUID, RemoteTuple<T>>()
|
protected val remoteByUUID: MutableMap<UUID, RemoteTuple<T>> = HashMap()
|
||||||
|
|
||||||
// локальный UUID -> Локальный кортеж
|
// локальный 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 для скорости работы
|
// ArrayList для скорости работы
|
||||||
protected val listeners = ArrayList<IStorageListener<T>>()
|
protected val listeners: MutableSet<IStorageEventConsumer<T>> = ObjectArraySet()
|
||||||
protected val set = ObjectArraySet<Any>()
|
protected val set: MutableSet<IStorage<T>> = ObjectArraySet()
|
||||||
protected val consumers = ArrayList<IStorageConsumer<T>>()
|
protected val consumers: MutableSet<IStorageAcceptor<T>> = ObjectArraySet()
|
||||||
|
|
||||||
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 (set.add(identity)) {
|
||||||
if (identity is IStorageView<T>) {
|
if (identity is IStorageProvider<T>) {
|
||||||
identity.addListenerAuto(this)
|
identity.addListenerAuto(this)
|
||||||
} else if (identity is IStorageTrigger<T>) {
|
} else if (identity is IStorageEventProducer<T>) {
|
||||||
identity.addListener(this)
|
identity.addListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (identity is IStorageConsumer<T>) {
|
if (identity is IStorageAcceptor<T>) {
|
||||||
consumers.add(identity)
|
consumers.add(identity)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,13 +71,13 @@ 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 (set.remove(identity)) {
|
||||||
if (identity is IStorageView<T>) {
|
if (identity is IStorageProvider<T>) {
|
||||||
identity.removeListenerAuto(this)
|
identity.removeListenerAuto(this)
|
||||||
} else if (identity is IStorageTrigger<T>) {
|
} else if (identity is IStorageEventProducer<T>) {
|
||||||
identity.removeListener(this)
|
identity.removeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (identity is IStorageConsumer<T>) {
|
if (identity is IStorageAcceptor<T>) {
|
||||||
consumers.remove(identity)
|
consumers.remove(identity)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +89,7 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
|||||||
return set.contains(identity)
|
return set.contains(identity)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addListener(listener: IStorageListener<T>): Boolean {
|
override fun addListener(listener: IStorageEventConsumer<T>): Boolean {
|
||||||
if (!listeners.contains(listener)) {
|
if (!listeners.contains(listener)) {
|
||||||
listeners.add(listener)
|
listeners.add(listener)
|
||||||
return true
|
return true
|
||||||
@ -96,31 +98,31 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeListener(listener: IStorageListener<T>): Boolean {
|
override fun removeListener(listener: IStorageEventConsumer<T>): Boolean {
|
||||||
return listeners.remove(listener)
|
return listeners.remove(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStack(id: UUID): T {
|
override fun get(id: UUID): T {
|
||||||
return localByUUID[id]?.stack ?: this.storageType.empty
|
return localByUUID[id]?.stack ?: this.storageType.empty
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStacks(): List<IStorageTuple<T>> {
|
override val stacks: Stream<IStorageTuple<T>> get() {
|
||||||
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }
|
return ArrayList<IStorageTuple<T>>(tuples.size).also { it.addAll(tuples.values) }.stream()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@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" }
|
check(!remoteByUUID.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>? = tuples[key]
|
||||||
var oldCount = ImpreciseFraction.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, UUID.randomUUID(), ArrayList<RemoteTuple<T>>(1))
|
||||||
localByUUID[local.id] = local
|
localByUUID[local.id] = local
|
||||||
tuples[key as T] = local
|
tuples[key] = local
|
||||||
} else {
|
} else {
|
||||||
oldCount = local.stack.count
|
oldCount = local.stack.count
|
||||||
local.stack.grow(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)
|
require(stack.count.isPositive)
|
||||||
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id")
|
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id")
|
||||||
|
|
||||||
val diff = stack.count - tuple.obj.count
|
val diff = stack.count - tuple.stack.count
|
||||||
tuple.obj.count = stack.count
|
tuple.stack.count = stack.count
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING") val oldCount = tuple.local.stack.count
|
@Suppress("NAME_SHADOWING") val oldCount = tuple.local.stack.count
|
||||||
tuple.local.stack.grow(diff)
|
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) {
|
override fun removeStack(stack: T, id: UUID) {
|
||||||
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id")
|
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)
|
tuple.local.tuples.remove(tuple)
|
||||||
|
|
||||||
remoteByUUID.remove(id)
|
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
|
val b = tuple.local.tuples.size == 0
|
||||||
|
|
||||||
if (a || b) {
|
if (a || b) {
|
||||||
@ -194,8 +196,8 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
|
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T {
|
||||||
if (amount.isZero)
|
if (!amount.isPositive)
|
||||||
return this.storageType.empty
|
return this.storageType.empty
|
||||||
|
|
||||||
@Suppress("name_shadowing")
|
@Suppress("name_shadowing")
|
||||||
@ -205,18 +207,16 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
|||||||
if (tuple == null || amount.isZero)
|
if (tuple == null || amount.isZero)
|
||||||
return this.storageType.empty
|
return this.storageType.empty
|
||||||
|
|
||||||
if (!storageType.fractional)
|
|
||||||
amount = amount.floor()
|
|
||||||
|
|
||||||
if (!amount.isPositive)
|
if (!amount.isPositive)
|
||||||
amount = tuple.stack.maxStackSize ?: tuple.stack.count
|
amount = tuple.stack.maxStackSize ?: tuple.stack.count
|
||||||
|
|
||||||
val toExtract = tuple.stack.count.coerceAtMost(amount)
|
val toExtract = tuple.stack.count.coerceAtMost(amount)
|
||||||
var extracted = ImpreciseFraction.ZERO
|
var extracted = BigInteger.ZERO
|
||||||
val copy = tuple.stack.copy() as T
|
val copy = tuple.stack.copy() as T
|
||||||
|
|
||||||
for (remote_tuple in tuple.tuples.let { Array(it.size) { i -> it[i] } }) {
|
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)
|
if (extracted >= toExtract)
|
||||||
break
|
break
|
||||||
@ -238,8 +238,8 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
|||||||
override val storageType: StorageStackType<T>
|
override val storageType: StorageStackType<T>
|
||||||
get() = parent.storageType
|
get() = parent.storageType
|
||||||
|
|
||||||
override fun addListener(listener: IStorageListener<T>) = parent.addListener(listener)
|
override fun addListener(listener: IStorageEventConsumer<T>) = parent.addListener(listener)
|
||||||
override fun removeListener(listener: IStorageListener<T>) = parent.removeListener(listener)
|
override fun removeListener(listener: IStorageEventConsumer<T>) = parent.removeListener(listener)
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
override fun insertStack(stack: T, simulate: Boolean): T {
|
override fun insertStack(stack: T, simulate: Boolean): T {
|
||||||
@ -273,7 +273,7 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
|||||||
@Suppress("name_shadowing")
|
@Suppress("name_shadowing")
|
||||||
val stack = stack.copy() as T
|
val stack = stack.copy() as T
|
||||||
val oldCount = stack.count
|
val oldCount = stack.count
|
||||||
stack.count = extracted / storageType.energyPerOperation
|
stack.count = (extracted / storageType.energyPerOperation).whole
|
||||||
val diff = oldCount - stack.count
|
val diff = oldCount - stack.count
|
||||||
val newRequired = storageType.energyPerOperation * stack.count
|
val newRequired = storageType.energyPerOperation * stack.count
|
||||||
val newExtracted = energy.extractEnergyInner(newRequired, true)
|
val newExtracted = energy.extractEnergyInner(newRequired, true)
|
||||||
@ -291,7 +291,7 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
val requiredNew = (stack.count - leftover.count) * storageType.energyPerOperation
|
val requiredNew = storageType.energyPerOperation * (stack.count - leftover.count)
|
||||||
energy.extractEnergyInner(requiredNew, false)
|
energy.extractEnergyInner(requiredNew, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,9 +302,9 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
|||||||
return stack
|
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 required = storageType.energyPerOperation * amount
|
||||||
val energy = energyProvider.invoke()
|
val energy = energyProvider.invoke()
|
||||||
val extracted = energy.extractEnergyInner(required, true)
|
val extracted = energy.extractEnergyInner(required, true)
|
||||||
@ -324,7 +324,7 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
|||||||
if (extractedStack.count == amount) {
|
if (extractedStack.count == amount) {
|
||||||
energy.extractEnergyInner(required, false)
|
energy.extractEnergyInner(required, false)
|
||||||
} else {
|
} 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")
|
@Suppress("name_shadowing")
|
||||||
val amount = required / storageType.energyPerOperation
|
val amount = (required / storageType.energyPerOperation).whole
|
||||||
val extractedStack = parent.extractStack(id, amount, simulate)
|
val extractedStack = parent.extractStack(id, amount, simulate)
|
||||||
|
|
||||||
if (extractedStack.isEmpty) {
|
if (extractedStack.isEmpty) {
|
||||||
@ -340,13 +340,13 @@ open class PoweredComponent<T : IStorageStack>(open val parent: IStorageComponen
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
energy.extractEnergyInner(extractedStack.count * storageType.energyPerOperation, false)
|
energy.extractEnergyInner(storageType.energyPerOperation * extractedStack.count, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return extractedStack
|
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: 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: IStorageView<T>) = parent.addStack(stack, id, provider)
|
override fun addStack(stack: T, id: UUID, provider: IStorageProvider<T>) = parent.addStack(stack, id, provider)
|
||||||
override fun changeStack(stack: T, id: UUID, oldCount: ImpreciseFraction) = parent.changeStack(stack, id, oldCount)
|
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 removeStack(stack: T, id: UUID) = parent.removeStack(stack, id)
|
||||||
|
|
||||||
override fun add(identity: IStorage<T>) = parent.add(identity)
|
override fun add(identity: IStorage<T>) = parent.add(identity)
|
||||||
|
Loading…
Reference in New Issue
Block a user