Add player icon to temporary waypoints
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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) ->
|
||||
waypoint(waypoint.pos, Text.translatable("firmament.waypoint.temporary", player))
|
||||
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,15 +78,13 @@ 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(
|
||||
BlockPos(
|
||||
matcher.group(1).toInt(),
|
||||
matcher.group(2).toInt(),
|
||||
matcher.group(3).toInt(),
|
||||
),
|
||||
TimeMark.now()
|
||||
)
|
||||
temporaryWaypointList[it.nameHeuristic] = TemporaryWaypoint(
|
||||
BlockPos(
|
||||
matcher.group(1).toInt(),
|
||||
matcher.group(2).toInt(),
|
||||
matcher.group(3).toInt(),
|
||||
),
|
||||
TimeMark.now()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user