diff --git a/src/client/java/net/vinrobot/mcemote/client/font/CustomFontStorage.java b/src/client/java/net/vinrobot/mcemote/client/font/CustomFontStorage.java index 61b90f0..308c444 100644 --- a/src/client/java/net/vinrobot/mcemote/client/font/CustomFontStorage.java +++ b/src/client/java/net/vinrobot/mcemote/client/font/CustomFontStorage.java @@ -5,12 +5,15 @@ import net.minecraft.client.font.FontStorage; import net.minecraft.client.font.Glyph; import net.minecraft.client.font.GlyphRenderer; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.texture.TextureManager; import net.minecraft.util.Identifier; import java.util.List; public abstract class CustomFontStorage extends FontStorage { + public static final float GLYPH_HEIGHT = TextRenderer.ARABIC_SHAPING_LETTERS_SHAPE; + private final Identifier identifier; private final TextureManager textureManager; private final GlyphRenderer blankGlyphRenderer; diff --git a/src/client/java/net/vinrobot/mcemote/client/font/EmoteFontStorage.java b/src/client/java/net/vinrobot/mcemote/client/font/EmoteFontStorage.java index 8446b8e..34d61a7 100644 --- a/src/client/java/net/vinrobot/mcemote/client/font/EmoteFontStorage.java +++ b/src/client/java/net/vinrobot/mcemote/client/font/EmoteFontStorage.java @@ -21,7 +21,6 @@ public class EmoteFontStorage extends CustomFontStorage { public static final Identifier IDENTIFIER = new Identifier("mcemote.fonts", "emotes"); - public static final float GLYPH_HEIGHT = 8; private final EmotesManager emotesManager; private final Map> framesCache = new HashMap<>(); diff --git a/src/client/java/net/vinrobot/mcemote/client/mixin/MinecraftEmoteClientMixin.java b/src/client/java/net/vinrobot/mcemote/client/mixin/MinecraftEmoteClientMixin.java deleted file mode 100644 index bd25b5a..0000000 --- a/src/client/java/net/vinrobot/mcemote/client/mixin/MinecraftEmoteClientMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.vinrobot.mcemote.client.mixin; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MinecraftClient.class) -@Environment(EnvType.CLIENT) -public class MinecraftEmoteClientMixin { - @Inject(at = @At("HEAD"), method = "run") - private void run(CallbackInfo info) { - // This code is injected into the start of MinecraftClient.run()V - } -} diff --git a/src/client/java/net/vinrobot/mcemote/client/mixin/TextRendererDrawerMixin.java b/src/client/java/net/vinrobot/mcemote/client/mixin/TextRendererDrawerMixin.java new file mode 100644 index 0000000..cc27946 --- /dev/null +++ b/src/client/java/net/vinrobot/mcemote/client/mixin/TextRendererDrawerMixin.java @@ -0,0 +1,54 @@ +package net.vinrobot.mcemote.client.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.FontStorage; +import net.minecraft.client.font.Glyph; +import net.minecraft.client.font.GlyphRenderer; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.option.GameOptions; +import net.minecraft.client.render.VertexConsumer; +import net.vinrobot.mcemote.client.font.NativeImageGlyph; +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import static net.vinrobot.mcemote.client.font.CustomFontStorage.GLYPH_HEIGHT; + +@Mixin(TextRenderer.Drawer.class) +public abstract class TextRendererDrawerMixin { + @Accessor("x") + abstract void setX(float x); + + @Unique + private volatile Glyph localGlyph = null; // Used to catch the local variable in TextRenderer.Drawer#accept() + + @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/FontStorage;getGlyph(IZ)Lnet/minecraft/client/font/Glyph;")) + private Glyph acceptGetGlyph(final FontStorage instance, final int codePoint, final boolean validateAdvance) { + return this.localGlyph = instance.getGlyph(codePoint, validateAdvance); + } + + @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer;drawGlyph(Lnet/minecraft/client/font/GlyphRenderer;ZZFFFLorg/joml/Matrix4f;Lnet/minecraft/client/render/VertexConsumer;FFFFI)V")) + private void acceptDrawGlyph(final TextRenderer instance, final GlyphRenderer glyphRenderer, final boolean bold, final boolean italic, final float weight, final float x, final float y, final Matrix4f matrix, final VertexConsumer vertexConsumer, final float red, final float green, final float blue, final float alpha, final int light) { + if (this.localGlyph instanceof NativeImageGlyph glyph) { + final GameOptions options = MinecraftClient.getInstance().options; + final float lineSpacing = options.getChatLineSpacing().getValue().floatValue(); + final float scale = (lineSpacing + 1); + + final float newX = x / scale; + // Align the glyph to the top of the line + final float newY = (y - (lineSpacing * GLYPH_HEIGHT) / 2) / scale; + + matrix.scale(scale); + instance.drawGlyph(glyphRenderer, bold, italic, weight, newX, newY, matrix, vertexConsumer, red, green, blue, alpha, light); + matrix.scale(1 / scale); + + // Fix the spacing between glyphs + this.setX(x + glyph.getAdvance(bold) * lineSpacing); + } else { + instance.drawGlyph(glyphRenderer, bold, italic, weight, x, y, matrix, vertexConsumer, red, green, blue, alpha, light); + } + } +} diff --git a/src/client/java/net/vinrobot/mcemote/client/widget/ConfigurationScreen.java b/src/client/java/net/vinrobot/mcemote/client/widget/ConfigurationScreen.java index 54bc5f1..ba22ce4 100644 --- a/src/client/java/net/vinrobot/mcemote/client/widget/ConfigurationScreen.java +++ b/src/client/java/net/vinrobot/mcemote/client/widget/ConfigurationScreen.java @@ -13,6 +13,8 @@ public class ConfigurationScreen extends BaseScreen { private static final Text MENU_TITLE = Text.translatableWithFallback("mcemote.options.title", "Minecraft Emote Options"); private static final Text TWITCH_ID_LABEL = Text.translatableWithFallback("mcemote.options.twitchId", "Twitch ID"); + private static final Text EMOTE_SCALING_LABEL = Text.translatableWithFallback("mcemote.options.emoteScaling", "Emote Scaling"); + private static final Text EMOTE_SCALING_INFO = Text.translatableWithFallback("mcemote.options.emoteScalingInfo", "Chat Settings → Line Spacing"); private static final int TITLE_COLOR = 0xFFFFFF; private static final int LABEL_COLOR = 0xA0A0A0; @@ -23,6 +25,7 @@ public class ConfigurationScreen extends BaseScreen { private ButtonWidget doneButton; private TextFieldWidget twitchIdField; + private SliderFieldWidget emoteScalingField; public ConfigurationScreen(final Screen parent, final ConfigurationManager configManager) { super(parent, MENU_TITLE); @@ -48,6 +51,9 @@ protected void init() { this.twitchIdField.setChangedListener((value) -> this.validateInputs()); this.addDrawableChild(this.twitchIdField); + this.emoteScalingField = new SliderFieldWidget(widgetX, 118, widgetWidth, widgetHeight, EMOTE_SCALING_INFO, 0); + this.addDrawable(this.emoteScalingField); + final int buttonSpacing = widgetHeight + 6; int buttonY = this.height - 5; @@ -100,6 +106,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 16, TITLE_COLOR); context.drawTextWithShadow(this.textRenderer, TWITCH_ID_LABEL, this.width / 2 - 100, 60, LABEL_COLOR); + context.drawTextWithShadow(this.textRenderer, EMOTE_SCALING_LABEL, this.width / 2 - 100, 106, LABEL_COLOR); super.render(context, mouseX, mouseY, delta); } diff --git a/src/client/java/net/vinrobot/mcemote/client/widget/SliderFieldWidget.java b/src/client/java/net/vinrobot/mcemote/client/widget/SliderFieldWidget.java new file mode 100644 index 0000000..dc0c944 --- /dev/null +++ b/src/client/java/net/vinrobot/mcemote/client/widget/SliderFieldWidget.java @@ -0,0 +1,18 @@ +package net.vinrobot.mcemote.client.widget; + +import net.minecraft.client.gui.widget.SliderWidget; +import net.minecraft.text.Text; + +public class SliderFieldWidget extends SliderWidget { + public SliderFieldWidget(final int x, final int y, final int width, final int height, final Text text, final double value) { + super(x, y, width, height, text, value); + } + + @Override + protected void updateMessage() { + } + + @Override + protected void applyValue() { + } +} diff --git a/src/client/resources/mcemote.client.mixins.json b/src/client/resources/mcemote.client.mixins.json index 4479f94..52d8624 100644 --- a/src/client/resources/mcemote.client.mixins.json +++ b/src/client/resources/mcemote.client.mixins.json @@ -5,7 +5,7 @@ "client": [ "ChatHudMixin", "FontManagerMixin", - "MinecraftEmoteClientMixin" + "TextRendererDrawerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/resources/mcemote.accesswidener b/src/main/resources/mcemote.accesswidener index a76573e..5f54049 100644 --- a/src/main/resources/mcemote.accesswidener +++ b/src/main/resources/mcemote.accesswidener @@ -1,5 +1,7 @@ accessWidener v1 named accessible class net/minecraft/client/font/FontManager$ProviderIndex +accessible class net/minecraft/client/font/TextRenderer$Drawer accessible method net/minecraft/client/font/FontStorage getGlyphRenderer (Lnet/minecraft/client/font/RenderableGlyph;)Lnet/minecraft/client/font/GlyphRenderer; +accessible method net/minecraft/client/font/TextRenderer drawGlyph (Lnet/minecraft/client/font/GlyphRenderer;ZZFFFLorg/joml/Matrix4f;Lnet/minecraft/client/render/VertexConsumer;FFFFI)V