diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt index e6eb2170f..ae24ab448 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt @@ -55,7 +55,12 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat var lastTick by syncher.decimal() internal set - var displayChartOnBlock by syncher.int(0, setter = DelegateSetter { field, value -> if (value in 0 .. charts.size + 1) field.accept(value) }) + var displayChartOnBlock by syncher.int(0, setter = DelegateSetter { field, value -> + if (value in 0 .. charts.size + 1) { + field.accept(value) + markDirtyFast() + } + }) var ioLimit: Decimal? = null @@ -266,13 +271,6 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat thisTick = Decimal.ZERO } - fun clientTick() { - // TODO - // historyTick = (historyTick + 1) % history.size - // history[historyTick] = lastTick - // passed += lastTick - } - companion object { private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.energy_counter") const val PASSED_ENERGY_KEY = "passedEnergy" diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt index 900dfce06..791533331 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt @@ -46,12 +46,9 @@ class EnergyCounterBlock(val color: DyeColor?) : MatteryBlock(DEFAULT_MACHINE_PR blockState: BlockState, blockEntityType: BlockEntityType ): BlockEntityTicker? { - if (blockEntityType !== MBlockEntities.ENERGY_COUNTER) + if (blockEntityType !== MBlockEntities.ENERGY_COUNTER || level.isClientSide) return null - if (level.isClientSide) - return BlockEntityTicker { _, _, _, tile -> if (tile is EnergyCounterBlockEntity) tile.clientTick() } - return BlockEntityTicker { _, _, _, tile -> if (tile is EnergyCounterBlockEntity) tile.tick() } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ChartRendering.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ChartRendering.kt index facdfa1c0..cbd6e7a4e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ChartRendering.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ChartRendering.kt @@ -4,6 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.vertex.ByteBufferBuilder import com.mojang.blaze3d.vertex.DefaultVertexFormat import com.mojang.blaze3d.vertex.PoseStack +import com.mojang.blaze3d.vertex.VertexConsumer import com.mojang.blaze3d.vertex.VertexFormat import com.mojang.blaze3d.vertex.VertexSorting import net.minecraft.client.gui.Font @@ -106,9 +107,35 @@ val CHART_RENDER_TYPE = run { ) as RenderType } +val CHART_RENDER_TYPE2 = 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_chart2", + DefaultVertexFormat.POSITION_COLOR, + VertexFormat.Mode.TRIANGLES, + 16_000, + false, + true, + builder.createCompositeState(false) + ) as RenderType +} + private val buffer = DynamicBufferSource(vertexSorting = VertexSorting.ORTHOGRAPHIC_Z) private fun buffer() = buffer +private val sinValues = FloatArray(16) { sin(it / 16f * PI.toFloat() * 2f) } +private val cosValues = FloatArray(16) { cos(it / 16f * PI.toFloat() * 2f) } + fun renderChart( poseStack: PoseStack, charts: List>, @@ -125,6 +152,8 @@ fun renderChart( require(charts.all { it.first.size == charts[0].first.size }) { "Provided chart data is not of same width" } val builder = buffer.getBuffer(CHART_RENDER_TYPE) val step = width / charts[0].first.size + // so we can work with crumbling buffer sources + val bendFuncs = ArrayList Unit>() val checkLabels = labels != null && labels.mouseY in 0f .. height && labels.mouseX in 0f .. width @@ -134,20 +163,24 @@ fun renderChart( var drawPointX = 0f var drawPointY = 0f + val halfWidth = lineWidth / 2f + if (levelLabels != null) { for ((level, label) in levelLabels.labels) { val y0 = y + (1f - level) * height - builder.vertex(poseStack, x + width, lineWidth / 2f + y0, 0f).color(levelLabels.lineColor) - builder.vertex(poseStack, x + width, -lineWidth / 2f + y0, 0f).color(levelLabels.lineColor) - builder.vertex(poseStack, x, -lineWidth / 2f + y0, 0f).color(levelLabels.lineColor) - builder.vertex(poseStack, x, lineWidth / 2f + y0, 0f).color(levelLabels.lineColor) + builder.vertex(poseStack, x + width, halfWidth + y0, 0f).color(levelLabels.lineColor) + builder.vertex(poseStack, x + width, -halfWidth + y0, 0f).color(levelLabels.lineColor) + builder.vertex(poseStack, x, -halfWidth + y0, 0f).color(levelLabels.lineColor) + builder.vertex(poseStack, x, halfWidth + y0, 0f).color(levelLabels.lineColor) } } poseStack.translate(0f, 0f, 0.2f) for ((normalized, color) in charts) { + var previousAngle = 0f + for (i in 0 until normalized.size - 1) { val y0 = y + (1f - normalized[i]) * height val y1 = y + (1f - normalized[i + 1]) * height @@ -158,17 +191,22 @@ fun renderChart( val xDiff = x1 - x0 val yDiff = y1 - y0 + val currentAngle: Float + if (yDiff.sign == 0f) { - builder.vertex(poseStack, x0, y0 + lineWidth / 2f, 0f).color(color) - builder.vertex(poseStack, x0, y0 - lineWidth / 2f, 0f).color(color) - builder.vertex(poseStack, x1, y1 - lineWidth / 2f, 0f).color(color) - builder.vertex(poseStack, x1, y1 + lineWidth / 2f, 0f).color(color) + builder.vertex(poseStack, x0, y0 + halfWidth, 0f).color(color) + builder.vertex(poseStack, x0, y0 - halfWidth, 0f).color(color) + builder.vertex(poseStack, x1, y1 - halfWidth, 0f).color(color) + builder.vertex(poseStack, x1, y1 + halfWidth, 0f).color(color) + + currentAngle = PI.toFloat() / 2f } else { 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.toFloat() / 2f // rotate 90 deg + currentAngle = angle - val xDisp = cos(angle).toFloat() * lineWidth / 2f - val yDisp = sin(angle).toFloat() * lineWidth / 2f + val xDisp = cos(angle) * halfWidth + val yDisp = sin(angle) * halfWidth builder.vertex(poseStack, x0 + xDisp, y0 + yDisp, 0f).color(color) builder.vertex(poseStack, x0 - xDisp, y0 - yDisp, 0f).color(color) @@ -176,7 +214,60 @@ fun renderChart( builder.vertex(poseStack, x1 + xDisp, y1 + yDisp, 0f).color(color) } - //graphics.renderRect(x0, y0, LINE_WIDTH, LINE_WIDTH) + if (currentAngle != previousAngle) { + for (i2 in sinValues.indices) { + val i3 = (i2 + 1) % cosValues.size + val cos0 = cosValues[i2] * halfWidth + val cos1 = cosValues[i3] * halfWidth + val sin0 = sinValues[i2] * halfWidth + val sin1 = sinValues[i3] * halfWidth + + bendFuncs.add { + vertex(poseStack, x0 + cos0, y0 + sin0, 0f).color(color) + vertex(poseStack, x0, y0, 0f).color(color) + vertex(poseStack, x0 + cos1, y0 + sin1, 0f).color(color) + } + } + } + + // TODO: actually make this work, because this should be more efficient than drawing full circle + /* + if (previousAngle < currentAngle) { + // peak bend + var bendAngle = previousAngle - 0.05f + + while (bendAngle < currentAngle + 0.05f) { + val sin0 = sin(bendAngle) + val cos0 = cos(bendAngle) + val sin1 = sin(bendAngle + 0.05f) + val cos1 = cos(bendAngle + 0.05f) + + builder2.vertex(poseStack, x0 + cos0, y0 + sin0, 0f).color(color) + builder2.vertex(poseStack, x0, y0, 0f).color(color) + builder2.vertex(poseStack, x0 + cos1, y0 + sin1, 0f).color(color) + + bendAngle += 0.05f + } + } else if (previousAngle > currentAngle) { + // chasm bend + var bendAngle = currentAngle - 0.05f + + while (bendAngle < previousAngle + 0.05f) { + val sin0 = sin(bendAngle) + val cos0 = cos(bendAngle) + val sin1 = sin(bendAngle + 0.05f) + val cos1 = cos(bendAngle + 0.05f) + + builder2.vertex(poseStack, x0 + cos0, y0 + sin0, 0f).color(color) + builder2.vertex(poseStack, x0, y0, 0f).color(color) + builder2.vertex(poseStack, x0 + cos1, y0 + sin1, 0f).color(color) + + bendAngle += 0.05f + } + } + */ + + previousAngle = currentAngle if (checkLabels && drawLabel == -1 && labels!!.mouseX in x1 .. x0) { drawLabel = i @@ -186,6 +277,11 @@ fun renderChart( } } + if (bendFuncs.isNotEmpty()) { + val builder2 = buffer.getBuffer(CHART_RENDER_TYPE2) + bendFuncs.forEach { it.invoke(builder2) } + } + if (levelLabels != null && levelLabels.labels.isNotEmpty()) { poseStack.translate(0f, 0f, 0.2f) val font = levelLabels.font ?: minecraft.font diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/DynamicBufferSource.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/DynamicBufferSource.kt index b90716096..9ed298079 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/DynamicBufferSource.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/DynamicBufferSource.kt @@ -165,6 +165,7 @@ class DynamicBufferSource( 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(CHART_RENDER_TYPE2, 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) @@ -250,13 +251,7 @@ class DynamicBufferSource( } override fun getBuffer(renderType: RenderType): VertexConsumer { - var getState = buffers[renderType] - - if (getState == null) { - getState = State(renderType) - } - - return getState.begin() + return (buffers[renderType] ?: State(renderType)).begin() } fun getBuffer(renderType: RenderType, after: RenderType): VertexConsumer {