From 87e2c8d1d8d523e36512f96d542947f516ad5684 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 10 Jun 2023 20:18:21 +0700 Subject: [PATCH] Update matter interface to match energy one, add profiled matter storage Add weighted average to profiled storage to make "transferred last second" display less stiff --- .../dbotthepony/mc/otm/GlobalEventHandler.kt | 3 +- .../entity/matter/MatterBottlerBlockEntity.kt | 13 +- .../matter/MatterCapacitorBankBlockEntity.kt | 4 +- .../matter/MatterDecomposerBlockEntity.kt | 9 +- .../matter/MatterReconstructorBlockEntity.kt | 9 +- .../matter/MatterRecyclerBlockEntity.kt | 9 +- .../matter/MatterReplicatorBlockEntity.kt | 15 +- .../otm/capability/AbstractProfiledStorage.kt | 206 ++++++++++++++++++ .../energy/ProfiledEnergyStorage.kt | 158 +------------- .../otm/capability/matter/IMatterStorage.kt | 37 +++- .../capability/matter/MatterStorageImpl.kt | 14 -- .../matter/ProfiledMatterStorage.kt | 45 ++++ .../screen/matter/MatterBottlerScreen.kt | 3 +- .../screen/matter/MatterDecomposerScreen.kt | 3 +- .../matter/MatterReconstructorScreen.kt | 3 +- .../screen/matter/MatterRecyclerScreen.kt | 3 +- .../screen/matter/MatterReplicatorScreen.kt | 3 +- .../widget/HorizontalPowerGaugePanel.kt | 7 +- .../client/screen/widget/MatterGaugePanel.kt | 62 ++++++ .../client/screen/widget/PowerGaugePanel.kt | 22 +- .../mc/otm/graph/matter/MatterGraph.kt | 6 +- .../mc/otm/menu/matter/MatterBottlerMenu.kt | 8 +- .../otm/menu/matter/MatterDecomposerMenu.kt | 6 +- .../menu/matter/MatterReconstructorMenu.kt | 6 +- .../mc/otm/menu/matter/MatterRecyclerMenu.kt | 6 +- .../otm/menu/matter/MatterReplicatorMenu.kt | 6 +- .../mc/otm/menu/matter/MatterScannerMenu.kt | 4 +- .../mc/otm/menu/tech/AndroidStationMenu.kt | 4 +- .../mc/otm/menu/tech/BatteryBankMenu.kt | 7 +- .../mc/otm/menu/tech/ChemicalGeneratorMenu.kt | 5 +- .../mc/otm/menu/tech/EnergyServoMenu.kt | 5 +- .../mc/otm/menu/tech/PlatePressMenu.kt | 4 +- .../menu/widget/ProfiledEnergyGaugeWidget.kt | 44 ---- .../menu/widget/ProfiledLevelGaugeWidget.kt | 62 ++++++ 34 files changed, 495 insertions(+), 306 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/ProfiledMatterStorage.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledEnergyGaugeWidget.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt index 8eaa30141..c290f27f9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt @@ -15,6 +15,7 @@ import net.minecraftforge.event.server.ServerStoppedEvent import net.minecraftforge.event.server.ServerStoppingEvent import net.minecraftforge.fml.loading.FMLLoader import org.apache.logging.log4j.LogManager +import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.core.util.IConditionalTickable @@ -149,7 +150,7 @@ fun onServerTick(event: ServerTickEvent) { postServerTick.tick() // чтоб не плодить кучу подписчиков, вызовем напрямую отсюда Abstract6Graph.tick() - ProfiledEnergyStorage.onServerPostTick() + AbstractProfiledStorage.onServerPostTick() } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt index 812c7045d..0cb9a6b8f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt @@ -21,6 +21,7 @@ import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.graph.matter.MatterGraph @@ -99,11 +100,11 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } }) - val matter: MatterStorageImpl = object : MatterStorageImpl(this::setChangedLight, FlowDirection.BI_DIRECTIONAL, ::CAPACITY) { + val matter: ProfiledMatterStorage = ProfiledMatterStorage(object : MatterStorageImpl(this::setChangedLight, FlowDirection.BI_DIRECTIONAL, ::CAPACITY) { override val matterFlow: FlowDirection get() { return if (this@MatterBottlerBlockEntity.isBottling) FlowDirection.INPUT else FlowDirection.OUTPUT } - } + }) val matterNode = SimpleMatterNode(matter = matter) @@ -232,7 +233,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : energy.extractEnergy(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE, false) capability.receiveMatter(matter, false) - this.matter.extractMatterInner(matter, false) + this.matter.extractMatter(matter, false) if (capability.missingMatter.isZero) { for (i in 3..5) { @@ -256,7 +257,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : this.energy.extractEnergy(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE,false) capability.extractMatter(matter, false) - this.matter.receiveMatterInner(matter, false) + this.matter.receiveMatter(matter, false) if (capability.storedMatter.isZero) { for (i in 2 downTo 0) { @@ -275,9 +276,9 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } if (!isBottling && !matter.storedMatter.isZero && graph != null) { - val diff = matter.extractMatterInner(matter.storedMatter, true) + val diff = matter.extractMatter(matter.storedMatter, true) val diff2 = graph.receiveMatter(diff, true) - matter.extractMatterInner(diff2, false) + matter.extractMatter(diff2, false) graph.receiveMatter(diff2, false) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt index cc597834f..ba365952a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt @@ -70,7 +70,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) for (stack in container) { if (!stack.isEmpty) { stack.getCapability(MatteryCapability.MATTER).ifPresent { - val diff = it.receiveMatter(howMuch, simulate) + val diff = it.receiveMatterChecked(howMuch, simulate) summ += diff howMuch -= diff } @@ -99,7 +99,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) for (stack in container) { if (!stack.isEmpty) { stack.getCapability(MatteryCapability.MATTER).ifPresent { - val diff = it.extractMatter(howMuch, simulate) + val diff = it.extractMatterChecked(howMuch, simulate) summ += diff howMuch -= diff } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt index 359024ca2..987166ca1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt @@ -16,6 +16,7 @@ import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.config.ConciseBalanceValues import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.MatteryContainer @@ -125,7 +126,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) savetables.stateful(::energy, ENERGY_KEY) } - val matter = MatterStorageImpl(::setChangedLight, FlowDirection.OUTPUT, ::CAPACITY) + val matter = ProfiledMatterStorage(MatterStorageImpl(::setChangedLight, FlowDirection.OUTPUT, ::CAPACITY)) val matterNode = SimpleMatterNode(matter = matter) init { @@ -172,7 +173,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) return Status.SUCCESS } - job.matterValue -= matter.receiveMatterInner(job.matterValue, false) + job.matterValue -= matter.receiveMatter(job.matterValue, false) if (job.matterValue.isPositive) { return Status.FAILURE_MATTER @@ -215,10 +216,10 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) val grid = matterNode.graph as MatterGraph? ?: return if (!matter.storedMatter.isZero) { - val diff = matter.extractMatterInner(matter.storedMatter, true) + val diff = matter.extractMatter(matter.storedMatter, true) val diff2 = grid.receiveMatter(diff, true) - matter.extractMatterInner(diff2, false) + matter.extractMatter(diff2, false) grid.receiveMatter(diff2, false) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt index 65f5b559b..6f09ba35c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt @@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage import ru.dbotthepony.mc.otm.capability.matter.IPatternState import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.config.ConciseBalanceValues import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.MatteryContainer @@ -54,7 +55,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState) var isUnableToProcess = false private set - val matter = MatterStorageImpl(::setChangedLight, FlowDirection.INPUT, ::CAPACITY) + val matter = ProfiledMatterStorage(MatterStorageImpl(::setChangedLight, FlowDirection.INPUT, ::CAPACITY)) val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::setChangedLight, ENERGY_VALUES)) val matterNode = object : MatterNode() { @@ -232,12 +233,12 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState) if (graph != null) { val toDrain = (matterPerTick * EXTRACT_TICKS.coerceAtMost(item.damageValue) - matter.storedMatter).coerceAtLeast(Decimal.ZERO).coerceAtMost(matter.missingMatter) - matter.receiveMatterInner(graph.extractMatter(toDrain, false), false) + matter.receiveMatter(graph.extractMatter(toDrain, false), false) } } val toDrain = matterPerTick * (progressPerTick / this.progressPerTick) - val drain = matter.extractMatterInner(toDrain, true) + val drain = matter.extractMatter(toDrain, true) if (!drain.isPositive) { isUnableToProcess = true return @@ -253,7 +254,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState) repairProgress += progressPerTick energy.extractEnergy(ENERGY_CONSUMPTION * (progressPerTick / this.progressPerTick), false) - matter.extractMatterInner(matterPerTick * (progressPerTick / this.progressPerTick), false) + matter.extractMatter(matterPerTick * (progressPerTick / this.progressPerTick), false) if (repairProgress >= 1.0) { item.damageValue = (item.damageValue - repairProgress.toInt()).coerceAtLeast(0) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt index 6bae9450c..46d3dddec 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt @@ -18,6 +18,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.core.math.Decimal @@ -62,7 +63,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) } } - val matter = MatterStorageImpl(::matterLevelUpdated, FlowDirection.OUTPUT, ::CAPACITY) + val matter = ProfiledMatterStorage(MatterStorageImpl(::matterLevelUpdated, FlowDirection.OUTPUT, ::CAPACITY)) val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer) val matterNode = SimpleMatterNode(matter = matter) @@ -130,12 +131,12 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) if (receive.isZero) return Status.SUCCESS - val received = matter.receiveMatterInner(receive, true) + val received = matter.receiveMatter(receive, true) if (receive != received) return Status.FAILURE_MATTER - matter.receiveMatterInner(receive, false) + matter.receiveMatter(receive, false) job.totalMatter -= received return Status.SUCCESS } @@ -147,7 +148,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) val received = graph.receiveMatter(matter.storedMatter, false) if (!received.isZero) { - matter.extractMatterInner(received, false) + matter.extractMatter(received, false) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt index 494df7e09..354ea52ba 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt @@ -20,6 +20,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IPatternState import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl import ru.dbotthepony.mc.otm.capability.matter.PatternState +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.capability.matter.ReplicationTask import ru.dbotthepony.mc.otm.config.ConciseBalanceValues import ru.dbotthepony.mc.otm.container.HandlerFilter @@ -101,7 +102,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::powerLevelUpdated, ENERGY_VALUES)) - val matter = MatterStorageImpl(::matterLevelUpdated, FlowDirection.INPUT, ::MATTER_CAPACITY) + val matter = ProfiledMatterStorage(MatterStorageImpl(::matterLevelUpdated, FlowDirection.INPUT, ::MATTER_CAPACITY)) val container = MatteryContainer(::itemContainerUpdated, 5).also(::addDroppableContainer) val energyConfig = ConfigurableEnergy(energy) @@ -217,12 +218,12 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: ReplicatorJob): Status { val drainPerTick = job.matterPerTick * ticksAdvanced - if (matter.extractMatterInner(drainPerTick, true) < drainPerTick) { + if (matter.extractMatter(drainPerTick, true) < drainPerTick) { // в машине недостаточно материи if (drainPerTick > matter.maxStoredMatter) { // в тик требуется больше материи, чем её может хранить репликатор - val toExtract = drainPerTick - matter.extractMatterInner(drainPerTick, true) + val toExtract = drainPerTick - matter.extractMatter(drainPerTick, true) val drain = matterNode.graph.extractMatter(toExtract, true) if (drain != toExtract) { @@ -231,7 +232,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } // достаточно материи в сети + внутри машины - matter.extractMatterInner(drainPerTick, false) + matter.extractMatter(drainPerTick, false) matterNode.graph.extractMatter(drain, false) return Status.SUCCESS } else { @@ -250,8 +251,8 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : matter.receiveMatter(drain, false) // получили материю, проверяем возможность работы - if (matter.extractMatterInner(drainPerTick, true) >= drainPerTick) { - matter.extractMatterInner(drainPerTick, false) + if (matter.extractMatter(drainPerTick, true) >= drainPerTick) { + matter.extractMatter(drainPerTick, false) return Status.SUCCESS } else { // :( @@ -261,7 +262,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } // в машине достаточно материи - matter.extractMatterInner(drainPerTick, false) + matter.extractMatter(drainPerTick, false) visualProgress = workProgress return Status.SUCCESS } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt new file mode 100644 index 000000000..f1c86aa18 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt @@ -0,0 +1,206 @@ +package ru.dbotthepony.mc.otm.capability + +import com.google.common.collect.ImmutableList +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.ListTag +import net.minecraft.nbt.NumericTag +import net.minecraftforge.common.util.INBTSerializable +import ru.dbotthepony.mc.otm.core.forValidRefs +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.nbt.map +import ru.dbotthepony.mc.otm.core.nbt.set +import java.lang.ref.WeakReference +import java.util.* +import kotlin.collections.ArrayList + +abstract class AbstractProfiledStorage(val parent: P) : INBTSerializable { + init { + storages.add(WeakReference(this)) + } + + private val historyReceiveInternal = ArrayList(HISTORY_SIZE) + private val historyTransferInternal = ArrayList(HISTORY_SIZE) + + val historyReceive: List = Collections.unmodifiableList(historyReceiveInternal) + val historyTransfer: List = Collections.unmodifiableList(historyTransferInternal) + + val lastTickReceive + get() = historyReceiveInternal[tick] + + val lastTickTransfer + get() = historyTransferInternal[tick] + + private var thisTickReceive = Decimal.ZERO + private var thisTickTransfer = Decimal.ZERO + + var tick = 0 + private set + + init { + for (i in 0 until HISTORY_SIZE) { + historyReceiveInternal.add(Decimal.ZERO) + historyTransferInternal.add(Decimal.ZERO) + } + } + + protected fun recordTransfer(value: Decimal, simulate: Boolean): Decimal { + if (!simulate) { + thisTickTransfer += value + } + + return value + } + + protected fun recordReceive(value: Decimal, simulate: Boolean): Decimal { + if (!simulate) { + thisTickReceive += value + } + + return value + } + + private fun tick() { + tick = (tick + 1) % HISTORY_SIZE + + historyReceiveInternal[tick] = thisTickReceive + historyTransferInternal[tick] = thisTickTransfer + + thisTickReceive = Decimal.ZERO + thisTickTransfer = Decimal.ZERO + } + + val savedata: INBTSerializable = object : INBTSerializable { + override fun serializeNBT(): CompoundTag { + return CompoundTag().also { tag -> + tag["historyReceive"] = ListTag().also { + for (value in historyReceiveInternal) { + it.add(value.serializeNBT()) + } + } + + tag["historyTransfer"] = ListTag().also { + for (value in historyTransferInternal) { + it.add(value.serializeNBT()) + } + } + + tag["historyTick"] = tick + } + } + + override fun deserializeNBT(nbt: CompoundTag?) { + tick = 0 + thisTickReceive = Decimal.ZERO + thisTickTransfer = Decimal.ZERO + + for (i in 0 until HISTORY_SIZE) { + historyReceiveInternal[i] = Decimal.ZERO + historyTransferInternal[i] = Decimal.ZERO + } + + nbt ?: return + + nbt.map("historyTick") { it: NumericTag -> + tick = it.asInt + } + + nbt.map("historyReceive") { it: ListTag -> + for (i in 0 until HISTORY_SIZE.coerceAtMost(it.size)) { + historyReceiveInternal[i] = Decimal.deserializeNBT(it[i]) + } + } + + nbt.map("historyTransfer") { it: ListTag -> + for (i in 0 until HISTORY_SIZE.coerceAtMost(it.size)) { + historyTransferInternal[i] = Decimal.deserializeNBT(it[i]) + } + } + } + } + + override fun serializeNBT(): CompoundTag { + val tag: CompoundTag + + if (parent is INBTSerializable<*>) { + tag = (parent as INBTSerializable).serializeNBT() ?: CompoundTag() + } else { + tag = CompoundTag() + } + + val tag2 = savedata.serializeNBT()!! + + for (k in tag2.allKeys) { + tag[k] = tag2[k]!! + } + + return tag + } + + val weightedTransfer: Decimal get() { + return calcWeightedAverage(historyTransfer, tick) + } + + val weightedReceive: Decimal get() { + return calcWeightedAverage(historyReceive, tick) + } + + override fun deserializeNBT(nbt: CompoundTag?) { + if (parent is INBTSerializable<*>) { + (parent as INBTSerializable).deserializeNBT(nbt) + } + + savedata.deserializeNBT(nbt) + } + + companion object { + const val HISTORY_SIZE = 20 + private val storages = ArrayList>>() + + val HISTORY_WEIGHTERS: ImmutableList = ImmutableList.of( + Decimal("0.313335967"), + Decimal("0.146176397"), + Decimal("0.09357867"), + Decimal("0.068193701"), + Decimal("0.053351084"), + Decimal("0.043655993"), + Decimal("0.036847023"), + Decimal("0.031813486"), + Decimal("0.027947534"), + Decimal("0.024889161"), + Decimal("0.02241188"), + Decimal("0.020366241"), + Decimal("0.018649731"), + Decimal("0.017189744"), + Decimal("0.015933452"), + Decimal("0.014841516"), + Decimal("0.013884059"), + Decimal("0.013037985"), + Decimal("0.012285173"), + Decimal("0.011611204"), + ) + + fun calcWeightedAverage(inputs: List, pointer: Int): Decimal { + require(inputs.size == HISTORY_WEIGHTERS.size) { "Expected list of size ${HISTORY_WEIGHTERS.size}, got ${inputs.size}" } + require(pointer in 0 until HISTORY_WEIGHTERS.size) { "Invalid pointer position: $pointer" } + + var result = Decimal.ZERO + var i = 0 + + for (i2 in pointer downTo 0) + result += inputs[i2] * HISTORY_WEIGHTERS[i++] + + for (i2 in HISTORY_WEIGHTERS.size - 1 downTo pointer + 1) + result += inputs[i2] * HISTORY_WEIGHTERS[i++] + + return result + } + + // после раздумий, наиболее корректное место для обновления состояния профилированных + // хранилищ энергии и материи будет после всех остальных хуков на тики после тика сервера + // разумеется, такое решение может несколько снизить производительность сервера, + // но ничего страшного произойти не должно + internal fun onServerPostTick() { + storages.forValidRefs { it.tick() } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ProfiledEnergyStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ProfiledEnergyStorage.kt index a176e5d65..3cb14c888 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ProfiledEnergyStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ProfiledEnergyStorage.kt @@ -1,25 +1,10 @@ package ru.dbotthepony.mc.otm.capability.energy -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.ListTag -import net.minecraft.nbt.NumericTag -import net.minecraft.nbt.Tag -import net.minecraftforge.common.util.INBTSerializable +import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.capability.FlowDirection -import ru.dbotthepony.mc.otm.core.forValidRefs import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.math.set -import ru.dbotthepony.mc.otm.core.nbt.map -import ru.dbotthepony.mc.otm.core.nbt.set -import java.lang.ref.WeakReference -import java.util.* -import kotlin.collections.ArrayList - -class ProfiledEnergyStorage(val parent: E) : IMatteryEnergyStorage, INBTSerializable { - init { - storages.add(WeakReference(this)) - } +class ProfiledEnergyStorage(parent: E) : AbstractProfiledStorage(parent), IMatteryEnergyStorage { override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { return recordTransfer(parent.extractEnergy(howMuch, simulate), simulate) } @@ -53,143 +38,4 @@ class ProfiledEnergyStorage(val parent: E) : IMattery override val maxBatteryLevel: Decimal get() = parent.maxBatteryLevel override val energyFlow: FlowDirection get() = parent.energyFlow - - private val historyReceiveInternal = ArrayList(HISTORY_SIZE) - private val historyTransferInternal = ArrayList(HISTORY_SIZE) - - val historyReceive: List = Collections.unmodifiableList(historyReceiveInternal) - val historyTransfer: List = Collections.unmodifiableList(historyTransferInternal) - - val lastTickReceive - get() = historyReceiveInternal[tick] - - val lastTickTransfer - get() = historyTransferInternal[tick] - - private var thisTickReceive = Decimal.ZERO - private var thisTickTransfer = Decimal.ZERO - - var tick = 0 - private set - - init { - for (i in 0 until HISTORY_SIZE) { - historyReceiveInternal.add(Decimal.ZERO) - historyTransferInternal.add(Decimal.ZERO) - } - } - - private fun recordTransfer(value: Decimal, simulate: Boolean): Decimal { - if (!simulate) { - thisTickTransfer += value - } - - return value - } - - private fun recordReceive(value: Decimal, simulate: Boolean): Decimal { - if (!simulate) { - thisTickReceive += value - } - - return value - } - - private fun tick() { - tick = (tick + 1) % HISTORY_SIZE - - historyReceiveInternal[tick] = thisTickReceive - historyTransferInternal[tick] = thisTickTransfer - - thisTickReceive = Decimal.ZERO - thisTickTransfer = Decimal.ZERO - } - - val savedata: INBTSerializable = object : INBTSerializable { - override fun serializeNBT(): CompoundTag { - return CompoundTag().also { tag -> - tag["historyReceive"] = ListTag().also { - for (value in historyReceiveInternal) { - it.add(value.serializeNBT()) - } - } - - tag["historyTransfer"] = ListTag().also { - for (value in historyTransferInternal) { - it.add(value.serializeNBT()) - } - } - - tag["historyTick"] = tick - } - } - - override fun deserializeNBT(nbt: CompoundTag?) { - tick = 0 - thisTickReceive = Decimal.ZERO - thisTickTransfer = Decimal.ZERO - - for (i in 0 until HISTORY_SIZE) { - historyReceiveInternal[i] = Decimal.ZERO - historyTransferInternal[i] = Decimal.ZERO - } - - nbt ?: return - - nbt.map("historyTick") { it: NumericTag -> - tick = it.asInt - } - - nbt.map("historyReceive") { it: ListTag -> - for (i in 0 until HISTORY_SIZE.coerceAtMost(it.size)) { - historyReceiveInternal[i] = Decimal.deserializeNBT(it[i]) - } - } - - nbt.map("historyTransfer") { it: ListTag -> - for (i in 0 until HISTORY_SIZE.coerceAtMost(it.size)) { - historyTransferInternal[i] = Decimal.deserializeNBT(it[i]) - } - } - } - } - - override fun serializeNBT(): CompoundTag { - val tag: CompoundTag - - if (parent is INBTSerializable<*>) { - tag = (parent as INBTSerializable).serializeNBT() ?: CompoundTag() - } else { - tag = CompoundTag() - } - - val tag2 = savedata.serializeNBT()!! - - for (k in tag2.allKeys) { - tag[k] = tag2[k]!! - } - - return tag - } - - override fun deserializeNBT(nbt: CompoundTag?) { - if (parent is INBTSerializable<*>) { - (parent as INBTSerializable).deserializeNBT(nbt) - } - - savedata.deserializeNBT(nbt) - } - - companion object { - const val HISTORY_SIZE = 20 - private val storages = ArrayList>>() - - // после раздумий, наиболее корректное место для обновления состояния профилированных - // хранилищ энергии будет после всех остальных хуков на тики после тика сервера - // разумеется, такое решение может несколько снизить производительность сервера, - // но ничего страшного произойти не должно - internal fun onServerPostTick() { - storages.forValidRefs { it.tick() } - } - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt index c8544371f..7c75ad595 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt @@ -6,10 +6,13 @@ import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.orNull +import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import kotlin.math.roundToInt /** * Matter interface in Overdrive That Matters + * + * Contracts of this interface follow the ones of [IMatteryEnergyStorage] */ interface IMatterStorage { /** @@ -37,7 +40,7 @@ interface IMatterStorage { val maxStoredMatter: Decimal /** - * Empties matter stored of this matter storage + * Empties matter stored of this matter storage, if possible * * @throws [UnsupportedOperationException] * @see storedMatter @@ -47,7 +50,7 @@ interface IMatterStorage { } /** - * Fully fills matter stored in this matter storage + * Fully fills matter stored, if possible * * @throws [UnsupportedOperationException] * @see storedMatter @@ -57,19 +60,45 @@ interface IMatterStorage { } /** - * Fill matter into this object + * Fill matter into this object, ignoring [matterFlow] * * @return matter accepted */ fun receiveMatter(howMuch: Decimal, simulate: Boolean): Decimal /** - * Extract matter from this matter storage + * Extract matter from this matter storage, ignoring [matterFlow] * * @return matter extracted */ fun extractMatter(howMuch: Decimal, simulate: Boolean): Decimal + /** + * Fill matter into this object, accounting for [matterFlow] + * + * @return matter accepted + */ + fun receiveMatterChecked(howMuch: Decimal, simulate: Boolean): Decimal { + if (matterFlow.input) { + return receiveMatter(howMuch, simulate) + } + + return Decimal.ZERO + } + + /** + * Extract matter from this matter storage, accounting for [matterFlow] + * + * @return matter extracted + */ + fun extractMatterChecked(howMuch: Decimal, simulate: Boolean): Decimal { + if (matterFlow.output) { + return extractMatter(howMuch, simulate) + } + + return Decimal.ZERO + } + /** * How much matter (estimated) is missing in this matter storage. Why estimated? Because some objects can be bottomless. * diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt index ee47b32fe..72daab76b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt @@ -63,13 +63,6 @@ open class MatterStorageImpl @JvmOverloads constructor( } override fun receiveMatter(howMuch: Decimal, simulate: Boolean): Decimal { - if (!canReceiveMatter) - return Decimal.ZERO - - return receiveMatterInner(howMuch, simulate) - } - - fun receiveMatterInner(howMuch: Decimal, simulate: Boolean): Decimal { val new: Decimal if (maxReceive == null) { @@ -89,13 +82,6 @@ open class MatterStorageImpl @JvmOverloads constructor( } override fun extractMatter(howMuch: Decimal, simulate: Boolean): Decimal { - if (canExtractMatter) - return Decimal.ZERO - - return extractMatterInner(howMuch, simulate) - } - - fun extractMatterInner(howMuch: Decimal, simulate: Boolean): Decimal { val new: Decimal if (maxExtract == null) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/ProfiledMatterStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/ProfiledMatterStorage.kt new file mode 100644 index 000000000..b3ebe61f0 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/ProfiledMatterStorage.kt @@ -0,0 +1,45 @@ +package ru.dbotthepony.mc.otm.capability.matter + +import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage +import ru.dbotthepony.mc.otm.capability.FlowDirection +import ru.dbotthepony.mc.otm.core.math.Decimal + +class ProfiledMatterStorage(parent: M) : AbstractProfiledStorage(parent), IMatterStorage { + override var storedMatter by parent::storedMatter + + override val maxStoredMatter: Decimal + get() = parent.maxStoredMatter + + override fun receiveMatter(howMuch: Decimal, simulate: Boolean): Decimal { + return recordReceive(parent.receiveMatter(howMuch, simulate), simulate) + } + + override fun extractMatter(howMuch: Decimal, simulate: Boolean): Decimal { + return recordTransfer(parent.extractMatter(howMuch, simulate), simulate) + } + + override fun receiveMatterChecked(howMuch: Decimal, simulate: Boolean): Decimal { + return recordReceive(parent.receiveMatterChecked(howMuch, simulate), simulate) + } + + override fun extractMatterChecked(howMuch: Decimal, simulate: Boolean): Decimal { + return recordTransfer(parent.extractMatterChecked(howMuch, simulate), simulate) + } + + override val matterFlow: FlowDirection + get() = parent.matterFlow + + override val canSetMatterLevel: Boolean + get() = parent.canSetMatterLevel + + override fun drainMatter() { + parent.drainMatter() + } + + override fun fillMatter() { + parent.fillMatter() + } + + override val missingMatter: Decimal + get() = parent.missingMatter +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterBottlerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterBottlerScreen.kt index def4b18a2..f18d7725c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterBottlerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterBottlerScreen.kt @@ -11,6 +11,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.slot.BatterySlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.MatterCapacitorSlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledMatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.menu.matter.MatterBottlerMenu @@ -24,7 +25,7 @@ class MatterBottlerScreen(menu: MatterBottlerMenu, inventory: Inventory, title: val frame = super.makeMainFrame()!! val p = ProfiledPowerGaugePanel(this, frame, menu.profiledEnergy, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) - MatterGaugePanel(this, frame, menu.matterWidget, LEFT_MARGIN + p.width, GAUGE_TOP_WITH_SLOT) + ProfiledMatterGaugePanel(this, frame, menu.matterWidget, LEFT_MARGIN + p.width, GAUGE_TOP_WITH_SLOT) BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterDecomposerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterDecomposerScreen.kt index 81a6488d0..f399232ac 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterDecomposerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterDecomposerScreen.kt @@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledMatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel @@ -20,7 +21,7 @@ class MatterDecomposerScreen(p_97741_: MatterDecomposerMenu, p_97742_: Inventory val frame = super.makeMainFrame()!! val m = ProfiledPowerGaugePanel(this, frame, menu.profiledEnergy, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) - MatterGaugePanel(this, frame, menu.matterWidget, LEFT_MARGIN + m.width, GAUGE_TOP_WITH_SLOT) + ProfiledMatterGaugePanel(this, frame, menu.matterWidget, LEFT_MARGIN + m.width, GAUGE_TOP_WITH_SLOT) BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReconstructorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReconstructorScreen.kt index 29c2c6163..d87f67aec 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReconstructorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReconstructorScreen.kt @@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.slot.BatterySlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledMatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.menu.matter.MatterReconstructorMenu @@ -22,7 +23,7 @@ class MatterReconstructorScreen(menu: MatterReconstructorMenu, inventory: Invent val frame = super.makeMainFrame()!! val p = ProfiledPowerGaugePanel(this, frame, menu.profiledEnergy, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) - MatterGaugePanel(this, frame, menu.matterWidget, LEFT_MARGIN + p.width, GAUGE_TOP_WITH_SLOT) + ProfiledMatterGaugePanel(this, frame, menu.matterWidget, LEFT_MARGIN + p.width, GAUGE_TOP_WITH_SLOT) BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterRecyclerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterRecyclerScreen.kt index 3763dee00..a48875e3a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterRecyclerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterRecyclerScreen.kt @@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledMatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu @@ -18,7 +19,7 @@ class MatterRecyclerScreen(menu: MatterRecyclerMenu, inventory: Inventory, title val frame = super.makeMainFrame()!! val m = ProfiledPowerGaugePanel(this, frame, menu.profiledEnergy, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) - MatterGaugePanel(this, frame, menu.matter, LEFT_MARGIN + m.width, GAUGE_TOP_WITH_SLOT) + ProfiledMatterGaugePanel(this, frame, menu.matter, LEFT_MARGIN + m.width, GAUGE_TOP_WITH_SLOT) BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReplicatorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReplicatorScreen.kt index a74d83ae8..2bec6d949 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReplicatorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterReplicatorScreen.kt @@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledMatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.menu.matter.MatterReplicatorMenu @@ -19,7 +20,7 @@ class MatterReplicatorScreen(p_97741_: MatterReplicatorMenu, p_97742_: Inventory val frame = super.makeMainFrame()!! val m = ProfiledPowerGaugePanel(this, frame, menu.profiledEnergy, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) - MatterGaugePanel(this, frame, menu.matter, LEFT_MARGIN + m.width, GAUGE_TOP_WITH_SLOT) + ProfiledMatterGaugePanel(this, frame, menu.matter, LEFT_MARGIN + m.width, GAUGE_TOP_WITH_SLOT) BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/HorizontalPowerGaugePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/HorizontalPowerGaugePanel.kt index 552a48882..6664b16c3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/HorizontalPowerGaugePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/HorizontalPowerGaugePanel.kt @@ -1,13 +1,12 @@ package ru.dbotthepony.mc.otm.client.screen.widget -import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.Screen import ru.dbotthepony.mc.otm.client.render.UVWindingOrder import ru.dbotthepony.mc.otm.client.render.WidgetLocation import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget private fun PowerGaugePanel<*>.doRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float, flop: Boolean) { if (height >= 18f) { @@ -74,7 +73,7 @@ fun TallHorizontalPowerGaugePanel( open class HorizontalProfiledPowerGaugePanel( screen: S, parent: EditablePanel<*>? = null, - widget: ProfiledEnergyGaugeWidget, + widget: ProfiledLevelGaugeWidget<*>, x: Float = 0f, y: Float = 0f, width: Float = HorizontalPowerGaugePanel.GAUGE_BACKGROUND.width, @@ -94,7 +93,7 @@ open class HorizontalProfiledPowerGaugePanel( fun TallHorizontalProfiledPowerGaugePanel( screen: S, parent: EditablePanel<*>? = null, - widget: ProfiledEnergyGaugeWidget, + widget: ProfiledLevelGaugeWidget<*>, x: Float = 0f, y: Float = 0f, width: Float = HorizontalPowerGaugePanel.GAUGE_BACKGROUND_TALL.width, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt index 609490059..ec764b57e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt @@ -5,18 +5,29 @@ import com.mojang.blaze3d.vertex.BufferUploader import com.mojang.blaze3d.vertex.DefaultVertexFormat import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.VertexFormat +import it.unimi.dsi.fastutil.ints.IntArrayList +import net.minecraft.ChatFormatting import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.Screen import net.minecraft.client.renderer.GameRenderer import net.minecraft.network.chat.Component import org.lwjgl.opengl.GL11 +import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.client.ShiftPressedCond +import ru.dbotthepony.mc.otm.client.isShiftDown +import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.WidgetLocation import ru.dbotthepony.mc.otm.client.render.tesselator import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel +import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.util.formatMatter import ru.dbotthepony.mc.otm.core.util.formatMatterLevel +import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.nanoTime import kotlin.math.absoluteValue import kotlin.math.cos @@ -121,3 +132,54 @@ open class MatterGaugePanel @JvmOverloads constructor( val GAUGE_FOREGROUND = WidgetLocation.VERTICAL_GAUGES.sprite(x = 27f, width = 9f) } } + +private fun formatLevel(a: Decimal, b: Decimal): Component { + val diff = a - b + + val fa = a.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN) + val fb = b.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED) + + if (diff.isZero) { + return TranslatableComponent("otm.gui.diff", diff.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.GRAY), fa, fb) + } else if (diff.isPositive) { + return TranslatableComponent("otm.gui.diff", diff.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN), fa, fb) + } else { + return TranslatableComponent("otm.gui.diff", (-diff).formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED), fa, fb) + } +} + +open class ProfiledMatterGaugePanel( + screen: S, + parent: EditablePanel<*>? = null, + val profiledWidget: ProfiledLevelGaugeWidget<*>, + x: Float = 0f, + y: Float = 0f +): MatterGaugePanel(screen, parent, profiledWidget.gauge, x, y) { + override fun makeTooltip(): MutableList { + return super.makeTooltip().also { + it.add(TextComponent("")) + + if (minecraft.window.isShiftDown) { + it.add(formatLevel(profiledWidget.lastTickReceive, profiledWidget.lastTickTransfer)) + it.add(TextComponent("---")) + } + + it.add(formatLevel( + profiledWidget.weightedReceive, + profiledWidget.weightedTransfer, + )) + + if (minecraft.window.isShiftDown && minecraft.options.advancedItemTooltips) { + it.add(TextComponent("---")) + val values = IntArrayList() + + values.addAll(profiledWidget.tick downTo 0) + values.addAll(AbstractProfiledStorage.HISTORY_SIZE - 1 downTo profiledWidget.tick + 1) + + for (i in values.intIterator()) { + it.add(formatLevel(profiledWidget.historyReceive[i].value, profiledWidget.historyTransfer[i].value)) + } + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt index 285d3112e..4af6f338f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt @@ -1,11 +1,11 @@ package ru.dbotthepony.mc.otm.client.screen.widget -import com.mojang.blaze3d.vertex.PoseStack import it.unimi.dsi.fastutil.ints.IntArrayList import net.minecraft.ChatFormatting import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component +import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.client.ShiftPressedCond import ru.dbotthepony.mc.otm.client.isShiftDown @@ -19,7 +19,7 @@ import ru.dbotthepony.mc.otm.core.stream import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.core.util.formatPowerLevel import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget open class PowerGaugePanel( screen: S, @@ -113,7 +113,7 @@ private fun formatLevel(a: Decimal, b: Decimal): Component { open class ProfiledPowerGaugePanel( screen: S, parent: EditablePanel<*>? = null, - val profiledWidget: ProfiledEnergyGaugeWidget, + val profiledWidget: ProfiledLevelGaugeWidget<*>, x: Float = 0f, y: Float = 0f, width: Float = GAUGE_BACKGROUND.width, @@ -129,16 +129,8 @@ open class ProfiledPowerGaugePanel( } it.add(formatLevel( - profiledWidget.historyReceive - .stream() - .map { it.value } - .reduce(Decimal.ZERO) { a, b -> a + b } - .div(profiledWidget.historyReceive.size), - - profiledWidget.historyTransfer.stream() - .map { it.value } - .reduce(Decimal.ZERO) { a, b -> a + b } - .div(profiledWidget.historyReceive.size), + profiledWidget.weightedReceive, + profiledWidget.weightedTransfer, )) if (minecraft.window.isShiftDown && minecraft.options.advancedItemTooltips) { @@ -146,7 +138,7 @@ open class ProfiledPowerGaugePanel( val values = IntArrayList() values.addAll(profiledWidget.tick downTo 0) - values.addAll(ProfiledEnergyStorage.HISTORY_SIZE - 1 downTo profiledWidget.tick + 1) + values.addAll(AbstractProfiledStorage.HISTORY_SIZE - 1 downTo profiledWidget.tick + 1) for (i in values.intIterator()) { it.add(formatLevel(profiledWidget.historyReceive[i].value, profiledWidget.historyTransfer[i].value)) @@ -163,7 +155,7 @@ open class ProfiledPowerGaugePanel( fun WideProfiledPowerGaugePanel( screen: S, parent: EditablePanel<*>? = null, - widget: ProfiledEnergyGaugeWidget, + widget: ProfiledLevelGaugeWidget<*>, x: Float = 0f, y: Float = 0f, width: Float = 18f, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterGraph.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterGraph.kt index b0e0e2a10..86f0e6b26 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterGraph.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterGraph.kt @@ -110,7 +110,7 @@ class MatterGraph : Abstract6Graph(), IMatterGraphListe val matter = node.getMatterHandler() if (matter != null) { - val value = matter.extractMatter(howMuch, simulate) + val value = matter.extractMatterChecked(howMuch, simulate) howMuch -= value extracted += value @@ -134,7 +134,7 @@ class MatterGraph : Abstract6Graph(), IMatterGraphListe val matter = node.getMatterHandler() if (matter != null && matter.matterFlow == FlowDirection.BI_DIRECTIONAL) { - val value = matter.receiveMatter(howMuch, simulate) + val value = matter.receiveMatterChecked(howMuch, simulate) howMuch -= value received += value @@ -158,7 +158,7 @@ class MatterGraph : Abstract6Graph(), IMatterGraphListe val matter = node.getMatterHandler() if (matter != null && matter.matterFlow != FlowDirection.OUTPUT) { - val value = matter.receiveMatter(howMuch, simulate) + val value = matter.receiveMatterChecked(howMuch, simulate) howMuch -= value received += value diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterBottlerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterBottlerMenu.kt index 492ba1891..cc50fadfc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterBottlerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterBottlerMenu.kt @@ -6,6 +6,7 @@ import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.capability.matter.canExtractMatter import ru.dbotthepony.mc.otm.capability.matter.canReceiveMatter import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback @@ -14,7 +15,7 @@ import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatterySlot -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus class MatterBottlerMenu @JvmOverloads constructor( @@ -26,16 +27,15 @@ class MatterBottlerMenu @JvmOverloads constructor( ) { val workFlow = BooleanInputWithFeedback(this) val progressWidget = ProgressGaugeWidget(this) - val matterWidget = LevelGaugeWidget(this) + val matterWidget = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter)) val storageSlots: List - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { val container = tile?.container ?: SimpleContainer(6) if (tile != null) { progressWidget.with(tile::getWorkProgress) - matterWidget.with(tile.matter) workFlow.with(tile::isBottling) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterDecomposerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterDecomposerMenu.kt index 3a2084fff..f4dbfcdfe 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterDecomposerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterDecomposerMenu.kt @@ -15,7 +15,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus class MatterDecomposerMenu @JvmOverloads constructor( @@ -30,10 +30,10 @@ class MatterDecomposerMenu @JvmOverloads constructor( val outputMain: MachineOutputSlot val outputStacking: MachineOutputSlot val progressWidget = ProgressGaugeWidget(this, tile) - val matterWidget = LevelGaugeWidget(this, tile?.getCapability(MatteryCapability.MATTER)?.orNull()) + val matterWidget = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter)) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig) val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { val container = tile?.outputContainer ?: SimpleContainer(2) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReconstructorMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReconstructorMenu.kt index 96e7bb91c..8527bf717 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReconstructorMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReconstructorMenu.kt @@ -9,7 +9,7 @@ import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus @@ -18,7 +18,7 @@ class MatterReconstructorMenu( inventory: Inventory, tile: MatterReconstructorBlockEntity? = null ) : MatteryPoweredMenu(MMenus.ITEM_REPAIER, containerId, inventory, tile) { - val matterWidget = LevelGaugeWidget(this, tile?.matter) + val matterWidget = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter)) val slot = object : MatterySlot(tile?.repairContainer ?: SimpleContainer(1), 0) { override fun mayPlace(itemStack: ItemStack): Boolean { return itemStack.isRepairable && itemStack.isDamaged && super.mayPlace(itemStack) @@ -30,7 +30,7 @@ class MatterReconstructorMenu( val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig) - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { addStorageSlot(slot) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterRecyclerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterRecyclerMenu.kt index 373719f59..0441c860d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterRecyclerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterRecyclerMenu.kt @@ -10,7 +10,7 @@ import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus @@ -26,10 +26,10 @@ class MatterRecyclerMenu @JvmOverloads constructor( } val progress = ProgressGaugeWidget(this, tile) - val matter = LevelGaugeWidget(this, tile?.matter) + val matter = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter)) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig) val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { addStorageSlot(input) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReplicatorMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReplicatorMenu.kt index 09ca29654..949333bbb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReplicatorMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterReplicatorMenu.kt @@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.menu.MachineOutputSlot import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus class MatterReplicatorMenu @JvmOverloads constructor( @@ -19,12 +19,12 @@ class MatterReplicatorMenu @JvmOverloads constructor( inventory: Inventory, tile: MatterReplicatorBlockEntity? = null ) : MatteryPoweredMenu(MMenus.MATTER_REPLICATOR, p_38852_, inventory, tile) { - val matter = LevelGaugeWidget(this, tile?.matter) + val matter = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter)) val progress = ProgressGaugeWidget(this, tile) val storageSlots: List val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig) val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { val container = tile?.container ?: SimpleContainer(5) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterScannerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterScannerMenu.kt index f07f1d3e3..2482505d6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterScannerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterScannerMenu.kt @@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus class MatterScannerMenu @JvmOverloads constructor( @@ -26,7 +26,7 @@ class MatterScannerMenu @JvmOverloads constructor( val patterns = LevelGaugeWidget(this) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig) val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { val container = tile?.container ?: SimpleContainer(1) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AndroidStationMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AndroidStationMenu.kt index a96447a9b..e3203da1d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AndroidStationMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AndroidStationMenu.kt @@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus import kotlin.reflect.KMutableProperty0 @@ -113,7 +113,7 @@ class AndroidStationMenu @JvmOverloads constructor( val equipment = makeEquipmentSlots() val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { addInventorySlots() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/BatteryBankMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/BatteryBankMenu.kt index 4483e591d..a9d284f09 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/BatteryBankMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/BatteryBankMenu.kt @@ -7,16 +7,13 @@ import ru.dbotthepony.mc.otm.block.entity.tech.BatteryBankBlockEntity import net.minecraft.world.SimpleContainer import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.core.immutableList -import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.menu.BatterySlot import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus class BatteryBankMenu @JvmOverloads constructor( @@ -24,7 +21,7 @@ class BatteryBankMenu @JvmOverloads constructor( inventory: Inventory, tile: BatteryBankBlockEntity? = null, ) : MatteryMenu(MMenus.BATTERY_BANK, p_38852_, inventory, tile) { - val powerLevel = ProfiledEnergyGaugeWidget(this, tile?.energyConfig?.capability) + val powerLevel = ProfiledLevelGaugeWidget(this, tile?.energyConfig?.capability) val storageSlots: List val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java) val energyConfig = EnergyConfigPlayerInput(this, allowPull = false, allowPush = true) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt index b4c125658..5239bc527 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt @@ -13,8 +13,7 @@ import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus @@ -54,7 +53,7 @@ class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, t } val progress = ProgressGaugeWidget(this) - val energy = ProfiledEnergyGaugeWidget(this, tile?.energy) + val energy = ProfiledLevelGaugeWidget(this, tile?.energy) var burnTime by mSynchronizer.int().property init { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyServoMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyServoMenu.kt index cb8ce6b39..e336e01c9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyServoMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyServoMenu.kt @@ -11,8 +11,7 @@ import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus class EnergyServoMenu @JvmOverloads constructor( @@ -34,7 +33,7 @@ class EnergyServoMenu @JvmOverloads constructor( val equipment = makeEquipmentSlots(mapMoveToExternal = true) - val powerGauge = ProfiledEnergyGaugeWidget(this, tile?.energy) + val powerGauge = ProfiledLevelGaugeWidget(this, tile?.energy) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig) val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig, allowPull = true, allowPush = true) val redstoneConfig = EnumInputWithFeedback(this) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt index 63bdd4b0f..0f33d9ed6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt @@ -9,7 +9,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput -import ru.dbotthepony.mc.otm.menu.widget.ProfiledEnergyGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus @@ -24,7 +24,7 @@ class PlatePressMenu @JvmOverloads constructor( val progressGauge = ProgressGaugeWidget(this, tile) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true) val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig, allowPull = true) - val profiledEnergy = ProfiledEnergyGaugeWidget(this, tile?.energy, energyWidget) + val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) init { addStorageSlot(inputSlot) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledEnergyGaugeWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledEnergyGaugeWidget.kt deleted file mode 100644 index 1a63d3dd7..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledEnergyGaugeWidget.kt +++ /dev/null @@ -1,44 +0,0 @@ -package ru.dbotthepony.mc.otm.menu.widget - -import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage -import ru.dbotthepony.mc.otm.core.immutableList -import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec -import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer - -class ProfiledEnergyGaugeWidget(synchronizer: FieldSynchronizer, val gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) { - var parent: ProfiledEnergyStorage<*>? = null - private set - - val historyReceive = immutableList(ProfiledEnergyStorage.HISTORY_SIZE) { - synchronizer.ComputedField({ parent?.historyReceive?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) - } - - val historyTransfer = immutableList(ProfiledEnergyStorage.HISTORY_SIZE) { - synchronizer.ComputedField({ parent?.historyTransfer?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) - } - - val tick by synchronizer.ComputedIntField({ parent?.tick ?: 0 }).property - val lastTickReceive by synchronizer.ComputedField({ parent?.lastTickReceive ?: Decimal.ZERO }, DecimalValueCodec) - val lastTickTransfer by synchronizer.ComputedField({ parent?.lastTickTransfer ?: Decimal.ZERO }, DecimalValueCodec) - - constructor(synchronizer: FieldSynchronizer, storage: ProfiledEnergyStorage<*>?, gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) : this(synchronizer, gauge = gauge) { - if (storage != null) { - with(storage) - } - } - - constructor(menu: MatteryMenu, storage: ProfiledEnergyStorage<*>?, gauge: LevelGaugeWidget = LevelGaugeWidget(menu)) : this(menu.mSynchronizer, storage, gauge = gauge) - constructor(menu: MatteryMenu, gauge: LevelGaugeWidget = LevelGaugeWidget(menu)) : this(menu.mSynchronizer, gauge = gauge) - - constructor(menu: MatteryPoweredMenu, storage: ProfiledEnergyStorage<*>?) : this(menu.mSynchronizer, storage, menu.energyWidget) - constructor(menu: MatteryPoweredMenu) : this(menu.mSynchronizer, menu.energyWidget) - - fun with(storage: ProfiledEnergyStorage<*>): ProfiledEnergyGaugeWidget { - gauge.with(storage) - parent = storage - return this - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt new file mode 100644 index 000000000..486168417 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt @@ -0,0 +1,62 @@ +package ru.dbotthepony.mc.otm.menu.widget + +import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage +import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage +import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage +import ru.dbotthepony.mc.otm.core.collect.SupplierList +import ru.dbotthepony.mc.otm.core.immutableList +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu +import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer + +class ProfiledLevelGaugeWidget

>(synchronizer: FieldSynchronizer, val gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) { + var parent: P? = null + private set + + val historyReceive = immutableList(AbstractProfiledStorage.HISTORY_SIZE) { + synchronizer.ComputedField({ parent?.historyReceive?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) + } + + val historyTransfer = immutableList(AbstractProfiledStorage.HISTORY_SIZE) { + synchronizer.ComputedField({ parent?.historyTransfer?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) + } + + val directHistoryReceive = SupplierList(historyReceive) + val directHistoryTransfer = SupplierList(historyTransfer) + + val tick by synchronizer.ComputedIntField({ parent?.tick ?: 0 }).property + val lastTickReceive by synchronizer.ComputedField({ parent?.lastTickReceive ?: Decimal.ZERO }, DecimalValueCodec) + val lastTickTransfer by synchronizer.ComputedField({ parent?.lastTickTransfer ?: Decimal.ZERO }, DecimalValueCodec) + + constructor(synchronizer: FieldSynchronizer, storage: P?, gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) : this(synchronizer, gauge = gauge) { + if (storage != null) { + with(storage) + } + } + + constructor(menu: MatteryMenu, storage: P?, gauge: LevelGaugeWidget = LevelGaugeWidget(menu)) : this(menu.mSynchronizer, storage, gauge = gauge) + constructor(menu: MatteryMenu, gauge: LevelGaugeWidget = LevelGaugeWidget(menu)) : this(menu.mSynchronizer, gauge = gauge) + + constructor(menu: MatteryPoweredMenu, storage: P?) : this(menu.mSynchronizer, storage, menu.energyWidget) + constructor(menu: MatteryPoweredMenu) : this(menu.mSynchronizer, menu.energyWidget) + + fun with(storage: P): ProfiledLevelGaugeWidget

{ + if (storage is IMatterStorage) + gauge.with(storage) + else if (storage is IMatteryEnergyStorage) + gauge.with(storage) + + parent = storage + return this + } + + val weightedTransfer: Decimal get() { + return AbstractProfiledStorage.calcWeightedAverage(directHistoryTransfer, tick) + } + + val weightedReceive: Decimal get() { + return AbstractProfiledStorage.calcWeightedAverage(directHistoryReceive, tick) + } +}