Skip to content

Commit 31157fc

Browse files
committed
Fixed styled minecraft texts being blank
1 parent 218aa2d commit 31157fc

File tree

7 files changed

+124
-152
lines changed

7 files changed

+124
-152
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.mixin.render;
19+
20+
import com.lambda.module.modules.client.LambdaMoji;
21+
import net.minecraft.client.font.TextRenderer;
22+
import net.minecraft.client.gui.DrawContext;
23+
import net.minecraft.client.gui.hud.ChatHud;
24+
import net.minecraft.text.OrderedText;
25+
import org.spongepowered.asm.mixin.Mixin;
26+
import org.spongepowered.asm.mixin.injection.At;
27+
import org.spongepowered.asm.mixin.injection.Redirect;
28+
29+
@Mixin(ChatHud.class)
30+
public class ChatHudMixin {
31+
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/OrderedText;III)I"))
32+
int redirectRenderCall(DrawContext instance, TextRenderer textRenderer, OrderedText text, int x, int y, int color) {
33+
return instance.drawTextWithShadow(textRenderer, LambdaMoji.INSTANCE.parse(text, x, y, color), 0, y, 16777215 + (color << 24));
34+
}
35+
}

common/src/main/java/com/lambda/mixin/render/TextRendererMixin.java

Lines changed: 0 additions & 134 deletions
This file was deleted.

common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ package com.lambda.graphics.renderer.gui.font
1919

2020
import com.lambda.graphics.buffer.VertexPipeline
2121
import com.lambda.graphics.buffer.vertex.attributes.VertexAttrib
22-
import com.lambda.graphics.pipeline.ScissorAdapter
2322
import com.lambda.graphics.renderer.gui.AbstractGUIRenderer
2423
import com.lambda.graphics.renderer.gui.font.core.GlyphInfo
2524
import com.lambda.graphics.renderer.gui.font.core.LambdaAtlas.get
2625
import com.lambda.graphics.renderer.gui.font.core.LambdaAtlas.height
27-
import com.lambda.graphics.shader.Shader
2826
import com.lambda.graphics.shader.Shader.Companion.shader
2927
import com.lambda.graphics.texture.TextureOwner.bind
3028
import com.lambda.module.modules.client.LambdaMoji
@@ -33,7 +31,6 @@ import com.lambda.util.math.Vec2d
3331
import com.lambda.util.math.a
3432
import com.lambda.util.math.setAlpha
3533
import java.awt.Color
36-
import java.awt.Font
3734

3835
/**
3936
* Renders text and emoji glyphs using a shader-based font rendering system.
@@ -77,6 +74,29 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
7774
}
7875
}
7976

77+
fun drawGlyph(
78+
glyph: GlyphInfo,
79+
position: Vec2d,
80+
color: Color = Color.WHITE,
81+
scale: Double = 1.0
82+
) = render {
83+
shader["u_FontTexture"] = 0
84+
shader["u_EmojiTexture"] = 1
85+
shader["u_SDFMin"] = 0.3
86+
shader["u_SDFMax"] = 1.0
87+
88+
bind(chars, emojis)
89+
90+
val actualScale = getScaleFactor(scale)
91+
val scaledSize = glyph.size * actualScale
92+
93+
val posY = getHeight(scale) * -0.5 + baselineOffset * actualScale
94+
val pos1 = Vec2d(0.0, posY) * actualScale
95+
val pos2 = pos1 + scaledSize
96+
97+
buildGlyph(glyph, position, pos1, pos2, color)
98+
}
99+
80100
/**
81101
* Renders a single glyph at a given position.
82102
*
@@ -89,9 +109,9 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
89109
private fun VertexPipeline.buildGlyph(
90110
glyph: GlyphInfo,
91111
origin: Vec2d = Vec2d.ZERO,
92-
pos1: Vec2d = Vec2d.ZERO,
93-
pos2: Vec2d = pos1 + glyph.size,
94-
color: Color = Color.WHITE,
112+
pos1: Vec2d,
113+
pos2: Vec2d,
114+
color: Color,
95115
) {
96116
val x1 = pos1.x + origin.x
97117
val y1 = pos1.y + origin.y
@@ -198,9 +218,9 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
198218

199219
// Iterate the emojis from left to right
200220
val start = section.indexOf(emoji)
201-
val end = start + emoji.length + 1
221+
val end = start + emoji.length
202222

203-
val preEmojiText = section.substring(0, start - 1)
223+
val preEmojiText = section.substring(0, start)
204224
val postEmojiText = section.substring(end)
205225

206226
// Draw the text without emoji

common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaAtlas.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ object LambdaAtlas : Loadable {
7373
private val heightCache = Object2DoubleArrayMap<Font>()
7474

7575
operator fun LambdaFont.get(char: Char): GlyphInfo? = fontMap.getValue(this)[char]
76-
operator fun LambdaEmoji.get(string: String): GlyphInfo? = emojiMap.getValue(this)[string]
76+
operator fun LambdaEmoji.get(string: String): GlyphInfo? = emojiMap.getValue(this)[string.removeSurrounding(":")]
7777

7878
val LambdaFont.height: Double
7979
get() = heightCache.getDouble(fontCache[this@height])

common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaEmoji.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ enum class LambdaEmoji(val url: String) {
3232
* @return A list of parsed strings that does not contain the colons
3333
*/
3434
fun parse(text: String): MutableList<String> =
35-
emojiRegex.findAll(text).map { it.value.drop(1).dropLast(1) }.toMutableList()
35+
emojiRegex.findAll(text).map { it.value }.toMutableList()
3636

3737
fun load(): String {
3838
entries.forEach { it.buildBuffer() }
3939
return "Loaded ${entries.size} emoji sets"
4040
}
41-
}
41+
}

common/src/main/kotlin/com/lambda/module/modules/client/LambdaMoji.kt

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,20 @@
1717

1818
package com.lambda.module.modules.client
1919

20+
import com.lambda.Lambda.mc
2021
import com.lambda.event.events.RenderEvent
2122
import com.lambda.event.listener.SafeListener.Companion.listen
22-
import com.lambda.graphics.renderer.gui.font.FontRenderer
23-
import com.lambda.graphics.renderer.gui.font.FontRenderer.drawString
23+
import com.lambda.graphics.renderer.gui.font.FontRenderer.drawGlyph
24+
import com.lambda.graphics.renderer.gui.font.core.GlyphInfo
25+
import com.lambda.graphics.renderer.gui.font.core.LambdaAtlas.get
2426
import com.lambda.module.Module
2527
import com.lambda.module.tag.ModuleTag
2628
import com.lambda.util.math.Vec2d
29+
import net.minecraft.text.OrderedText
30+
import net.minecraft.text.Style
2731
import java.awt.Color
2832

33+
// This is the worst code I have ever wrote in my life
2934
object LambdaMoji : Module(
3035
name = "LambdaMoji",
3136
description = "",
@@ -35,17 +40,63 @@ object LambdaMoji : Module(
3540
val scale by setting("Emoji Scale", 1.0, 0.5..1.5, 0.1)
3641
val suggestions by setting("Chat Suggestions", true)
3742

38-
private val renderQueue = mutableListOf<Triple<String, Vec2d, Color>>()
43+
private val emojiWhitespace: String
44+
get() = " ".repeat(((mc.textRenderer.fontHeight / 2 / mc.textRenderer.getWidth(" ")) * scale).toInt())
45+
46+
private val renderQueue = mutableListOf<Triple<GlyphInfo, Vec2d, Color>>()
3947

4048
init {
4149
listen<RenderEvent.GUI.Scaled> {
42-
renderQueue.forEach { (text, position, color) ->
43-
drawString(text, position, color, scale = scale)
50+
renderQueue.forEach { (glyph, position, color) ->
51+
drawGlyph(glyph, position, color)
4452
}
4553

4654
renderQueue.clear()
4755
}
4856
}
4957

50-
fun push(text: String, position: Vec2d, color: Color) = renderQueue.add(Triple(text, position, color))
58+
// FixMe: Doesn't render properly when the chat scale is modified
59+
fun parse(text: OrderedText, x: Float, y: Float, color: Int): OrderedText {
60+
val saved = mutableMapOf<Int, Style>()
61+
val builder = StringBuilder()
62+
63+
var absoluteIndex = 0
64+
text.accept { _, style, codePoint ->
65+
saved[absoluteIndex++] = style
66+
builder.appendCodePoint(codePoint)
67+
true
68+
}
69+
70+
var raw = builder.toString()
71+
RenderSettings.emojiFont.parse(raw)
72+
.forEach { emoji ->
73+
val index = raw.indexOf(emoji)
74+
if (index == -1) return@forEach
75+
76+
val height = mc.textRenderer.fontHeight
77+
val width = mc.textRenderer.getWidth(raw.substring(0, index))
78+
79+
// Dude I'm sick of working with the shitcode that is minecraft's codebase :sob:
80+
val trueColor = when (color) {
81+
0x00E0E0E0, 0 -> Color(255, 255, 255, 255)
82+
else -> Color(255, 255, 255, (color shr 24 and 0xFF))
83+
}
84+
85+
val glyph = RenderSettings.emojiFont[emoji]!!
86+
renderQueue.add(Triple(glyph, Vec2d(x + width, y + height / 2), trueColor))
87+
88+
// Replace the emoji with whitespaces depending on the player's settings
89+
raw = raw.replaceFirst(emoji, emojiWhitespace)
90+
}
91+
92+
val constructed = mutableListOf<OrderedText>()
93+
94+
// Will not work properly if the emoji is part of the style
95+
saved.forEach { (charIndex: Int, style: Style) ->
96+
if (charIndex >= raw.length) return@forEach
97+
constructed.add(OrderedText.styledForwardsVisitedString(raw.substring(charIndex, charIndex + 1), style))
98+
}
99+
100+
return OrderedText.concat(constructed)
101+
}
51102
}

common/src/main/resources/lambda.mixins.common.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"render.BackgroundRendererMixin",
2929
"render.BlockRenderManagerMixin",
3030
"render.CameraMixin",
31+
"render.ChatHudMixin",
3132
"render.ChatInputSuggestorMixin",
3233
"render.ChatScreenMixin",
3334
"render.DebugHudMixin",
@@ -45,7 +46,6 @@
4546
"render.ScreenHandlerMixin",
4647
"render.SplashOverlayMixin",
4748
"render.SplashOverlayMixin$LogoTextureMixin",
48-
"render.TextRendererMixin",
4949
"render.VertexBufferMixin",
5050
"render.WorldRendererMixin",
5151
"world.BlockCollisionSpliteratorMixin",

0 commit comments

Comments
 (0)