Files
OpenZen/src/main/java/shit/zen/hud/PlayerListHud.java
T
Shirona1337andClaude Opus 4.7 41f3d972b8 refactor: rename Procyon-style locals to readable names
Rename ~2887 unreadable Procyon-decompiler locals/params (f/f2/fN,
n/n2, bl/bl2, nArray, bufferedImage, etc.) across 169 files to
context-aware camelCase identifiers (x, y, width, height, alpha,
color, sensitivity, etc.). Logic, control flow, field/method names
and method signatures (types/arity) are preserved; only local
variable and parameter names changed.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-21 19:21:20 +08:00

478 lines
24 KiB
Java

package shit.zen.hud;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BowItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import shit.zen.event.impl.GlRenderEvent;
import shit.zen.event.impl.PacketEvent;
import shit.zen.event.impl.Render2DEvent;
import shit.zen.event.impl.TickEvent;
import shit.zen.render.DrawContext;
import shit.zen.render.FontPresets;
import shit.zen.render.FontRenderer;
import shit.zen.render.GlHelper;
import shit.zen.render.Paint;
import shit.zen.utils.animation.SmoothAnimationTimer;
import shit.zen.utils.game.ItemUtil;
import shit.zen.utils.math.Easings;
import shit.zen.utils.misc.ChatUtil;
import shit.zen.utils.render.ColorUtil;
import shit.zen.utils.render.RenderUtil;
import shit.zen.event.EventTarget;
public class PlayerListHud
extends HudElement {
public static final class PlayerEntry {
public final PlayerListHud parent;
public final net.minecraft.world.entity.player.Player player;
public java.util.List<ItemStack> items;
public final java.util.Map<net.minecraft.world.item.Item, ItemStack> itemStacks = new java.util.HashMap<>();
public final java.util.Map<net.minecraft.world.item.Item, Integer> cheatItems = new java.util.HashMap<>();
public final java.util.Set<net.minecraft.world.item.Item> flaggedItems = new java.util.HashSet<>();
public final SmoothAnimationTimer fadeAnim = new SmoothAnimationTimer();
public final SmoothAnimationTimer slideAnim = new SmoothAnimationTimer();
public final SmoothAnimationTimer heightAnim = new SmoothAnimationTimer();
public final SmoothAnimationTimer alphaAnim = new SmoothAnimationTimer();
public final SmoothAnimationTimer widthAnim = new SmoothAnimationTimer();
public String displayName;
public float nameWidth;
public boolean visible = true;
public boolean rightAligned = false;
public float alpha = 1.0f;
public float targetY;
public float currentY;
public boolean removing = false;
public PlayerEntry(PlayerListHud parent, net.minecraft.world.entity.player.Player player, java.util.List<ItemStack> items) {
this.parent = parent;
this.player = player;
this.items = items;
this.displayName = player.getName().getString();
for (ItemStack stack : items) {
this.itemStacks.put(stack.getItem(), stack);
}
}
public void startRemove() {
this.removing = true;
}
public void updateItems(java.util.List<ItemStack> newItems) {
this.items = newItems;
}
public boolean isRemoveDone() {
return this.removing && this.alpha <= 0.01f;
}
public void tick() {
float target = this.removing ? 0.0f : 1.0f;
this.alpha += (target - this.alpha) * 0.18f;
this.currentY += (this.targetY - this.currentY) * 0.18f;
this.fadeAnim.tick();
this.slideAnim.tick();
this.heightAnim.tick();
this.alphaAnim.tick();
}
}
private final List<PlayerListHud.PlayerEntry> playerEntryList = new ArrayList<>();
private final FontRenderer nameFont = FontPresets.poppinsMedium(15.0f);
final FontRenderer headerFont = FontPresets.pingfang(15.0f);
private final FontRenderer subFont = FontPresets.materialIcons(18.0f);
private final SmoothAnimationTimer slideAnim = new SmoothAnimationTimer();
private final SmoothAnimationTimer fadeAnim = new SmoothAnimationTimer();
private final SmoothAnimationTimer rightAlignAnim = new SmoothAnimationTimer();
boolean wasRightAligned = false;
private boolean rightAlign = false;
private final Set<UUID> playerEntries = new HashSet<>();
private final Set<UUID> removedEntries = new HashSet<>();
public PlayerListHud() {
super("PlayerList");
this.setWidth(150.0f);
this.setHeight(100.0f);
this.setEnabled(true);
this.fadeAnim.setCurrentValue(1.0);
this.rightAlignAnim.setCurrentValue(1.0);
}
@Override
public void onEnable() {
if (this.playerEntryList != null) {
this.playerEntryList.clear();
}
if (this.removedEntries != null) {
this.removedEntries.clear();
}
}
private boolean isCheatItem(ItemStack itemStack) {
if (itemStack.isEmpty()) {
return false;
}
return ItemUtil.isOtherCheat(itemStack) || ItemUtil.isWeaponItem(itemStack) || ItemUtil.isEnchantedGoldenApple(itemStack) || ItemUtil.isEndCrystal(itemStack) || ItemUtil.isKBSlimeBall(itemStack) || ItemUtil.isKBStick(itemStack) || ItemUtil.getPunchLevel(itemStack) > 2 && itemStack.getItem() instanceof BowItem || ItemUtil.getPowerLevel(itemStack) > 3 && itemStack.getItem() instanceof BowItem;
}
@EventTarget
public void onTick(TickEvent tickEvent) {
if (mc.player == null || mc.level == null) {
if (this.playerEntryList != null && !this.playerEntryList.isEmpty()) {
this.playerEntryList.clear();
}
if (this.removedEntries != null && !this.removedEntries.isEmpty()) {
this.removedEntries.clear();
}
return;
}
List<? extends Player> levelPlayers = mc.level.players();
ArrayList<Player> playerList = new ArrayList<>(levelPlayers);
for (PlayerListHud.PlayerEntry entry : this.playerEntryList) {
if (!playerList.stream().noneMatch(p -> p.getUUID().equals(entry.player.getUUID()))) continue;
entry.startRemove();
}
for (Player currentPlayer : playerList) {
List<ItemStack> playerItems;
boolean alreadyTracked = this.playerEntryList.stream().anyMatch(e -> e.player.getUUID().equals(currentPlayer.getUUID()));
if (alreadyTracked || (playerItems = this.getPlayerItems(currentPlayer)).isEmpty()) continue;
this.playerEntryList.add(0, new PlayerListHud.PlayerEntry(this, currentPlayer, playerItems));
}
for (PlayerListHud.PlayerEntry entry : this.playerEntryList) {
playerList.stream().filter(p -> p.getUUID().equals(entry.player.getUUID())).findFirst().ifPresent(p -> {
if (p == mc.player) {
entry.updateItems(this.getPlayerItems(p));
} else {
this.getPlayerItems(p).forEach(itemStack -> entry.itemStacks.putIfAbsent(itemStack.getItem(), itemStack));
ItemStack handItem = p.getMainHandItem();
if (ItemUtil.isOtherCheat(handItem)) {
int dmg = handItem.getDamageValue();
Integer prev = entry.cheatItems.get(handItem.getItem());
if (prev != null && dmg > prev && !entry.flaggedItems.contains(handItem.getItem())) {
ChatUtil.print(String.format("§c[ALERT] §f%s used a God Axe!", p.getName().getString()));
entry.flaggedItems.add(handItem.getItem());
}
entry.cheatItems.put(handItem.getItem(), dmg);
}
ArrayList<ItemStack> filtered = new ArrayList<>();
for (ItemStack itemStack : entry.itemStacks.values()) {
if (entry.flaggedItems.contains(itemStack.getItem())) continue;
filtered.add(itemStack);
}
entry.updateItems(filtered);
}
});
}
this.removedEntries.removeIf(uuid -> {
Player player = mc.level.getPlayerByUUID(uuid);
if (player == null) {
return true;
}
MobEffectInstance absorption = player.getEffect(MobEffects.ABSORPTION);
return absorption == null || absorption.getAmplifier() < 3;
});
}
private List<ItemStack> getPlayerItems(Player player) {
Stream<ItemStack> stream = player == mc.player
? Stream.concat(player.getInventory().items.stream(), Stream.concat(player.getInventory().armor.stream(), player.getInventory().offhand.stream()))
: Stream.concat(player.getInventory().armor.stream(), Stream.of(player.getMainHandItem(), player.getOffhandItem()));
return stream.filter(this::isCheatItem).collect(Collectors.toList());
}
@EventTarget
public void onPacket(PacketEvent packetEvent) {
MobEffectInstance absorption;
Player player;
Entity entity;
ClientboundEntityEventPacket entityEventPacket;
if (mc.level == null) {
return;
}
Packet<?> packet = packetEvent.getPacket();
if (packet instanceof ClientboundEntityEventPacket && (entityEventPacket = (ClientboundEntityEventPacket)packet).getEventId() == 35 && (entity = entityEventPacket.getEntity(mc.level)) instanceof Player) {
player = (Player)entity;
ChatUtil.print("§e[提示] §f" + player.getName().getString() + " 触发了不死图腾!");
this.updatePlayerItem(player, Items.TOTEM_OF_UNDYING);
}
if (packet instanceof ClientboundSetEntityDataPacket dataPacket
&& (entity = mc.level.getEntity(dataPacket.id())) instanceof Player
&& (absorption = (player = (Player)entity).getEffect(MobEffects.ABSORPTION)) != null
&& absorption.getAmplifier() >= 3
&& player.hasEffect(MobEffects.REGENERATION)
&& !this.removedEntries.contains(player.getUUID())) {
ChatUtil.print("§6[提示] §f" + player.getName().getString() + " 吃下了附魔金苹果!");
this.updatePlayerItem(player, Items.ENCHANTED_GOLDEN_APPLE);
this.removedEntries.add(player.getUUID());
}
}
private void updatePlayerItem(Player player, Item item) {
this.playerEntryList.stream().filter(entry -> entry.player.getUUID().equals(player.getUUID())).findFirst().ifPresent(entry -> {
entry.flaggedItems.add(item);
entry.itemStacks.remove(item);
});
}
@Override
public void onRender2D(Render2DEvent render2DEvent, float x, float y) {
}
@Override
public void onGlRender(GlRenderEvent glRenderEvent, float x, float y) {
float rightFade;
float leftFade;
float entryY;
float panelWidth;
boolean isRightAligned;
this.playerEntryList.removeIf(PlayerListHud.PlayerEntry::isRemoveDone);
this.playerEntryList.forEach(PlayerListHud.PlayerEntry::tick);
this.slideAnim.tick();
this.fadeAnim.tick();
this.rightAlignAnim.tick();
if (this.playerEntryList.isEmpty() && this.slideAnim.isDone() && this.fadeAnim.isDone()) {
return;
}
boolean rightSide = isRightAligned = x + this.getWidth() / 2.0f > (float)mc.getWindow().getGuiScaledWidth() / 2.0f;
if (this.wasRightAligned != isRightAligned && this.rightAlignAnim.isDone()) {
this.rightAlign = this.wasRightAligned;
this.wasRightAligned = isRightAligned;
this.rightAlignAnim.setCurrentValue(0.0);
this.rightAlignAnim.animate(1.0, 0.3, Easings.EASE_OUT_SINE);
}
float padding = 5.0f;
float gap = 3.0f;
float spacing = 4.5f;
float cornerRadius = 15.0f;
float blurStrength = 0.7f;
String iconText = "";
String titleText = "Playerlist";
float iconWidth = GlHelper.getStringWidth(iconText, this.subFont);
float titleWidth = GlHelper.getStringWidth(titleText, this.nameFont);
float headerHeight = (float)GlHelper.getFontAscent(this.nameFont) + padding * 2.0f;
float headerWidth = iconWidth + gap + titleWidth + padding * 2.0f;
float headSize = 20.0f;
float itemSize = 16.0f;
float entryHeight = headSize + padding * 2.0f;
float targetWidth = headerWidth;
if (!this.playerEntryList.isEmpty()) {
panelWidth = 0.0f;
for (PlayerListHud.PlayerEntry entry : this.playerEntryList) {
float itemsWidth;
entryY = GlHelper.getStringWidth(entry.displayName, this.headerFont);
float rowWidth = headSize + gap + entryY + gap + (itemsWidth = (float)entry.items.size() * (itemSize + gap)) + padding * 2.0f;
if (!(rowWidth > panelWidth)) continue;
panelWidth = rowWidth;
}
targetWidth = Math.max(headerWidth, panelWidth);
}
if (this.slideAnim.isDone() && this.playerEntryList.isEmpty()) {
this.slideAnim.setCurrentValue(targetWidth);
}
this.slideAnim.animate(targetWidth, 0.2, Easings.EASE_OUT_SINE);
if (this.playerEntryList.isEmpty()) {
this.fadeAnim.animate(0.0, 0.2, Easings.EASE_IN_POW3);
} else {
this.fadeAnim.animate(1.0, 0.2, Easings.EASE_OUT_POW3);
}
panelWidth = this.slideAnim.getValueF();
float drawX = x;
if (this.wasRightAligned) {
drawX = x + this.getWidth() - panelWidth;
}
float finalX = drawX;
entryY = y + headerHeight + gap;
for (PlayerListHud.PlayerEntry entry : this.playerEntryList) {
if (entry.visible) {
entry.visible = false;
entry.fadeAnim.setCurrentValue(entryY);
entry.slideAnim.setCurrentValue(entry.rightAligned ? 20.0 : -20.0);
entry.heightAnim.setCurrentValue(0.0);
entry.alphaAnim.setCurrentValue(0.0);
entry.slideAnim.animate(0.0, 0.2, Easings.EASE_OUT_POW3);
entry.heightAnim.animate(1.0, 0.2, Easings.EASE_OUT_POW3);
entry.alphaAnim.animate(entryHeight + gap, 0.2, Easings.EASE_OUT_POW3);
}
entry.fadeAnim.animate(entryY, 0.15, Easings.EASE_OUT_SINE);
entryY += entry.alphaAnim.getValueF();
}
GuiGraphics guiGraphics = new GuiGraphics(mc, mc.renderBuffers().bufferSource());
float globalAlpha = this.fadeAnim.getValueF();
if (!this.rightAlignAnim.isDone()) {
float prevSideFade = 1.0f - this.rightAlignAnim.getValueF();
leftFade = this.rightAlignAnim.getValueF();
this.renderLegacy(guiGraphics.pose(), finalX, y, panelWidth, this.rightAlign, globalAlpha * prevSideFade, entryHeight, spacing, cornerRadius, blurStrength, padding);
this.renderLegacy(guiGraphics.pose(), finalX, y, panelWidth, this.wasRightAligned, globalAlpha * leftFade, entryHeight, spacing, cornerRadius, blurStrength, padding);
} else {
this.renderLegacy(guiGraphics.pose(), finalX, y, panelWidth, this.wasRightAligned, globalAlpha, entryHeight, spacing, cornerRadius, blurStrength, padding);
}
DrawContext drawContext = glRenderEvent.drawContext();
if (!this.rightAlignAnim.isDone()) {
leftFade = 1.0f - this.rightAlignAnim.getValueF();
rightFade = this.rightAlignAnim.getValueF();
this.renderEntry(drawContext, finalX, y, panelWidth, this.rightAlign, globalAlpha * leftFade, iconText, titleText, iconWidth, titleWidth, headerHeight, padding, gap, spacing, headSize);
this.renderEntry(drawContext, finalX, y, panelWidth, this.wasRightAligned, globalAlpha * rightFade, iconText, titleText, iconWidth, titleWidth, headerHeight, padding, gap, spacing, headSize);
} else {
this.renderEntry(drawContext, finalX, y, panelWidth, this.wasRightAligned, globalAlpha, iconText, titleText, iconWidth, titleWidth, headerHeight, padding, gap, spacing, headSize);
}
if (!this.rightAlignAnim.isDone()) {
leftFade = 1.0f - this.rightAlignAnim.getValueF();
rightFade = this.rightAlignAnim.getValueF();
this.renderEntryGui(guiGraphics, finalX, y, panelWidth, this.rightAlign, globalAlpha * leftFade, headSize, itemSize, padding, gap);
this.renderEntryGui(guiGraphics, finalX, y, panelWidth, this.wasRightAligned, globalAlpha * rightFade, headSize, itemSize, padding, gap);
} else {
this.renderEntryGui(guiGraphics, finalX, y, panelWidth, this.wasRightAligned, globalAlpha, headSize, itemSize, padding, gap);
}
guiGraphics.flush();
if (this.wasRightAligned) {
this.setX(drawX);
}
this.setWidth(panelWidth);
this.setHeight(entryY - y);
}
private void renderLegacy(PoseStack poseStack, float x, float y, float width, boolean rightAligned, float alpha, float entryHeight, float spacing, float cornerRadius, float blurStrength, float padding) {
if (alpha <= 0.01f) {
return;
}
for (PlayerListHud.PlayerEntry entry : this.playerEntryList) {
float heightFactor = entry.heightAnim.getValueF();
if (heightFactor <= 0.0f) continue;
float baseX = rightAligned ? x + width - entry.widthAnim.getValueF() : x;
float entryX = baseX + entry.slideAnim.getValueF();
float entryY = entry.fadeAnim.getValueF();
float entryAlpha = blurStrength * alpha * heightFactor;
float entryWidth = entry.widthAnim.getValueF();
float drawX = entryX;
RenderUtil.drawBlurredRect(poseStack, drawX, entryY, entryWidth, entryHeight, spacing, cornerRadius, entryAlpha, 0);
}
}
private void renderEntry(DrawContext drawContext, float x, float y, float width, boolean rightAligned, float alpha, String iconText, String titleText, float iconWidth, float titleWidth, float headerHeight, float padding, float gap, float spacing, float headSize) {
if (alpha <= 0.01f) {
return;
}
float headerTextY = y + padding + (headerHeight - padding * 2.0f - (float)GlHelper.getFontAscent(this.nameFont)) / 2.0f + 1.0f;
int textColor = ColorUtil.fromARGB(255, 255, 255, (int)(255.0f * alpha));
Paint textPaint = GlHelper.toPaint(textColor);
try (Paint bgPaint = new Paint()){
bgPaint.setColor(ColorUtil.fromARGB(0, 0, 0, (int)(190.0f * alpha)));
GlHelper.drawRoundedRect(x, y, width, headerHeight, spacing, bgPaint);
}
if (rightAligned) {
float iconX = x + width - padding - iconWidth;
float titleX = iconX - gap - titleWidth;
GlHelper.drawTextWithShadow(titleText, titleX, headerTextY, this.nameFont, textPaint);
GlHelper.drawTextWithShadow(iconText, iconX, headerTextY + 1.0f, this.subFont, textPaint);
} else {
GlHelper.drawTextWithShadow(iconText, x + padding, headerTextY + 1.0f, this.subFont, textPaint);
GlHelper.drawTextWithShadow(titleText, x + padding + iconWidth + gap, headerTextY, this.nameFont, textPaint);
}
for (PlayerListHud.PlayerEntry entry : this.playerEntryList) {
float headX;
float entryAlpha;
float heightFactor = entry.heightAnim.getValueF();
if (heightFactor <= 0.0f || (entryAlpha = alpha * heightFactor) <= 0.0f) continue;
float baseX = rightAligned ? x + width - entry.widthAnim.getValueF() : x;
float entryX = baseX + entry.slideAnim.getValueF();
float entryY = entry.fadeAnim.getValueF();
float entryHeight = headSize + padding * 2.0f;
try (Paint entryBgPaint = new Paint()){
entryBgPaint.setColor(ColorUtil.fromARGB(0, 0, 0, (int)(90.0f * entryAlpha)));
float entryWidth = entry.widthAnim.getValueF();
float entryDrawX = entryX;
GlHelper.drawRoundedRect(entryDrawX, entryY, entryWidth, entryHeight, spacing, entryBgPaint);
}
float contentY = entryY + padding;
int nameColor = entry.player == mc.player ? ColorUtil.fromRGB(100, 150, 255) : -1;
int nameAlpha = ColorUtil.withAlpha(nameColor, (int)entryAlpha);
float nameY = entryY + padding + (entryHeight - padding * 2.0f - (float)GlHelper.getFontAscent(this.headerFont)) / 2.0f;
if (rightAligned) {
headX = entryX + entry.widthAnim.getValueF();
float headDrawX = headX - padding - headSize;
if (entry.player instanceof AbstractClientPlayer) {
GlHelper.drawPlayerHeadRounded((AbstractClientPlayer)entry.player, headDrawX, contentY, headSize, headSize, entryAlpha, spacing);
}
float nameX = headDrawX - spacing - entry.nameWidth;
GlHelper.drawTextShadowLegacy(entry.displayName, nameX, nameY, this.headerFont, nameAlpha);
continue;
}
if (entry.player instanceof AbstractClientPlayer) {
headX = entryX + padding;
GlHelper.drawPlayerHeadRounded((AbstractClientPlayer)entry.player, headX, contentY, headSize, headSize, entryAlpha, spacing);
}
headX = entryX + padding + headSize + spacing;
GlHelper.drawTextShadowLegacy(entry.displayName, headX, nameY, this.headerFont, nameAlpha);
}
}
private void renderEntryGui(GuiGraphics guiGraphics, float x, float y, float width, boolean rightAligned, float alpha, float headSize, float itemSize, float padding, float gap) {
if (alpha <= 0.01f) {
return;
}
for (PlayerListHud.PlayerEntry entry : this.playerEntryList) {
float entryAlpha;
float heightFactor = entry.heightAnim.getValueF();
if (heightFactor <= 0.0f || (entryAlpha = alpha * heightFactor) <= 0.01f) continue;
float baseX = rightAligned ? x + width - entry.widthAnim.getValueF() : x;
float entryX = baseX + entry.slideAnim.getValueF();
float entryY = entry.fadeAnim.getValueF();
float itemY = entryY + padding + (headSize - itemSize) / 2.0f;
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, entryAlpha);
float rightEdge;
if (rightAligned) {
rightEdge = entryX + entry.widthAnim.getValueF();
float headRight = rightEdge - padding - headSize;
float nameRight = headRight - gap - entry.nameWidth;
float itemsTotal = (float)entry.items.size() * (itemSize + gap);
float itemX = nameRight - gap - itemsTotal;
for (ItemStack itemStack : entry.items) {
PoseStack poseStack = guiGraphics.pose();
poseStack.pushPose();
poseStack.translate(itemX, itemY, 0.0f);
guiGraphics.renderItem(itemStack, 0, 0);
poseStack.popPose();
itemX += itemSize + gap;
}
} else {
rightEdge = entryX + padding + headSize + gap + entry.nameWidth + gap;
for (ItemStack itemStack : entry.items) {
PoseStack poseStack = guiGraphics.pose();
poseStack.pushPose();
poseStack.translate(rightEdge, itemY, 0.0f);
guiGraphics.renderItem(itemStack, 0, 0);
poseStack.popPose();
rightEdge += itemSize + gap;
}
}
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.disableBlend();
}
guiGraphics.flush();
}
@Override
public void onSettings() {
}
}