From 90348d5789a906c40487b44cc8a722cbc595aa18 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 17 Aug 2023 12:16:59 +0700 Subject: [PATCH] idling machines are now faster than ever Rotate faaaster banan-a --- .../mc/otm/block/entity/MatteryBlockEntity.kt | 15 +++- .../block/entity/MatteryDeviceBlockEntity.kt | 40 ++++++---- .../block/entity/MatteryPoweredBlockEntity.kt | 10 ++- .../block/entity/MatteryWorkerBlockEntity.kt | 44 +++++++--- .../entity/decorative/FluidTankBlockEntity.kt | 8 +- .../entity/decorative/PainterBlockEntity.kt | 4 +- .../entity/matter/MatterBottlerBlockEntity.kt | 10 +-- .../matter/MatterCapacitorBankBlockEntity.kt | 2 +- .../matter/MatterDecomposerBlockEntity.kt | 10 +-- .../matter/MatterReconstructorBlockEntity.kt | 6 +- .../matter/MatterRecyclerBlockEntity.kt | 2 +- .../matter/MatterReplicatorBlockEntity.kt | 4 +- .../entity/matter/MatterScannerBlockEntity.kt | 4 +- .../entity/storage/DriveRackBlockEntity.kt | 8 +- .../entity/storage/DriveViewerBlockEntity.kt | 10 +-- .../entity/storage/ItemMonitorBlockEntity.kt | 5 +- .../entity/storage/StorageBusBlockEntity.kt | 10 +-- .../block/entity/storage/StorageInterfaces.kt | 6 +- .../StoragePowerSupplierBlockEntity.kt | 2 +- .../entity/tech/AndroidChargerBlockEntity.kt | 2 +- .../entity/tech/AndroidStationBlockEntity.kt | 2 +- .../entity/tech/BatteryBankBlockEntity.kt | 2 +- .../tech/ChemicalGeneratorBlockEntity.kt | 16 ++-- .../entity/tech/EnergyServoBlockEntity.kt | 4 +- .../entity/tech/EssenceStorageBlockEntity.kt | 6 +- .../entity/tech/PlatePressBlockEntity.kt | 11 ++- .../entity/tech/PoweredFurnaceBlockEntity.kt | 4 +- .../otm/capability/AbstractProfiledStorage.kt | 24 ++++-- .../core/util/AtomicallyInvalidatedLazy.kt | 14 +++- .../otm/core/util/CounterInvalidatedLazy.kt | 80 +++++++++++++++++++ .../mc/otm/core/util/IntCounter.kt | 59 ++++++++++++++ .../dbotthepony/mc/otm/core/util/TickList.kt | 20 +++++ .../mc/otm/menu/MatteryPoweredMenu.kt | 3 +- 33 files changed, 331 insertions(+), 116 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt index 7c3b27a5a..5f091b914 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt @@ -54,6 +54,7 @@ import ru.dbotthepony.mc.otm.core.math.BlockRotation import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.core.math.minus import ru.dbotthepony.mc.otm.core.math.plus +import ru.dbotthepony.mc.otm.core.util.IntCounter import ru.dbotthepony.mc.otm.core.util.Savetables import ru.dbotthepony.mc.otm.core.util.TickList import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket @@ -106,6 +107,8 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc private data class SidelessCap(val cap: T, var optional: LazyOptional) private val sidelessCaps = Reference2ObjectOpenHashMap, SidelessCap<*>>() protected val tickList = TickList() + protected val blockStateChangesCounter = IntCounter() + protected val dirtyListeners = ISubscriptable.Impl() /** * Shared savetables, written both to level storage and to item tag @@ -484,6 +487,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc @Suppress("OVERRIDE_DEPRECATION") override fun setBlockState(pBlockState: BlockState) { + blockStateChangesCounter.increment() val old = blockRotation @Suppress("DEPRECATION") super.setBlockState(pBlockState) @@ -513,14 +517,23 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } } + override fun setChanged() { + super.setChanged() + + dirtyListeners.accept(Unit) + } + // Just to mark chunk unsaved - open fun setChangedLight() { + open fun markDirtyFast() { val level = level + if (level is ServerLevel) { level.chunkSource.getChunkNow( SectionPos.blockToSectionCoord(blockPos.x), SectionPos.blockToSectionCoord(blockPos.z))?.isUnsaved = true } + + dirtyListeners.accept(Unit) } val synchronizer = FieldSynchronizer { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt index 9e9b368e1..d728a45ce 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt @@ -44,7 +44,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo var customDisplayName: Component? = null override val redstoneControl: AbstractRedstoneControl = RedstoneControl { new, old -> - setChangedLight() + markDirtyFast() if (new != old) redstoneStatusUpdated(new, old) @@ -149,7 +149,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo if (access.read() != value) { access.write(value) - setChangedLight() + markDirtyFast() if (value == FlowDirection.NONE) { controller.close() @@ -166,7 +166,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo var automatePull = false set(value) { field = value - setChangedLight() + markDirtyFast() updateTickerState() } @@ -174,7 +174,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo var automatePush = false set(value) { field = value - setChangedLight() + markDirtyFast() updateTickerState() } @@ -281,6 +281,11 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo val rightDefault: FlowDirection = modesRight, val topDefault: FlowDirection = modesTop, val bottomDefault: FlowDirection = modesBottom, + + /** + * If battery level can update without calling [markDirtyFast]/[setChanged] + */ + val volatileEnergyValues: Boolean = false ) { constructor( energy: T, @@ -291,6 +296,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo rightDefault: FlowDirection = possibleModes, topDefault: FlowDirection = possibleModes, bottomDefault: FlowDirection = possibleModes, + volatileEnergyValues: Boolean = false ) : this( energy, modesFront = possibleModes, frontDefault = frontDefault, @@ -299,6 +305,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo modesRight = possibleModes, rightDefault = rightDefault, modesTop = possibleModes, topDefault = topDefault, modesBottom = possibleModes, bottomDefault = bottomDefault, + volatileEnergyValues = volatileEnergyValues, ) init { @@ -349,14 +356,18 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo private val ticker = tickList.Ticker(this) private fun updateTickerState() { - ticker.isEnabled = (automatePull || automatePush) && energyFlow != FlowDirection.NONE && !redstoneControl.isBlockedByRedstone && neighbour.get().isPresent + ticker.isEnabled = (automatePull || automatePush) && + energyFlow != FlowDirection.NONE && + !redstoneControl.isBlockedByRedstone && + neighbour.get().isPresent && + (volatileEnergyValues || energy.batteryLevel.isPositive) } // var automatePull by synchronizer.bool().property var automatePull = false set(value) { field = value - setChangedLight() + markDirtyFast() updateTickerState() } @@ -364,7 +375,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo var automatePush = false set(value) { field = value - setChangedLight() + markDirtyFast() updateTickerState() } @@ -373,6 +384,10 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo savetables.bool(::automatePull, "energy_${side}_pull") savetables.bool(::automatePush, "energy_${side}_push") + dirtyListeners.addListener { + updateTickerState() + } + tickList.once { redstoneControl.addListener { updateTickerState() @@ -417,9 +432,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo } override fun tick() { - if (energyFlow == FlowDirection.NONE || !automatePull && !automatePush || redstoneControl.isBlockedByRedstone) - return - neighbour.get().ifPresentK { if (energyFlow.input && automatePull) { moveEnergy(source = it, destination = energy, simulate = false) @@ -436,7 +448,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo if (access.read() != value) { access.write(value) - setChangedLight() + markDirtyFast() if (value == FlowDirection.NONE) { for (controller in capControllers) @@ -604,7 +616,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo if (access.read() != value) { access.write(value) - setChangedLight() + markDirtyFast() if (value == ItemHandlerMode.DISABLED) { capController.close() @@ -627,7 +639,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo set(value) { if (field != value) { field = value - setChangedLight() + markDirtyFast() if (value) { innerSlotPush = 0 @@ -642,7 +654,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo set(value) { if (field != value) { field = value - setChangedLight() + markDirtyFast() if (value) { innerSlotPush = 0 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt index 92045b5d8..ee7854a35 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt @@ -12,6 +12,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.ForgeCapabilities import ru.dbotthepony.mc.otm.capability.* +import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.ItemEnergyStorageImpl import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.MatteryContainer @@ -21,8 +22,10 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.nbt.map abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) { - val batteryContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) + val batteryContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) val batteryItemHandler = batteryContainer.handler(HandlerFilter.Dischargeable) + open val energy: IMatteryEnergyStorage? + get() = null init { savetables.stateful(::batteryContainer, BATTERY_KEY) @@ -31,10 +34,9 @@ abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229 override fun tick() { super.tick() - val energy = matteryEnergy - if (energy == null || batteryContainer.isEmpty) - return + if (batteryContainer.isEmpty) return + val energy = energy ?: return var demand = energy.receiveEnergy(energy.missingPower, true) if (demand.isZero) return diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt index 90af20413..a89abd728 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt @@ -16,10 +16,10 @@ import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage -import ru.dbotthepony.mc.otm.capability.matteryEnergy import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.nbt.getCompoundList import ru.dbotthepony.mc.otm.core.nbt.set +import ru.dbotthepony.mc.otm.core.util.countingLazy /** * Simple machine, which can work on only one job type. @@ -36,7 +36,7 @@ abstract class MatteryWorkerBlockEntity( val jobEventLoops: ImmutableList> = immutableList(maxJobs) { id -> object : MachineJobEventLoop(jobCodec) { override val energy: IMatteryEnergyStorage? - get() = matteryEnergy + get() = this@MatteryWorkerBlockEntity.energy override val isBlockedByRedstone: Boolean get() = redstoneControl.isBlockedByRedstone override val upgrades: IMatteryUpgrade? @@ -55,7 +55,7 @@ abstract class MatteryWorkerBlockEntity( } override fun onJobTick(status: JobStatus) { - super@MatteryWorkerBlockEntity.setChangedLight() + super@MatteryWorkerBlockEntity.markDirtyFast() return this@MatteryWorkerBlockEntity.onJobTick(status, id) } } @@ -105,13 +105,13 @@ abstract class MatteryWorkerBlockEntity( jobEventLoops.forEach { it.isIdling = false } } - override fun setChangedLight() { - super.setChangedLight() + override fun markDirtyFast() { + super.markDirtyFast() jobEventLoops.forEach { it.isIdling = false } } protected fun energyLevelUpdated() { - super.setChangedLight() + super.markDirtyFast() jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.POWER) } } @@ -121,7 +121,7 @@ abstract class MatteryWorkerBlockEntity( } protected fun matterLevelUpdated() { - super.setChangedLight() + super.markDirtyFast() jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.MATTER) } } @@ -130,16 +130,34 @@ abstract class MatteryWorkerBlockEntity( jobEventLoops.forEach { it.isIdling = newBlocked } } + private val hasWorkerState by countingLazy(blockStateChangesCounter) { + this.blockState.hasProperty(WorkerState.WORKER_STATE) + } + + private val isWorkingState by countingLazy(blockStateChangesCounter) { + hasWorkerState && this.blockState.getValue(WorkerState.WORKER_STATE) == WorkerState.WORKING + } + + private val isErrorState by countingLazy(blockStateChangesCounter) { + hasWorkerState && this.blockState.getValue(WorkerState.WORKER_STATE) == WorkerState.ERROR + } + + private val isIdleState by countingLazy(blockStateChangesCounter) { + hasWorkerState && this.blockState.getValue(WorkerState.WORKER_STATE) == WorkerState.IDLE + } + override fun tick() { super.tick() jobEventLoops.forEach { it.think() } - if (jobEventLoops.any { it.workingTicksAnim > 20 } && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.WORKING) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) - } else if (jobEventLoops.any { it.errorTicksAnim > 20 } && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.ERROR) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.ERROR), Block.UPDATE_CLIENTS) - } else if (jobEventLoops.all { it.idleTicksAnim > 20 } && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) + if (hasWorkerState) { + if (jobEventLoops.any { it.workingTicksAnim > 20 } && !isWorkingState) { + level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) + } else if (jobEventLoops.any { it.errorTicksAnim > 20 } && !isErrorState) { + level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.ERROR), Block.UPDATE_CLIENTS) + } else if (jobEventLoops.all { it.idleTicksAnim > 20 } && !isIdleState) { + level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt index a5daaf14a..7eadaf2e3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt @@ -34,9 +34,9 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery level?.lightEngine?.checkBlock(blockPos) }) - val fillInput = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) - val drainInput = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) - val output = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) + val fillInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) + val drainInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) + val output = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) val itemConfig = ConfigurableItemHandler( input = CombinedItemHandler( @@ -75,7 +75,7 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery private fun onChanged(new: FluidStack, old: FluidStack) { synchronizedFluid = new.copy() - setChangedLight() + markDirtyFast() } private fun drainItem() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt index d354bf5e9..19dd30f42 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt @@ -26,7 +26,7 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe return PainterMenu(containerID, inventory, this) } - val dyeInput = MatteryContainer(this::setChangedLight, 1) + val dyeInput = MatteryContainer(this::markDirtyFast, 1) private val dyeStored = EnumMap(DyeColor::class.java) val dyeStoredView: Map = Collections.unmodifiableMap(dyeStored) @@ -46,7 +46,7 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe } } - setChangedLight() + markDirtyFast() } val config = ConfigurableItemHandler(input = dyeInput.handler(object : HandlerFilter { 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 5e622489b..ae2a73a8f 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 @@ -31,7 +31,7 @@ import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, blockPos, blockState) { - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, MachinesConfig.MatterBottler.VALUES)) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.MatterBottler.VALUES)) val energyConfig = ConfigurableEnergy(energy) private inner class Container : MatteryContainer(3) { @@ -44,7 +44,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : } override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { - setChangedLight() + markDirtyFast() updateBlockState() } } @@ -57,7 +57,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : field = value initialCapacity = null workProgress = 0f - this.setChangedLight() + this.markDirtyFast() if (value) { inputHandler.parent = bottlingHandler @@ -73,7 +73,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : var spitItemsWhenCantWork = false set(value) { field = value - this.setChangedLight() + this.markDirtyFast() } val bottlingHandler = bottling.handler(object : HandlerFilter { @@ -97,7 +97,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : battery = batteryItemHandler ) - val matter: ProfiledMatterStorage = ProfiledMatterStorage(object : MatterStorageImpl(this::setChangedLight, FlowDirection.BI_DIRECTIONAL, MachinesConfig.MatterBottler.VALUES::matterCapacity) { + val matter: ProfiledMatterStorage = ProfiledMatterStorage(object : MatterStorageImpl(this::markDirtyFast, FlowDirection.BI_DIRECTIONAL, MachinesConfig.MatterBottler.VALUES::matterCapacity) { override val matterFlow: FlowDirection get() { return if (this@MatterBottlerBlockEntity.isBottling) FlowDirection.INPUT else FlowDirection.OUTPUT } 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 a45fd8958..b225e7f1a 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 @@ -120,7 +120,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) override val matterFlow: FlowDirection get() = FlowDirection.BI_DIRECTIONAL - val container = object : MatteryContainer(this::setChangedLight, BatteryBankBlockEntity.CAPACITY) { + val container = object : MatteryContainer(this::markDirtyFast, BatteryBankBlockEntity.CAPACITY) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { super.setChanged(slot, new, old) capacitorStatus[slot].boolean = new.getCapability(MatteryCapability.MATTER).isPresent 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 abab0b27d..4e93fe6be 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 @@ -54,15 +54,15 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) } } - override val upgrades = UpgradeContainer(this::setChangedLight, 4, UpgradeType.REPLICATOR) - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, upgrades.transform(MachinesConfig.MATTER_DECOMPOSER))) + override val upgrades = UpgradeContainer(this::markDirtyFast, 4, UpgradeType.REPLICATOR) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, upgrades.transform(MachinesConfig.MATTER_DECOMPOSER))) val energyConfig = ConfigurableEnergy(energy) init { savetables.stateful(::energy, ENERGY_KEY) } - val matter = ProfiledMatterStorage(MatterStorageImpl(::setChangedLight, FlowDirection.OUTPUT, upgrades.matterCapacity(MachinesConfig.MATTER_DECOMPOSER::matterCapacity))) + val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.OUTPUT, upgrades.matterCapacity(MachinesConfig.MATTER_DECOMPOSER::matterCapacity))) val matterNode = SimpleMatterNode(matter = matter) init { @@ -72,8 +72,8 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) } // вход, выход - val inputContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) - val outputContainer = MatteryContainer(::setChangedLight, 2).also(::addDroppableContainer) + val inputContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) + val outputContainer = MatteryContainer(::markDirtyFast, 2).also(::addDroppableContainer) val itemConfig = ConfigurableItemHandler( input = inputContainer.handler(object : HandlerFilter { 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 3e312cf0b..489a00ccc 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 @@ -52,9 +52,9 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState) var isUnableToProcess = false private set - val upgrades = UpgradeContainer(this::setChangedLight, 3, UpgradeType.REPLICATOR) - val matter = ProfiledMatterStorage(MatterStorageImpl(::setChangedLight, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MatterReconstructor.VALUES::matterCapacity))) - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::setChangedLight, upgrades.transform(MachinesConfig.MatterReconstructor.VALUES))) + val upgrades = UpgradeContainer(this::markDirtyFast, 3, UpgradeType.REPLICATOR) + val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MatterReconstructor.VALUES::matterCapacity))) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::markDirtyFast, upgrades.transform(MachinesConfig.MatterReconstructor.VALUES))) val matterNode = object : MatterNode() { override fun getMatterHandler(): IMatterStorage { 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 2717c81e7..7bf692a9d 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 @@ -48,7 +48,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer) val matterNode = SimpleMatterNode(matter = matter) - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, MachinesConfig.MatterRecycler.VALUES)) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, MachinesConfig.MatterRecycler.VALUES)) val itemConfig = ConfigurableItemHandler(input = container.handler(object : HandlerFilter { override fun canInsert(slot: Int, stack: ItemStack): Boolean { 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 a8a108693..76688494d 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 @@ -65,8 +65,8 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } } - override val upgrades = UpgradeContainer(this::setChangedLight, 3, UpgradeType.REPLICATOR) - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_REPLICATOR))) + override val upgrades = UpgradeContainer(this::markDirtyFast, 3, UpgradeType.REPLICATOR) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_REPLICATOR))) val matter = ProfiledMatterStorage(MatterStorageImpl(::matterLevelUpdated, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MATTER_REPLICATOR::matterCapacity))) val outputContainer = MatteryContainer(::itemContainerUpdated, 3).also(::addDroppableContainer) val dustContainer = MatteryContainer(::itemContainerUpdated, 2).also(::addDroppableContainer) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt index 1c64fd770..bd758bf51 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt @@ -31,9 +31,9 @@ import kotlin.math.pow class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryWorkerBlockEntity(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ItemJob.CODEC) { - override val upgrades = UpgradeContainer(this::setChangedLight, 2, UpgradeType.BASIC) + override val upgrades = UpgradeContainer(this::markDirtyFast, 2, UpgradeType.BASIC) val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer) - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_SCANNER))) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_SCANNER))) val itemConfig = ConfigurableItemHandler(inputOutput = container.handler(object : HandlerFilter { override fun canInsert(slot: Int, stack: ItemStack): Boolean { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt index 8e6c5f6d2..90ce6f6d1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt @@ -23,26 +23,26 @@ import ru.dbotthepony.mc.otm.storage.optics.powered import ru.dbotthepony.mc.otm.storage.optics.flow class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, blockPos, blockState) { - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, MachinesConfig.DRIVE_RACK)) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.DRIVE_RACK)) val cell = StorageNode(energy) val energyConfig = ConfigurableEnergy(energy) var insertPriority = 0 set(value) { field = value - setChangedLight() + markDirtyFast() } var extractPriority = 0 set(value) { field = value - setChangedLight() + markDirtyFast() } var mode = FlowDirection.BI_DIRECTIONAL set(value) { field = value - setChangedLight() + markDirtyFast() } val container: MatteryContainer = object : MatteryContainer(this::setChanged, 4) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt index fbe4d849c..87da29344 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt @@ -26,10 +26,10 @@ import ru.dbotthepony.mc.otm.menu.storage.DriveViewerMenu import java.util.UUID class DriveViewerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.DRIVE_VIEWER, blockPos, blockState) { - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyUpdated, MachinesConfig.DRIVE_VIEWER)) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyUpdated, MachinesConfig.DRIVE_VIEWER)) val energyConfig = ConfigurableEnergy(energy) - val container: MatteryContainer = object : MatteryContainer(this::setChangedLight, 1) { + val container: MatteryContainer = object : MatteryContainer(this::markDirtyFast, 1) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { super.setChanged(slot, new, old) @@ -63,13 +63,13 @@ class DriveViewerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte override var sorting: ItemStorageStackSorter = ItemStorageStackSorter.DEFAULT set(value) { field = value - setChangedLight() + markDirtyFast() } override var isAscending: Boolean = true set(value) { field = value - setChangedLight() + markDirtyFast() } } @@ -85,7 +85,7 @@ class DriveViewerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte if (state != blockState) { level?.setBlock(blockPos, state, Block.UPDATE_CLIENTS) } else { - setChangedLight() + markDirtyFast() } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt index b95bb3dfe..c4d3543e7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt @@ -45,7 +45,6 @@ import ru.dbotthepony.mc.otm.client.render.Widgets8 import ru.dbotthepony.mc.otm.container.CombinedContainer import ru.dbotthepony.mc.otm.container.addItem import ru.dbotthepony.mc.otm.container.fullIterator -import ru.dbotthepony.mc.otm.container.iterator import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.toList import ru.dbotthepony.mc.otm.core.isNotEmpty @@ -173,7 +172,7 @@ class ItemMonitorPlayerSettings : INBTSerializable, IItemMonitorPla } class ItemMonitorBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.ITEM_MONITOR, blockPos, blockState), IStorageEventConsumer { - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, MachinesConfig.ITEM_MONITOR)) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.ITEM_MONITOR)) val energyConfig = ConfigurableEnergy(energy) init { @@ -213,7 +212,7 @@ class ItemMonitorBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte // hence we are forced to work around this by providing proxy container val craftingGrid = object : MatteryContainer(3 * 3) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { - setChangedLight() + markDirtyFast() craftingGridVanilla[slot] = new if (!inProcessOfCraft) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt index dd37cadf8..d15bcee90 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt @@ -52,7 +52,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter return StorageBusMenu(containerID, inventory, this) } - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, MachinesConfig.STORAGE_INTERFACES)) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.STORAGE_INTERFACES)) val energyConfig = ConfigurableEnergy(energy, modesFront = FlowDirection.NONE) val cell: StorageNode = object : StorageNode(energy) { @@ -80,19 +80,19 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter var insertPriority = 0 set(value) { field = value - setChangedLight() + markDirtyFast() } var extractPriority = 0 set(value) { field = value - setChangedLight() + markDirtyFast() } var mode: FlowDirection = FlowDirection.BI_DIRECTIONAL set(value) { field = value - setChangedLight() + markDirtyFast() } init { @@ -123,7 +123,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter val filter = ItemFilter(MAX_FILTERS) { component?.scan() - setChangedLight() + markDirtyFast() } init { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt index da0082640..39907eb94 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt @@ -47,7 +47,7 @@ abstract class AbstractStorageImportExport( blockState: BlockState, energyValues: EnergyBalanceValues = MachinesConfig.STORAGE_INTERFACES ) : MatteryPoweredBlockEntity(blockType, blockPos, blockState) { - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::setChangedLight, energyValues)) + final override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::markDirtyFast, energyValues)) val energyConfig = ConfigurableEnergy(energy, modesFront = FlowDirection.NONE) val cell: StorageNode = object : StorageNode(energy) { @@ -115,7 +115,7 @@ class StorageImporterBlockEntity( blockPos: BlockPos, blockState: BlockState ) : AbstractStorageImportExport(MBlockEntities.STORAGE_IMPORTER, blockPos, blockState), IItemHandler { override val filter = ItemFilter(MAX_FILTERS) { - setChangedLight() + markDirtyFast() } private var lastSlot = 0 @@ -264,7 +264,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : lastSlot = 0 - setChangedLight() + markDirtyFast() }.also { it.isWhitelist = true } private var lastSlot = 0 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt index 64f4fdc01..a2a7214ef 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt @@ -22,7 +22,7 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState } val cell = StorageNode() - val energy = WorkerEnergyStorage(this::setChangedLight, MachinesConfig.STORAGE_POWER_SUPPLIER) + override val energy = WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.STORAGE_POWER_SUPPLIER) init { savetable(::energy, ENERGY_KEY) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidChargerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidChargerBlockEntity.kt index 943589746..88f41a6f2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidChargerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidChargerBlockEntity.kt @@ -25,7 +25,7 @@ class AndroidChargerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma return AndroidChargerMenu(containerID, inventory, this) } - val energyConfig = ConfigurableEnergy(ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, MachinesConfig.ANDROID_CHARGER)), modesTop = FlowDirection.NONE) + val energyConfig = ConfigurableEnergy(ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.ANDROID_CHARGER)), modesTop = FlowDirection.NONE) init { savetables.stateful(energyConfig::energy, ENERGY_KEY) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidStationBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidStationBlockEntity.kt index 878e8a789..95c323e12 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidStationBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AndroidStationBlockEntity.kt @@ -28,7 +28,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : return AndroidStationMenu(containerID, inventory, this) } - val energy: ProfiledEnergyStorage = ProfiledEnergyStorage(object : WorkerEnergyStorage(::setChangedLight, MachinesConfig.AndroidStation.VALUES) { + override val energy: ProfiledEnergyStorage = ProfiledEnergyStorage(object : WorkerEnergyStorage(::markDirtyFast, MachinesConfig.AndroidStation.VALUES) { override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { return super.extractEnergy(howMuch, simulate).also { if (!simulate && this.batteryLevel.isZero) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt index 8e429535c..fa1f08a61 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt @@ -88,7 +88,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte } if (!simulate && !summ.isZero) { - setChangedLight() + markDirtyFast() gaugeLevel = batteryLevel.percentage(maxBatteryLevel) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt index 04cf52774..0ef5e8939 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt @@ -24,15 +24,15 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe return ChemicalGeneratorMenu(containerID, inventory, this) } - val batteryContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) - val residueContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) - val fuelContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) + val batteryContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) + val residueContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) + val fuelContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) val batteryItemHandler = batteryContainer.handler(HandlerFilter.Chargeable) val residueItemHandler = residueContainer.handler(HandlerFilter.OnlyOut) val fuelItemHandler = fuelContainer.handler(HandlerFilter.ChemicalFuel) - val energy = ProfiledEnergyStorage(GeneratorEnergyStorage(::setChangedLight, MachinesConfig.ChemicalGenerator.VALUES::energyCapacity, MachinesConfig.ChemicalGenerator.VALUES::energyThroughput)) + val energy = ProfiledEnergyStorage(GeneratorEnergyStorage(::markDirtyFast, MachinesConfig.ChemicalGenerator.VALUES::energyCapacity, MachinesConfig.ChemicalGenerator.VALUES::energyThroughput)) val itemConfig = ConfigurableItemHandler( input = fuelItemHandler, @@ -55,8 +55,8 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe savetables.int(::workTicksTotal) } - override fun setChangedLight() { - super.setChangedLight() + override fun markDirtyFast() { + super.markDirtyFast() checkFuelSlot = true } @@ -106,9 +106,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe } if (energy.batteryLevel.isPositive) { - val item = batteryContainer[0] - - if (!item.isEmpty) { + for (item in batteryContainer) { item.energy?.also { moveEnergy(energy, it, MachinesConfig.ChemicalGenerator.VALUES.energyThroughput, simulate = false) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyServoBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyServoBlockEntity.kt index 9d6c16322..693606ea7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyServoBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyServoBlockEntity.kt @@ -22,8 +22,8 @@ import ru.dbotthepony.mc.otm.menu.tech.EnergyServoMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities class EnergyServoBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.ENERGY_SERVO, blockPos, blockState) { - val discharge = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) - val charge = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) + val discharge = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) + val charge = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) val energy: ProfiledEnergyStorage = ProfiledEnergyStorage(object : IMatteryEnergyStorage { override val energyFlow: FlowDirection get() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt index 0bac233a6..5862e0000 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt @@ -18,11 +18,11 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma set(value) { require(value >= 0L) { "Negative experience: $value" } field = value - setChangedLight() + markDirtyFast() } - val capsuleContainer = MatteryContainer(::setChangedLight, 1) - val servoContainer = MatteryContainer(::setChangedLight, 1) + val capsuleContainer = MatteryContainer(::markDirtyFast, 1) + val servoContainer = MatteryContainer(::markDirtyFast, 1) init { savetables.long(::experienceStored) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt index 30b72f565..3c2e7368d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt @@ -21,7 +21,6 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.container.balance import ru.dbotthepony.mc.otm.core.collect.filter -import ru.dbotthepony.mc.otm.core.collect.find import ru.dbotthepony.mc.otm.core.collect.maybe import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu @@ -29,12 +28,12 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MRecipes class PlatePressBlockEntity( - p_155229_: BlockPos, - p_155230_: BlockState, + blockPos: BlockPos, + blockState: BlockState, val isTwin: Boolean = false, -) : MatteryWorkerBlockEntity(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ItemJob.CODEC, if (isTwin) 2 else 1) { - override val upgrades = UpgradeContainer(this::setChangedLight, if (isTwin) 4 else 3, UpgradeType.BASIC_PROCESSING) - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(MachinesConfig.PLATE_PRESS))) +) : MatteryWorkerBlockEntity(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, blockPos, blockState, ItemJob.CODEC, if (isTwin) 2 else 1) { + override val upgrades = UpgradeContainer(this::markDirtyFast, if (isTwin) 4 else 3, UpgradeType.BASIC_PROCESSING) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(MachinesConfig.PLATE_PRESS))) val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) val outputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt index ab30d0401..ab5974e82 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt @@ -35,8 +35,8 @@ class PoweredFurnaceBlockEntity( val recipeType: RecipeType, val config: WorkerBalanceValues ) : MatteryWorkerBlockEntity(type, blockPos, blockState, ItemJob.CODEC, 2) { - override val upgrades = UpgradeContainer(this::setChangedLight, 2, UpgradeType.BASIC_PROCESSING) - val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config))) + override val upgrades = UpgradeContainer(this::markDirtyFast, 2, UpgradeType.BASIC_PROCESSING) + override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config))) val inputs = immutableList(2) { MatteryContainer(this::itemContainerUpdated, 1) } val outputs = immutableList(2) { MatteryContainer(this::itemContainerUpdated, 1) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt index 3d484f6d0..f63328fb4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt @@ -15,13 +15,18 @@ 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) + private var isTicking = false + + private fun startTicking() { + if (!isTicking) { + isTicking = true + storages.add(this) + } + } + val historyReceive: List = Collections.unmodifiableList(historyReceiveInternal) val historyTransfer: List = Collections.unmodifiableList(historyTransferInternal) @@ -47,6 +52,7 @@ abstract class AbstractProfiledStorage(val parent: P) : INBTSerializable< protected fun recordTransfer(value: Decimal, simulate: Boolean): Decimal { if (!simulate) { thisTickTransfer += value + if (!value.isZero) startTicking() } return value @@ -55,19 +61,23 @@ abstract class AbstractProfiledStorage(val parent: P) : INBTSerializable< protected fun recordReceive(value: Decimal, simulate: Boolean): Decimal { if (!simulate) { thisTickReceive += value + if (!value.isZero) startTicking() } return value } - private fun tick() { + private fun tick(): Boolean { tick = (tick + 1) % HISTORY_SIZE historyReceiveInternal[tick] = thisTickReceive historyTransferInternal[tick] = thisTickTransfer + isTicking = !thisTickReceive.isZero || !thisTickTransfer.isZero || historyReceiveInternal.any { !it.isZero } || historyTransferInternal.any { !it.isZero } thisTickReceive = Decimal.ZERO thisTickTransfer = Decimal.ZERO + + return isTicking } val savedata: INBTSerializable = object : INBTSerializable { @@ -155,7 +165,7 @@ abstract class AbstractProfiledStorage(val parent: P) : INBTSerializable< companion object { const val HISTORY_SIZE = 20 - private val storages = ObjectArrayList>>() + private val storages = ObjectArrayList>() val HISTORY_WEIGHTERS: ImmutableList = ImmutableList.of( Decimal("0.313335967"), @@ -201,7 +211,7 @@ abstract class AbstractProfiledStorage(val parent: P) : INBTSerializable< // разумеется, такое решение может несколько снизить производительность сервера, // но ничего страшного произойти не должно internal fun onServerPostTick() { - storages.forValidRefs { it.tick() } + storages.removeIf { !it.tick() } } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/AtomicallyInvalidatedLazy.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/AtomicallyInvalidatedLazy.kt index 239f96bce..76b16fe62 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/AtomicallyInvalidatedLazy.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/AtomicallyInvalidatedLazy.kt @@ -2,8 +2,14 @@ package ru.dbotthepony.mc.otm.core.util import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.locks.ReentrantLock +import java.util.function.IntSupplier + +/** + * If synchronization is not required, [CounterInvalidatedLazy] should be used instead. + */ +class AtomicallyInvalidatedLazy(private val invalidator: IntSupplier, private val initializer: () -> V) : Lazy { + constructor(invalidator: AtomicInteger, initializer: () -> V) : this(invalidator::get, initializer) -class AtomicallyInvalidatedLazy(private val invalidator: AtomicInteger, private val initializer: () -> V) : Lazy { @Volatile private var thisCounter = -1 @Volatile @@ -11,10 +17,10 @@ class AtomicallyInvalidatedLazy(private val invalidator: AtomicInteger, priva private val lock = ReentrantLock() override val value: V get() { - if (thisCounter != invalidator.get()) { + if (thisCounter != invalidator.asInt) { lock.lock() this.stored = Companion - thisCounter = invalidator.get() + thisCounter = invalidator.asInt lock.unlock() } @@ -35,7 +41,7 @@ class AtomicallyInvalidatedLazy(private val invalidator: AtomicInteger, priva } override fun isInitialized(): Boolean { - return stored !== Companion && thisCounter == invalidator.get() + return stored !== Companion && thisCounter == invalidator.asInt } private companion object diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt new file mode 100644 index 000000000..eb277cdc3 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt @@ -0,0 +1,80 @@ +package ru.dbotthepony.mc.otm.core.util + +import java.util.concurrent.atomic.AtomicInteger +import java.util.function.IntConsumer +import java.util.function.IntSupplier + +/** + * This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined + * + * For synchronized use case, [AtomicallyInvalidatedLazy] should be used + */ +fun countingLazy(invalidator: IntSupplier, initializer: () -> V): Lazy { + if (invalidator is IntCounter) { + return SmartCounterInvalidatedLazy(invalidator, initializer) + } + + return CounterInvalidatedLazy(invalidator, initializer) +} + +/** + * This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined + * + * For synchronized use case, [AtomicallyInvalidatedLazy] should be used + */ +class CounterInvalidatedLazy(private val invalidator: IntSupplier, private val initializer: () -> V) : Lazy { + constructor(invalidator: AtomicInteger, initializer: () -> V) : this(invalidator::get, initializer) + + private var thisCounter = -1 + private var stored: Any? = Companion + + override val value: V get() { + var stored = stored + + if (stored !== Companion && thisCounter == invalidator.asInt) + return stored as V + + stored = initializer.invoke() + this.stored = stored + this.thisCounter = invalidator.asInt + return stored + } + + override fun isInitialized(): Boolean { + return stored !== Companion && thisCounter == invalidator.asInt + } + + private companion object +} + +/** + * This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined + * + * For synchronized use case, [AtomicallyInvalidatedLazy] should be used + */ +class SmartCounterInvalidatedLazy(invalidator: IntCounter, private val initializer: () -> V) : Lazy { + init { + invalidator.addListener(IntConsumer { + stored = Companion + }) + } + + private var stored: Any? = Companion + + override val value: V get() { + var stored = stored + + if (stored !== Companion) + return stored as V + + stored = initializer.invoke() + this.stored = stored + return stored + } + + override fun isInitialized(): Boolean { + return stored !== Companion + } + + private companion object +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt new file mode 100644 index 000000000..0c4c56e23 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt @@ -0,0 +1,59 @@ +package ru.dbotthepony.mc.otm.core.util + +import ru.dbotthepony.mc.otm.core.IIntSubcripable +import ru.dbotthepony.mc.otm.core.ISubscriptable +import java.util.function.BooleanSupplier +import java.util.function.IntConsumer +import java.util.function.IntSupplier + +class IntCounter : IntSupplier, IIntSubcripable { + /** + * Doesn't subscribe to counter (counter does not reference this invalidator) + */ + inner class WeakInvalidator : BooleanSupplier { + private var thisValue = value + + override fun getAsBoolean(): Boolean { + if (thisValue != value) { + thisValue = value + return true + } + + return false + } + } + + /** + * Subscribes to counter (counter references this invalidator, can be removed using [remove]) + */ + inner class StrongInvalidator : BooleanSupplier, ISubscriptable.L { + private var isValid = true + private val l = listeners.addListener(IntConsumer { isValid = false }) + + override fun getAsBoolean(): Boolean { + val isValid = isValid + this.isValid = true + return isValid + } + + override fun remove() { + l.remove() + } + } + + private val listeners = IIntSubcripable.Impl() + private var value = 0 + + fun increment() { + value++ + listeners.accept(value) + } + + override fun addListener(listener: IntConsumer): ISubscriptable.L { + return listeners.addListener(listener) + } + + override fun getAsInt(): Int { + return value + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt index 7062a7054..3b74ac44b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt @@ -18,6 +18,8 @@ class TickList : ITickable { private val timers = ArrayDeque() private val namedTimers = Object2ObjectOpenHashMap(0) + private var shouldTick = false + var inTicker = false private set var ticks = 0 @@ -92,6 +94,8 @@ class TickList : ITickable { } private fun add(value: T, regular: MutableList, queue: MutableList) { + shouldTick = true + if (inTicker) { queue.add(value) } else { @@ -148,10 +152,14 @@ class TickList : ITickable { } ticks++ + if (!shouldTick) return + inTicker = true + shouldTick = timers.isNotEmpty() try { if (conditional.isNotEmpty()) { + shouldTick = true val iterator = conditional.iterator() for (ticker in iterator) { @@ -162,6 +170,8 @@ class TickList : ITickable { } if (once.isNotEmpty()) { + shouldTick = true + for (ticker in once) { ticker.tick() } @@ -170,23 +180,31 @@ class TickList : ITickable { } if (toRemoveFromAlways.isNotEmpty()) { + shouldTick = true + for (v in toRemoveFromAlways) always.remove(v) toRemoveFromAlways.clear() } if (always.isNotEmpty()) { + shouldTick = true + for (ticker in always) { ticker.tick() } } if (alwaysQueued.isNotEmpty()) { + shouldTick = true + always.ensureCapacity(always.size + alwaysQueued.size) for (v in alwaysQueued) always.add(v) // avoid toArray() alwaysQueued.clear() } if (conditionalQueued.isNotEmpty()) { + shouldTick = true + for (ticker in conditionalQueued) { conditional.addFirst(ticker) } @@ -195,6 +213,8 @@ class TickList : ITickable { } if (onceQueued.isNotEmpty()) { + shouldTick = true + for (ticker in onceQueued) { once.addFirst(ticker) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryPoweredMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryPoweredMenu.kt index a9b5cec8a..8f0e8ca81 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryPoweredMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryPoweredMenu.kt @@ -6,7 +6,6 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import net.minecraft.world.SimpleContainer import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting -import ru.dbotthepony.mc.otm.capability.matteryEnergy import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback abstract class MatteryPoweredMenu protected constructor( @@ -15,7 +14,7 @@ abstract class MatteryPoweredMenu protected constructor( inventory: Inventory, tile: MatteryPoweredBlockEntity? = null ) : MatteryMenu(menuType, containerID, inventory, tile) { - val energyWidget = LevelGaugeWidget(this, tile?.matteryEnergy) + val energyWidget = LevelGaugeWidget(this, tile?.energy) val batterySlot = BatterySlot(tile?.batteryContainer ?: SimpleContainer(1), 0) val redstoneConfig = EnumInputWithFeedback(this)