Microwave oven in-world rendering

This commit is contained in:
DBotThePony 2024-01-05 19:18:10 +07:00
parent ef4f65656c
commit 2dcfa99f9c
Signed by: DBot
GPG Key ID: DCC23B5715498507
5 changed files with 104 additions and 7 deletions

View File

@ -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<P : AbstractCookingRecipe, S : Ma
blockState: BlockState,
val recipeType: RecipeType<P>,
val secondaryRecipeType: RecipeType<S>?,
val config: WorkerBalanceValues
) : MatteryWorkerBlockEntity<ItemJob>(type, blockPos, blockState, ItemJob.CODEC, 2) {
val config: WorkerBalanceValues,
maxJobs: Int = 2
) : MatteryWorkerBlockEntity<ItemJob>(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<P : AbstractCookingRecipe, S : Ma
override fun onJobFinish(status: JobStatus<ItemJob>, 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<ItemJob>, id: Int) {
super.onJobTick(status, id)
syncSlots[id].progress = status.workProgress
}
override fun computeNextJob(id: Int): JobContainer<ItemJob> {
if (!energy.batteryLevel.isPositive)
return JobContainer.noEnergy()
@ -129,9 +150,14 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
return level.recipeManager.getRecipeFor(recipeType, inputs[id], level).map {
val output = it.value.assemble(inputs[id], level.registryAccess())
val inputItem = inputs[id][0].copyWithCount(1)
val toProcess = inputs[id][0].count.coerceAtMost(upgrades.processingItems + 1)
inputs[id][0].shrink(toProcess)
syncSlots[id].inputItem = inputItem
syncSlots[id].outputItem = output.copy()
syncSlots[id].progress = 0f
JobContainer.success(ItemJob(
output.copyWithCount(toProcess), it.value.cookingTime * config.workTimeMultiplier, config.energyConsumption * toProcess, it.value.experience * toProcess
))

View File

@ -58,7 +58,7 @@ class MatterReplicatorRenderer(private val context: BlockEntityRendererProvider.
tile.particleRenderScore += diff
if (tile.particleRenderScore > 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

View File

@ -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<AbstractPoweredFurnaceBlockEntity<*, *>> {
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
}
}
}

View File

@ -52,9 +52,10 @@ class Savetables : INBTSerializable<CompoundTag?> {
return stateful(getter, name, T::class.java)
}
inline fun <V : INBTSerializable<T?>, reified T : Tag> stateful(values: List<V>, name: String): ImmutableList<Stateful<V, T>> {
inline fun <V : INBTSerializable<T?>, reified T : Tag> stateful(values: Collection<V>, name: String): ImmutableList<Stateful<V, T>> {
val iterator = values.iterator()
return immutableList(values.size) {
stateful(values[it], "${name}_$it", T::class.java)
stateful(iterator.next(), "${name}_$it", T::class.java)
}
}

View File

@ -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)
}