Add player icon to temporary waypoints

This commit is contained in:
Linnea Gräf
2024-01-27 18:16:11 +01:00
parent 9b0e966d66
commit 0cb6e308ac
5 changed files with 153 additions and 76 deletions

View File

@@ -154,7 +154,7 @@ git push "$REMOTE" "$BRANCH" "$newversion"
if command -v gh; then
echo Creating github release
(set -x; gh release create "$newversion" -F "$releasenotes" "$basedir/build/libs/Firmament-$newversion.jar")
(set -x; gh release create -t "Firmament $newversion" "$newversion" -F "$releasenotes" "$basedir/build/libs/Firmament-$newversion.jar")
else
echo Could not find github command utility. Opening github releases
xdg-open "https://github.com/nea89o/firmament/releases/new"

View File

@@ -9,7 +9,6 @@ package moe.nea.firmament.features.world
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.seconds
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
import moe.nea.firmament.events.ProcessChatEvent
import moe.nea.firmament.events.WorldReadyEvent
@@ -36,19 +35,40 @@ object Waypoints : FirmamentFeature {
override val config get() = TConfig
val temporaryWaypointList = mutableMapOf<String, TemporaryWaypoint>()
val temporaryWaypointMatcher = "x: (-?[0-9]+),? y: (-?[0-9]+),? z: (-?[0-9]+)".toPattern()
val temporaryWaypointMatcher = "(?i)x: (-?[0-9]+),? y: (-?[0-9]+),? z: (-?[0-9]+)".toPattern()
override fun onLoad() {
WorldRenderLastEvent.subscribe {
WorldRenderLastEvent.subscribe { event ->
temporaryWaypointList.entries.removeIf { it.value.postedAt.passedTime() > TConfig.tempWaypointDuration }
if (temporaryWaypointList.isNotEmpty())
RenderInWorldContext.renderInWorld(it) {
RenderInWorldContext.renderInWorld(event) {
color(1f, 1f, 0f, 1f)
temporaryWaypointList.forEach { (player, waypoint) ->
block(waypoint.pos)
}
color(1f, 1f, 1f, 1f)
temporaryWaypointList.forEach { (player, waypoint) ->
val skin =
MC.networkHandler?.listedPlayerListEntries?.find { it.profile.name == player }
?.skinTextures
?.texture
withFacingThePlayer(waypoint.pos.toCenterPos()) {
waypoint(waypoint.pos, Text.translatable("firmament.waypoint.temporary", player))
if (skin != null) {
matrixStack.translate(0F, -20F, 0F)
// Head front
texture(
skin, 16, 16,
1 / 8f, 1 / 8f,
2 / 8f, 2 / 8f,
)
// Head overlay
texture(
skin, 16, 16,
5 / 8f, 1 / 8f,
6 / 8f, 2 / 8f,
)
}
}
}
}
}
@@ -58,8 +78,7 @@ object Waypoints : FirmamentFeature {
ProcessChatEvent.subscribe {
val matcher = temporaryWaypointMatcher.matcher(it.unformattedString)
if (it.nameHeuristic != null && TConfig.tempWaypointDuration > 0.seconds && matcher.find()) {
temporaryWaypointList.put(
it.nameHeuristic, TemporaryWaypoint(
temporaryWaypointList[it.nameHeuristic] = TemporaryWaypoint(
BlockPos(
matcher.group(1).toInt(),
matcher.group(2).toInt(),
@@ -67,7 +86,6 @@ object Waypoints : FirmamentFeature {
),
TimeMark.now()
)
)
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package moe.nea.firmament.util.render
import com.mojang.blaze3d.systems.RenderSystem
import org.joml.Matrix4f
import net.minecraft.client.font.TextRenderer
import net.minecraft.client.render.BufferRenderer
import net.minecraft.client.render.GameRenderer
import net.minecraft.client.render.LightmapTextureManager
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexConsumer
import net.minecraft.client.render.VertexFormat
import net.minecraft.client.render.VertexFormats
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.assertTrueOr
@RenderContextDSL
class FacingThePlayerContext(val worldContext: RenderInWorldContext) {
val matrixStack by worldContext::matrixStack
fun waypoint(position: BlockPos, label: Text) {
text(
label,
Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}")
)
}
fun text(
vararg texts: Text,
verticalAlign: RenderInWorldContext.VerticalAlign = RenderInWorldContext.VerticalAlign.CENTER
) {
assertTrueOr(texts.isNotEmpty()) { return@text }
for ((index, text) in texts.withIndex()) {
worldContext.matrixStack.push()
val width = MC.font.getWidth(text)
worldContext.matrixStack.translate(-width / 2F, verticalAlign.align(index, texts.size), 0F)
val vertexConsumer: VertexConsumer =
worldContext.vertexConsumers.getBuffer(RenderLayer.getTextBackgroundSeeThrough())
val matrix4f = worldContext.matrixStack.peek().positionMatrix
vertexConsumer.vertex(matrix4f, -1.0f, -1.0f, 0.0f).color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
vertexConsumer.vertex(matrix4f, -1.0f, MC.font.fontHeight.toFloat(), 0.0f).color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
vertexConsumer.vertex(matrix4f, width.toFloat(), MC.font.fontHeight.toFloat(), 0.0f)
.color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
vertexConsumer.vertex(matrix4f, width.toFloat(), -1.0f, 0.0f).color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
worldContext.matrixStack.translate(0F, 0F, 0.01F)
MC.font.draw(
text,
0F,
0F,
-1,
false,
worldContext.matrixStack.peek().positionMatrix,
worldContext.vertexConsumers,
TextRenderer.TextLayerType.SEE_THROUGH,
0,
LightmapTextureManager.MAX_LIGHT_COORDINATE
)
worldContext.matrixStack.pop()
}
}
fun texture(
texture: Identifier, width: Int, height: Int,
u1: Float, v1: Float,
u2: Float, v2: Float,
) {
RenderSystem.setShaderTexture(0, texture)
RenderSystem.setShader(GameRenderer::getPositionColorTexProgram)
val hw = width / 2F
val hh = height / 2F
val matrix4f: Matrix4f = worldContext.matrixStack.peek().positionMatrix
val buf = Tessellator.getInstance().buffer
buf.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE)
buf.fixedColor(255, 255, 255, 255)
buf.vertex(matrix4f, -hw, -hh, 0F)
.texture(u1, v1).next()
buf.vertex(matrix4f, -hw, +hh, 0F)
.texture(u1, v2).next()
buf.vertex(matrix4f, +hw, +hh, 0F)
.texture(u2, v2).next()
buf.vertex(matrix4f, +hw, -hh, 0F)
.texture(u2, v1).next()
buf.unfixColor()
BufferRenderer.drawWithGlobalProgram(buf.end())
}
}

View File

@@ -0,0 +1,11 @@
/*
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package moe.nea.firmament.util.render
@DslMarker
annotation class RenderContextDSL {
}

View File

@@ -12,16 +12,11 @@ import java.lang.Math.toRadians
import org.joml.Matrix4f
import org.joml.Vector3f
import kotlin.math.tan
import net.minecraft.client.font.TextRenderer
import net.minecraft.client.gl.VertexBuffer
import net.minecraft.client.render.BufferBuilder
import net.minecraft.client.render.BufferRenderer
import net.minecraft.client.render.Camera
import net.minecraft.client.render.GameRenderer
import net.minecraft.client.render.LightmapTextureManager
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexConsumer
import net.minecraft.client.render.VertexConsumerProvider
import net.minecraft.client.render.VertexFormat
import net.minecraft.client.render.VertexFormats
@@ -36,14 +31,14 @@ import moe.nea.firmament.events.WorldRenderLastEvent
import moe.nea.firmament.mixins.accessor.AccessorGameRenderer
import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.assertTrueOr
@RenderContextDSL
class RenderInWorldContext private constructor(
private val tesselator: Tessellator,
private val matrixStack: MatrixStack,
val matrixStack: MatrixStack,
private val camera: Camera,
private val tickDelta: Float,
private val vertexConsumers: VertexConsumerProvider.Immediate,
val vertexConsumers: VertexConsumerProvider.Immediate,
) {
private val buffer = tesselator.buffer
val effectiveFov = (MC.instance.gameRenderer as AccessorGameRenderer).getFov_firmament(camera, tickDelta, true)
@@ -82,7 +77,7 @@ class RenderInWorldContext private constructor(
)
}
fun withFacingThePlayer(position: Vec3d, block: () -> Unit) {
fun withFacingThePlayer(position: Vec3d, block: FacingThePlayerContext.() -> Unit) {
matrixStack.push()
matrixStack.translate(position.x, position.y, position.z)
val actualCameraDistance = position.distanceTo(camera.pos)
@@ -92,7 +87,7 @@ class RenderInWorldContext private constructor(
matrixStack.multiply(camera.rotation)
matrixStack.scale(-0.025F, -0.025F, -1F)
block()
FacingThePlayerContext(this).run(block)
matrixStack.pop()
vertexConsumers.drawCurrentLayer()
@@ -110,62 +105,13 @@ class RenderInWorldContext private constructor(
u2: Float, v2: Float,
) {
withFacingThePlayer(position) {
RenderSystem.setShaderTexture(0, texture)
RenderSystem.setShader(GameRenderer::getPositionColorTexProgram)
val hw = width / 2F
val hh = height / 2F
val matrix4f: Matrix4f = matrixStack.peek().positionMatrix
val buf = Tessellator.getInstance().buffer
buf.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE)
buf.fixedColor(255, 255, 255, 255)
buf.vertex(matrix4f, -hw, -hh, 0F)
.texture(u1, v1).next()
buf.vertex(matrix4f, -hw, +hh, 0F)
.texture(u1, v2).next()
buf.vertex(matrix4f, +hw, +hh, 0F)
.texture(u2, v2).next()
buf.vertex(matrix4f, +hw, -hh, 0F)
.texture(u2, v1).next()
buf.unfixColor()
BufferRenderer.drawWithGlobalProgram(buf.end())
texture(texture, width, height, u1, v1, u2, v2)
}
}
fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER) {
assertTrueOr(texts.isNotEmpty()) { return@text }
withFacingThePlayer(position) {
for ((index, text) in texts.withIndex()) {
matrixStack.push()
val width = MC.font.getWidth(text)
matrixStack.translate(-width / 2F, verticalAlign.align(index, texts.size), 0F)
val vertexConsumer: VertexConsumer =
vertexConsumers.getBuffer(RenderLayer.getTextBackgroundSeeThrough())
val matrix4f = matrixStack.peek().positionMatrix
vertexConsumer.vertex(matrix4f, -1.0f, -1.0f, 0.0f).color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
vertexConsumer.vertex(matrix4f, -1.0f, MC.font.fontHeight.toFloat(), 0.0f).color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
vertexConsumer.vertex(matrix4f, width.toFloat(), MC.font.fontHeight.toFloat(), 0.0f)
.color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
vertexConsumer.vertex(matrix4f, width.toFloat(), -1.0f, 0.0f).color(0x70808080)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
matrixStack.translate(0F, 0F, 0.01F)
MC.font.draw(
text,
0F,
0F,
-1,
false,
matrixStack.peek().positionMatrix,
vertexConsumers,
TextRenderer.TextLayerType.SEE_THROUGH,
0,
LightmapTextureManager.MAX_LIGHT_COORDINATE
)
matrixStack.pop()
}
text(*texts, verticalAlign = verticalAlign)
}
}