diff --git a/README.md b/README.md index 2f43ee8..b365e7a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Better Ping Display - Fabric Edition -[![](http://cf.way2muchnoise.eu/full_406343_downloads.svg)](https://curseforge.com/minecraft/mc-mods/better-ping-display-fabric) +[![](http://cf.way2muchnoise.eu/full_406343_downloads.svg)](https://curseforge.com/minecraft/mc-mods/better-ping-display-fabric) A [Fabric](https://fabricmc.net/) mod for Minecraft to display each player's ping in the player list as a number. @@ -23,6 +23,10 @@ This mod's config file is `betterpingdisplay.json`. It contains the following op ## Supported Minecraft Versions * **1.15.x** * **1.16.x** +* **1.17.x** +* **1.18.x** +* **1.19.x** +* **1.20.x** ## Requirements -* [Fabric](https://fabricmc.net/) +* [Fabric](https://fabricmc.net/) \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8f22a16..1230e96 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ plugins { - id 'fabric-loom' version '0.4-SNAPSHOT' + id 'fabric-loom' version '1.2-SNAPSHOT' id 'maven-publish' } -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 +sourceCompatibility = JavaVersion.VERSION_14 +targetCompatibility = JavaVersion.VERSION_14 archivesBaseName = project.archives_base_name version = project.mod_version @@ -20,6 +20,7 @@ dependencies { processResources { inputs.property "version", project.version + duplicatesStrategy = 'warn' from(sourceSets.main.resources.srcDirs) { include "fabric.mod.json" @@ -31,18 +32,10 @@ processResources { } } -tasks.withType(JavaCompile) { +tasks.withType(JavaCompile).configureEach { options.encoding = "UTF-8" } -// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task -// if it is present. -// If you remove this task, sources will not be generated. -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = "sources" - from sourceSets.main.allSource -} - jar { from "LICENSE" } @@ -55,9 +48,6 @@ publishing { artifact(remapJar) { builtBy remapJar } - artifact(sourcesJar) { - builtBy remapSourcesJar - } } } diff --git a/gradle.properties b/gradle.properties index 76ef33a..4d13014 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,16 +2,16 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties - # check these on https://fabricmc.net/use - minecraft_version=1.15.2 - yarn_mappings=1.15.2+build.17 - loader_version=0.9.2+build.206 +# check these on https://fabricmc.net/use +minecraft_version=1.20.1 +yarn_mappings=1.20.1+build.1 +loader_version=0.14.21 # Mod Properties - mod_version = 1.1.0 - maven_group = com.vladmarica - archives_base_name = BetterPingDisplay-Fabric +mod_version = 1.1.4 +maven_group = com.vladmarica +archives_base_name = BetterPingDisplay-Fabric # Dependencies - # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - fabric_version=0.19.0+build.325-1.15 +# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api +fabric_version=0.83.0+1.20.1 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 490fda8..62d4c05 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 622ab64..fae0804 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 2fe81a7..fbd7c51 100755 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 62bd9b9..5093609 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%* set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% diff --git a/src/main/java/com/vladmarica/betterpingdisplay/BetterPingDisplayMod.java b/src/main/java/com/vladmarica/betterpingdisplay/BetterPingDisplayMod.java index b9b3450..012b282 100644 --- a/src/main/java/com/vladmarica/betterpingdisplay/BetterPingDisplayMod.java +++ b/src/main/java/com/vladmarica/betterpingdisplay/BetterPingDisplayMod.java @@ -1,52 +1,53 @@ package com.vladmarica.betterpingdisplay; import com.vladmarica.betterpingdisplay.Config.ConfigData; -import java.io.File; -import java.nio.file.Path; import net.fabricmc.api.ModInitializer; import net.fabricmc.loader.api.FabricLoader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.io.File; +import java.nio.file.Path; + public class BetterPingDisplayMod implements ModInitializer { - public static final String MODID = "betterpingdisplay"; - public static final Logger LOGGER = LogManager.getLogger(MODID); - private static final String CONFIG_FILE_NAME = MODID + ".json"; - private static BetterPingDisplayMod INSTANCE; + public static final String MODID = "betterpingdisplay"; + public static final Logger LOGGER = LogManager.getLogger(MODID); + private static final String CONFIG_FILE_NAME = MODID + ".json"; + private static BetterPingDisplayMod INSTANCE; - private Config config = new Config(); + private Config config = new Config(); - @Override - public void onInitialize() { - INSTANCE = this; + @Override + public void onInitialize() { + INSTANCE = this; - Path configFilePath = FabricLoader.getInstance().getConfigDir().resolve(CONFIG_FILE_NAME); - File configFile = configFilePath.toFile(); - if (configFile.exists()) { - try { - ConfigData data = Config.loadConfigFile(configFile); - config = new Config(data); - Config.writeConfigFile(configFile, data); - } catch (Exception ex) { - LOGGER.error("Failed to load config file, using default. Error: {}", ex.getMessage()); - } - } else { - try { - LOGGER.warn("Could not find config file, creating a default one"); - Config.writeConfigFile(configFile, new ConfigData()); - } catch (Exception ex) { - LOGGER.error("Failed to write default config file. Error: {}", ex.getMessage()); - } - } + Path configFilePath = FabricLoader.getInstance().getConfigDir().resolve(CONFIG_FILE_NAME); + File configFile = configFilePath.toFile(); + if (configFile.exists()) { + try { + ConfigData data = Config.loadConfigFile(configFile); + config = new Config(data); + Config.writeConfigFile(configFile, data); + } catch (Exception ex) { + LOGGER.error("Failed to load config file, using default. Error: {}", ex.getMessage()); + } + } else { + try { + LOGGER.warn("Could not find config file, creating a default one"); + Config.writeConfigFile(configFile, new ConfigData()); + } catch (Exception ex) { + LOGGER.error("Failed to write default config file. Error: {}", ex.getMessage()); + } + } - LOGGER.info("BetterPingDisplay mod loaded"); - } + LOGGER.info("BetterPingDisplay mod loaded"); + } - public Config getConfig() { - return this.config; - } + public Config getConfig() { + return config; + } - public static BetterPingDisplayMod instance() { - return INSTANCE; - } + public static BetterPingDisplayMod instance() { + return INSTANCE; + } } diff --git a/src/main/java/com/vladmarica/betterpingdisplay/Config.java b/src/main/java/com/vladmarica/betterpingdisplay/Config.java index 3b65a9f..9e29cb8 100644 --- a/src/main/java/com/vladmarica/betterpingdisplay/Config.java +++ b/src/main/java/com/vladmarica/betterpingdisplay/Config.java @@ -3,103 +3,96 @@ package com.vladmarica.betterpingdisplay; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Expose; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Serializable; + +import java.io.*; public class Config { - private static final int DEFAULT_PING_TEXT_COLOR = 0xA0A0A0; - private static final String DEFAULT_PING_TEXT_FORMAT = "%dms"; + private static final int DEFAULT_PING_TEXT_COLOR = 0xA0A0A0; + private static final String DEFAULT_PING_TEXT_FORMAT = "%dms"; - private boolean autoColorPingText; - private boolean renderPingBars; - private int textColor = DEFAULT_PING_TEXT_COLOR; - private String textFormatString = DEFAULT_PING_TEXT_FORMAT; + private final boolean autoColorPingText; + private final boolean renderPingBars; + private int textColor = DEFAULT_PING_TEXT_COLOR; + private String textFormatString = DEFAULT_PING_TEXT_FORMAT; - public Config(ConfigData confileFileFormat) { - if (confileFileFormat.pingTextColor.startsWith("#")) { - try { - textColor = Integer.parseInt(confileFileFormat.pingTextColor.substring(1), 16); - } - catch (NumberFormatException ex) { - BetterPingDisplayMod.LOGGER.error("Config option 'pingTextColor' is invalid - it must be a hex color code"); - } - } - else { - BetterPingDisplayMod.LOGGER.error("Config option 'pingTextColor' is invalid - it must be a hex color code"); + public Config(ConfigData configFileFormat) { + if (configFileFormat.pingTextColor.startsWith("#")) { + try { + textColor = Integer.parseInt(configFileFormat.pingTextColor.substring(1), 16); + } catch (NumberFormatException ex) { + BetterPingDisplayMod.LOGGER.error("Config option 'pingTextColor' is invalid - it must be a hex color code"); + } + } else { + BetterPingDisplayMod.LOGGER.error("Config option 'pingTextColor' is invalid - it must be a hex color code"); + } + + if (configFileFormat.pingTextFormatString.contains("%d")) { + textFormatString = configFileFormat.pingTextFormatString; + } else { + BetterPingDisplayMod.LOGGER.error("Config option 'pingTextFormatString' is invalid - it needs to contain %d"); + } + + autoColorPingText = configFileFormat.autoColorPingText; + renderPingBars = configFileFormat.renderPingBars; } - if (confileFileFormat.pingTextFormatString.contains("%d")) { - textFormatString = confileFileFormat.pingTextFormatString; - } - else { - BetterPingDisplayMod.LOGGER.error("Config option 'pingTextFormatString' is invalid - it needs to contain %d"); + public Config() { + this(new ConfigData()); } - autoColorPingText = confileFileFormat.autoColorPingText; - renderPingBars = confileFileFormat.renderPingBars; - } - - public Config() { - this(new ConfigData()); - } - - public int getTextColor() { - return this.textColor; - } - - public String getTextFormatString() { - return this.textFormatString; - } - - public boolean shouldAutoColorPingText() { - return this.autoColorPingText; - } - - public boolean shouldRenderPingBars() { - return this.renderPingBars; - } - - public static ConfigData loadConfigFile(File configFile) throws IOException { - FileReader reader = null; - try { - Gson gson = new Gson(); - reader = new FileReader(configFile); - return gson.fromJson(reader, ConfigData.class); + public int getTextColor() { + return this.textColor; } - finally { - if (reader != null) { - reader.close(); - } + + public String getTextFormatString() { + return this.textFormatString; } - } - public static void writeConfigFile(File configFile, ConfigData data) throws IOException { - FileWriter writer = null; - try { - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - writer = new FileWriter(configFile); - writer.write(gson.toJson(data)); - } finally { - if (writer != null) { - writer.close(); - } + public boolean shouldAutoColorPingText() { + return this.autoColorPingText; } - } - public static class ConfigData implements Serializable { - @Expose - private boolean autoColorPingText = true; + public boolean shouldRenderPingBars() { + return this.renderPingBars; + } - @Expose - private boolean renderPingBars = false; + public static ConfigData loadConfigFile(File configFile) throws IOException { + FileReader reader = null; + try { + Gson gson = new Gson(); + reader = new FileReader(configFile); + return gson.fromJson(reader, ConfigData.class); + } finally { + if (reader != null) { + reader.close(); + } + } + } - @Expose - private String pingTextColor = "#A0A0A0"; + public static void writeConfigFile(File configFile, ConfigData data) throws IOException { + FileWriter writer = null; + try { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + writer = new FileWriter(configFile); + writer.write(gson.toJson(data)); + } finally { + if (writer != null) { + writer.close(); + } + } + } - @Expose - private String pingTextFormatString = "%dms"; - } + public static class ConfigData implements Serializable { + @Expose + private boolean autoColorPingText = true; + + @Expose + private boolean renderPingBars = false; + + @Expose + private String pingTextColor = "#A0A0A0"; + + @Expose + private String pingTextFormatString = "%dms"; + } } diff --git a/src/main/java/com/vladmarica/betterpingdisplay/hud/ColorUtil.java b/src/main/java/com/vladmarica/betterpingdisplay/hud/ColorUtil.java index 599506e..249ccb7 100644 --- a/src/main/java/com/vladmarica/betterpingdisplay/hud/ColorUtil.java +++ b/src/main/java/com/vladmarica/betterpingdisplay/hud/ColorUtil.java @@ -1,32 +1,39 @@ package com.vladmarica.betterpingdisplay.hud; -public class ColorUtil { +import com.google.common.annotations.VisibleForTesting; - public static int interpolate(int colorStart, int colorEnd, float offset) { - if (offset < 0 || offset > 1) { - throw new IllegalArgumentException("Offset must be between 0.0 and 1.0"); +public final class ColorUtil { + public static int interpolate(int colorStart, int colorEnd, float offset) { + if (offset < 0 || offset > 1) { + throw new IllegalArgumentException("Offset must be between 0.0 and 1.0"); + } + + int redDiff = getRed(colorEnd) - getRed(colorStart); + int greenDiff = getGreen(colorEnd) - getGreen(colorStart); + int blueDiff = getBlue(colorEnd) - getBlue(colorStart); + + int newRed = Math.round(getRed(colorStart) + (redDiff * offset)); + int newGreen = Math.round(getGreen(colorStart) + (greenDiff * offset)); + int newBlue = Math.round(getBlue(colorStart) + (blueDiff * offset)); + + return (newRed << 16) | (newGreen << 8) | newBlue; } - int redDiff = getRed(colorEnd) - getRed(colorStart); - int greenDiff = getGreen(colorEnd) - getGreen(colorStart); - int blueDiff = getBlue(colorEnd) - getBlue(colorStart); + @VisibleForTesting + static int getRed(int color) { + return (color >> 16) & 0xFF; + } - int newRed = Math.round(getRed(colorStart) + (redDiff * offset)); - int newGreen = Math.round(getGreen(colorStart) + (greenDiff * offset)); - int newBlue = Math.round(getBlue(colorStart) + (blueDiff * offset)); + @VisibleForTesting + static int getGreen(int color) { + return (color >> 8) & 0xFF; + } - return (newRed << 16) | (newGreen << 8) | newBlue; - } + @VisibleForTesting + static int getBlue(int color) { + return color & 0xFF; + } - static int getRed(int color) { - return (color >> 16) & 0xFF; - } - - static int getGreen(int color) { - return (color >> 8) & 0xFF; - } - - static int getBlue(int color) { - return color & 0xFF; - } + private ColorUtil() { + } } diff --git a/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java b/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java index f980b34..79d5d2b 100644 --- a/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java +++ b/src/main/java/com/vladmarica/betterpingdisplay/hud/CustomPlayerListHud.java @@ -1,234 +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.BetterPingDisplayMod; import com.vladmarica.betterpingdisplay.Config; -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.mixin.PlayerListHudInvoker; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.render.entity.PlayerModelPart; -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.Text; -import net.minecraft.util.Formatting; -import net.minecraft.world.GameMode; public final class CustomPlayerListHud { + private static final int PING_TEXT_RENDER_OFFSET = -13; + private static final int PING_BARS_WIDTH = 11; + private static final Config config = BetterPingDisplayMod.instance().getConfig(); - 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; - - public static void render(PlayerListHud hud, 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(); - - ClientPlayNetworkHandler clientPlayNetworkHandler = mc.player.networkHandler; - List playerList = ENTRY_ORDERING.sortedCopy(clientPlayNetworkHandler.getPlayerList()); - int i = 0; - int j = 0; - Iterator playerListIterator = playerList.iterator(); - - int n; - while(playerListIterator.hasNext()) { - PlayerListEntry playerListEntry = (PlayerListEntry)playerListIterator.next(); - n = mc.textRenderer.getStringWidth(hud.getPlayerName(playerListEntry).asFormattedString()); - i = Math.max(i, n); - if (obj != null && obj.getRenderType() != ScoreboardCriterion.RenderType.HEARTS) { - n = textRenderer.getStringWidth(" " + scoreboard.getPlayerScore(playerListEntry.getProfile().getName(), obj).getScore()); - j = Math.max(j, n); - } - } - - 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; - } - } 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 list2 = null; - if (header != null) { - list2 = mc.textRenderer.wrapStringToWidthAsList(header.asFormattedString(), width - 50); - - String string; - for(Iterator var18 = list2.iterator(); var18.hasNext(); u = Math.max(u, mc.textRenderer.getStringWidth(string))) { - string = (String)var18.next(); - } - } - - List list3 = null; - String string3; - Iterator var36; - if (footer != null) { - list3 = mc.textRenderer.wrapStringToWidthAsList(footer.asFormattedString(), width - 50); - - for(var36 = list3.iterator(); var36.hasNext(); u = Math.max(u, mc.textRenderer.getStringWidth(string3))) { - string3 = (String)var36.next(); - } - } - - int var10000; - int var10001; - int var10002; - int var10004; - int y; - if (list2 != null) { - var10000 = width / 2 - u / 2 - 1; - var10001 = t - 1; - var10002 = width / 2 + u / 2 + 1; - var10004 = list2.size(); - DrawableHelper.fill(var10000, var10001, var10002, t + var10004 * 9, Integer.MIN_VALUE); - - for(var36 = list2.iterator(); var36.hasNext(); t += 9) { - string3 = (String)var36.next(); - y = mc.textRenderer.getStringWidth(string3); - mc.textRenderer.drawWithShadow(string3, (float)(width / 2 - y / 2), (float)t, -1); - } - - ++t; - } - - DrawableHelper.fill(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(aa, ab, aa + r - 1, ab + 8, w); - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.enableAlphaTest(); - 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())); - mc.getTextureManager().bindTexture(player.getSkinTexture()); - ah = 8 + (bl2 ? 8 : 0); - int ad = 8 * (bl2 ? -1 : 1); - DrawableHelper.blit(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.blit(aa, ab, 8, 8, 40.0F, (float)ae, 8, af, 64, 64); - } - - aa += 9; - } - - String string4 = hud.getPlayerName(player).asFormattedString(); - if (player.getGameMode() == GameMode.SPECTATOR) { - mc.textRenderer.drawWithShadow(Formatting.ITALIC + string4, (float)aa, (float)ab, -1862270977); - } else { - mc.textRenderer.drawWithShadow(string4, (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, obj, ab, gameProfile.getName(), ag, ah, player); - } - } - - // Here is the magic, rendering the ping text + public static void renderPingDisplay( + MinecraftClient client, PlayerListHud hud, DrawContext context, int width, int x, int y, PlayerListEntry player) { String pingString = String.format(config.getTextFormatString(), player.getLatency()); - int pingStringWidth = textRenderer.getStringWidth(pingString); - int textX = r + aa - pingStringWidth + PING_TEXT_RENDER_OFFSET; - - if (displayPlayerIcons) { - textX -= PLAYER_ICON_WIDTH; - } + int pingStringWidth = client.textRenderer.getWidth(pingString); + int pingTextColor = config.shouldAutoColorPingText() + ? PingColors.getColor(player.getLatency()) : config.getTextColor(); + int textX = width + x - pingStringWidth + PING_TEXT_RENDER_OFFSET; if (!config.shouldRenderPingBars()) { - textX += PING_BARS_WIDTH; + textX += PING_BARS_WIDTH; } - int pingTextColor = config.shouldAutoColorPingText() - ? PingColors.getColor(player.getLatency()) - : config.getTextColor(); - - textRenderer.drawWithShadow(pingString, (float) textX, (float) ab, pingTextColor); + // Draw the ping text for the given player + context.drawTextWithShadow(client.textRenderer, pingString, textX, y, pingTextColor); if (config.shouldRenderPingBars()) { - PlayerListHudUtil.renderLatencyIcon( - hud, r, aa - (displayPlayerIcons ? PLAYER_ICON_WIDTH : 0), ab, player); + ((PlayerListHudInvoker) hud).invokeRenderLatencyIcon(context, width, x, y, 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.color4f(1.0F, 1.0F, 1.0F, 1.0F); + // 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 (list3 != null) { - t += m * 9 + 1; - var10000 = width / 2 - u / 2 - 1; - var10001 = t - 1; - var10002 = width / 2 + u / 2 + 1; - var10004 = list3.size(); - DrawableHelper.fill(var10000, var10001, var10002, t + var10004 * 9, Integer.MIN_VALUE); - - for(Iterator var39 = list3.iterator(); var39.hasNext(); t += 9) { - String string5 = (String)var39.next(); - ai = textRenderer.getStringWidth(string5); - textRenderer.drawWithShadow(string5, (float)(width / 2 - ai / 2), (float)t, -1); - } - } - } - - @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(); - } - } } diff --git a/src/main/java/com/vladmarica/betterpingdisplay/hud/PingColors.java b/src/main/java/com/vladmarica/betterpingdisplay/hud/PingColors.java index e981567..a22a09a 100644 --- a/src/main/java/com/vladmarica/betterpingdisplay/hud/PingColors.java +++ b/src/main/java/com/vladmarica/betterpingdisplay/hud/PingColors.java @@ -2,36 +2,39 @@ package com.vladmarica.betterpingdisplay.hud; import net.minecraft.util.math.MathHelper; -public class PingColors { - public static final int PING_START = 0; - public static final int PING_MID = 150; - public static final int PING_END = 300; +public final class PingColors { + public static final int PING_START = 0; + public static final int PING_MID = 150; + public static final int PING_END = 300; - public static final int COLOR_GREY = 0x535353; - public static final int COLOR_START = 0x00E676; - public static final int COLOR_MID = 0xD6CD30; - public static final int COLOR_END = 0xE53935; + public static final int COLOR_GREY = 0x535353; + public static final int COLOR_START = 0x00E676; + public static final int COLOR_MID = 0xD6CD30; + public static final int COLOR_END = 0xE53935; - public static int getColor(int ping) { - if (ping < PING_START) { - return COLOR_GREY; + public static int getColor(int ping) { + if (ping < PING_START) { + return COLOR_GREY; + } + + if (ping < PING_MID) { + return ColorUtil.interpolate( + COLOR_START, + COLOR_MID, + computeOffset(PING_START, PING_MID, ping)); + } + + return ColorUtil.interpolate( + COLOR_MID, + COLOR_END, + computeOffset(PING_MID, PING_END, Math.min(ping, PING_END))); } - if (ping < PING_MID) { - return ColorUtil.interpolate( - COLOR_START, - COLOR_MID, - computeOffset(PING_START, PING_MID, ping)); + private static float computeOffset(int start, int end, int value) { + float offset = (value - start) / (float) (end - start); + return MathHelper.clamp(offset, 0.0F, 1.0F); } - return ColorUtil.interpolate( - COLOR_MID, - COLOR_END, - computeOffset(PING_MID, PING_END, Math.min(ping, PING_END))); - } - - static float computeOffset(int start, int end, int value) { - float offset = (value - start) / (float) ( end - start); - return MathHelper.clamp(offset, 0.0F, 1.0F); - } + private PingColors() { + } } 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 aeb376c..0000000 --- a/src/main/java/com/vladmarica/betterpingdisplay/hud/PlayerListHudUtil.java +++ /dev/null @@ -1,27 +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.scoreboard.ScoreboardObjective; -import net.minecraft.text.Text; - -public class PlayerListHudUtil { - /** Calls {@link net.minecraft.client.gui.hud.PlayerListHud#renderLatencyIcon}. */ - static void renderLatencyIcon(PlayerListHud hud, int x, int offsetX, int y, PlayerListEntry player) { - ((PlayerListHudAccessor) hud).invokeRenderLatencyIcon(x, offsetX, y, player); - } - - /** Calls {@link net.minecraft.client.gui.hud.PlayerListHud#renderScoreboardObjective} */ - static void renderScoreboardObjective(PlayerListHud hud, ScoreboardObjective obj, int i, String str, int j, int k, PlayerListEntry player) { - ((PlayerListHudAccessor) hud).invokeRenderScoreboardObjective(obj, i, str, j, k, player); - } - - 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 43f098d..0000000 --- a/src/main/java/com/vladmarica/betterpingdisplay/mixin/InGameHudMixin.java +++ /dev/null @@ -1,19 +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.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(ILnet/minecraft/scoreboard/Scoreboard;Lnet/minecraft/scoreboard/ScoreboardObjective;)V")) - private void render(PlayerListHud hud, int width, Scoreboard scoreboard, ScoreboardObjective objective) { - CustomPlayerListHud.render(hud, 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 1f8cd62..0000000 --- a/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudAccessor.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.vladmarica.betterpingdisplay.mixin; - -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.network.PlayerListEntry; -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(int x, int offsetX, int y, PlayerListEntry player); - - @Invoker - void invokeRenderScoreboardObjective(ScoreboardObjective obj, int i, String str, int j, int k, PlayerListEntry player); - - @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..5d57e0c --- /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.DrawContext; +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.PlayerListEntry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(PlayerListHud.class) +public interface PlayerListHudInvoker { + @Invoker("renderLatencyIcon") + void invokeRenderLatencyIcon(DrawContext context, 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..e1612b5 --- /dev/null +++ b/src/main/java/com/vladmarica/betterpingdisplay/mixin/PlayerListHudMixin.java @@ -0,0 +1,48 @@ +package com.vladmarica.betterpingdisplay.mixin; + +import com.vladmarica.betterpingdisplay.hud.CustomPlayerListHud; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.PlayerListEntry; +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; + + /** + * Increases the int constant {@code 13} in the {@link PlayerListHud#render} method by + * {@value #PLAYER_SLOT_EXTRA_WIDTH}. This constant is used to define the width of the "slots" in the player list. + * In order to fit the ping text, this needs to be increased. + */ + @ModifyConstant(method = "render", constant = @Constant(intValue = 13)) + private int modifySlotWidthConstant(int original) { + return original + PLAYER_SLOT_EXTRA_WIDTH; + } + + /** + * Redirects the call to {@code renderLatencyIcon} in {@link PlayerListHud#render} to instead call + * {@link CustomPlayerListHud#renderPingDisplay}. + */ + @Redirect(method = "render", + at = @At(value = "INVOKE", target = "net/minecraft/client/gui/hud/PlayerListHud.renderLatencyIcon(Lnet/minecraft/client/gui/DrawContext;IIILnet/minecraft/client/network/PlayerListEntry;)V")) + private void redirectRenderLatencyIconCall( + PlayerListHud instance, DrawContext context, int width, int x, int y, @NotNull PlayerListEntry entry) { + CustomPlayerListHud.renderPingDisplay(client, instance, context, 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 } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ec4cafe..7e3b308 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,20 +1,22 @@ { "schemaVersion": 1, "id": "betterpingdisplay", - "version": "1.1", + "version": "1.1.3", "name": "Better Ping Display", "description": "Shows the actual ping number instead of just bars in the player list!", "authors": [ - "Quintinity" + "Quintinity", + "Yuuki" ], "contact": { - "homepage": "https://github.com/vladmarica/better-ping-display-fabric", - "sources": "https://github.com/vladmarica/better-ping-display-fabric" + "homepage": "https://git.raiza.dev/Raiza.dev/better-ping-display-fabric", + "sources": "https://git.raiza.dev/Raiza.dev/better-ping-display-fabric", + "issues": "https://git.raiza.dev/Raiza.dev/better-ping-display-fabric/issues" }, "license": "MIT", - "icon": "assets/modid/icon.png", + "icon": "assets/betterpingdisplay/icon.png", "environment": "client", "entrypoints": { @@ -27,10 +29,8 @@ ], "depends": { - "fabricloader": ">=0.7.4", - "minecraft": "1.15.x" + "fabricloader": ">=0.14", + "minecraft": ">=1.19" }, - "suggests": { - "flamingo": "*" - } + "suggests": {} } diff --git a/src/test/java/com/vladmarica/betterpingdisplay/hud/ColorUtilTest.java b/src/test/java/com/vladmarica/betterpingdisplay/hud/ColorUtilTest.java index 65a94c0..936717b 100644 --- a/src/test/java/com/vladmarica/betterpingdisplay/hud/ColorUtilTest.java +++ b/src/test/java/com/vladmarica/betterpingdisplay/hud/ColorUtilTest.java @@ -9,6 +9,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +/** Unit tests for {@link ColorUtil} */ @RunWith(JUnit4.class) public class ColorUtilTest { @@ -45,4 +46,4 @@ public class ColorUtilTest { assertThrows(IllegalArgumentException.class, () -> ColorUtil.interpolate(0, 1, -0.1F)); assertThrows(IllegalArgumentException.class, () -> ColorUtil.interpolate(0, 1, 1.1F)); } -} +} \ No newline at end of file