fix(identity): remove stale Leaf prefixes
Release / release (push) Successful in 2m11s
CI / build (push) Successful in 57s

This commit is contained in:
dmg
2026-08-10 21:13:02 -04:00
parent 07bc1d9382
commit e064c7398c
7 changed files with 93 additions and 30 deletions
+35 -23
View File
@@ -15,11 +15,9 @@ import org.bukkit.scoreboard.Team;
public final class LeafIdentity {
private static final String TEAM_NAME = "leaf_protected";
private record Names(String display, String playerList, String decoratedDisplay, String decoratedList) { }
private final Server server;
private final Logger logger;
private final Map<UUID, Names> names = new HashMap<>();
private final Map<UUID, String> managedPrefixes = new HashMap<>();
private final Map<UUID, String> teamEntries = new HashMap<>();
public LeafIdentity(Server server, Logger logger) {
@@ -28,43 +26,57 @@ public final class LeafIdentity {
}
public synchronized void apply(Player player, String configuredPrefix) {
String prefix = ChatColor.translateAlternateColorCodes('&', configuredPrefix);
String prefix = color(configuredPrefix);
UUID playerId = player.getUniqueId();
Names previous = names.get(playerId);
String baseDisplay = previous == null ? player.getDisplayName() : previous.display();
String baseList = previous == null ? player.getPlayerListName() : previous.playerList();
String decoratedDisplay = prefix + baseDisplay;
String decoratedList = prefix + baseList;
String previousPrefix = managedPrefixes.get(playerId);
String display = normalized(player.getDisplayName(), previousPrefix, prefix);
String playerList = normalized(player.getPlayerListName(), previousPrefix, prefix);
String decoratedDisplay = prefix + display;
String decoratedList = prefix + playerList;
if (previous == null || player.getDisplayName().equals(previous.decoratedDisplay())) {
if (!player.getDisplayName().equals(decoratedDisplay)) {
player.setDisplayName(decoratedDisplay);
}
if (previous == null || player.getPlayerListName().equals(previous.decoratedList())) {
if (!player.getPlayerListName().equals(decoratedList)) {
player.setPlayerListName(decoratedList);
}
names.put(playerId, new Names(baseDisplay, baseList, decoratedDisplay, decoratedList));
managedPrefixes.put(playerId, prefix);
applyOverhead(player, prefix);
}
public synchronized void remove(Player player) {
public synchronized void remove(Player player, String configuredPrefix) {
UUID playerId = player.getUniqueId();
Names installed = names.remove(playerId);
if (installed != null) {
if (player.getDisplayName().equals(installed.decoratedDisplay())) {
player.setDisplayName(installed.display());
}
if (player.getPlayerListName().equals(installed.decoratedList())) {
player.setPlayerListName(installed.playerList());
}
String configured = color(configuredPrefix);
String installed = managedPrefixes.remove(playerId);
String display = normalized(player.getDisplayName(), installed, configured);
String playerList = normalized(player.getPlayerListName(), installed, configured);
if (!player.getDisplayName().equals(display)) {
player.setDisplayName(display);
}
if (!player.getPlayerListName().equals(playerList)) {
player.setPlayerListName(playerList);
}
String entry = teamEntries.remove(playerId);
Team team = leafTeam(false);
if (entry != null && team != null) {
team.removeEntry(entry);
if (team != null) {
team.removeEntry(entry == null ? player.getName() : entry);
}
}
private static String normalized(String value, String previousPrefix, String prefix) {
String normalized = value;
if (previousPrefix != null && !previousPrefix.equals(prefix)) {
normalized = normalized.replace(previousPrefix, "");
}
return normalized.replace(prefix, "");
}
private static String color(String configuredPrefix) {
return ChatColor.translateAlternateColorCodes('&', configuredPrefix);
}
private void applyOverhead(Player player, String prefix) {
Scoreboard scoreboard = mainScoreboard();
if (scoreboard == null) {
@@ -222,7 +222,7 @@ public final class LeafRuntime {
if (protection.apply(player, settings.resistanceLevel())) {
identity.apply(player, settings.prefix());
} else {
identity.remove(player);
identity.remove(player, settings.prefix());
}
} else {
removePresentation(player);
@@ -231,7 +231,7 @@ public final class LeafRuntime {
public void removePresentation(Player player) {
protection.remove(player);
identity.remove(player);
identity.remove(player, settingsProvider.current().prefix());
}
public void reconcileAllOnline() {
@@ -30,7 +30,7 @@ final class LeafIdentityTest {
when(fixtures.player().getDisplayName()).thenReturn(decorated);
when(fixtures.player().getPlayerListName()).thenReturn(decorated);
identity.remove(fixtures.player());
identity.remove(fixtures.player(), "&a🍃 ");
verify(fixtures.player()).setDisplayName("Alex");
verify(fixtures.player()).setPlayerListName("Alex");
@@ -38,7 +38,48 @@ final class LeafIdentityTest {
}
@Test
void leavesThirdPartyChangesAndTeamsUntouched() {
void removesManagedPrefixWhilePreservingLaterThirdPartyFormatting() {
Fixtures fixtures = fixtures();
LeafIdentity identity = new LeafIdentity(fixtures.server(), Logger.getAnonymousLogger());
identity.apply(fixtures.player(), "&a🍃 ");
when(fixtures.player().getDisplayName()).thenReturn("[Admin] §a🍃 Alex");
when(fixtures.player().getPlayerListName()).thenReturn("[Admin] §a🍃 Alex");
identity.remove(fixtures.player(), "&a🍃 ");
verify(fixtures.player()).setDisplayName("[Admin] Alex");
verify(fixtures.player()).setPlayerListName("[Admin] Alex");
verify(fixtures.team()).removeEntry("Alex");
}
@Test
void normalizesRepeatedStalePrefixesWhenApplying() {
Fixtures fixtures = fixtures();
when(fixtures.player().getDisplayName()).thenReturn("§a🍃 §a🍃 Alex");
when(fixtures.player().getPlayerListName()).thenReturn("§a🍃 §a🍃 Alex");
LeafIdentity identity = new LeafIdentity(fixtures.server(), Logger.getAnonymousLogger());
identity.apply(fixtures.player(), "&a🍃 ");
verify(fixtures.player()).setDisplayName("§a🍃 Alex");
verify(fixtures.player()).setPlayerListName("§a🍃 Alex");
}
@Test
void removesStalePrefixWithoutRuntimeTracking() {
Fixtures fixtures = fixtures();
when(fixtures.player().getDisplayName()).thenReturn("§a🍃 Alex");
when(fixtures.player().getPlayerListName()).thenReturn("§a🍃 Alex");
LeafIdentity identity = new LeafIdentity(fixtures.server(), Logger.getAnonymousLogger());
identity.remove(fixtures.player(), "&a🍃 ");
verify(fixtures.player()).setDisplayName("Alex");
verify(fixtures.player()).setPlayerListName("Alex");
}
@Test
void leavesUnrelatedThirdPartyChangesAndTeamsUntouched() {
Fixtures fixtures = fixtures();
Team otherTeam = mock(Team.class);
when(fixtures.scoreboard().getEntryTeam("Alex")).thenReturn(otherTeam);
@@ -47,7 +88,7 @@ final class LeafIdentityTest {
when(fixtures.player().getDisplayName()).thenReturn("ThirdPartyAlex");
when(fixtures.player().getPlayerListName()).thenReturn("ThirdPartyAlex");
identity.remove(fixtures.player());
identity.remove(fixtures.player(), "&a🍃 ");
verify(otherTeam, never()).removeEntry("Alex");
verify(fixtures.player(), never()).setDisplayName("Alex");
@@ -125,7 +125,7 @@ final class LeafRuntimeTest {
assertEquals(4, settings.current().resistanceLevel());
verify(protection, org.mockito.Mockito.atLeastOnce()).remove(player);
verify(protection).apply(player, 4);
verify(identity, org.mockito.Mockito.atLeastOnce()).remove(player);
verify(identity, org.mockito.Mockito.atLeastOnce()).remove(player, "&a🍃 ");
}
@Test