From 2dcfa99f9c7475bda7429f2232c88a49d72efc17 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 5 Jan 2024 19:18:10 +0700 Subject: [PATCH] Microwave oven in-world rendering --- .../tech/AbstractPoweredFurnaceBlockEntity.kt | 34 +++++++-- .../blockentity/MatterReplicatorRenderer.kt | 2 +- .../blockentity/PoweredSmokerRenderer.kt | 69 +++++++++++++++++++ .../mc/otm/core/util/Savetables.kt | 5 +- .../mc/otm/registry/MBlockEntities.kt | 1 + 5 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/PoweredSmokerRenderer.kt 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) }