This commit is contained in:
Hiajen Hiajen 2021-06-20 10:58:55 +02:00
parent 6587d3aff0
commit 2cb319c065
13 changed files with 509 additions and 5 deletions

View File

@ -1,6 +1,7 @@
package net.saltymc.eaa;
import net.saltymc.eaa.commands.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -10,7 +11,8 @@ import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public final class EaaMod implements ClientModInitializer {
private static final Logger LOGGER = LogManager.getLogger();
public static final Logger LOGGER = LogManager.getLogger("EAA-MOD");
public static Logger getLogger() {
return LOGGER;

View File

@ -4,8 +4,8 @@ import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.client.toast.SystemToast;
import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.text.Text;
@ -14,6 +14,8 @@ import net.saltymc.eaa.util.database.DB_Player;
import net.saltymc.eaa.util.database.DB_Tag;
import net.saltymc.eaa.util.mojangApi.PlayerInfo;
import java.util.Collection;
import static net.fabricmc.fabric.api.client.command.v1.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v1.ClientCommandManager.literal;
@ -36,7 +38,6 @@ public class TagCommand extends EaaModCommand{
source.sendFeedback(Text.of(e.toString()));
}
SystemToast.add(source.getClient().getToastManager(), SystemToast.Type.TUTORIAL_HINT, Text.of("Player Tagged"),
Text.of(player + " | " + tag.name() + " | " + grade));

View File

@ -0,0 +1,35 @@
package net.saltymc.eaa.custom.ping;
/**
* By: https://github.com/vladmarica/better-ping-display-fabric/
*/
public 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;
}
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;
}
}

View File

@ -0,0 +1,234 @@
package net.saltymc.eaa.custom.ping;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Ordering;
import com.mojang.authlib.GameProfile;
import com.mojang.blaze3d.systems.RenderSystem;
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.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.world.GameMode;
/**
* By: https://github.com/vladmarica/better-ping-display-fabric/
*/
public final class CustomPlayerListHud {
public static final PingConfig config = new PingConfig();
private static final Ordering<PlayerListEntry> 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, 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);
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.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);
}
}
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<OrderedText> 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<OrderedText> 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.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.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.color4f(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;
}
}
}
@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();
}
}
}

View File

@ -0,0 +1,40 @@
package net.saltymc.eaa.custom.ping;
import net.minecraft.util.math.MathHelper;
/**
* By: https://github.com/vladmarica/better-ping-display-fabric/
*/
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 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;
}
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)));
}
static float computeOffset(int start, int end, int value) {
float offset = (value - start) / (float) ( end - start);
return MathHelper.clamp(offset, 0.0F, 1.0F);
}
}

View File

@ -0,0 +1,107 @@
package net.saltymc.eaa.custom.ping;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import net.saltymc.eaa.EaaMod;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
public class PingConfig {
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;
public PingConfig(ConfigData confileFileFormat) {
if (confileFileFormat.pingTextColor.startsWith("#")) {
try {
textColor = Integer.parseInt(confileFileFormat.pingTextColor.substring(1), 16);
}
catch (NumberFormatException ex) {
EaaMod.LOGGER.error("Config option 'pingTextColor' is invalid - it must be a hex color code");
}
}
else {
EaaMod.LOGGER.error("Config option 'pingTextColor' is invalid - it must be a hex color code");
}
if (confileFileFormat.pingTextFormatString.contains("%d")) {
textFormatString = confileFileFormat.pingTextFormatString;
}
else {
EaaMod.LOGGER.error("Config option 'pingTextFormatString' is invalid - it needs to contain %d");
}
autoColorPingText = confileFileFormat.autoColorPingText;
renderPingBars = confileFileFormat.renderPingBars;
}
public PingConfig() {
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);
}
finally {
if (reader != null) {
reader.close();
}
}
}
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 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";
}
}

View File

@ -0,0 +1,31 @@
package net.saltymc.eaa.custom.ping;
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 net.saltymc.eaa.mixin.PlayerListHudAccessor;
/**
* By: https://github.com/vladmarica/better-ping-display-fabric/
*/
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();
}
}

View File

@ -0,0 +1,23 @@
package net.saltymc.eaa.mixin;
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 net.saltymc.eaa.custom.ping.CustomPlayerListHud;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* By: https://github.com/vladmarica/better-ping-display-fabric/
*/
@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);
}
}

View File

@ -0,0 +1,29 @@
package net.saltymc.eaa.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;
/**
* By: https://github.com/vladmarica/better-ping-display-fabric/
*/
@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();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -6,7 +6,9 @@
"mixins": [
],
"client": [
"ExampleMixin"
"ExampleMixin",
"InGameHudMixin",
"PlayerListHudAccessor"
],
"injectors": {
"defaultRequire": 1

View File

@ -24,7 +24,7 @@
]
},
"mixins": [
"modid.mixins.json"
"eaamod.mixins.json"
],
"depends": {