Allow MatteryWorkerBlockEntity to have multiple job event loops

This commit is contained in:
DBotThePony 2023-06-23 00:00:35 +07:00
parent 4e62b47f84
commit 97d3a07065
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -1,7 +1,9 @@
package ru.dbotthepony.mc.otm.block.entity package ru.dbotthepony.mc.otm.block.entity
import com.google.common.collect.ImmutableList
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag 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.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matteryEnergy 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.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.map
import ru.dbotthepony.mc.otm.core.nbt.set 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]. * From technical point, this is a specialized use case of [MachineJobEventLoop].
*/ */
@ -25,32 +29,35 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
type: BlockEntityType<*>, type: BlockEntityType<*>,
blockPos: BlockPos, blockPos: BlockPos,
blockState: BlockState, blockState: BlockState,
val jobDeserializer: (tag: CompoundTag) -> JobType? val jobDeserializer: (tag: CompoundTag) -> JobType?,
maxJobs: Int = 1
) : MatteryPoweredBlockEntity(type, blockPos, blockState) { ) : MatteryPoweredBlockEntity(type, blockPos, blockState) {
val jobEventLoop = object : MachineJobEventLoop<JobType>() { val jobEventLoops: ImmutableList<MachineJobEventLoop<JobType>> = immutableList(maxJobs) {
override val energy: IMatteryEnergyStorage? object : MachineJobEventLoop<JobType>() {
get() = matteryEnergy override val energy: IMatteryEnergyStorage?
override val isBlockedByRedstone: Boolean get() = matteryEnergy
get() = redstoneControl.isBlockedByRedstone override val isBlockedByRedstone: Boolean
get() = redstoneControl.isBlockedByRedstone
override fun deserializeJob(nbt: CompoundTag): JobType? { override fun deserializeJob(nbt: CompoundTag): JobType? {
return jobDeserializer.invoke(nbt) return jobDeserializer.invoke(nbt)
} }
override fun onJobFinish(job: JobType): JobStatus { override fun onJobFinish(job: JobType): JobStatus {
return this@MatteryWorkerBlockEntity.onJobFinish(job) return this@MatteryWorkerBlockEntity.onJobFinish(job)
} }
override fun computeNextJob(): JobContainer<JobType> { override fun computeNextJob(): JobContainer<JobType> {
return this@MatteryWorkerBlockEntity.computeNextJob() return this@MatteryWorkerBlockEntity.computeNextJob()
} }
override fun jobUpdated(new: JobType?, old: JobType?) { override fun jobUpdated(new: JobType?, old: JobType?) {
this@MatteryWorkerBlockEntity.jobUpdated(new, old) this@MatteryWorkerBlockEntity.jobUpdated(new, old)
} }
override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: JobType): JobStatus { override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: JobType): JobStatus {
return this@MatteryWorkerBlockEntity.onWorkTick(requiredPower, extractedPower, ticksAdvanced, job) return this@MatteryWorkerBlockEntity.onWorkTick(requiredPower, extractedPower, ticksAdvanced, job)
}
} }
} }
@ -64,53 +71,68 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
override fun saveShared(nbt: CompoundTag) { override fun saveShared(nbt: CompoundTag) {
super.saveShared(nbt) 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) { override fun load(nbt: CompoundTag) {
super.load(nbt) 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() { override fun setChanged() {
super.setChanged() super.setChanged()
jobEventLoop.isIdling = false jobEventLoops.forEach { it.isIdling = false }
} }
override fun setChangedLight() { override fun setChangedLight() {
super.setChangedLight() super.setChangedLight()
jobEventLoop.isIdling = false jobEventLoops.forEach { it.isIdling = false }
} }
protected fun powerLevelUpdated() { protected fun powerLevelUpdated() {
super.setChangedLight() super.setChangedLight()
jobEventLoop.notify(MachineJobEventLoop.IdleReason.POWER) jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.POWER) }
} }
protected fun itemContainerUpdated() { protected fun itemContainerUpdated() {
super.setChanged() super.setChanged()
jobEventLoop.notify(MachineJobEventLoop.IdleReason.ITEM) jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.ITEM) }
} }
protected fun matterLevelUpdated() { protected fun matterLevelUpdated() {
super.setChangedLight() super.setChangedLight()
jobEventLoop.notify(MachineJobEventLoop.IdleReason.MATTER) jobEventLoops.forEach { it.notify(MachineJobEventLoop.IdleReason.MATTER) }
} }
override fun redstoneStatusUpdated(newBlocked: Boolean, oldBlocked: Boolean) { override fun redstoneStatusUpdated(newBlocked: Boolean, oldBlocked: Boolean) {
super.redstoneStatusUpdated(newBlocked, oldBlocked) super.redstoneStatusUpdated(newBlocked, oldBlocked)
jobEventLoop.isIdling = newBlocked jobEventLoops.forEach { it.isIdling = newBlocked }
} }
override fun tick() { override fun tick() {
super.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) { 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.ERROR), Block.UPDATE_CLIENTS)
} else if (jobEventLoop.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) 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) level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
} }
} }