diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt
index b8ea06589..ed41c96f8 100644
--- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt
@@ -5,6 +5,7 @@ import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
+import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.AbstractCookingRecipe
import net.minecraft.world.item.crafting.BlastingRecipe
import net.minecraft.world.item.crafting.RecipeType
@@ -44,19 +45,31 @@ sealed class AbstractPoweredFurnaceBlockEntity
,
val secondaryRecipeType: RecipeType?,
- val config: WorkerBalanceValues
-) : MatteryWorkerBlockEntity(type, blockPos, blockState, ItemJob.CODEC, 2) {
+ val config: WorkerBalanceValues,
+ maxJobs: Int = 2
+) : MatteryWorkerBlockEntity(type, blockPos, blockState, ItemJob.CODEC, maxJobs) {
final override val upgrades = UpgradeContainer(this::markDirtyFast, 2, UpgradeType.BASIC_PROCESSING)
final 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) }
+ val inputs = immutableList(maxJobs) { MatteryContainer(this::itemContainerUpdated, 1) }
+ val outputs = immutableList(maxJobs) { MatteryContainer(this::itemContainerUpdated, 1) }
init {
inputs.forEach { addDroppableContainer(it) }
outputs.forEach { addDroppableContainer(it) }
}
+ inner class SyncSlot {
+ var inputItem by synchronizer.item(observe = false)
+ var outputItem by synchronizer.item(observe = false)
+ var progress by synchronizer.float().property
+ var visualRotation = 0f
+ }
+
+ var lastRender = 0L
+
+ val syncSlots = immutableList(maxJobs) { SyncSlot() }
+
val experience = ExperienceStorage(config::maxExperienceStored).also(::addNeighbourListener)
val energyConfig = ConfigurableEnergy(energy)
val itemConfig = ConfigurableItemHandler(
@@ -90,11 +103,19 @@ sealed class AbstractPoweredFurnaceBlockEntity, id: Int) {
if (outputs[id].fullyAddItem(status.job.itemStack)) {
experience.storeExperience(status.experience, this)
+ syncSlots[id].inputItem = ItemStack.EMPTY
+ syncSlots[id].outputItem = ItemStack.EMPTY
+ syncSlots[id].progress = 0f
} else {
status.noItem()
}
}
+ override fun onJobTick(status: JobStatus, id: Int) {
+ super.onJobTick(status, id)
+ syncSlots[id].progress = status.workProgress
+ }
+
override fun computeNextJob(id: Int): JobContainer {
if (!energy.batteryLevel.isPositive)
return JobContainer.noEnergy()
@@ -129,9 +150,14 @@ sealed class AbstractPoweredFurnaceBlockEntity 30_000_000L) {
- tile.particleRenderScore = tile.particleRenderScore % 30_000_000L
+ tile.particleRenderScore %= 30_000_000L
if (rand.nextDouble() > 0.75 && !isPaused && tile.blockState[WorkerState.WORKER_STATE] == WorkerState.WORKING) {
val (x, y, z) = tile.blockPos
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/PoweredSmokerRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/PoweredSmokerRenderer.kt
new file mode 100644
index 000000000..5790041a7
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/PoweredSmokerRenderer.kt
@@ -0,0 +1,69 @@
+package ru.dbotthepony.mc.otm.client.render.blockentity
+
+import com.mojang.blaze3d.vertex.PoseStack
+import net.minecraft.client.renderer.MultiBufferSource
+import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
+import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
+import net.minecraft.world.item.ItemDisplayContext
+import ru.dbotthepony.mc.otm.block.entity.tech.AbstractPoweredFurnaceBlockEntity
+import ru.dbotthepony.mc.otm.core.math.normalizeAngle
+import ru.dbotthepony.mc.otm.core.math.rotateY
+
+class PoweredSmokerRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer> {
+ override fun render(tile: AbstractPoweredFurnaceBlockEntity<*, *>, partialTick: Float, pose: PoseStack, buffers: MultiBufferSource, packedLight: Int, packedOverlay: Int) {
+ val diff = System.nanoTime() - tile.lastRender
+ tile.lastRender = System.nanoTime()
+
+ for (slot in tile.syncSlots) {
+ if (slot.inputItem.isEmpty && slot.outputItem.isEmpty) continue
+ slot.visualRotation = normalizeAngle(slot.visualRotation + diff / 400_000_000f)
+
+ pose.pushPose()
+ pose.translate(0.625f, 0.5f, 0.5f)
+ pose.scale(0.25f, 0.25f, 0.25f)
+
+ pose.rotateY(slot.visualRotation)
+
+ if (slot.progress <= 0.8f && !slot.inputItem.isEmpty) {
+ val model = context.itemRenderer.getModel(
+ slot.inputItem,
+ tile.level,
+ null,
+ 0
+ )
+
+ context.itemRenderer.render(
+ slot.inputItem,
+ ItemDisplayContext.NONE,
+ false,
+ pose,
+ buffers,
+ packedLight,
+ packedOverlay,
+ model
+ )
+ } else if (slot.progress > 0.8f && !slot.outputItem.isEmpty) {
+ val model = context.itemRenderer.getModel(
+ slot.outputItem,
+ tile.level,
+ null,
+ 0
+ )
+
+ context.itemRenderer.render(
+ slot.outputItem,
+ ItemDisplayContext.NONE,
+ false,
+ pose,
+ buffers,
+ packedLight,
+ packedOverlay,
+ model
+ )
+ }
+
+ pose.popPose()
+ break
+ }
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt
index bd8a2b099..e348fb661 100644
--- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt
@@ -52,9 +52,10 @@ class Savetables : INBTSerializable {
return stateful(getter, name, T::class.java)
}
- inline fun , reified T : Tag> stateful(values: List, name: String): ImmutableList> {
+ inline fun , reified T : Tag> stateful(values: Collection, name: String): ImmutableList> {
+ val iterator = values.iterator()
return immutableList(values.size) {
- stateful(values[it], "${name}_$it", T::class.java)
+ stateful(iterator.next(), "${name}_$it", T::class.java)
}
}
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt
index 4795cabdc..0c6d5bab5 100644
--- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt
@@ -118,6 +118,7 @@ object MBlockEntities {
BlockEntityRenderers.register(MATTER_RECONSTRUCTOR, ::MatterReconstructorRenderer)
BlockEntityRenderers.register(MATTER_REPLICATOR, ::MatterReplicatorRenderer)
BlockEntityRenderers.register(MATTER_SCANNER, ::MatterScannerRenderer)
+ BlockEntityRenderers.register(POWERED_SMOKER, ::PoweredSmokerRenderer)
BlockEntityRenderers.register(HOLO_SIGN, ::HoloSignRenderer)
BlockEntityRenderers.register(FLUID_TANK, ::FluidTankRenderer)
}