Initial work on the 1.15.2 Fabric port of this mod
This commit is contained in:
parent
182592e051
commit
7f253fd09a
17 changed files with 753 additions and 0 deletions
|
@ -0,0 +1,15 @@
|
|||
package com.vladmarica.betterpingdisplay;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class BetterPingDisplayMod implements ModInitializer {
|
||||
public static final String MODID = "betterpingdisplay";
|
||||
public static final Logger LOGGER = LogManager.getLogger(MODID);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
LOGGER.info("BetterPingDisplay mod loaded");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
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.mixin.PlayerListHudAccessor;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
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.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 Ordering<PlayerListEntry> ENTRY_ORDERING = Ordering.from(new EntryOrderComparator());
|
||||
|
||||
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);
|
||||
|
||||
ClientPlayNetworkHandler clientPlayNetworkHandler = mc.player.networkHandler;
|
||||
List<PlayerListEntry> 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 bl = 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 * ((bl ? 9 : 0) + i + q + 13), width - 50) / n;
|
||||
int s = width / 2 - (r * n + (n - 1) * 5) / 2;
|
||||
int t = 10;
|
||||
int u = r * n + (n - 1) * 5;
|
||||
List<String> 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<String> 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, 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 (bl) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
PlayerListHudUtil.renderLatencyIcon(hud, r, aa - (bl ? 9 : 0), ab, player);
|
||||
}
|
||||
}
|
||||
|
||||
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<PlayerListEntry> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
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 {
|
||||
static void renderLatencyIcon(PlayerListHud hud, int x, int offsetX, int y, PlayerListEntry player) {
|
||||
((PlayerListHudAccessor) hud).invokeRenderLatencyIcon(x, offsetX, y, player);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
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();
|
||||
}
|
BIN
src/main/resources/assets/betterpingdisplay/icon.png
Normal file
BIN
src/main/resources/assets/betterpingdisplay/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
15
src/main/resources/betterpingdisplay.mixins.json
Normal file
15
src/main/resources/betterpingdisplay.mixins.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "com.vladmarica.betterpingdisplay.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
],
|
||||
"client": [
|
||||
"InGameHudMixin",
|
||||
"PlayerListHudAccessor"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
37
src/main/resources/fabric.mod.json
Normal file
37
src/main/resources/fabric.mod.json
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "modid",
|
||||
"version": "${version}",
|
||||
|
||||
"name": "Better Ping Display",
|
||||
"description": "This is an example description! Tell everyone what your mod is about!",
|
||||
"authors": [
|
||||
"Quintinity"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://github.com/vladmarica/better-ping-display-fabric",
|
||||
"sources": "https://github.com/vladmarica/better-ping-display-fabric"
|
||||
},
|
||||
|
||||
"license": "MIT",
|
||||
"icon": "assets/modid/icon.png",
|
||||
|
||||
"environment": "client",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"com.vladmarica.betterpingdisplay.BetterPingDisplayMod"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"betterpingdisplay.mixins.json"
|
||||
],
|
||||
|
||||
"depends": {
|
||||
"fabricloader": ">=0.7.4",
|
||||
"fabric": "*",
|
||||
"minecraft": "1.15.x"
|
||||
},
|
||||
"suggests": {
|
||||
"flamingo": "*"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue