Microwave oven in-world rendering
This commit is contained in:
parent
ef4f65656c
commit
2dcfa99f9c
@ -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
|
||||
))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user