feat(identity): display Leaf protection prefixes
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package games.dmg.leaf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.ScoreboardManager;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
|
||||
/** Conservatively decorates standard Spigot player identity surfaces. */
|
||||
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> teamEntries = new HashMap<>();
|
||||
|
||||
public LeafIdentity(Server server, Logger logger) {
|
||||
this.server = server;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public synchronized void apply(Player player, String configuredPrefix) {
|
||||
String prefix = ChatColor.translateAlternateColorCodes('&', 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;
|
||||
|
||||
if (previous == null || player.getDisplayName().equals(previous.decoratedDisplay())) {
|
||||
player.setDisplayName(decoratedDisplay);
|
||||
}
|
||||
if (previous == null || player.getPlayerListName().equals(previous.decoratedList())) {
|
||||
player.setPlayerListName(decoratedList);
|
||||
}
|
||||
names.put(playerId, new Names(baseDisplay, baseList, decoratedDisplay, decoratedList));
|
||||
applyOverhead(player, prefix);
|
||||
}
|
||||
|
||||
public synchronized void remove(Player player) {
|
||||
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 entry = teamEntries.remove(playerId);
|
||||
Team team = leafTeam(false);
|
||||
if (entry != null && team != null) {
|
||||
team.removeEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyOverhead(Player player, String prefix) {
|
||||
Scoreboard scoreboard = mainScoreboard();
|
||||
if (scoreboard == null) {
|
||||
return;
|
||||
}
|
||||
String entry = player.getName();
|
||||
Team existing = scoreboard.getEntryTeam(entry);
|
||||
Team leafTeam = leafTeam(true);
|
||||
if (leafTeam == null) {
|
||||
return;
|
||||
}
|
||||
if (existing != null && existing != leafTeam) {
|
||||
logger.fine("Leaf overhead prefix skipped for " + entry + ": player uses another team");
|
||||
return;
|
||||
}
|
||||
String oldEntry = teamEntries.put(player.getUniqueId(), entry);
|
||||
if (oldEntry != null && !oldEntry.equals(entry)) {
|
||||
leafTeam.removeEntry(oldEntry);
|
||||
}
|
||||
leafTeam.setPrefix(prefix);
|
||||
leafTeam.addEntry(entry);
|
||||
}
|
||||
|
||||
private Team leafTeam(boolean create) {
|
||||
Scoreboard scoreboard = mainScoreboard();
|
||||
if (scoreboard == null) {
|
||||
return null;
|
||||
}
|
||||
Team team = scoreboard.getTeam(TEAM_NAME);
|
||||
if (team == null && create) {
|
||||
try {
|
||||
team = scoreboard.registerNewTeam(TEAM_NAME);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
logger.warning("Could not create Leaf scoreboard team: " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
return team;
|
||||
}
|
||||
|
||||
private Scoreboard mainScoreboard() {
|
||||
ScoreboardManager manager = server.getScoreboardManager();
|
||||
return manager == null ? null : manager.getMainScoreboard();
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public final class LeafListener implements Listener {
|
||||
runtime.observe(event.getPlayer(), clock.instant());
|
||||
} catch (IOException exception) {
|
||||
logger.log(Level.SEVERE, "Could not persist Leaf player state on join", exception);
|
||||
runtime.removeProtection(event.getPlayer());
|
||||
runtime.removePresentation(event.getPlayer());
|
||||
event.getPlayer().sendMessage("Leaf protection is unavailable because state could not be saved.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ public final class LeafPlugin extends JavaPlugin {
|
||||
getServer(),
|
||||
settingsProvider,
|
||||
stateManager,
|
||||
new LeafProtection()
|
||||
new LeafProtection(),
|
||||
new LeafIdentity(getServer(), getLogger())
|
||||
);
|
||||
registerRuntime();
|
||||
} catch (IllegalArgumentException | IOException exception) {
|
||||
@@ -43,7 +44,7 @@ public final class LeafPlugin extends JavaPlugin {
|
||||
public void onDisable() {
|
||||
if (runtime != null) {
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
runtime.removeProtection(player);
|
||||
runtime.removePresentation(player);
|
||||
}
|
||||
}
|
||||
saveState();
|
||||
|
||||
@@ -27,17 +27,20 @@ public final class LeafRuntime {
|
||||
private final LeafSettingsProvider settingsProvider;
|
||||
private final LeafStateManager stateManager;
|
||||
private final LeafProtection protection;
|
||||
private final LeafIdentity identity;
|
||||
|
||||
public LeafRuntime(
|
||||
Server server,
|
||||
LeafSettingsProvider settingsProvider,
|
||||
LeafStateManager stateManager,
|
||||
LeafProtection protection
|
||||
LeafProtection protection,
|
||||
LeafIdentity identity
|
||||
) {
|
||||
this.server = Objects.requireNonNull(server, "server");
|
||||
this.settingsProvider = Objects.requireNonNull(settingsProvider, "settingsProvider");
|
||||
this.stateManager = Objects.requireNonNull(stateManager, "stateManager");
|
||||
this.protection = Objects.requireNonNull(protection, "protection");
|
||||
this.identity = Objects.requireNonNull(identity, "identity");
|
||||
}
|
||||
|
||||
public PlayerLeafState observe(Player player, Instant observedAt) throws IOException {
|
||||
@@ -105,13 +108,15 @@ public final class LeafRuntime {
|
||||
LeafSettings settings = settingsProvider.current();
|
||||
if (state != null && state.optedIn() && settings.enabled()) {
|
||||
protection.apply(player, settings.resistanceLevel());
|
||||
identity.apply(player, settings.prefix());
|
||||
} else {
|
||||
protection.remove(player);
|
||||
removePresentation(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeProtection(Player player) {
|
||||
public void removePresentation(Player player) {
|
||||
protection.remove(player);
|
||||
identity.remove(player);
|
||||
}
|
||||
|
||||
public LeafStateManager stateManager() {
|
||||
|
||||
Reference in New Issue
Block a user