From 2a335862b2ac59053951d822b319328360be0e44 Mon Sep 17 00:00:00 2001 From: Alex 'mcmonkey' Goodwin Date: Sat, 9 Oct 2021 06:22:10 -0700 Subject: [PATCH] scoreboard command cleanup --- .../denizen/objects/PlayerTag.java | 15 ++++ .../commands/server/ScoreboardCommand.java | 55 +++++++------- .../core/BukkitWorldScriptHelper.java | 5 +- .../denizen/utilities/ScoreboardHelper.java | 72 +++++++------------ 4 files changed, 76 insertions(+), 71 deletions(-) diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java index 0f2f5d46c8..d397ce79fd 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java @@ -7,6 +7,7 @@ import com.denizenscript.denizen.scripts.commands.player.SidebarCommand; import com.denizenscript.denizen.utilities.AdvancedTextImpl; import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.ScoreboardHelper; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.blocks.FakeBlock; import com.denizenscript.denizen.utilities.debugging.Debug; @@ -2345,6 +2346,20 @@ else if (foodLevel / maxHunger < 1) { long relativeMillis = System.nanoTime() / 1000000L - playerMilliTime; return new TimeTag(System.currentTimeMillis() - relativeMillis); }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @description + // Returns the ID of the scoreboard from <@link command scoreboard> that a player is currently viewing, if any. + // --> + registerOnlineOnlyTag("scoreboard_id", (attribute, object) -> { + String id = ScoreboardHelper.viewerMap.get(object.getUUID()); + if (id == null) { + return null; + } + return new ElementTag(id); + }); } public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>(); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/ScoreboardCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/ScoreboardCommand.java index 99b91e7e97..91b0bc0ecc 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/ScoreboardCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/ScoreboardCommand.java @@ -1,5 +1,6 @@ package com.denizenscript.denizen.scripts.commands.server; +import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.entity.FakeOfflinePlayer; import com.denizenscript.denizen.utilities.ScoreboardHelper; @@ -7,13 +8,17 @@ import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; import com.denizenscript.denizencore.objects.Argument; +import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.ArgumentHelper; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.scripts.ScriptEntry; import com.denizenscript.denizencore.scripts.commands.AbstractCommand; +import com.denizenscript.denizencore.utilities.CoreUtilities; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.Objective; import org.bukkit.scoreboard.RenderType; @@ -79,6 +84,7 @@ public ScoreboardCommand() { // @Tags // )].exists> // )].team[].members> + // // // @Usage // Add a score for the defined player to the default scoreboard under the objective "cookies" and let him see it @@ -168,13 +174,25 @@ else if (!scriptEntry.hasObject("viewers") scriptEntry.defaultObject("id", new ElementTag("main")); } - public static OfflinePlayer getOfflinePlayer(String name) { - if (PlayerTag.playerNameIsValid(name)) { - return Bukkit.getOfflinePlayer(name); + public static String checkLine(ObjectTag obj) { + if (obj instanceof PlayerTag) { + return ((PlayerTag) obj).getName(); } - else { - return new FakeOfflinePlayer(name); + else if (obj instanceof EntityTag && ((EntityTag) obj).isSpawned()) { + Entity ent = ((EntityTag) obj).getBukkitEntity(); + if (ent instanceof Player) { + return ent.getName(); + } + return ent.getUniqueId().toString(); } + String raw = obj.toString(); + if (raw.startsWith("p@")) { + PlayerTag player = PlayerTag.valueOf(raw, CoreUtilities.noDebugContext); + if (player != null) { + return player.getName(); + } + } + return raw; } @Override @@ -260,17 +278,8 @@ else if (!existedAlready) { score = new ElementTag(0); } - // Set all the score lines in the scoreboard, creating fake players - // for those lines that are not meant to track players - // - // Read https://forums.bukkit.org/threads/help-with-multi-line-scoreboards.181149/ - // for clarifications - for (String line : lines) { - line = line.replaceAll("[pP]@", ""); - if (line.length() > 48) { - line = line.substring(0, 48); - } - ScoreboardHelper.addScore(obj, getOfflinePlayer(line), score.asInt()); + for (ObjectTag line : lines.objectForms) { + ScoreboardHelper.addScore(obj, checkLine(line), score.asInt()); } } } @@ -292,9 +301,8 @@ else if (act.equals(Action.REMOVE)) { obj.unregister(); } else { - for (String line : lines) { - line = line.replaceAll("[pP]@", ""); - ScoreboardHelper.removeScore(obj, getOfflinePlayer(line)); + for (ObjectTag line : lines.objectForms) { + ScoreboardHelper.removeScore(obj, checkLine(line)); } } } @@ -309,9 +317,8 @@ else if (!lines.isEmpty()) { Debug.echoDebug(scriptEntry, "Removing lines " + lines.identify() + " from all objectives in scoreboard " + id.asString()); - for (String line : lines) { - line = line.replaceAll("[pP]@", ""); - ScoreboardHelper.removePlayer(id.asString(), getOfflinePlayer(line)); + for (ObjectTag line : lines.objectForms) { + ScoreboardHelper.removePlayer(id.asString(), checkLine(line)); } } // Only remove all objectives from scoreboard if viewers @@ -329,7 +336,7 @@ else if (viewers == null) { // If this isn't the main scoreboard, add this viewer // to the map of viewers saved by Denizen if (!id.asString().equalsIgnoreCase("main")) { - ScoreboardHelper.viewerMap.put(viewer.getName(), id.asString()); + ScoreboardHelper.viewerMap.put(viewer.getUUID(), id.asString()); } // Make this player view the scoreboard if he/she // is already online @@ -340,7 +347,7 @@ else if (viewers == null) { // Remove viewers for this scoreboard else if (act.equals(Action.REMOVE)) { // Take this player out of the map of viewers - ScoreboardHelper.viewerMap.remove(viewer.getName()); + ScoreboardHelper.viewerMap.remove(viewer.getUUID()); // Make the player view a blank scoreboard if he/she // is online (in lieu of a scoreboard-removing method diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java index 79c94ca8cd..18c2cd4a60 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java @@ -72,8 +72,9 @@ public void onPlayerJoins(PlayerJoinEvent event) { if (EntityTag.isNPC(event.getPlayer())) { return; } - if (ScoreboardHelper.viewerMap.containsKey(event.getPlayer().getName())) { - Scoreboard score = ScoreboardHelper.getScoreboard(ScoreboardHelper.viewerMap.get(event.getPlayer().getName())); + String board = ScoreboardHelper.viewerMap.get(event.getPlayer().getUniqueId()); + if (board != null) { + Scoreboard score = ScoreboardHelper.getScoreboard(board); if (score != null) { event.getPlayer().setScoreboard(score); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/ScoreboardHelper.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/ScoreboardHelper.java index 496cfcdd80..f7eded144a 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/ScoreboardHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/ScoreboardHelper.java @@ -25,7 +25,7 @@ public class ScoreboardHelper { // A map with scoreboard IDs as keys and scoreboards as values public static Map scoreboardMap = new HashMap<>(); // A map with viewer names as keys and scoreboard IDs as values - public static Map viewerMap = new HashMap<>(); + public static Map viewerMap = new HashMap<>(); /* * Called on server startup or /denizen reload saves @@ -40,9 +40,9 @@ public static void _recallScoreboards() { Scoreboard emptyBoard = createScoreboard(); // Clear every viewer's set scoreboard - for (Map.Entry entry : viewerMap.entrySet()) { - OfflinePlayer player = ScoreboardCommand.getOfflinePlayer(entry.getKey()); - if (player.isOnline()) { + for (Map.Entry entry : viewerMap.entrySet()) { + OfflinePlayer player = Bukkit.getPlayer(entry.getKey()); + if (player != null && player.isOnline()) { player.getPlayer().setScoreboard(emptyBoard); } } @@ -74,7 +74,7 @@ public static void _recallScoreboards() { for (String viewer : viewerList) { if (PlayerTag.matches(viewer)) { PlayerTag player = PlayerTag.valueOf(viewer, CoreUtilities.basicContext); - viewerMap.put(player.getName(), id); + viewerMap.put(player.getUUID(), id); if (player.isOnline()) { player.getPlayerEntity().setScoreboard(board); @@ -121,7 +121,7 @@ public static void _recallScoreboards() { // Iterate through scores and add them to this objective for (String scoreName : scoreSection.getKeys(false)) { int scoreInt = scoreSection.getInt(scoreName); - addScore(o, ScoreboardCommand.getOfflinePlayer(scoreName), scoreInt); + addScore(o, scoreName, scoreInt); } } } @@ -146,9 +146,9 @@ public static void _saveScoreboards() { // Find all of the viewers that are viewing this scoreboard // and put them on a list - for (Map.Entry viewerEntry : viewerMap.entrySet()) { + for (Map.Entry viewerEntry : viewerMap.entrySet()) { if (id.equalsIgnoreCase(viewerEntry.getValue())) { - viewerList.add(viewerEntry.getKey()); + viewerList.add(viewerEntry.getKey().toString()); } } @@ -210,21 +210,20 @@ public static void _saveScoreboards() { ///////////////// /** - * Add a score to an Objective for an OfflinePlayer. + * Add a score to an Objective for a name. * * @param o the Objective to add the score to - * @param player the OfflinePlayer to set the score for * @param score the score */ - public static void addScore(Objective o, OfflinePlayer player, int score) { + public static void addScore(Objective o, String playerName, int score) { Score sc; - if (player.getName().length() <= 16) { - sc = o.getScore(player.getName()); + if (playerName.length() <= 16) { + sc = o.getScore(playerName); } else { - Map.Entry teamData = createTeam(o.getScoreboard(), player.getName()); + Map.Entry teamData = createTeam(o.getScoreboard(), playerName); sc = o.getScore(teamData.getValue()); - teamData.getKey().addPlayer(ScoreboardCommand.getOfflinePlayer(teamData.getValue())); + teamData.getKey().addEntry(teamData.getValue()); } // If the score is 0, it won't normally be displayed at first, @@ -239,12 +238,11 @@ public static void addScore(Objective o, OfflinePlayer player, int score) { } /** - * Remove a score from an Objective for an OfflinePlayer. + * Remove a score from an Objective for a name. * * @param o the Objective to remove the score from - * @param player the OfflinePlayer to remove the score for */ - public static void removeScore(Objective o, OfflinePlayer player) { + public static void removeScore(Objective o, String playerName) { // There is no method to remove a single score from an // objective, as confirmed here: @@ -257,7 +255,7 @@ public static void removeScore(Objective o, OfflinePlayer player) { // Go through every score for this (real or fake) player // and put it in scoreMap if it doesn't belong to the // objective we want to remove the score from - String name = createTeam(board, player.getName()).getValue(); + String name = createTeam(board, playerName).getValue(); // TODO: Properly remove when teams are involved for (Score sc : board.getScores(name)) { if (!sc.getObjective().equals(o)) { @@ -266,13 +264,12 @@ public static void removeScore(Objective o, OfflinePlayer player) { } // Remove all the scores for this (real or fake) player - board.resetScores(player.getName()); + board.resetScores(playerName); // Go through scoreMap and add back all the scores we saved // for this (real or fake) player for (Map.Entry entry : scoreMap.entrySet()) { - board.getObjective(entry.getKey()) - .getScore(player.getName()).setScore(entry.getValue()); + board.getObjective(entry.getKey()).getScore(playerName).setScore(entry.getValue()); } } @@ -301,8 +298,7 @@ private static Map.Entry createTeam(Scoreboard scoreboard, String ///////////////// /** - * Clears all the objectives from a Scoreboard, making - * it empty. + * Clears all the objectives from a Scoreboard, making it empty. * * @param board the Scoreboard to clear */ @@ -313,8 +309,7 @@ public static void clearScoreboard(Scoreboard board) { } /** - * Creates an anonymous new Scoreboard that isn't - * saved anywhere. + * Creates an anonymous new Scoreboard that isn't saved anywhere. * * @return the new Scoreboard */ @@ -323,8 +318,7 @@ public static Scoreboard createScoreboard() { } /** - * Creates a new Scoreboard with a certain id and - * stories it in the scoreboards map. + * Creates a new Scoreboard with a certain id and stories it in the scoreboards map. * * @param id the id of the new Scoreboard * @return the new Scoreboard @@ -336,9 +330,7 @@ public static Scoreboard createScoreboard(String id) { } /** - * Deletes a Scoreboard, clearing it and removing it from - * the scoreboards map, unless it is the server's main - * scoreboard, in which case it is just cleared. + * Deletes a Scoreboard, clearing it and removing it from the scoreboards map, unless it is the server's main scoreboard, in which case it is just cleared. * * @param id the id of the Scoreboard */ @@ -353,9 +345,7 @@ public static void deleteScoreboard(String id) { } /** - * Returns the server's main scoreboard, that isn't stored - * in the scoreboards map because Bukkit already saves it - * by itself. + * Returns the server's main scoreboard, that isn't stored in the scoreboards map because Bukkit already saves it by itself. * * @return the main Scoreboard */ @@ -374,8 +364,7 @@ public static Scoreboard getScoreboard(String id) { } /** - * Returns true if the scoreboards map contains a certain - * scoreboard id. + * Returns true if the scoreboards map contains a certain scoreboard id. * * @param id the id of the Scoreboard * @return true or false @@ -384,14 +373,7 @@ public static boolean hasScoreboard(String id) { return scoreboardMap.containsKey(id.toUpperCase()); } - /** - * Removes all the scores of an OfflinePlayer from a - * Scoreboard. - * - * @param id the id of the Scoreboard - * @param player the OfflinePlayer - */ - public static void removePlayer(String id, OfflinePlayer player) { - scoreboardMap.get(id.toUpperCase()).resetScores(player.getName()); + public static void removePlayer(String id, String name) { + scoreboardMap.get(id.toUpperCase()).resetScores(name); } }