fix(hud): rewrite PlayerListHud.PlayerEntry to match obfuscated semantics

The hand-written PlayerEntry never initialized widthAnim, so the
render path read 0 for entry width and drew nothing visible. Other
gaps:
- nameWidth was never measured, so item layouts collapsed.
- displayName bypassed NameProtect.replacePlayerName, leaking real
  IGNs through the streamer/anti-doxx filter.
- startRemove() flipped a flag but never triggered the slide-out or
  height-collapse animations, so isRemoveDone() (which used a custom
  alpha decay) effectively never returned true.
- tick() mutated alpha / currentY by hand instead of just ticking
  the animation timers the render code already consults.

Rewrite per Recaf's PlayerListHud$PlayerEntry:
- Constructor seeds itemStacks/cheatItems from initialItems, calls
  updateItems(...) to set displayName, nameWidth, totalWidth, then
  primes slide/height/alpha/width anims (width starts at totalWidth
  so the row is visible from frame 1, then animates if it grows).
- updateItems() recomputes displayName via NameProtect, the cached
  nameWidth via headerFont, the totalWidth from padding/head/items,
  and animates widthAnim to the new total.
- startRemove() actually slides the entry out and animates height
  to 0; isRemoveDone() defers to heightAnim.isDone().
- Drop the dead alpha / targetY / currentY / parent fields.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Shirona1337
2026-05-21 23:46:32 +08:00
parent e02133547c
commit 346e17a3ca
2 changed files with 57 additions and 28 deletions
+5
View File
@@ -127,6 +127,8 @@ repositories {
// flatDir {
// dir 'libs'
// }
maven { url = "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" }
}
dependencies {
@@ -146,6 +148,9 @@ dependencies {
implementation 'org.ow2.asm:asm-commons:9.6'
implementation 'org.ow2.asm:asm-util:9.6'
// Dev Auth
runtimeOnly("me.djtheredstoner:DevAuth-forge-latest:1.2.2")
// Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")
+52 -28
View File
@@ -22,6 +22,7 @@ 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.modules.impl.render.NameProtect;
import shit.zen.event.impl.GlRenderEvent;
import shit.zen.event.impl.PacketEvent;
import shit.zen.event.impl.Render2DEvent;
@@ -42,56 +43,79 @@ import shit.zen.event.EventTarget;
public class PlayerListHud
extends HudElement {
public static final class PlayerEntry {
public final PlayerListHud parent;
public final PlayerListHud outer;
public final net.minecraft.world.entity.player.Player player;
public String displayName;
public float nameWidth;
public java.util.List<ItemStack> items;
public final java.util.Map<net.minecraft.world.item.Item, ItemStack> itemStacks = new java.util.HashMap<>();
public float totalWidth;
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 java.util.Map<net.minecraft.world.item.Item, ItemStack> itemStacks = new java.util.HashMap<>();
public final long createdTime;
public final SmoothAnimationTimer slideAnim = new SmoothAnimationTimer();
public final SmoothAnimationTimer fadeAnim = 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 boolean visible = true;
public final boolean rightAligned;
public PlayerEntry(PlayerListHud parent, net.minecraft.world.entity.player.Player player, java.util.List<ItemStack> items) {
this.parent = parent;
public PlayerEntry(PlayerListHud outer, net.minecraft.world.entity.player.Player player, java.util.List<ItemStack> initialItems) {
this.outer = outer;
this.player = player;
this.items = items;
this.displayName = player.getName().getString();
for (ItemStack stack : items) {
this.itemStacks.put(stack.getItem(), stack);
this.rightAligned = outer.wasRightAligned;
this.createdTime = System.currentTimeMillis();
initialItems.forEach(this::addItemStack);
ArrayList<ItemStack> initialList = new ArrayList<>();
for (ItemStack stack : this.itemStacks.values()) {
if (ItemUtil.isOtherCheat(stack)) {
this.cheatItems.put(stack.getItem(), stack.getDamageValue());
}
initialList.add(stack);
}
this.updateItems(initialList);
this.slideAnim.setCurrentValue(this.rightAligned ? 20.0 : -20.0);
this.heightAnim.setCurrentValue(0.0);
this.alphaAnim.setCurrentValue(0.0);
this.widthAnim.setCurrentValue(this.totalWidth);
}
public void updateItems(java.util.List<ItemStack> items) {
this.items = items;
this.displayName = NameProtect.replacePlayerName(this.player.getName().getString());
this.nameWidth = GlHelper.getStringWidth(this.displayName, this.outer.headerFont);
float padding = 5.0f;
float gap = 3.0f;
float headSize = 20.0f;
float itemSize = 16.0f;
this.totalWidth = padding + headSize + gap + this.nameWidth + gap + items.size() * (itemSize + gap) + padding;
this.widthAnim.animate(this.totalWidth, 0.25, Easings.EASE_OUT_SINE);
}
public void startRemove() {
if (this.removing) return;
this.removing = true;
}
public void updateItems(java.util.List<ItemStack> newItems) {
this.items = newItems;
}
public boolean isRemoveDone() {
return this.removing && this.alpha <= 0.01f;
float dist = 40.0f;
this.slideAnim.animate(this.rightAligned ? dist : -dist, 0.2, Easings.EASE_IN_POW3);
this.heightAnim.animate(0.0, 0.2, Easings.EASE_OUT_POW3);
}
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.fadeAnim.tick();
this.heightAnim.tick();
this.alphaAnim.tick();
this.widthAnim.tick();
}
public boolean isRemoveDone() {
return this.removing && this.heightAnim.isDone();
}
private void addItemStack(ItemStack stack) {
this.itemStacks.putIfAbsent(stack.getItem(), stack);
}
}