Skip to content

Commit

Permalink
Fluid rendering, complete
Browse files Browse the repository at this point in the history
  • Loading branch information
ATPStorages committed May 3, 2024
1 parent 5b6bba4 commit 8a5c726
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 34 deletions.
25 changes: 18 additions & 7 deletions src/main/kotlin/breadmod/block/entity/DoughMachineBlockEntity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ class DoughMachineBlockEntity(
pPos: BlockPos,
pBlockState: BlockState
) : BlockEntity(ModBlockEntities.DOUGH_MACHINE.get(), pPos, pBlockState), MenuProvider {
val data = SimpleContainerData(6)
val data = SimpleContainerData(7)
init { data[1] = MAX_PROGRESS }

val itemHandlerOptional: LazyOptional<ItemStackHandler> = LazyOptional.of {
object : ItemStackHandler(3) {
override fun onContentsChanged(slot: Int) = setChanged()
}
}
val energyHandlerOptional: LazyOptional<EnergyStorage> = LazyOptional.of {
object : EnergyStorage(100000000, 2000) {
private val energyHandlerOptional: LazyOptional<EnergyStorage> = LazyOptional.of {
object : EnergyStorage(50000, 2000) {
override fun receiveEnergy(maxReceive: Int, simulate: Boolean): Int = super.receiveEnergy(maxReceive, simulate).also {
setChanged()
data[2] = energyStored
Expand All @@ -58,8 +58,10 @@ class DoughMachineBlockEntity(
}
}.also { data[3] = it.maxEnergyStored }
}
val fluidHandlerOptional: LazyOptional<FluidTank> = LazyOptional.of {
object : FluidTank(5000) {

private var lastFluidCount = 0
private val fluidHandlerOptional: LazyOptional<FluidTank> = LazyOptional.of {
object : FluidTank(50000) {
override fun onContentsChanged() {
setChanged()
data[4] = fluidAmount
Expand Down Expand Up @@ -107,9 +109,15 @@ class DoughMachineBlockEntity(
override fun load(pTag: CompoundTag) {
super.load(pTag)
val dataTag = pTag.getCompound(BreadMod.ID)
energyHandlerOptional.ifPresent { it.deserializeNBT(dataTag.get("energy")) }
energyHandlerOptional.ifPresent {
it.deserializeNBT(dataTag.get("energy"))
data[2] = it.energyStored; data[3] = it.maxEnergyStored
}
fluidHandlerOptional.ifPresent {
it.readFromNBT(dataTag.getCompound("fluids"))
data[4] = it.fluidAmount; data[5] = it.capacity
}
itemHandlerOptional.ifPresent { it.deserializeNBT(dataTag.getCompound("items")) }
fluidHandlerOptional.ifPresent { it.readFromNBT(dataTag.getCompound("fluids")) }
}

override fun getUpdateTag(): CompoundTag = super.getUpdateTag().also { saveAdditional(it) }
Expand All @@ -120,6 +128,9 @@ class DoughMachineBlockEntity(
val fluidHandle = pBlockEntity.fluidHandlerOptional.resolve().getOrNull() ?: return
val itemHandle = pBlockEntity.itemHandlerOptional.resolve().getOrNull() ?: return

data[6] = fluidHandle.fluidAmount.compareTo(lastFluidCount)
lastFluidCount = fluidHandle.fluidAmount

itemHandle.getStackInSlot(2).let {
if(!it.isEmpty && (it.item as? BucketItem)?.fluid?.isSame(Fluids.WATER) == true && fluidHandle.space > 1000) {
fluidHandle.fill(FluidStack(Fluids.WATER, 1000), IFluidHandler.FluidAction.EXECUTE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class DoughMachineMenu(

fun getScaledProgress(): Int = ((parent.data[0].toFloat() / DoughMachineBlockEntity.MAX_PROGRESS) * 24).toInt()
fun getEnergyStoredScaled(): Int = ((parent.data[2].toFloat() / parent.data[3]) * 47).toInt()
fun getFluidStoredScaled(): Int = ((parent.data[4].toFloat() / parent.data[5]) * 47).toInt()
fun isCrafting(): Boolean = parent.data[0] > 0

class DoughMachineResultSlot(handler: IItemHandler) : SlotItemHandler(handler,1, 78, 35) {
Expand Down
49 changes: 27 additions & 22 deletions src/main/kotlin/breadmod/block/entity/menu/DoughMachineScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@ package breadmod.block.entity.menu

import breadmod.BreadMod
import breadmod.util.formatUnit
import breadmod.util.renderFluid
import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
import net.minecraft.client.renderer.GameRenderer
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.level.material.Fluids

class DoughMachineScreen(
pMenu: DoughMachineMenu,
pPlayerInventory: Inventory,
pTitle: Component
pTitle: Component,
) : AbstractContainerScreen<DoughMachineMenu>(pMenu, pPlayerInventory, pTitle) {
val texture = ResourceLocation(BreadMod.ID, "textures/gui/container/dough_machine.png")

Expand All @@ -22,34 +24,40 @@ class DoughMachineScreen(
RenderSystem.setShaderColor(1.0F,1.0F,1.0F,1.0F)
RenderSystem.setShaderTexture(0, texture)

val x = (width - imageWidth) / 2
val y = (height - imageHeight) / 2
pGuiGraphics.blit(texture, leftPos, topPos, 0, 0, imageWidth, imageHeight)

pGuiGraphics.blit(texture, x, y, 0, 0, imageWidth, imageHeight)

renderProgressArrow(pGuiGraphics, x, y)
renderEnergyMeter(pGuiGraphics, x, y)
renderFluidMeter(pGuiGraphics, x, y)
renderProgressArrow(pGuiGraphics)
renderEnergyMeter(pGuiGraphics)
}

private fun renderProgressArrow(pGuiGraphics : GuiGraphics, x : Int, y : Int) {
if(menu.isCrafting()) {
pGuiGraphics.blit(texture, x + 46, y + 35, 176, 0, menu.getScaledProgress(), 17)
}
private fun renderProgressArrow(pGuiGraphics: GuiGraphics) {
if(menu.isCrafting())
pGuiGraphics.blit(texture, leftPos + 46, topPos + 35, 176, 0, menu.getScaledProgress(), 17)
}

private fun renderEnergyMeter(pGuiGraphics: GuiGraphics, x: Int, y: Int) {
private fun renderEnergyMeter(pGuiGraphics: GuiGraphics) {
val energyStored = menu.getEnergyStoredScaled()
pGuiGraphics.blit(texture, x + 132, y + 28 + 47 - energyStored, 176, 64 - energyStored, 16, 47)
}

private fun renderFluidMeter(pGuiGraphics: GuiGraphics, x: Int, y: Int) {
val fluidStored = menu.getFluidStoredScaled()
pGuiGraphics.blit(texture, x + 153, y + 28 + 47 - fluidStored, 192, 64 - fluidStored, 16, 47)
pGuiGraphics.blit(texture, leftPos + 132, topPos + 28 + 47 - energyStored, 176, 64 - energyStored, 16, 47)
}

override fun render(pGuiGraphics: GuiGraphics, pMouseX: Int, pMouseY: Int, delta: Float) {
renderBackground(pGuiGraphics)
super.render(pGuiGraphics, pMouseX, pMouseY, delta)

val fluid = menu.parent.data[4]
val maxFluid = menu.parent.data[5]
if(fluid > 0) {
val fluidDelta = menu.parent.data[6]
val percentage = (fluid.toFloat() / maxFluid) * 47
pGuiGraphics.renderFluid(
leftPos + 153F,
(topPos + 75F),
if(fluidDelta == 1) -16 else 16,
percentage.toInt(),
Fluids.WATER, fluidDelta != 0

Check warning on line 57 in src/main/kotlin/breadmod/block/entity/menu/DoughMachineScreen.kt

View workflow job for this annotation

GitHub Actions / qodana

Constant conditions

Condition 'fluidDelta != 0' is always false
)
}

renderTooltip(pGuiGraphics, pMouseX, pMouseY)

// Power Tooltip
Expand All @@ -59,10 +67,7 @@ class DoughMachineScreen(
}
// Fluid Tooltip
if(this.isHovering(153,28, 16, 47, pMouseX.toDouble(), pMouseY.toDouble())) {
val fluid = menu.parent.data[4]; val maxFluid = menu.parent.data[5]
pGuiGraphics.renderComponentTooltip(this.font, listOf(Component.literal(formatUnit(fluid, maxFluid, "B", true, 2, -1))), pMouseX, pMouseY)
}

super.render(pGuiGraphics, pMouseX, pMouseY, delta)
}
}
91 changes: 87 additions & 4 deletions src/main/kotlin/breadmod/util/General.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
package breadmod.util

import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.*
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.renderer.GameRenderer
import net.minecraft.world.inventory.InventoryMenu
import net.minecraft.world.level.material.Fluid
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions
import org.joml.Matrix4f
import java.awt.Color
import kotlin.math.abs
import kotlin.math.min

val formatArray = listOf("p", "n", "m", "", "k", "M", "G", "T", "P", "E")
fun formatNumber(number: Double, offset: Int): Pair<Double, String> {
var num = number
var index = 3 - offset
var index = 3 + offset
while (num >= 1000 && index < formatArray.size - 1) {
num /= 1000
index++
Expand All @@ -15,7 +28,77 @@ fun formatNumber(number: Double, offset: Int): Pair<Double, String> {
return num to formatArray[index]
}

fun formatUnit(from: Double, to: Double, unit: String, formatShort: Boolean, places: Int, offset: Int = 0): String =
"${String.format("%.${places}f", if(formatShort) formatNumber(from, offset).first else from)} / ${if(formatShort) formatNumber(to, offset).let { "${String.format("%.${places}f", it.first)}${it.second}$unit" } else "$to $unit"} (${String.format("%.${places}f", (from / to)*100)}%)"
fun formatUnit(from: Double, to: Double, unit: String, formatShort: Boolean, places: Int, offset: Int = 0): String {
val formatStr = "%.${places}f %s/ %.${places}f %s (%.${places}f%%)"
val percent = (from / to) * 100
if (formatShort) {
val toFormat = formatNumber(to, offset)
val fromFormat = formatNumber(from, offset)
return String.format(
formatStr,
fromFormat.first, if(toFormat.second != fromFormat.second) "${fromFormat.second}$unit " else "",
toFormat.first, toFormat.second + unit,
percent
)
} else {
return String.format(
formatStr,
from, "",
to, unit,
percent
)
}
}
fun formatUnit(from: Int, to: Int, unit: String, formatShort: Boolean, places: Int, offset: Int = 0): String =
formatUnit(from.toDouble(), to.toDouble(), unit, formatShort, places, offset)
formatUnit(from.toDouble(), to.toDouble(), unit, formatShort, places, offset)

fun GuiGraphics.renderFluid(pX: Float, pY: Float, pWidth: Int, pHeight: Int, fluid: Fluid, flowing: Boolean) {
val minecraft = Minecraft.getInstance()
val nWidth = abs(pWidth)

val ext = IClientFluidTypeExtensions.of(fluid)
val texture = if(flowing) ext.flowingTexture else ext.stillTexture
val sprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture)
val colors = FloatArray(4).also { Color(ext.tintColor).getComponents(it) }

val spriteData = sprite.contents()
val matrix4f: Matrix4f = this.pose().last().pose()

RenderSystem.setShaderTexture(0, sprite.atlasLocation())
RenderSystem.setShader { GameRenderer.getPositionColorTexShader() }
RenderSystem.enableBlend()
val bufferBuilder = Tesselator.getInstance().builder
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX)

val pX2 = pX + nWidth

var v1: Float = sprite.v1; var u1: Float = sprite.u1
var remainingFluid = pHeight; var ranDiff = false
while(remainingFluid > 0) {
val lpY = (pY - remainingFluid); val lpY2 = lpY + min(remainingFluid, nWidth)

if(flowing && !ranDiff) {
val stillSprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(ext.stillTexture)
val diff = (stillSprite.contents().width().toFloat() / spriteData.width())
v1 = sprite.v0 + ((v1 - sprite.v0) * diff)
u1 = sprite.u0 + ((u1 - sprite.u0) * diff)

ranDiff = true
}
if(remainingFluid < nWidth) v1 = sprite.v0 + (((v1 - sprite.v0) / nWidth) * remainingFluid)

fun VertexConsumer.color() = this.color(colors[0], colors[1], colors[2], colors[3])
val flipped = pWidth < 0
val fX1 = if(flipped) pX else pX2; val fX2 = if(flipped) pX2 else pX
val fY1 = if(flipped) lpY else lpY2; val fY2 = if(flipped) lpY2 else lpY
bufferBuilder.vertex(matrix4f, fX2, fY2, 0F).color().uv(sprite.u0, sprite.v0).endVertex()
bufferBuilder.vertex(matrix4f, fX2, fY1, 0F).color().uv(sprite.u0, v1).endVertex()
bufferBuilder.vertex(matrix4f, fX1, fY1, 0F).color().uv(u1, v1).endVertex()
bufferBuilder.vertex(matrix4f, fX1, fY2, 0F).color().uv(u1, sprite.v0).endVertex()

remainingFluid -= nWidth
}

BufferUploader.drawWithShader(bufferBuilder.end())
RenderSystem.disableBlend()
}
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8a5c726

Please sign in to comment.