From 826a8b4b721d2ea64ed0970f21c5788704a7d6a1 Mon Sep 17 00:00:00 2001 From: Crec0 <83436716+Crec0@users.noreply.github.com> Date: Sun, 12 Dec 2021 19:21:15 -0800 Subject: [PATCH] Rework mixin to only redirect the renderLatencyIcon method (#6) --- .../hud/CustomPlayerListHud.java | 233 ++---------------- .../hud/PlayerListHudUtil.java | 28 --- .../mixin/InGameHudMixin.java | 20 -- .../mixin/PlayerListHudAccessor.java | 25 -- .../mixin/PlayerListHudInvoker.java | 13 + .../mixin/PlayerListHudMixin.java | 37 +++ .../resources/betterpingdisplay.mixins.json | 24 +- 7 files changed, 81 insertions(+), 299 deletions(-) delete mode 100644 src/main/java/com/vladmarica/betterpingdisplay/hud/PlayerListHudUtil.java delete mode 100644 src/main/java/com/vladmarica/betterpingdisplay/mixin/InGameHudMixin.java delete mode 100644 src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudAccessor.java create mode 100644 src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudInvoker.java create mode 100644 src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudMixin.java diff --git a/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java b/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java index e1eb865..d4f76d7 100644 --- a/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java +++ b/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java @@ -1,235 +1,40 @@ package com.vladmarica.betterpingdisplay.hud; -import com.google.common.collect.ComparisonChain; -import com.google.common.collect.Ordering; -import com.mojang.authlib.GameProfile; import com.mojang.blaze3d.systems.RenderSystem; -import com.vladmarica.betterpingdisplay.Config; -import com.vladmarica.betterpingdisplay.hud.CustomPlayerListHud.EntryOrderComparator; import com.vladmarica.betterpingdisplay.BetterPingDisplayMod; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import com.vladmarica.betterpingdisplay.Config; +import com.vladmarica.betterpingdisplay.mixin.PlayerListHudInvoker; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.render.entity.PlayerModelPart; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.ScoreboardCriterion; -import net.minecraft.scoreboard.ScoreboardObjective; -import net.minecraft.scoreboard.Team; -import net.minecraft.text.OrderedText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.world.GameMode; public final class CustomPlayerListHud { - - private static final Ordering ENTRY_ORDERING = Ordering.from(new EntryOrderComparator()); private static final int PING_TEXT_RENDER_OFFSET = -13; - private static final int PLAYER_SLOT_EXTRA_WIDTH = 45; - private static final int PLAYER_ICON_WIDTH = 9; private static final int PING_BARS_WIDTH = 11; + private static final Config config = BetterPingDisplayMod.instance().getConfig(); - public static void render(PlayerListHud hud, MatrixStack stack, int width, Scoreboard scoreboard, ScoreboardObjective obj) { - MinecraftClient mc = MinecraftClient.getInstance(); - TextRenderer textRenderer = mc.textRenderer; - Text header = PlayerListHudUtil.getHeader(hud); - Text footer = PlayerListHudUtil.getFooter(hud); - Config config = BetterPingDisplayMod.instance().getConfig(); + public static void render(MinecraftClient client, PlayerListHud hud, MatrixStack matrixStack, int width, int x, int y, PlayerListEntry player) { + TextRenderer textRenderer = client.textRenderer; - ClientPlayNetworkHandler clientPlayNetworkHandler = mc.player.networkHandler; - List playerList = ENTRY_ORDERING.sortedCopy(clientPlayNetworkHandler.getPlayerList()); - int i = 0; - int j = 0; - Iterator playerListIterator = playerList.iterator(); + String pingString = String.format(config.getTextFormatString(), player.getLatency()); + int pingStringWidth = textRenderer.getWidth(pingString); - int n; - while(playerListIterator.hasNext()) { - PlayerListEntry playerListEntry = (PlayerListEntry)playerListIterator.next(); - n = mc.textRenderer.getWidth(hud.getPlayerName(playerListEntry)); - i = Math.max(i, n); - if (obj != null && obj.getRenderType() != ScoreboardCriterion.RenderType.HEARTS) { - n = textRenderer.getWidth(" " + scoreboard.getPlayerScore(playerListEntry.getProfile().getName(), obj).getScore()); - j = Math.max(j, n); - } + int textX = width + x - pingStringWidth + PING_TEXT_RENDER_OFFSET; + + if (!config.shouldRenderPingBars()) { + textX += PING_BARS_WIDTH; } - playerList = playerList.subList(0, Math.min(playerList.size(), 80)); - int l = playerList.size(); - int m = l; - - for(n = 1; m > 20; m = (l + n - 1) / n) { - ++n; - } - - boolean displayPlayerIcons = mc.isInSingleplayer() || mc.getNetworkHandler().getConnection().isEncrypted(); - int q; - if (obj != null) { - if (obj.getRenderType() == ScoreboardCriterion.RenderType.HEARTS) { - q = 90; - } else { - q = j; - } + int pingTextColor = config.shouldAutoColorPingText() ? PingColors.getColor(player.getLatency()) : config.getTextColor(); + textRenderer.drawWithShadow(matrixStack, pingString, (float) textX, (float) y, pingTextColor); + if (config.shouldRenderPingBars()) { + ((PlayerListHudInvoker) hud).renderLatencyText(matrixStack, width, x, y, player); } else { - q = 0; - } - int r = Math.min(n * ((displayPlayerIcons ? PLAYER_ICON_WIDTH : 0) + i + q + 13 + PLAYER_SLOT_EXTRA_WIDTH), width - 50) / n; - int s = width / 2 - (r * n + (n - 1) * 5) / 2; - int t = 10; - int u = r * n + (n - 1) * 5; - List headerLines = null; - if (header != null) { - headerLines = mc.textRenderer.wrapLines(header, width - 50); - - for (OrderedText headerLine : headerLines) { - u = Math.max(u, mc.textRenderer.getWidth(headerLine)); - } - } - - List footerLines = null; - if (footer != null) { - footerLines = mc.textRenderer.wrapLines(footer, width - 50); - - for (OrderedText footerLine : footerLines) { - u = Math.max(u, mc.textRenderer.getWidth(footerLine)); - } - } - - int var10000; - int var10001; - int var10002; - int var10004; - int y; - if (headerLines != null) { - var10000 = width / 2 - u / 2 - 1; - var10001 = t - 1; - var10002 = width / 2 + u / 2 + 1; - var10004 = headerLines.size(); - DrawableHelper.fill(stack, var10000, var10001, var10002, t + var10004 * 9, Integer.MIN_VALUE); - - for (OrderedText headerLine : headerLines) { - y = mc.textRenderer.getWidth(headerLine); - mc.textRenderer.drawWithShadow(stack, headerLine, (float)(width / 2 - y / 2), (float)t, -1); - t += 9; - } - - ++t; - } - - DrawableHelper.fill(stack, width / 2 - u / 2 - 1, t - 1, width / 2 + u / 2 + 1, t + m * 9, Integer.MIN_VALUE); - int w = mc.options.getTextBackgroundColor(553648127); - - int ai; - for(int x = 0; x < l; ++x) { - y = x / m; - ai = x % m; - int aa = s + y * r + y * 5; - int ab = t + ai * 9; - DrawableHelper.fill(stack, aa, ab, aa + r, ab + 8, w); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.setShader(GameRenderer::getPositionColorShader); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - if (x < playerList.size()) { - PlayerListEntry player = playerList.get(x); - GameProfile gameProfile = player.getProfile(); - int ah; - if (displayPlayerIcons) { - PlayerEntity playerEntity = mc.world.getPlayerByUuid(gameProfile.getId()); - boolean bl2 = playerEntity != null && playerEntity.isPartVisible(PlayerModelPart.CAPE) && ("Dinnerbone".equals(gameProfile.getName()) || "Grumm".equals(gameProfile.getName())); - RenderSystem.setShaderTexture(0, player.getSkinTexture()); - ah = 8 + (bl2 ? 8 : 0); - int ad = 8 * (bl2 ? -1 : 1); - DrawableHelper.drawTexture(stack, aa, ab, 8, 8, 8.0F, (float)ah, 8, ad, 64, 64); - if (playerEntity != null && playerEntity.isPartVisible(PlayerModelPart.HAT)) { - int ae = 8 + (bl2 ? 8 : 0); - int af = 8 * (bl2 ? -1 : 1); - DrawableHelper.drawTexture(stack, aa, ab, 8, 8, 40.0F, (float)ae, 8, af, 64, 64); - } - - aa += 9; - } - - Text playerName = hud.getPlayerName(player); - if (player.getGameMode() == GameMode.SPECTATOR) { - mc.textRenderer.drawWithShadow(stack, playerName, (float)aa, (float)ab, -1862270977); - } else { - mc.textRenderer.drawWithShadow(stack, playerName, (float)aa, (float)ab, -1); - } - - if (obj != null && player.getGameMode() != GameMode.SPECTATOR) { - int ag = aa + i + 1; - ah = ag + q; - if (ah - ag > 5) { - PlayerListHudUtil.renderScoreboardObjective(hud, stack, obj, ab, gameProfile.getName(), ag, ah, player); - } - } - - // Here is the magic, rendering the ping text - String pingString = String.format(config.getTextFormatString(), player.getLatency()); - int pingStringWidth = textRenderer.getWidth(pingString); - int textX = r + aa - pingStringWidth + PING_TEXT_RENDER_OFFSET; - - if (displayPlayerIcons) { - textX -= PLAYER_ICON_WIDTH; - } - - if (!config.shouldRenderPingBars()) { - textX += PING_BARS_WIDTH; - } - - int pingTextColor = config.shouldAutoColorPingText() - ? PingColors.getColor(player.getLatency()) - : config.getTextColor(); - - textRenderer.drawWithShadow(stack, pingString, (float) textX, (float) ab, pingTextColor); - - if (config.shouldRenderPingBars()) { - PlayerListHudUtil.renderLatencyIcon( - hud, stack, r, aa - (displayPlayerIcons ? PLAYER_ICON_WIDTH : 0), ab, player); - } else { - // If we don't render ping bars, we need to reset the render system color so the rest - // of the player list renders properly - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - } - } - } - - if (footerLines != null) { - t += m * 9 + 1; - var10000 = width / 2 - u / 2 - 1; - var10001 = t - 1; - var10002 = width / 2 + u / 2 + 1; - var10004 = footerLines.size(); - DrawableHelper.fill(stack, var10000, var10001, var10002, t + var10004 * 9, Integer.MIN_VALUE); - - for (OrderedText footerLine : footerLines) { - ai = textRenderer.getWidth(footerLine); - textRenderer.drawWithShadow(stack, footerLine, (float)(width / 2 - ai / 2), (float)t, -1); - t += 9; - } + // If we don't render ping bars, we need to reset the render system color so the rest + // of the player list renders properly + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); } } - - @Environment(EnvType.CLIENT) - static class EntryOrderComparator implements Comparator { - public int compare(PlayerListEntry p1, PlayerListEntry p2) { - Team team = p1.getScoreboardTeam(); - Team team2 = p2.getScoreboardTeam(); - return ComparisonChain.start() - .compareTrueFirst(p1.getGameMode() != GameMode.SPECTATOR, p2.getGameMode() != GameMode.SPECTATOR) - .compare(team != null ? team.getName() : "", team2 != null ? team2.getName() : "") - .compare(p1.getProfile().getName(), p2.getProfile().getName(), String::compareToIgnoreCase) - .result(); - } - } -} \ No newline at end of file +} diff --git a/src/main/java/com/vladmarica/betterpingdisplay/hud/PlayerListHudUtil.java b/src/main/java/com/vladmarica/betterpingdisplay/hud/PlayerListHudUtil.java deleted file mode 100644 index fc1ebd5..0000000 --- a/src/main/java/com/vladmarica/betterpingdisplay/hud/PlayerListHudUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.vladmarica.betterpingdisplay.hud; - -import com.vladmarica.betterpingdisplay.mixin.PlayerListHudAccessor; -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.scoreboard.ScoreboardObjective; -import net.minecraft.text.Text; - -public class PlayerListHudUtil { - /** Calls {@link net.minecraft.client.gui.hud.PlayerListHud#renderLatencyIcon}. */ - static void renderLatencyIcon(PlayerListHud hud, MatrixStack stack, int x, int offsetX, int y, PlayerListEntry player) { - ((PlayerListHudAccessor) hud).invokeRenderLatencyIcon(stack, x, offsetX, y, player); - } - - /** Calls {@link net.minecraft.client.gui.hud.PlayerListHud#renderScoreboardObjective} */ - static void renderScoreboardObjective(PlayerListHud hud, MatrixStack stack, ScoreboardObjective obj, int i, String str, int j, int k, PlayerListEntry player) { - ((PlayerListHudAccessor) hud).invokeRenderScoreboardObjective(obj, i, str, j, k, player, stack); - } - - static Text getHeader(PlayerListHud hud) { - return ((PlayerListHudAccessor) hud).getHeader(); - } - - static Text getFooter(PlayerListHud hud) { - return ((PlayerListHudAccessor) hud).getFooter(); - } -} diff --git a/src/main/java/com/vladmarica/betterpingdisplay/mixin/InGameHudMixin.java b/src/main/java/com/vladmarica/betterpingdisplay/mixin/InGameHudMixin.java deleted file mode 100644 index 4911b83..0000000 --- a/src/main/java/com/vladmarica/betterpingdisplay/mixin/InGameHudMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.vladmarica.betterpingdisplay.mixin; - -import com.vladmarica.betterpingdisplay.hud.CustomPlayerListHud; -import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.ScoreboardObjective; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(InGameHud.class) -abstract class InGameHudMixin { - @Redirect(method = "render", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/PlayerListHud;render(Lnet/minecraft/client/util/math/MatrixStack;ILnet/minecraft/scoreboard/Scoreboard;Lnet/minecraft/scoreboard/ScoreboardObjective;)V")) - private void render(PlayerListHud hud, MatrixStack stack, int width, Scoreboard scoreboard, ScoreboardObjective objective) { - CustomPlayerListHud.render(hud, stack, width, scoreboard, objective); - } -} diff --git a/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudAccessor.java b/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudAccessor.java deleted file mode 100644 index 8d5f8d8..0000000 --- a/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudAccessor.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.vladmarica.betterpingdisplay.mixin; - -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.scoreboard.ScoreboardObjective; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(PlayerListHud.class) -public interface PlayerListHudAccessor { - @Invoker - void invokeRenderLatencyIcon(MatrixStack stack, int x, int offsetX, int y, PlayerListEntry player); - - @Invoker - void invokeRenderScoreboardObjective(ScoreboardObjective obj, int i, String str, int j, int k, PlayerListEntry player, MatrixStack stack); - - @Accessor("header") - Text getHeader(); - - @Accessor("footer") - Text getFooter(); -} diff --git a/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudInvoker.java b/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudInvoker.java new file mode 100644 index 0000000..91a78f1 --- /dev/null +++ b/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudInvoker.java @@ -0,0 +1,13 @@ +package com.vladmarica.betterpingdisplay.mixin; + +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(PlayerListHud.class) +public interface PlayerListHudInvoker { + @Invoker("renderLatencyIcon") + void renderLatencyText(MatrixStack matrices, int width, int x, int y, PlayerListEntry entry); +} diff --git a/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudMixin.java b/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudMixin.java new file mode 100644 index 0000000..a7b49bc --- /dev/null +++ b/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudMixin.java @@ -0,0 +1,37 @@ +package com.vladmarica.betterpingdisplay.mixin; + +import com.vladmarica.betterpingdisplay.hud.CustomPlayerListHud; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.client.util.math.MatrixStack; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(PlayerListHud.class) +public abstract class PlayerListHudMixin { + @Unique + @Final + private static final int PLAYER_SLOT_EXTRA_WIDTH = 45; + + @Shadow + @Final + private MinecraftClient client; + + @ModifyConstant(method = "render", constant = @Constant(intValue = 13)) + private int on13(int original) { + return original + PLAYER_SLOT_EXTRA_WIDTH; + } + + @Redirect(method = "render", at = @At(value = "INVOKE", target = "net/minecraft/client/gui/hud/PlayerListHud.renderLatencyIcon(Lnet/minecraft/client/util/math/MatrixStack;IIILnet/minecraft/client/network/PlayerListEntry;)V")) + private void redirectLatencyDrawCall(PlayerListHud instance, MatrixStack matrices, int width, int x, int y, @NotNull PlayerListEntry entry) { + CustomPlayerListHud.render(this.client, instance, matrices, width, x, y, entry); + } +} diff --git a/src/main/resources/betterpingdisplay.mixins.json b/src/main/resources/betterpingdisplay.mixins.json index 45b09ed..0fe092b 100644 --- a/src/main/resources/betterpingdisplay.mixins.json +++ b/src/main/resources/betterpingdisplay.mixins.json @@ -1,15 +1,15 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.vladmarica.betterpingdisplay.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - ], - "client": [ - "InGameHudMixin", - "PlayerListHudAccessor" - ], - "injectors": { - "defaultRequire": 1 + "required": true, + "minVersion": "0.8", + "package": "com.vladmarica.betterpingdisplay.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "PlayerListHudInvoker", + "PlayerListHudMixin" + ], + "injectors": { + "defaultRequire": 1 } }