soiz1's picture
Upload folder using huggingface_hub
d46f4a3 verified
package net.minecraft.client.gui.components;
import com.mojang.authlib.GameProfile;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.minecraft.ChatFormatting;
import net.minecraft.Optionull;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentUtils;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.numbers.NumberFormat;
import net.minecraft.network.chat.numbers.StyledFormat;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.GameType;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.ReadOnlyScoreInfo;
import net.minecraft.world.scores.ScoreHolder;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class PlayerTabOverlay {
private static final ResourceLocation PING_UNKNOWN_SPRITE = ResourceLocation.withDefaultNamespace("icon/ping_unknown");
private static final ResourceLocation PING_1_SPRITE = ResourceLocation.withDefaultNamespace("icon/ping_1");
private static final ResourceLocation PING_2_SPRITE = ResourceLocation.withDefaultNamespace("icon/ping_2");
private static final ResourceLocation PING_3_SPRITE = ResourceLocation.withDefaultNamespace("icon/ping_3");
private static final ResourceLocation PING_4_SPRITE = ResourceLocation.withDefaultNamespace("icon/ping_4");
private static final ResourceLocation PING_5_SPRITE = ResourceLocation.withDefaultNamespace("icon/ping_5");
private static final ResourceLocation HEART_CONTAINER_BLINKING_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/container_blinking");
private static final ResourceLocation HEART_CONTAINER_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/container");
private static final ResourceLocation HEART_FULL_BLINKING_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/full_blinking");
private static final ResourceLocation HEART_HALF_BLINKING_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/half_blinking");
private static final ResourceLocation HEART_ABSORBING_FULL_BLINKING_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/absorbing_full_blinking");
private static final ResourceLocation HEART_FULL_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/full");
private static final ResourceLocation HEART_ABSORBING_HALF_BLINKING_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/absorbing_half_blinking");
private static final ResourceLocation HEART_HALF_SPRITE = ResourceLocation.withDefaultNamespace("hud/heart/half");
private static final Comparator<PlayerInfo> PLAYER_COMPARATOR = Comparator.<PlayerInfo>comparingInt(p_357670_ -> -p_357670_.getTabListOrder())
.thenComparingInt(p_253306_ -> p_253306_.getGameMode() == GameType.SPECTATOR ? 1 : 0)
.thenComparing(p_269613_ -> Optionull.mapOrDefault(p_269613_.getTeam(), PlayerTeam::getName, ""))
.thenComparing(p_253305_ -> p_253305_.getProfile().getName(), String::compareToIgnoreCase);
public static final int MAX_ROWS_PER_COL = 20;
private final Minecraft minecraft;
private final Gui gui;
@Nullable
private Component footer;
@Nullable
private Component header;
private boolean visible;
private final Map<UUID, PlayerTabOverlay.HealthState> healthStates = new Object2ObjectOpenHashMap<>();
public PlayerTabOverlay(Minecraft p_94527_, Gui p_94528_) {
this.minecraft = p_94527_;
this.gui = p_94528_;
}
public Component getNameForDisplay(PlayerInfo p_94550_) {
return p_94550_.getTabListDisplayName() != null
? this.decorateName(p_94550_, p_94550_.getTabListDisplayName().copy())
: this.decorateName(p_94550_, PlayerTeam.formatNameForTeam(p_94550_.getTeam(), Component.literal(p_94550_.getProfile().getName())));
}
private Component decorateName(PlayerInfo p_94552_, MutableComponent p_94553_) {
return p_94552_.getGameMode() == GameType.SPECTATOR ? p_94553_.withStyle(ChatFormatting.ITALIC) : p_94553_;
}
public void setVisible(boolean p_94557_) {
if (this.visible != p_94557_) {
this.healthStates.clear();
this.visible = p_94557_;
if (p_94557_) {
Component component = ComponentUtils.formatList(this.getPlayerInfos(), Component.literal(", "), this::getNameForDisplay);
this.minecraft.getNarrator().sayNow(Component.translatable("multiplayer.player.list.narration", component));
}
}
}
private List<PlayerInfo> getPlayerInfos() {
return this.minecraft.player.connection.getListedOnlinePlayers().stream().sorted(PLAYER_COMPARATOR).limit(80L).toList();
}
public void render(GuiGraphics p_281484_, int p_283602_, Scoreboard p_282338_, @Nullable Objective p_282369_) {
List<PlayerInfo> list = this.getPlayerInfos();
List<PlayerTabOverlay.ScoreDisplayEntry> list1 = new ArrayList<>(list.size());
int i = this.minecraft.font.width(" ");
int j = 0;
int k = 0;
for (PlayerInfo playerinfo : list) {
Component component = this.getNameForDisplay(playerinfo);
j = Math.max(j, this.minecraft.font.width(component));
int l = 0;
Component component1 = null;
int i1 = 0;
if (p_282369_ != null) {
ScoreHolder scoreholder = ScoreHolder.fromGameProfile(playerinfo.getProfile());
ReadOnlyScoreInfo readonlyscoreinfo = p_282338_.getPlayerScoreInfo(scoreholder, p_282369_);
if (readonlyscoreinfo != null) {
l = readonlyscoreinfo.value();
}
if (p_282369_.getRenderType() != ObjectiveCriteria.RenderType.HEARTS) {
NumberFormat numberformat = p_282369_.numberFormatOrDefault(StyledFormat.PLAYER_LIST_DEFAULT);
component1 = ReadOnlyScoreInfo.safeFormatValue(readonlyscoreinfo, numberformat);
i1 = this.minecraft.font.width(component1);
k = Math.max(k, i1 > 0 ? i + i1 : 0);
}
}
list1.add(new PlayerTabOverlay.ScoreDisplayEntry(component, l, component1, i1));
}
if (!this.healthStates.isEmpty()) {
Set<UUID> set = list.stream().map(p_250472_ -> p_250472_.getProfile().getId()).collect(Collectors.toSet());
this.healthStates.keySet().removeIf(p_248583_ -> !set.contains(p_248583_));
}
int j2 = list.size();
int k2 = j2;
int l2;
for (l2 = 1; k2 > 20; k2 = (j2 + l2 - 1) / l2) {
l2++;
}
boolean flag1 = this.minecraft.isLocalServer() || this.minecraft.getConnection().getConnection().isEncrypted();
int i3;
if (p_282369_ != null) {
if (p_282369_.getRenderType() == ObjectiveCriteria.RenderType.HEARTS) {
i3 = 90;
} else {
i3 = k;
}
} else {
i3 = 0;
}
int j3 = Math.min(l2 * ((flag1 ? 9 : 0) + j + i3 + 13), p_283602_ - 50) / l2;
int k3 = p_283602_ / 2 - (j3 * l2 + (l2 - 1) * 5) / 2;
int l3 = 10;
int i4 = j3 * l2 + (l2 - 1) * 5;
List<FormattedCharSequence> list2 = null;
if (this.header != null) {
list2 = this.minecraft.font.split(this.header, p_283602_ - 50);
for (FormattedCharSequence formattedcharsequence : list2) {
i4 = Math.max(i4, this.minecraft.font.width(formattedcharsequence));
}
}
List<FormattedCharSequence> list3 = null;
if (this.footer != null) {
list3 = this.minecraft.font.split(this.footer, p_283602_ - 50);
for (FormattedCharSequence formattedcharsequence1 : list3) {
i4 = Math.max(i4, this.minecraft.font.width(formattedcharsequence1));
}
}
if (list2 != null) {
p_281484_.fill(p_283602_ / 2 - i4 / 2 - 1, l3 - 1, p_283602_ / 2 + i4 / 2 + 1, l3 + list2.size() * 9, Integer.MIN_VALUE);
for (FormattedCharSequence formattedcharsequence2 : list2) {
int j1 = this.minecraft.font.width(formattedcharsequence2);
p_281484_.drawString(this.minecraft.font, formattedcharsequence2, p_283602_ / 2 - j1 / 2, l3, -1);
l3 += 9;
}
l3++;
}
p_281484_.fill(p_283602_ / 2 - i4 / 2 - 1, l3 - 1, p_283602_ / 2 + i4 / 2 + 1, l3 + k2 * 9, Integer.MIN_VALUE);
int j4 = this.minecraft.options.getBackgroundColor(553648127);
for (int k4 = 0; k4 < j2; k4++) {
int l4 = k4 / k2;
int k1 = k4 % k2;
int l1 = k3 + l4 * j3 + l4 * 5;
int i2 = l3 + k1 * 9;
p_281484_.fill(l1, i2, l1 + j3, i2 + 8, j4);
if (k4 < list.size()) {
PlayerInfo playerinfo1 = list.get(k4);
PlayerTabOverlay.ScoreDisplayEntry playertaboverlay$scoredisplayentry = list1.get(k4);
GameProfile gameprofile = playerinfo1.getProfile();
if (flag1) {
Player player = this.minecraft.level.getPlayerByUUID(gameprofile.getId());
boolean flag = player != null && LivingEntityRenderer.isEntityUpsideDown(player);
PlayerFaceRenderer.draw(p_281484_, playerinfo1.getSkin().texture(), l1, i2, 8, playerinfo1.showHat(), flag, -1);
l1 += 9;
}
p_281484_.drawString(
this.minecraft.font,
playertaboverlay$scoredisplayentry.name,
l1,
i2,
playerinfo1.getGameMode() == GameType.SPECTATOR ? -1862270977 : -1
);
if (p_282369_ != null && playerinfo1.getGameMode() != GameType.SPECTATOR) {
int j5 = l1 + j + 1;
int k5 = j5 + i3;
if (k5 - j5 > 5) {
this.renderTablistScore(p_282369_, i2, playertaboverlay$scoredisplayentry, j5, k5, gameprofile.getId(), p_281484_);
}
}
this.renderPingIcon(p_281484_, j3, l1 - (flag1 ? 9 : 0), i2, playerinfo1);
}
}
if (list3 != null) {
l3 += k2 * 9 + 1;
p_281484_.fill(p_283602_ / 2 - i4 / 2 - 1, l3 - 1, p_283602_ / 2 + i4 / 2 + 1, l3 + list3.size() * 9, Integer.MIN_VALUE);
for (FormattedCharSequence formattedcharsequence3 : list3) {
int i5 = this.minecraft.font.width(formattedcharsequence3);
p_281484_.drawString(this.minecraft.font, formattedcharsequence3, p_283602_ / 2 - i5 / 2, l3, -1);
l3 += 9;
}
}
}
protected void renderPingIcon(GuiGraphics p_283286_, int p_281809_, int p_282801_, int p_282223_, PlayerInfo p_282986_) {
ResourceLocation resourcelocation;
if (p_282986_.getLatency() < 0) {
resourcelocation = PING_UNKNOWN_SPRITE;
} else if (p_282986_.getLatency() < 150) {
resourcelocation = PING_5_SPRITE;
} else if (p_282986_.getLatency() < 300) {
resourcelocation = PING_4_SPRITE;
} else if (p_282986_.getLatency() < 600) {
resourcelocation = PING_3_SPRITE;
} else if (p_282986_.getLatency() < 1000) {
resourcelocation = PING_2_SPRITE;
} else {
resourcelocation = PING_1_SPRITE;
}
p_283286_.pose().pushPose();
p_283286_.pose().translate(0.0F, 0.0F, 100.0F);
p_283286_.blitSprite(RenderType::guiTextured, resourcelocation, p_282801_ + p_281809_ - 11, p_282223_, 10, 8);
p_283286_.pose().popPose();
}
private void renderTablistScore(
Objective p_283381_, int p_282557_, PlayerTabOverlay.ScoreDisplayEntry p_312058_, int p_283533_, int p_281254_, UUID p_283099_, GuiGraphics p_282280_
) {
if (p_283381_.getRenderType() == ObjectiveCriteria.RenderType.HEARTS) {
this.renderTablistHearts(p_282557_, p_283533_, p_281254_, p_283099_, p_282280_, p_312058_.score);
} else if (p_312058_.formattedScore != null) {
p_282280_.drawString(this.minecraft.font, p_312058_.formattedScore, p_281254_ - p_312058_.scoreWidth, p_282557_, 16777215);
}
}
private void renderTablistHearts(int p_282904_, int p_283173_, int p_282149_, UUID p_283348_, GuiGraphics p_281723_, int p_281354_) {
PlayerTabOverlay.HealthState playertaboverlay$healthstate = this.healthStates
.computeIfAbsent(p_283348_, p_249546_ -> new PlayerTabOverlay.HealthState(p_281354_));
playertaboverlay$healthstate.update(p_281354_, (long)this.gui.getGuiTicks());
int i = Mth.positiveCeilDiv(Math.max(p_281354_, playertaboverlay$healthstate.displayedValue()), 2);
int j = Math.max(p_281354_, Math.max(playertaboverlay$healthstate.displayedValue(), 20)) / 2;
boolean flag = playertaboverlay$healthstate.isBlinking((long)this.gui.getGuiTicks());
if (i > 0) {
int k = Mth.floor(Math.min((float)(p_282149_ - p_283173_ - 4) / (float)j, 9.0F));
if (k <= 3) {
float f1 = Mth.clamp((float)p_281354_ / 20.0F, 0.0F, 1.0F);
int j1 = (int)((1.0F - f1) * 255.0F) << 16 | (int)(f1 * 255.0F) << 8;
float f = (float)p_281354_ / 2.0F;
Component component = Component.translatable("multiplayer.player.list.hp", f);
Component component1;
if (p_282149_ - this.minecraft.font.width(component) >= p_283173_) {
component1 = component;
} else {
component1 = Component.literal(Float.toString(f));
}
p_281723_.drawString(
this.minecraft.font, component1, (p_282149_ + p_283173_ - this.minecraft.font.width(component1)) / 2, p_282904_, j1
);
} else {
ResourceLocation resourcelocation = flag ? HEART_CONTAINER_BLINKING_SPRITE : HEART_CONTAINER_SPRITE;
for (int l = i; l < j; l++) {
p_281723_.blitSprite(RenderType::guiTextured, resourcelocation, p_283173_ + l * k, p_282904_, 9, 9);
}
for (int i1 = 0; i1 < i; i1++) {
p_281723_.blitSprite(RenderType::guiTextured, resourcelocation, p_283173_ + i1 * k, p_282904_, 9, 9);
if (flag) {
if (i1 * 2 + 1 < playertaboverlay$healthstate.displayedValue()) {
p_281723_.blitSprite(RenderType::guiTextured, HEART_FULL_BLINKING_SPRITE, p_283173_ + i1 * k, p_282904_, 9, 9);
}
if (i1 * 2 + 1 == playertaboverlay$healthstate.displayedValue()) {
p_281723_.blitSprite(RenderType::guiTextured, HEART_HALF_BLINKING_SPRITE, p_283173_ + i1 * k, p_282904_, 9, 9);
}
}
if (i1 * 2 + 1 < p_281354_) {
p_281723_.blitSprite(RenderType::guiTextured, i1 >= 10 ? HEART_ABSORBING_FULL_BLINKING_SPRITE : HEART_FULL_SPRITE, p_283173_ + i1 * k, p_282904_, 9, 9);
}
if (i1 * 2 + 1 == p_281354_) {
p_281723_.blitSprite(RenderType::guiTextured, i1 >= 10 ? HEART_ABSORBING_HALF_BLINKING_SPRITE : HEART_HALF_SPRITE, p_283173_ + i1 * k, p_282904_, 9, 9);
}
}
}
}
}
public void setFooter(@Nullable Component p_94555_) {
this.footer = p_94555_;
}
public void setHeader(@Nullable Component p_94559_) {
this.header = p_94559_;
}
public void reset() {
this.header = null;
this.footer = null;
}
@OnlyIn(Dist.CLIENT)
static class HealthState {
private static final long DISPLAY_UPDATE_DELAY = 20L;
private static final long DECREASE_BLINK_DURATION = 20L;
private static final long INCREASE_BLINK_DURATION = 10L;
private int lastValue;
private int displayedValue;
private long lastUpdateTick;
private long blinkUntilTick;
public HealthState(int p_250562_) {
this.displayedValue = p_250562_;
this.lastValue = p_250562_;
}
public void update(int p_251066_, long p_251460_) {
if (p_251066_ != this.lastValue) {
long i = p_251066_ < this.lastValue ? 20L : 10L;
this.blinkUntilTick = p_251460_ + i;
this.lastValue = p_251066_;
this.lastUpdateTick = p_251460_;
}
if (p_251460_ - this.lastUpdateTick > 20L) {
this.displayedValue = p_251066_;
}
}
public int displayedValue() {
return this.displayedValue;
}
public boolean isBlinking(long p_251847_) {
return this.blinkUntilTick > p_251847_ && (this.blinkUntilTick - p_251847_) % 6L >= 3L;
}
}
@OnlyIn(Dist.CLIENT)
static record ScoreDisplayEntry(Component name, int score, @Nullable Component formattedScore, int scoreWidth) {
}
}