Chart rendering right on energy counter
This commit is contained in:
parent
35769e5b57
commit
7d0b257928
@ -541,6 +541,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
|||||||
add(MBlocks.ENERGY_COUNTER[null]!!, "facing", "Input facing: %s")
|
add(MBlocks.ENERGY_COUNTER[null]!!, "facing", "Input facing: %s")
|
||||||
add(MBlocks.ENERGY_COUNTER[null]!!, "switch", "Switch input facing")
|
add(MBlocks.ENERGY_COUNTER[null]!!, "switch", "Switch input facing")
|
||||||
add(MBlocks.ENERGY_COUNTER[null]!!, "limit", "I/O Limit. -1 means no limit")
|
add(MBlocks.ENERGY_COUNTER[null]!!, "limit", "I/O Limit. -1 means no limit")
|
||||||
|
add(MBlocks.ENERGY_COUNTER[null]!!, "display_this", "Display this information on block's screen")
|
||||||
|
|
||||||
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "Chemical Generator")
|
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "Chemical Generator")
|
||||||
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "desc", "Generates power by burning solid fuels")
|
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "desc", "Generates power by burning solid fuels")
|
||||||
@ -840,6 +841,7 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
gui("time.short.5s", "5s")
|
gui("time.short.5s", "5s")
|
||||||
gui("time.short.15s", "15s")
|
gui("time.short.15s", "15s")
|
||||||
gui("time.short.1m", "1m")
|
gui("time.short.1m", "1m")
|
||||||
|
gui("time.short.10m", "10m")
|
||||||
gui("time.short.1h", "1h")
|
gui("time.short.1h", "1h")
|
||||||
gui("time.short.6h", "6h")
|
gui("time.short.6h", "6h")
|
||||||
gui("time.short.24h", "24h")
|
gui("time.short.24h", "24h")
|
||||||
|
@ -549,6 +549,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
|||||||
add(MBlocks.ENERGY_COUNTER[null]!!, "facing", "Сторона входа: %s")
|
add(MBlocks.ENERGY_COUNTER[null]!!, "facing", "Сторона входа: %s")
|
||||||
add(MBlocks.ENERGY_COUNTER[null]!!, "switch", "Сменить сторону входа")
|
add(MBlocks.ENERGY_COUNTER[null]!!, "switch", "Сменить сторону входа")
|
||||||
add(MBlocks.ENERGY_COUNTER[null]!!, "limit", "Лимит ввода/вывода. -1 для отключения лимитов")
|
add(MBlocks.ENERGY_COUNTER[null]!!, "limit", "Лимит ввода/вывода. -1 для отключения лимитов")
|
||||||
|
add(MBlocks.ENERGY_COUNTER[null]!!, "display_this", "Отображать эти данные на экране блока")
|
||||||
|
|
||||||
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "Химический генератор")
|
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "Химический генератор")
|
||||||
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "desc", "Генерирует энергию сжигая твёрдое топливо")
|
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "desc", "Генерирует энергию сжигая твёрдое топливо")
|
||||||
@ -848,6 +849,7 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
gui("time.short.5s", "5с")
|
gui("time.short.5s", "5с")
|
||||||
gui("time.short.15s", "15с")
|
gui("time.short.15s", "15с")
|
||||||
gui("time.short.1m", "1м")
|
gui("time.short.1m", "1м")
|
||||||
|
gui("time.short.10m", "10м")
|
||||||
gui("time.short.1h", "1ч")
|
gui("time.short.1h", "1ч")
|
||||||
gui("time.short.6h", "6ч")
|
gui("time.short.6h", "6ч")
|
||||||
gui("time.short.24h", "24ч")
|
gui("time.short.24h", "24ч")
|
||||||
|
@ -10,6 +10,7 @@ import net.minecraft.world.entity.player.Player
|
|||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities
|
import net.neoforged.neoforge.capabilities.Capabilities
|
||||||
|
import ru.dbotthepony.kommons.util.DelegateSetter
|
||||||
import ru.dbotthepony.kommons.util.getValue
|
import ru.dbotthepony.kommons.util.getValue
|
||||||
import ru.dbotthepony.kommons.util.setValue
|
import ru.dbotthepony.kommons.util.setValue
|
||||||
import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
|
import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
|
||||||
@ -21,7 +22,6 @@ import ru.dbotthepony.mc.otm.core.math.BlockRotation
|
|||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||||
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
|
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.core.util.countingLazy
|
import ru.dbotthepony.mc.otm.core.util.countingLazy
|
||||||
@ -43,22 +43,24 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
val history6h = DecimalHistoryChart(720 * 6, 100)
|
val history6h = DecimalHistoryChart(720 * 6, 100)
|
||||||
val history24h = DecimalHistoryChart(720 * 24, 100)
|
val history24h = DecimalHistoryChart(720 * 24, 100)
|
||||||
|
|
||||||
private val graphs = ImmutableList.of(
|
val charts: ImmutableList<DecimalHistoryChart> = ImmutableList.of(
|
||||||
history5s, history15s, history1m, history10m, history1h, history6h, history24h,
|
history5s, history15s, history1m, history10m, history1h, history6h, history24h,
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
syncher.add(history5s)
|
charts.forEach { syncher.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private var thisTick = Decimal.ZERO
|
private var thisTick = Decimal.ZERO
|
||||||
var lastTick by syncher.decimal()
|
var lastTick by syncher.decimal()
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
|
var displayChartOnBlock by syncher.int(0, setter = DelegateSetter { field, value -> if (value in 0 .. charts.size + 1) field.accept(value) })
|
||||||
|
|
||||||
var ioLimit: Decimal? = null
|
var ioLimit: Decimal? = null
|
||||||
|
|
||||||
fun resetStats() {
|
fun resetStats() {
|
||||||
graphs.forEach { it.clear() }
|
charts.forEach { it.clear() }
|
||||||
lastTick = Decimal.ZERO
|
lastTick = Decimal.ZERO
|
||||||
passed = Decimal.ZERO
|
passed = Decimal.ZERO
|
||||||
}
|
}
|
||||||
@ -69,16 +71,19 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
ioLimit?.let { nbt[IO_LIMIT_KEY] = it.serializeNBT() }
|
ioLimit?.let { nbt[IO_LIMIT_KEY] = it.serializeNBT() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
savetables.int(::displayChartOnBlock)
|
||||||
|
savetables.stateful(::history5s)
|
||||||
|
savetables.stateful(::history15s)
|
||||||
|
savetables.stateful(::history1m)
|
||||||
|
savetables.stateful(::history10m)
|
||||||
|
savetables.stateful(::history1h)
|
||||||
|
savetables.stateful(::history6h)
|
||||||
|
savetables.stateful(::history24h)
|
||||||
|
}
|
||||||
|
|
||||||
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||||
super.saveLevel(nbt, registry)
|
super.saveLevel(nbt, registry)
|
||||||
|
|
||||||
nbt["history5s"] = history5s.serializeNBT(registry)
|
|
||||||
nbt["history15s"] = history15s.serializeNBT(registry)
|
|
||||||
nbt["history1m"] = history1m.serializeNBT(registry)
|
|
||||||
nbt["history10m"] = history10m.serializeNBT(registry)
|
|
||||||
nbt["history1h"] = history1h.serializeNBT(registry)
|
|
||||||
nbt["history6h"] = history6h.serializeNBT(registry)
|
|
||||||
nbt["history24h"] = history24h.serializeNBT(registry)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||||
@ -86,14 +91,6 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
|
|
||||||
passed = nbt.getDecimal(PASSED_ENERGY_KEY)
|
passed = nbt.getDecimal(PASSED_ENERGY_KEY)
|
||||||
ioLimit = nbt.mapPresent(IO_LIMIT_KEY, Decimal.Companion::deserializeNBT)
|
ioLimit = nbt.mapPresent(IO_LIMIT_KEY, Decimal.Companion::deserializeNBT)
|
||||||
|
|
||||||
nbt.map("history5s") { it: CompoundTag -> history5s.deserializeNBT(registry, it) }
|
|
||||||
nbt.map("history15s") { it: CompoundTag -> history15s.deserializeNBT(registry, it) }
|
|
||||||
nbt.map("history1m") { it: CompoundTag -> history1m.deserializeNBT(registry, it) }
|
|
||||||
nbt.map("history10m") { it: CompoundTag -> history10m.deserializeNBT(registry, it) }
|
|
||||||
nbt.map("history1h") { it: CompoundTag -> history1h.deserializeNBT(registry, it) }
|
|
||||||
nbt.map("history6h") { it: CompoundTag -> history6h.deserializeNBT(registry, it) }
|
|
||||||
nbt.map("history24h") { it: CompoundTag -> history24h.deserializeNBT(registry, it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val defaultDisplayName: Component
|
override val defaultDisplayName: Component
|
||||||
@ -265,7 +262,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
super.tick()
|
super.tick()
|
||||||
|
|
||||||
lastTick = thisTick
|
lastTick = thisTick
|
||||||
graphs.forEach { it.add(thisTick) }
|
charts.forEach { it.add(thisTick) }
|
||||||
thisTick = Decimal.ZERO
|
thisTick = Decimal.ZERO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.render
|
package ru.dbotthepony.mc.otm.client.render
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder
|
|
||||||
import com.mojang.blaze3d.vertex.BufferUploader
|
|
||||||
import com.mojang.blaze3d.vertex.ByteBufferBuilder
|
import com.mojang.blaze3d.vertex.ByteBufferBuilder
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat
|
import com.mojang.blaze3d.vertex.VertexFormat
|
||||||
|
import com.mojang.blaze3d.vertex.VertexSorting
|
||||||
import net.minecraft.client.gui.Font
|
import net.minecraft.client.gui.Font
|
||||||
import net.minecraft.client.gui.GuiGraphics
|
import net.minecraft.client.gui.GuiGraphics
|
||||||
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent
|
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent
|
||||||
import net.minecraft.client.renderer.GameRenderer
|
import net.minecraft.client.renderer.GameRenderer
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource
|
||||||
|
import net.minecraft.client.renderer.RenderStateShard
|
||||||
|
import net.minecraft.client.renderer.RenderType
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.world.inventory.tooltip.TooltipComponent
|
import net.minecraft.world.inventory.tooltip.TooltipComponent
|
||||||
import net.neoforged.neoforge.client.event.RegisterClientTooltipComponentFactoriesEvent
|
import net.neoforged.neoforge.client.event.RegisterClientTooltipComponentFactoriesEvent
|
||||||
@ -68,7 +70,10 @@ class ChartTooltipElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun renderImage(font: Font, x: Int, y: Int, graphics: GuiGraphics) {
|
override fun renderImage(font: Font, x: Int, y: Int, graphics: GuiGraphics) {
|
||||||
renderChart(graphics.pose(), normalized, this.width, this.height - 10f, levelLabels = this.levelLabels, x = x.toFloat(), y = y.toFloat() + 10f)
|
graphics.pose().pushPose()
|
||||||
|
graphics.pose().translate(0f, 0f, 0.1f)
|
||||||
|
renderChart(graphics.pose(), normalized, this.width, this.height - 10f, levelLabels = this.levelLabels, x = x.toFloat(), y = y.toFloat() + 10f, buffer = graphics.bufferSource())
|
||||||
|
graphics.pose().popPose()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -78,6 +83,32 @@ class ChartTooltipElement(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CHART_RENDER_TYPE = run {
|
||||||
|
val builder = RenderType.CompositeState.builder()
|
||||||
|
|
||||||
|
builder.setShaderState(RenderStateShard.ShaderStateShard(GameRenderer::getPositionColorShader))
|
||||||
|
builder.setDepthTestState(RenderStateShard.DepthTestStateShard("always", GL_LESS))
|
||||||
|
|
||||||
|
builder.setTransparencyState(RenderStateShard.TransparencyStateShard("normal_blend", {
|
||||||
|
RenderSystem.enableBlend()
|
||||||
|
RenderSystem.defaultBlendFunc()
|
||||||
|
}, { RenderSystem.disableBlend() }))
|
||||||
|
|
||||||
|
@Suppress("INACCESSIBLE_TYPE")
|
||||||
|
RenderType.create(
|
||||||
|
"otm_chart",
|
||||||
|
DefaultVertexFormat.POSITION_COLOR,
|
||||||
|
VertexFormat.Mode.QUADS,
|
||||||
|
16_000,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
builder.createCompositeState(false)
|
||||||
|
) as RenderType
|
||||||
|
}
|
||||||
|
|
||||||
|
private val buffer = DynamicBufferSource(vertexSorting = VertexSorting.ORTHOGRAPHIC_Z)
|
||||||
|
private fun buffer() = buffer
|
||||||
|
|
||||||
fun renderChart(
|
fun renderChart(
|
||||||
poseStack: PoseStack,
|
poseStack: PoseStack,
|
||||||
charts: List<Pair<FloatArray, RGBAColor>>,
|
charts: List<Pair<FloatArray, RGBAColor>>,
|
||||||
@ -85,16 +116,20 @@ fun renderChart(
|
|||||||
height: Float,
|
height: Float,
|
||||||
labels: ChartMouseLabels? = null,
|
labels: ChartMouseLabels? = null,
|
||||||
levelLabels: ChartLevelLabels? = null,
|
levelLabels: ChartLevelLabels? = null,
|
||||||
|
buffer: MultiBufferSource = buffer(),
|
||||||
x: Float = 0f,
|
x: Float = 0f,
|
||||||
y: Float = 0f,
|
y: Float = 0f,
|
||||||
|
textScale: Float = 1f,
|
||||||
|
lineWidth: Float = LINE_WIDTH
|
||||||
) {
|
) {
|
||||||
require(charts.all { it.first.size == charts[0].first.size }) { "Provided chart data is not of same width" }
|
require(charts.all { it.first.size == charts[0].first.size }) { "Provided chart data is not of same width" }
|
||||||
val builder = BufferBuilder(BYTE_BUFFER_BUILDER, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR)
|
val builder = buffer.getBuffer(CHART_RENDER_TYPE)
|
||||||
val step = width / charts[0].first.size
|
val step = width / charts[0].first.size
|
||||||
|
|
||||||
val pose = poseStack.last().pose
|
|
||||||
val checkLabels = labels != null && labels.mouseY in 0f .. height && labels.mouseX in 0f .. width
|
val checkLabels = labels != null && labels.mouseY in 0f .. height && labels.mouseX in 0f .. width
|
||||||
|
|
||||||
|
poseStack.pushPose()
|
||||||
|
|
||||||
var drawLabel = -1
|
var drawLabel = -1
|
||||||
var drawPointX = 0f
|
var drawPointX = 0f
|
||||||
var drawPointY = 0f
|
var drawPointY = 0f
|
||||||
@ -103,13 +138,15 @@ fun renderChart(
|
|||||||
for ((level, label) in levelLabels.labels) {
|
for ((level, label) in levelLabels.labels) {
|
||||||
val y0 = y + (1f - level) * height
|
val y0 = y + (1f - level) * height
|
||||||
|
|
||||||
builder.vertex(pose, x + width, LINE_WIDTH / 2f + y0, 0f).color(levelLabels.lineColor)
|
builder.vertex(poseStack, x + width, lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
|
||||||
builder.vertex(pose, x + width, -LINE_WIDTH / 2f + y0, 0f).color(levelLabels.lineColor)
|
builder.vertex(poseStack, x + width, -lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
|
||||||
builder.vertex(pose, x, -LINE_WIDTH / 2f + y0, 0f).color(levelLabels.lineColor)
|
builder.vertex(poseStack, x, -lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
|
||||||
builder.vertex(pose, x, LINE_WIDTH / 2f + y0, 0f).color(levelLabels.lineColor)
|
builder.vertex(poseStack, x, lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
poseStack.translate(0f, 0f, 0.2f)
|
||||||
|
|
||||||
for ((normalized, color) in charts) {
|
for ((normalized, color) in charts) {
|
||||||
for (i in 0 until normalized.size - 1) {
|
for (i in 0 until normalized.size - 1) {
|
||||||
val y0 = y + (1f - normalized[i]) * height
|
val y0 = y + (1f - normalized[i]) * height
|
||||||
@ -122,21 +159,21 @@ fun renderChart(
|
|||||||
val yDiff = y1 - y0
|
val yDiff = y1 - y0
|
||||||
|
|
||||||
if (yDiff.sign == 0f) {
|
if (yDiff.sign == 0f) {
|
||||||
builder.vertex(pose, x0, y0 + LINE_WIDTH / 2f, 0f).color(color)
|
builder.vertex(poseStack, x0, y0 + lineWidth / 2f, 0f).color(color)
|
||||||
builder.vertex(pose, x0, y0 - LINE_WIDTH / 2f, 0f).color(color)
|
builder.vertex(poseStack, x0, y0 - lineWidth / 2f, 0f).color(color)
|
||||||
builder.vertex(pose, x1, y1 - LINE_WIDTH / 2f, 0f).color(color)
|
builder.vertex(poseStack, x1, y1 - lineWidth / 2f, 0f).color(color)
|
||||||
builder.vertex(pose, x1, y1 + LINE_WIDTH / 2f, 0f).color(color)
|
builder.vertex(poseStack, x1, y1 + lineWidth / 2f, 0f).color(color)
|
||||||
} else {
|
} else {
|
||||||
val length = (xDiff.pow(2f) + yDiff.pow(2f)).pow(0.5f)
|
val length = (xDiff.pow(2f) + yDiff.pow(2f)).pow(0.5f)
|
||||||
val angle = acos(xDiff / length) * yDiff.sign - PI / 2f // rotate 90 deg
|
val angle = acos(xDiff / length) * yDiff.sign - PI / 2f // rotate 90 deg
|
||||||
|
|
||||||
val xDisp = cos(angle).toFloat() * LINE_WIDTH / 2f
|
val xDisp = cos(angle).toFloat() * lineWidth / 2f
|
||||||
val yDisp = sin(angle).toFloat() * LINE_WIDTH / 2f
|
val yDisp = sin(angle).toFloat() * lineWidth / 2f
|
||||||
|
|
||||||
builder.vertex(pose, x0 + xDisp, y0 + yDisp, 0f).color(color)
|
builder.vertex(poseStack, x0 + xDisp, y0 + yDisp, 0f).color(color)
|
||||||
builder.vertex(pose, x0 - xDisp, y0 - yDisp, 0f).color(color)
|
builder.vertex(poseStack, x0 - xDisp, y0 - yDisp, 0f).color(color)
|
||||||
builder.vertex(pose, x1 - xDisp, y1 - yDisp, 0f).color(color)
|
builder.vertex(poseStack, x1 - xDisp, y1 - yDisp, 0f).color(color)
|
||||||
builder.vertex(pose, x1 + xDisp, y1 + yDisp, 0f).color(color)
|
builder.vertex(poseStack, x1 + xDisp, y1 + yDisp, 0f).color(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
//graphics.renderRect(x0, y0, LINE_WIDTH, LINE_WIDTH)
|
//graphics.renderRect(x0, y0, LINE_WIDTH, LINE_WIDTH)
|
||||||
@ -149,57 +186,58 @@ fun renderChart(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem.setShader(GameRenderer::getPositionColorShader)
|
|
||||||
// RenderSystem.setShaderColor(color.red, color.green, color.blue, color.alpha)
|
|
||||||
RenderSystem.disableDepthTest()
|
|
||||||
RenderSystem.disableBlend()
|
|
||||||
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
|
||||||
|
|
||||||
BufferUploader.drawWithShader(builder.buildOrThrow())
|
|
||||||
|
|
||||||
RenderSystem.enableDepthTest()
|
|
||||||
RenderSystem.depthFunc(GL_LESS)
|
|
||||||
|
|
||||||
if (levelLabels != null && levelLabels.labels.isNotEmpty()) {
|
if (levelLabels != null && levelLabels.labels.isNotEmpty()) {
|
||||||
|
poseStack.translate(0f, 0f, 0.2f)
|
||||||
val font = levelLabels.font ?: minecraft.font
|
val font = levelLabels.font ?: minecraft.font
|
||||||
|
|
||||||
for ((level, label) in levelLabels.labels) {
|
for ((level, label) in levelLabels.labels) {
|
||||||
val y0 = y + (1f - level) * height
|
val y0 = y + (1f - level) * height
|
||||||
|
|
||||||
val tX = x + levelLabels.textGravity.repositionX(width, font.width(label).toFloat()) - 1f
|
val tX = x + (levelLabels.textGravity.repositionX(width - 1f, font.width(label).toFloat() * textScale - 1f))
|
||||||
val tY = y0 - LINE_WIDTH - 1f - font.lineHeight + levelLabels.textGravity.repositionY(font.lineHeight * 2f + LINE_WIDTH + 2f, font.lineHeight.toFloat()) + 1f
|
val tY = y0 - lineWidth - 1f - font.lineHeight * textScale + levelLabels.textGravity.repositionY(font.lineHeight * 2f * textScale + lineWidth + 2f, font.lineHeight.toFloat() * textScale) + 1f
|
||||||
|
|
||||||
font.draw(
|
font.draw(
|
||||||
poseStack,
|
poseStack,
|
||||||
label,
|
label,
|
||||||
|
buffer = buffer,
|
||||||
x = tX,
|
x = tX,
|
||||||
y = tY,
|
y = tY,
|
||||||
color = levelLabels.textColor,
|
color = levelLabels.textColor,
|
||||||
drawOutline = true,
|
drawOutline = true,
|
||||||
outlineZ = -1f,
|
outlineZ = -0.1f,
|
||||||
outlineColor = levelLabels.textOutline
|
outlineColor = levelLabels.textOutline,
|
||||||
|
scale = textScale
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawLabel != -1) {
|
if (drawLabel != -1) {
|
||||||
renderRect(pose, drawPointX - LINE_WIDTH / 2f, y, LINE_WIDTH, height, color = labels!!.pillarColor)
|
poseStack.translate(0f, 0f, 0.2f)
|
||||||
renderRect(pose, drawPointX - HIGHLIGHT_WIDTH / 2f, drawPointY - HIGHLIGHT_WIDTH / 2f, HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, color = labels.color)
|
|
||||||
|
uploadRect(poseStack, drawPointX - lineWidth / 2f, y, lineWidth, height, buffer = buffer, color = labels!!.pillarColor)
|
||||||
|
uploadRect(poseStack, drawPointX - HIGHLIGHT_WIDTH / 2f, drawPointY - HIGHLIGHT_WIDTH / 2f, HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, buffer = buffer, color = labels.color)
|
||||||
|
|
||||||
val label = labels.labels(drawLabel)
|
val label = labels.labels(drawLabel)
|
||||||
|
|
||||||
if (label.isNotEmpty()) {
|
if (label.isNotEmpty()) {
|
||||||
val fWidth = label.maxOf { labels.font.width(it).toFloat() + 2f }
|
val fWidth = label.maxOf { (labels.font.width(it).toFloat() + 2f) * textScale }
|
||||||
val fHeight = labels.font.lineHeight.toFloat() * label.size + 2f
|
val fHeight = (labels.font.lineHeight.toFloat() * label.size + 2f) * textScale
|
||||||
|
|
||||||
val anchorX = labels.mouseX // drawPointX
|
val anchorX = labels.mouseX // drawPointX
|
||||||
var anchorY = labels.mouseY - fHeight - 2f
|
var anchorY = labels.mouseY - fHeight - 2f
|
||||||
|
|
||||||
renderRect(pose, anchorX - fWidth / 2f, anchorY - 2f, fWidth, fHeight + 4f, color = labels.textBackgroundColor)
|
uploadRect(poseStack, anchorX - fWidth / 2f, anchorY - 2f, fWidth, fHeight + 4f, buffer = buffer, color = labels.textBackgroundColor)
|
||||||
|
|
||||||
label.forEach {
|
label.forEach {
|
||||||
labels.font.draw(poseStack, it, anchorX, anchorY, gravity = RenderGravity.TOP_CENTER, color = labels.textColor)
|
labels.font.draw(poseStack, it, anchorX, anchorY, buffer = buffer, gravity = RenderGravity.TOP_CENTER, color = labels.textColor, scale = textScale)
|
||||||
anchorY += labels.font.lineHeight
|
anchorY += labels.font.lineHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
poseStack.popPose()
|
||||||
|
|
||||||
|
if (buffer === buffer()) {
|
||||||
|
buffer.endBatch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,15 @@ class DynamicBufferSource(
|
|||||||
next = State(Sheets.shulkerBoxSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(Sheets.shulkerBoxSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
next = State(Sheets.signSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(Sheets.signSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
//next = State(Sheets.hangingSignSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
//next = State(Sheets.hangingSignSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
|
|
||||||
next = State(Sheets.chestSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(Sheets.chestSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
|
next = State(CHART_RENDER_TYPE, ImmutableList.of(next.type), immutableAfter = true, chained = true)
|
||||||
|
|
||||||
|
next = State(rectRenderType(true, false, true), ImmutableList.of(next.type), immutableAfter = true, chained = true)
|
||||||
|
next = State(rectRenderType(true, false, false), ImmutableList.of(next.type), immutableAfter = true, chained = true)
|
||||||
|
next = State(rectRenderType(false, false, true), ImmutableList.of(next.type), immutableAfter = true, chained = true)
|
||||||
|
next = State(rectRenderType(false, false, false), ImmutableList.of(next.type), immutableAfter = true, chained = true)
|
||||||
|
|
||||||
next = State(RenderType.armorEntityGlint(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(RenderType.armorEntityGlint(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
next = State(RenderType.glint(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(RenderType.glint(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
next = State(RenderType.glintTranslucent(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(RenderType.glintTranslucent(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
@ -170,6 +178,9 @@ class DynamicBufferSource(
|
|||||||
next = State(RenderType.entityGlintDirect(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(RenderType.entityGlintDirect(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
next = State(RenderType.waterMask(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(RenderType.waterMask(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
|
|
||||||
|
next = State(rectRenderType(true, true, true), ImmutableList.of(next.type), immutableAfter = true, chained = true)
|
||||||
|
next = State(rectRenderType(true, true, false), ImmutableList.of(next.type), immutableAfter = true, chained = true)
|
||||||
|
|
||||||
ModelBakery.DESTROY_TYPES.forEach {
|
ModelBakery.DESTROY_TYPES.forEach {
|
||||||
next = State(it, ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
next = State(it, ImmutableList.of(next.type), immutableAfter = true, chained = false)
|
||||||
}
|
}
|
||||||
|
@ -165,8 +165,8 @@ private fun Font.drawInternal(
|
|||||||
|
|
||||||
drawInBatch(
|
drawInBatch(
|
||||||
text,
|
text,
|
||||||
(x + shadowX) * inv,
|
(x + shadowX * scale) * inv,
|
||||||
(y + shadowY) * inv,
|
(y + shadowY * scale) * inv,
|
||||||
shadowColor.toBGR(),
|
shadowColor.toBGR(),
|
||||||
false,
|
false,
|
||||||
poseStack.last().pose(),
|
poseStack.last().pose(),
|
||||||
@ -189,8 +189,8 @@ private fun Font.drawInternal(
|
|||||||
for ((_x, _y) in outlinePositions) {
|
for ((_x, _y) in outlinePositions) {
|
||||||
drawInBatch(
|
drawInBatch(
|
||||||
text,
|
text,
|
||||||
(x + _x) * inv,
|
(x + _x * scale) * inv,
|
||||||
(y + _y) * inv,
|
(y + _y * scale) * inv,
|
||||||
outlineColor.toBGR(),
|
outlineColor.toBGR(),
|
||||||
drawShadow,
|
drawShadow,
|
||||||
poseStack.last().pose(),
|
poseStack.last().pose(),
|
||||||
|
@ -18,6 +18,7 @@ val tesselator: Tesselator get() = Tesselator.getInstance()
|
|||||||
|
|
||||||
// what meth have you been smoking, mojang, with new names
|
// what meth have you been smoking, mojang, with new names
|
||||||
fun VertexConsumer.vertex(matrix4f: Matrix4f, x: Float, y: Float, z: Float): VertexConsumer = addVertex(matrix4f, x, y, z)
|
fun VertexConsumer.vertex(matrix4f: Matrix4f, x: Float, y: Float, z: Float): VertexConsumer = addVertex(matrix4f, x, y, z)
|
||||||
|
fun VertexConsumer.vertex(poseStack: PoseStack, x: Float, y: Float, z: Float): VertexConsumer = addVertex(poseStack.last.pose, x, y, z)
|
||||||
fun VertexConsumer.vertex(x: Float, y: Float, z: Float): VertexConsumer = addVertex(x, y, z)
|
fun VertexConsumer.vertex(x: Float, y: Float, z: Float): VertexConsumer = addVertex(x, y, z)
|
||||||
fun VertexConsumer.uv(u: Float, v: Float): VertexConsumer = setUv(u, v)
|
fun VertexConsumer.uv(u: Float, v: Float): VertexConsumer = setUv(u, v)
|
||||||
fun VertexConsumer.overlayCoords(coords: Int): VertexConsumer = setOverlay(coords)
|
fun VertexConsumer.overlayCoords(coords: Int): VertexConsumer = setOverlay(coords)
|
||||||
|
@ -4,6 +4,7 @@ import com.mojang.blaze3d.platform.GlStateManager
|
|||||||
import com.mojang.blaze3d.systems.RenderSystem
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
import com.mojang.blaze3d.vertex.*
|
import com.mojang.blaze3d.vertex.*
|
||||||
import net.minecraft.client.renderer.GameRenderer
|
import net.minecraft.client.renderer.GameRenderer
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource
|
||||||
import net.minecraft.client.renderer.RenderStateShard
|
import net.minecraft.client.renderer.RenderStateShard
|
||||||
import net.minecraft.client.renderer.RenderStateShard.LineStateShard
|
import net.minecraft.client.renderer.RenderStateShard.LineStateShard
|
||||||
import net.minecraft.client.renderer.RenderType
|
import net.minecraft.client.renderer.RenderType
|
||||||
@ -92,6 +93,76 @@ fun renderRect(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val IS_WHITE = 1
|
||||||
|
private const val IS_TRANSLUCENT = 2
|
||||||
|
private const val IS_3D = 4
|
||||||
|
|
||||||
|
private val rectRenderTypes = Array(1 shl 3) {
|
||||||
|
val isWhite = it and IS_WHITE != 0
|
||||||
|
val isTranslucent = it and IS_TRANSLUCENT != 0
|
||||||
|
val is3D = it and IS_3D != 0
|
||||||
|
val builder = RenderType.CompositeState.builder()
|
||||||
|
|
||||||
|
if (isWhite)
|
||||||
|
builder.setShaderState(RenderStateShard.ShaderStateShard(GameRenderer::getPositionShader))
|
||||||
|
else
|
||||||
|
builder.setShaderState(RenderStateShard.ShaderStateShard(GameRenderer::getPositionColorShader))
|
||||||
|
|
||||||
|
if (!is3D)
|
||||||
|
builder.setDepthTestState(RenderStateShard.DepthTestStateShard("always", GL_LESS))
|
||||||
|
|
||||||
|
if (isTranslucent) {
|
||||||
|
builder.setTransparencyState(RenderStateShard.TransparencyStateShard("normal_blend", {
|
||||||
|
RenderSystem.enableBlend()
|
||||||
|
RenderSystem.defaultBlendFunc()
|
||||||
|
}, { RenderSystem.disableBlend() }))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("INACCESSIBLE_TYPE")
|
||||||
|
RenderType.create(
|
||||||
|
"otm_rect_${isWhite}_${isTranslucent}_$is3D",
|
||||||
|
if (isWhite) DefaultVertexFormat.POSITION else DefaultVertexFormat.POSITION_COLOR,
|
||||||
|
VertexFormat.Mode.QUADS,
|
||||||
|
256,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
builder.createCompositeState(false)
|
||||||
|
) as RenderType
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun rectRenderType(isWhite: Boolean, isTranslucent: Boolean, is3D: Boolean): RenderType {
|
||||||
|
var index = 0
|
||||||
|
if (isWhite) index = IS_WHITE
|
||||||
|
if (isTranslucent) index = index or IS_TRANSLUCENT
|
||||||
|
if (is3D) index = index or IS_3D
|
||||||
|
return rectRenderTypes[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uploadRect(
|
||||||
|
poseStack: PoseStack,
|
||||||
|
x: Float,
|
||||||
|
y: Float,
|
||||||
|
width: Float,
|
||||||
|
height: Float,
|
||||||
|
buffer: MultiBufferSource,
|
||||||
|
z: Float = 0f,
|
||||||
|
color: RGBAColor = RGBAColor.WHITE
|
||||||
|
) {
|
||||||
|
val builder = buffer.getBuffer(rectRenderType(color.isWhite, color.alpha != 1f, is3DContext))
|
||||||
|
|
||||||
|
if (color.isWhite) {
|
||||||
|
builder.vertex(poseStack, x, y + height, z)
|
||||||
|
builder.vertex(poseStack, x + width, y + height, z)
|
||||||
|
builder.vertex(poseStack, x + width, y, z)
|
||||||
|
builder.vertex(poseStack, x, y, z)
|
||||||
|
} else {
|
||||||
|
builder.vertex(poseStack, x, y + height, z).color(color)
|
||||||
|
builder.vertex(poseStack, x + width, y + height, z).color(color)
|
||||||
|
builder.vertex(poseStack, x + width, y, z).color(color)
|
||||||
|
builder.vertex(poseStack, x, y, z).color(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
fun renderCheckerboard(
|
fun renderCheckerboard(
|
||||||
matrix: Matrix4f,
|
matrix: Matrix4f,
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.render.blockentity
|
package ru.dbotthepony.mc.otm.client.render.blockentity
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
|
import it.unimi.dsi.fastutil.floats.Float2ObjectArrayMap
|
||||||
import net.minecraft.client.renderer.MultiBufferSource
|
import net.minecraft.client.renderer.MultiBufferSource
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
|
import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity
|
||||||
@ -12,6 +14,7 @@ import ru.dbotthepony.mc.otm.client.minecraft
|
|||||||
import ru.dbotthepony.mc.otm.client.render.*
|
import ru.dbotthepony.mc.otm.client.render.*
|
||||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||||
import ru.dbotthepony.kommons.math.RGBAColor
|
import ru.dbotthepony.kommons.math.RGBAColor
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.asAngle
|
import ru.dbotthepony.mc.otm.core.math.asAngle
|
||||||
import ru.dbotthepony.mc.otm.core.util.formatPower
|
import ru.dbotthepony.mc.otm.core.util.formatPower
|
||||||
import ru.dbotthepony.mc.otm.core.math.times
|
import ru.dbotthepony.mc.otm.core.math.times
|
||||||
@ -47,23 +50,76 @@ class EnergyCounterRenderer(private val context: BlockEntityRendererProvider.Con
|
|||||||
poseStack.rotateAroundPoint(poseStack.translation(), screenDir.asAngle().copy(pitch = PI))
|
poseStack.rotateAroundPoint(poseStack.translation(), screenDir.asAngle().copy(pitch = PI))
|
||||||
}
|
}
|
||||||
|
|
||||||
var y = -16f
|
poseStack.scale(1f, 1f, -1f)
|
||||||
|
|
||||||
val finalX = font.draw(poseStack, buffer = sorse, text = "00000000", gravity = RenderGravity.CENTER_CENTER, x = -4f, y = y, color = RGBAColor.GRAY)
|
if (tile.displayChartOnBlock == 0) {
|
||||||
font.draw(poseStack, buffer = sorse, text = "00000000", gravity = RenderGravity.CENTER_CENTER, x = -4f, y = y + font.lineHeight, color = RGBAColor.GRAY)
|
var y = -16f
|
||||||
font.draw(poseStack, buffer = sorse, text = "/t", gravity = RenderGravity.CENTER_LEFT, x = finalX, y = y, color = RGBAColor.GRAY)
|
|
||||||
font.draw(poseStack, buffer = sorse, text = "/s", gravity = RenderGravity.CENTER_LEFT, x = finalX, y = y + font.lineHeight, color = RGBAColor.GRAY)
|
|
||||||
|
|
||||||
poseStack.pushPose()
|
val finalX = font.draw(poseStack, buffer = sorse, text = "00000000", gravity = RenderGravity.CENTER_CENTER, x = -4f, y = y, color = RGBAColor.GRAY)
|
||||||
poseStack.translate(-0.1, -0.1, -0.1)
|
font.draw(poseStack, buffer = sorse, text = "00000000", gravity = RenderGravity.CENTER_CENTER, x = -4f, y = y + font.lineHeight, color = RGBAColor.GRAY)
|
||||||
font.draw(poseStack, buffer = sorse, text = tile.lastTick.toString(0), gravity = RenderGravity.CENTER_RIGHT, x = finalX, y = y, color = RGBAColor.WHITE)
|
font.draw(poseStack, buffer = sorse, text = "/t", gravity = RenderGravity.CENTER_LEFT, x = finalX, y = y, color = RGBAColor.GRAY)
|
||||||
font.draw(poseStack, buffer = sorse, text = tile.history5s.calculateSum(20).toString(0), gravity = RenderGravity.CENTER_RIGHT, x = finalX, y = y + font.lineHeight, color = RGBAColor.WHITE)
|
font.draw(poseStack, buffer = sorse, text = "/s", gravity = RenderGravity.CENTER_LEFT, x = finalX, y = y + font.lineHeight, color = RGBAColor.GRAY)
|
||||||
poseStack.popPose()
|
|
||||||
|
|
||||||
y += font.lineHeight * 3
|
poseStack.pushPose()
|
||||||
|
poseStack.translate(-0.1f, -0.1f, 0.1f)
|
||||||
|
font.draw(poseStack, buffer = sorse, text = tile.lastTick.toString(0), gravity = RenderGravity.CENTER_RIGHT, x = finalX, y = y, color = RGBAColor.WHITE)
|
||||||
|
font.draw(poseStack, buffer = sorse, text = tile.history5s.calculateSum(20).toString(0), gravity = RenderGravity.CENTER_RIGHT, x = finalX, y = y + font.lineHeight, color = RGBAColor.WHITE)
|
||||||
|
poseStack.popPose()
|
||||||
|
|
||||||
font.draw(poseStack, buffer = sorse, text = TOTAL, gravity = RenderGravity.CENTER_CENTER, x = 0f, y = y, color = RGBAColor.WHITE)
|
y += font.lineHeight * 3
|
||||||
font.draw(poseStack, buffer = sorse,text = tile.passed.formatPower(), gravity = RenderGravity.CENTER_CENTER, x = 0f, y = y + font.lineHeight, color = RGBAColor.WHITE)
|
|
||||||
|
font.draw(poseStack, buffer = sorse, text = TOTAL, gravity = RenderGravity.CENTER_CENTER, x = 0f, y = y, color = RGBAColor.WHITE)
|
||||||
|
font.draw(poseStack, buffer = sorse, text = tile.passed.formatPower(), gravity = RenderGravity.CENTER_CENTER, x = 0f, y = y + font.lineHeight, color = RGBAColor.WHITE)
|
||||||
|
} else {
|
||||||
|
val chart = tile.charts.getOrNull(tile.displayChartOnBlock - 1)
|
||||||
|
|
||||||
|
if (chart != null) {
|
||||||
|
val maximum = chart.max()
|
||||||
|
val normalized: FloatArray
|
||||||
|
val levelLabels: ChartLevelLabels
|
||||||
|
|
||||||
|
if (maximum.isZero || maximum.isInfinite) {
|
||||||
|
normalized = FloatArray(chart.width) {
|
||||||
|
if (chart[it].isInfinite) 0.8f else 0.0f
|
||||||
|
}
|
||||||
|
|
||||||
|
levelLabels = ChartLevelLabels(
|
||||||
|
labels = mapOf(
|
||||||
|
1f to TextComponent("∞"),
|
||||||
|
0f to Decimal.ZERO.formatPower(),
|
||||||
|
),
|
||||||
|
font = font
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
normalized = FloatArray(chart.width) { (chart[it] / maximum).toFloat() }
|
||||||
|
|
||||||
|
val map = Float2ObjectArrayMap<Component>()
|
||||||
|
|
||||||
|
map[1f] = maximum.formatPower()
|
||||||
|
map[0.75f] = (maximum * 0.75).formatPower()
|
||||||
|
map[0.5f] = (maximum * 0.5).formatPower()
|
||||||
|
map[0.25f] = (maximum * 0.25).formatPower()
|
||||||
|
|
||||||
|
levelLabels = ChartLevelLabels(
|
||||||
|
labels = map,
|
||||||
|
font = font
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderChart(
|
||||||
|
poseStack,
|
||||||
|
listOf(normalized to RGBAColor.WHITE),
|
||||||
|
60f,
|
||||||
|
50f,
|
||||||
|
buffer = sorse,
|
||||||
|
levelLabels = levelLabels,
|
||||||
|
x = -30f,
|
||||||
|
y = -20f,
|
||||||
|
textScale = 0.3f,
|
||||||
|
lineWidth = 0.5f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
poseStack.popPose()
|
poseStack.popPose()
|
||||||
}
|
}
|
||||||
|
@ -193,9 +193,7 @@ sealed class AbstractMatterySprite : IGUIRenderable, IUVCoords {
|
|||||||
builder.setTransparencyState(RenderStateShard.TransparencyStateShard("normal_blend", {
|
builder.setTransparencyState(RenderStateShard.TransparencyStateShard("normal_blend", {
|
||||||
RenderSystem.enableBlend()
|
RenderSystem.enableBlend()
|
||||||
RenderSystem.defaultBlendFunc()
|
RenderSystem.defaultBlendFunc()
|
||||||
}, {
|
}, { RenderSystem.disableBlend() }))
|
||||||
RenderSystem.disableBlend()
|
|
||||||
}))
|
|
||||||
|
|
||||||
@Suppress("INACCESSIBLE_TYPE")
|
@Suppress("INACCESSIBLE_TYPE")
|
||||||
RenderType.create("otm_gui_element_no_depth",
|
RenderType.create("otm_gui_element_no_depth",
|
||||||
|
@ -35,7 +35,10 @@ open class DecimalHistoryChartPanel<out S : MatteryScreen<*>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
levelLabels = ChartLevelLabels(
|
levelLabels = ChartLevelLabels(
|
||||||
labels = mapOf(0.8f to formatText(maximum)),
|
labels = mapOf(
|
||||||
|
0.8f to TextComponent("∞"),
|
||||||
|
// 0f to formatText(Decimal.ZERO),
|
||||||
|
),
|
||||||
font = font
|
font = font
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
|||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.button.CheckBoxLabelInputPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
|
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkNumberInputPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkNumberInputPanel
|
||||||
import ru.dbotthepony.mc.otm.core.util.formatPower
|
import ru.dbotthepony.mc.otm.core.util.formatPower
|
||||||
@ -19,22 +20,31 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title:
|
|||||||
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
||||||
val frame = super.makeMainFrame()!!
|
val frame = super.makeMainFrame()!!
|
||||||
|
|
||||||
frame.height = 160f
|
frame.height = 180f
|
||||||
frame.width += 60f
|
frame.width += 80f
|
||||||
|
|
||||||
val graphs = linkedMapOf(
|
val graphs = listOf(
|
||||||
menu.history5s to "otm.gui.time.short.5s",
|
menu.history5s to "otm.gui.time.short.5s",
|
||||||
menu.history15s to "otm.gui.time.short.15s",
|
menu.history15s to "otm.gui.time.short.15s",
|
||||||
menu.history1m to "otm.gui.time.short.1m",
|
menu.history1m to "otm.gui.time.short.1m",
|
||||||
|
menu.history10m to "otm.gui.time.short.10m",
|
||||||
menu.history1h to "otm.gui.time.short.1h",
|
menu.history1h to "otm.gui.time.short.1h",
|
||||||
menu.history6h to "otm.gui.time.short.6h",
|
menu.history6h to "otm.gui.time.short.6h",
|
||||||
menu.history24h to "otm.gui.time.short.24h",
|
menu.history24h to "otm.gui.time.short.24h",
|
||||||
)
|
)
|
||||||
|
|
||||||
for ((graph, text) in graphs) {
|
kotlin.run {
|
||||||
val tab = frame.Tab(activeIcon = TextIcon(color = RGBAColor.BLACK, font = font, text = TranslatableComponent(text)))
|
var i = 1
|
||||||
val panel = DecimalHistoryChartPanel(this, tab.canvas, graph, formatText = { it.formatPower(formatAsReadable = ShiftPressedCond) })
|
|
||||||
panel.dock = Dock.FILL
|
for ((graph, text) in graphs) {
|
||||||
|
val tab = frame.Tab(activeIcon = TextIcon(color = RGBAColor.BLACK, font = font, text = TranslatableComponent(text)))
|
||||||
|
val panel = DecimalHistoryChartPanel(this, tab.canvas, graph, formatText = { it.formatPower(formatAsReadable = ShiftPressedCond) })
|
||||||
|
panel.dock = Dock.FILL
|
||||||
|
|
||||||
|
val current = i++
|
||||||
|
val button = CheckBoxLabelInputPanel(this, tab.canvas, menu.displayChartOnBlock.map({ it == current }, { current }), TranslatableComponent("block.overdrive_that_matters.energy_counter.display_this"))
|
||||||
|
button.dock = Dock.BOTTOM
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val informationTab = frame.Tab(activeIcon = Widgets18.STATISTICS_TAB)
|
val informationTab = frame.Tab(activeIcon = Widgets18.STATISTICS_TAB)
|
||||||
@ -51,6 +61,7 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title:
|
|||||||
labels.add(Label(this, informationTab.canvas, text = TranslatableComponent("otm.gui.power.last_tick")))
|
labels.add(Label(this, informationTab.canvas, text = TranslatableComponent("otm.gui.power.last_tick")))
|
||||||
labels.add(DynamicLabel(this, informationTab.canvas, textSupplier = { menu.lastTick.formatPower(formatAsReadable = ShiftPressedCond) }))
|
labels.add(DynamicLabel(this, informationTab.canvas, textSupplier = { menu.lastTick.formatPower(formatAsReadable = ShiftPressedCond) }))
|
||||||
labels.add(DynamicLabel(this, informationTab.canvas, textSupplier = { TranslatableComponent("block.overdrive_that_matters.energy_counter.facing", menu.inputDirection) }))
|
labels.add(DynamicLabel(this, informationTab.canvas, textSupplier = { TranslatableComponent("block.overdrive_that_matters.energy_counter.facing", menu.inputDirection) }))
|
||||||
|
labels.add(CheckBoxLabelInputPanel(this, informationTab.canvas, menu.displayChartOnBlock.map({ it == 0 }, { 0 }), TranslatableComponent("block.overdrive_that_matters.energy_counter.display_this")))
|
||||||
|
|
||||||
for ((i, label) in labels.withIndex()) {
|
for ((i, label) in labels.withIndex()) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
@ -52,6 +52,14 @@ fun interface BlockPredicate {
|
|||||||
return BlockPredicate { pos, access -> test(pos, access) || other.test(pos, access) }
|
return BlockPredicate { pos, access -> test(pos, access) || other.test(pos, access) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun and(other: BlockPredicate, vararg others: BlockPredicate): BlockPredicate {
|
||||||
|
return And(ImmutableSet.copyOf(listOf(other, *others)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun or(other: BlockPredicate, vararg others: BlockPredicate): BlockPredicate {
|
||||||
|
return Or(ImmutableSet.copyOf(listOf(other, *others)))
|
||||||
|
}
|
||||||
|
|
||||||
fun offset(offset: BlockPos): Positioned {
|
fun offset(offset: BlockPos): Positioned {
|
||||||
return Positioned(offset, this)
|
return Positioned(offset, this)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,29 @@ import kotlin.reflect.KMutableProperty0
|
|||||||
*
|
*
|
||||||
* Getting and setting values should ONLY be done clientside
|
* Getting and setting values should ONLY be done clientside
|
||||||
*/
|
*/
|
||||||
interface IPlayerInputWithFeedback<V> : ListenableDelegate<V>, Predicate<Player>
|
interface IPlayerInputWithFeedback<V> : ListenableDelegate<V>, Predicate<Player> {
|
||||||
|
private class Map<N, V>(private val parent: IPlayerInputWithFeedback<V>, private val from: (V) -> N, private val to: (N) -> V): IPlayerInputWithFeedback<N> {
|
||||||
|
override fun accept(t: N) {
|
||||||
|
parent.accept(to(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addListener(listener: Consumer<N>): Listenable.L {
|
||||||
|
return parent.addListener(Consumer { listener.accept(from(it)) })
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(): N {
|
||||||
|
return from(parent.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun test(t: Player): Boolean {
|
||||||
|
return parent.test(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <N> map(from: (V) -> N, to: (N) -> V): IPlayerInputWithFeedback<N> {
|
||||||
|
return Map(this, from, to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents Server to Client synchronization and Client to Server input
|
* Represents Server to Client synchronization and Client to Server input
|
||||||
|
@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
|
|||||||
import ru.dbotthepony.mc.otm.core.math.toDecimal
|
import ru.dbotthepony.mc.otm.core.math.toDecimal
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.IntInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
@ -48,11 +49,13 @@ class EnergyCounterMenu(
|
|||||||
tile.level?.setBlock(tile.blockPos, tile.blockState.setValue(EnergyCounterBlock.INPUT_DIRECTION, tile.blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION).opposite), Block.UPDATE_ALL)
|
tile.level?.setBlock(tile.blockPos, tile.blockState.setValue(EnergyCounterBlock.INPUT_DIRECTION, tile.blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION).opposite), Block.UPDATE_ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val displayChartOnBlock = IntInputWithFeedback(this)
|
||||||
val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java)
|
val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
redstone.with(tile.redstoneControl::redstoneSetting)
|
redstone.with(tile.redstoneControl::redstoneSetting)
|
||||||
|
displayChartOnBlock.with(tile::displayChartOnBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user