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 76b08ebb7..99bb0d976 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 @@ -1,7 +1,9 @@ package ru.dbotthepony.mc.otm.block.entity +import com.google.common.collect.ImmutableList import net.minecraft.core.BlockPos import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.ListTag import net.minecraft.network.chat.Component import net.minecraft.world.item.ItemStack import net.minecraft.world.item.TooltipFlag @@ -12,12 +14,14 @@ import net.minecraft.world.level.block.state.BlockState 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.math.Decimal +import ru.dbotthepony.mc.otm.core.nbt.getCompoundList import ru.dbotthepony.mc.otm.core.nbt.map import ru.dbotthepony.mc.otm.core.nbt.set /** - * Simple machine, which can work on only one job at time. + * Simple machine, which can work on only one job type. * * From technical point, this is a specialized use case of [MachineJobEventLoop]. */ @@ -25,32 +29,35 @@ abstract class MatteryWorkerBlockEntity( type: BlockEntityType<*>, blockPos: BlockPos, blockState: BlockState, - val jobDeserializer: (tag: CompoundTag) -> JobType? + val jobDeserializer: (tag: CompoundTag) -> JobType?, + maxJobs: Int = 1 ) : MatteryPoweredBlockEntity(type, blockPos, blockState) { - val jobEventLoop = object : MachineJobEventLoop() { - override val energy: IMatteryEnergyStorage? - get() = matteryEnergy - override val isBlockedByRedstone: Boolean - get() = redstoneControl.isBlockedByRedstone + val jobEventLoops: ImmutableList> = immutableList(maxJobs) { + object : MachineJobEventLoop() { + override val energy: IMatteryEnergyStorage? + get() = matteryEnergy + override val isBlockedByRedstone: Boolean + get() = redstoneControl.isBlockedByRedstone - override fun deserializeJob(nbt: CompoundTag): JobType? { - return jobDeserializer.invoke(nbt) - } + override fun deserializeJob(nbt: CompoundTag): JobType? { + return jobDeserializer.invoke(nbt) + } - override fun onJobFinish(job: JobType): JobStatus { - return this@MatteryWorkerBlockEntity.onJobFinish(job) - } + override fun onJobFinish(job: JobType): JobStatus { + return this@MatteryWorkerBlockEntity.onJobFinish(job) + } - override fun computeNextJob(): JobContainer { - return this@MatteryWorkerBlockEntity.computeNextJob() - } + override fun computeNextJob(): JobContainer { + return this@MatteryWorkerBlockEntity.computeNextJob() + } - override fun jobUpdated(new: JobType?, old: JobType?) { - this@MatteryWorkerBlockEntity.jobUpdated(new, old) - } + override fun jobUpdated(new: JobType?, old: JobType?) { + this@MatteryWorkerBlockEntity.jobUpdated(new, old) + } - override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: JobType): JobStatus { - return this@MatteryWorkerBlockEntity.onWorkTick(requiredPower, extractedPower, ticksAdvanced, job) + override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: JobType): JobStatus { + return this@MatteryWorkerBlockEntity.onWorkTick(requiredPower, extractedPower, ticksAdvanced, job) + } } } @@ -64,53 +71,68 @@ abstract class MatteryWorkerBlockEntity( override fun saveShared(nbt: CompoundTag) { super.saveShared(nbt) - nbt["JobLoop"] = jobEventLoop.serializeNBT() + nbt["jobs"] = ListTag().also { + for ((i, job) in jobEventLoops.withIndex()) { + it.add(job.serializeNBT().also { + it["_id"] = i + }) + } + } } override fun load(nbt: CompoundTag) { super.load(nbt) - nbt.map("JobLoop", jobEventLoop::deserializeNBT) + + for (v in nbt.getCompoundList("jobs")) { + if ("_id" in v) { + val id = v.getInt("_id") + + if (id in jobEventLoops.indices) { + jobEventLoops[id].deserializeNBT(v) + } + } + } } override fun setChanged() { super.setChanged() - jobEventLoop.isIdling = false + jobEventLoops.forEach { it.isIdling = false } } override fun setChangedLight() { super.setChangedLight() - jobEventLoop.isIdling = false + jobEventLoops.forEach { it.isIdling = false } } protected fun powerLevelUpdated() { super.setChangedLight() - jobEventLoop.notify(MachineJobEventLoop.IdleReason.POWER) + jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.POWER) } } protected fun itemContainerUpdated() { super.setChanged() - jobEventLoop.notify(MachineJobEventLoop.IdleReason.ITEM) + jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.ITEM) } } protected fun matterLevelUpdated() { super.setChangedLight() - jobEventLoop.notify(MachineJobEventLoop.IdleReason.MATTER) + jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.MATTER) } } override fun redstoneStatusUpdated(newBlocked: Boolean, oldBlocked: Boolean) { super.redstoneStatusUpdated(newBlocked, oldBlocked) - jobEventLoop.isIdling = newBlocked + jobEventLoops.forEach { it.isIdling = newBlocked } } override fun tick() { super.tick() - jobEventLoop.think() + jobEventLoops.forEach { it.think() } - if (jobEventLoop.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 (jobEventLoop.workingTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.WORKING) { + 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 (jobEventLoop.idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) { + } 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) } }