From 33cd10826d0af073e99e9e2301a927633e2a65b1 Mon Sep 17 00:00:00 2001 From: asofold Date: Mon, 19 Jan 2015 17:19:30 +0100 Subject: [PATCH] [BREAKING] Switch ExemptionManager to UUID use. Removes access by name and entity-id for now. Access by name might be re-added, though any kind of mappings will likely be maintained somewhere near DataManager. --- .../admin/exemption/ExemptionsCommand.java | 71 ++++--- .../admin/exemption/UnexemptCommand.java | 113 +++++----- .../hooks/NCPExemptionManager.java | 199 +++--------------- .../nocheatplus/players/DataManager.java | 21 +- .../neatmonster/nocheatplus/NoCheatPlus.java | 8 - 5 files changed, 153 insertions(+), 259 deletions(-) diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/ExemptionsCommand.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/ExemptionsCommand.java index e9089e7f..c66f891f 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/ExemptionsCommand.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/ExemptionsCommand.java @@ -2,6 +2,7 @@ package fr.neatmonster.nocheatplus.command.admin.exemption; import java.util.LinkedList; import java.util.List; +import java.util.UUID; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -17,33 +18,51 @@ import fr.neatmonster.nocheatplus.utilities.StringUtil; public class ExemptionsCommand extends BaseCommand { - public ExemptionsCommand(JavaPlugin plugin) { - super(plugin, "exemptions", Permissions.COMMAND_EXEMPTIONS, new String[]{"exe"}); - } + public ExemptionsCommand(JavaPlugin plugin) { + super(plugin, "exemptions", Permissions.COMMAND_EXEMPTIONS, new String[]{"exe"}); + } - @Override - public boolean onCommand(CommandSender sender, Command command, - String label, String[] args) { - if (args.length != 2) return false; - String playerName = args[1].trim(); - Player player = DataManager.getPlayer(playerName); - if (player != null) playerName = player.getName(); - final List entries = new LinkedList(); - for (CheckType type : CheckType.values()){ - if (NCPExemptionManager.isExempted(playerName, type)) entries.add(type.toString()); - } - if (entries.isEmpty()) sender.sendMessage(TAG + "No exemption entries available for " + playerName +" ."); - else sender.sendMessage(TAG + "Exemptions for " + playerName + ": " + StringUtil.join(entries, ", ")); - return true; - } + @Override + public boolean onCommand(CommandSender sender, Command command, + String label, String[] args) { + if (args.length != 2) return false; + String playerName = args[1].trim(); + Player player = DataManager.getPlayer(playerName); + UUID id; + if (player != null) { + playerName = player.getName(); + id = player.getUniqueId(); + } else { + id = DataManager.getUUID(playerName); + } + final List entries = new LinkedList(); + if (id == null) { + sender.sendMessage(TAG + "Not online nor a UUID: " + playerName); + return true; + } else { + for (CheckType type : CheckType.values()){ + if (NCPExemptionManager.isExempted(id, type)) { + entries.add(type.toString()); + } + } + } + if (entries.isEmpty()) { + sender.sendMessage(TAG + "No exemption entries available for " + playerName +" ."); + } + else { + // TODO: Compress entries ? + sender.sendMessage(TAG + "Exemptions for " + playerName + ": " + StringUtil.join(entries, ", ")); + } + return true; + } - /* (non-Javadoc) - * @see fr.neatmonster.nocheatplus.command.AbstractCommand#onTabComplete(org.bukkit.command.CommandSender, org.bukkit.command.Command, java.lang.String, java.lang.String[]) - */ - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - // Fill in players. - return null; - } + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.command.AbstractCommand#onTabComplete(org.bukkit.command.CommandSender, org.bukkit.command.Command, java.lang.String, java.lang.String[]) + */ + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // Fill in players. + return null; + } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/UnexemptCommand.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/UnexemptCommand.java index 7a432293..88112768 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/UnexemptCommand.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/exemption/UnexemptCommand.java @@ -2,6 +2,7 @@ package fr.neatmonster.nocheatplus.command.admin.exemption; import java.util.Arrays; import java.util.List; +import java.util.UUID; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -9,8 +10,8 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import fr.neatmonster.nocheatplus.checks.CheckType; -import fr.neatmonster.nocheatplus.command.CommandUtil; import fr.neatmonster.nocheatplus.command.BaseCommand; +import fr.neatmonster.nocheatplus.command.CommandUtil; import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager; import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.players.DataManager; @@ -18,56 +19,66 @@ import fr.neatmonster.nocheatplus.utilities.StringUtil; public class UnexemptCommand extends BaseCommand { - public UnexemptCommand(JavaPlugin plugin) { - super(plugin, "unexempt", Permissions.COMMAND_UNEXEMPT); - } + public UnexemptCommand(JavaPlugin plugin) { + super(plugin, "unexempt", Permissions.COMMAND_UNEXEMPT); + } - @Override - public boolean onCommand(CommandSender sender, Command command, - String label, String[] args) { - // TODO: Reduce copy and paste by introducing some super class. - if (args.length < 2 || args.length > 3) return false; - String playerName = args[1]; - final CheckType checkType; - if (args.length == 3){ - try{ - checkType = CheckType.valueOf(args[2].toUpperCase().replace('-', '_').replace('.', '_')); - } catch (Exception e){ - sender.sendMessage(TAG + "Could not interpret: " + args[2]); - sender.sendMessage(TAG + "Check type should be one of: " + StringUtil.join(Arrays.asList(CheckType.values()), " | ")); - return true; - } - } - else checkType = CheckType.ALL; - if (playerName.equals("*")){ - // Unexempt all. - // TODO: might care to find players only ? - NCPExemptionManager.clear(); - sender.sendMessage(TAG + "Nobody will be exempted from: " + checkType); - return true; - } - // Find player. - final Player player = DataManager.getPlayer(playerName); - if (player != null) playerName = player.getName(); - NCPExemptionManager.unexempt(playerName, checkType); - sender.sendMessage(TAG + "Player " + playerName + " will not be exempted from: " + checkType); - return true; - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) - { - // At least complete CheckType - if (args.length == 3) return CommandUtil.getCheckTypeTabMatches(args[2]); - return null; - } - - /* (non-Javadoc) - * @see fr.neatmonster.nocheatplus.command.AbstractCommand#testPermission(org.bukkit.command.CommandSender, org.bukkit.command.Command, java.lang.String, java.lang.String[]) - */ - @Override - public boolean testPermission(CommandSender sender, Command command, String alias, String[] args) { - return super.testPermission(sender, command, alias, args) || args.length >= 2 && args[1].trim().equalsIgnoreCase(sender.getName()) && sender.hasPermission(permission + ".self"); - } + @Override + public boolean onCommand(CommandSender sender, Command command, + String label, String[] args) { + // TODO: Reduce copy and paste by introducing some super class. + if (args.length < 2 || args.length > 3) return false; + String playerName = args[1]; + final CheckType checkType; + if (args.length == 3){ + try{ + checkType = CheckType.valueOf(args[2].toUpperCase().replace('-', '_').replace('.', '_')); + } catch (Exception e){ + sender.sendMessage(TAG + "Could not interpret: " + args[2]); + sender.sendMessage(TAG + "Check type should be one of: " + StringUtil.join(Arrays.asList(CheckType.values()), " | ")); + return true; + } + } + else checkType = CheckType.ALL; + if (playerName.equals("*")){ + // Unexempt all. + // TODO: might care to find players only ? + NCPExemptionManager.clear(); + sender.sendMessage(TAG + "Removed exemptions for all players for checks: " + checkType); + return true; + } + // Find player. + final Player player = DataManager.getPlayer(playerName); + final UUID id; + if (player != null) { + playerName = player.getName(); + id = player.getUniqueId(); + } else { + id = DataManager.getUUID(playerName); + } + if (id == null) { + sender.sendMessage(TAG + "Not an online player nor a UUID: " + playerName); + } else { + NCPExemptionManager.unexempt(id, checkType); + sender.sendMessage(TAG + "Remove exemptions for " + playerName + " for checks: " + checkType); + } + return true; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) + { + // At least complete CheckType + if (args.length == 3) return CommandUtil.getCheckTypeTabMatches(args[2]); + return null; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.command.AbstractCommand#testPermission(org.bukkit.command.CommandSender, org.bukkit.command.Command, java.lang.String, java.lang.String[]) + */ + @Override + public boolean testPermission(CommandSender sender, Command command, String alias, String[] args) { + return super.testPermission(sender, command, alias, args) || args.length >= 2 && args[1].trim().equalsIgnoreCase(sender.getName()) && sender.hasPermission(permission + ".self"); + } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/hooks/NCPExemptionManager.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/hooks/NCPExemptionManager.java index 46236fd1..3f4ec030 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/hooks/NCPExemptionManager.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/hooks/NCPExemptionManager.java @@ -3,23 +3,13 @@ package fr.neatmonster.nocheatplus.hooks; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerKickEvent; -import org.bukkit.event.player.PlayerQuitEvent; import fr.neatmonster.nocheatplus.checks.CheckType; -import fr.neatmonster.nocheatplus.components.NCPListener; -import fr.neatmonster.nocheatplus.logging.StaticLog; -import fr.neatmonster.nocheatplus.utilities.StringUtil; /** * API for exempting players of checks, checked before calculations are done. @@ -28,11 +18,8 @@ import fr.neatmonster.nocheatplus.utilities.StringUtil; */ public class NCPExemptionManager { - /** A map associating a check type with the entity ids of its exempted players. */ - private static final Map> exempted = new HashMap>(); - - /** A map associating the registered player with their entity id. */ - private static final Map registeredPlayers = new HashMap(); + /** A map associating a check type with the unique ids of its exempted players. */ + private static final Map> exempted = new HashMap>(); static { clear(); @@ -42,13 +29,14 @@ public class NCPExemptionManager { * Remove all exemptions. */ public static final void clear() { - registeredPlayers.clear(); // Use put with a new map to keep entries to stay thread safe. for (final CheckType checkType : CheckType.values()) - if (APIUtils.needsSynchronization(checkType)) - exempted.put(checkType, Collections.synchronizedSet(new HashSet())); - else - exempted.put(checkType, new HashSet()); + if (APIUtils.needsSynchronization(checkType)) { + exempted.put(checkType, Collections.synchronizedSet(new HashSet())); + } + else { + exempted.put(checkType, new HashSet()); + } } /** @@ -57,8 +45,8 @@ public class NCPExemptionManager { * @param entityId * the entity id */ - public static final void exemptPermanently(final int entityId) { - exemptPermanently(entityId, CheckType.ALL); + public static final void exemptPermanently(final UUID id) { + exemptPermanently(id, CheckType.ALL); } /** @@ -69,11 +57,11 @@ public class NCPExemptionManager { * @param checkType * the check type */ - public static final void exemptPermanently(final int entityId, final CheckType checkType) { - final Integer id = entityId; + public static final void exemptPermanently(final UUID id, final CheckType checkType) { exempted.get(checkType).add(id); - for (final CheckType child : APIUtils.getChildren(checkType)) + for (final CheckType child : APIUtils.getChildren(checkType)) { exempted.get(child).add(id); + } } /** @@ -95,35 +83,9 @@ public class NCPExemptionManager { * the check type */ public static final void exemptPermanently(final Player player, final CheckType checkType) { - exemptPermanently(player.getEntityId(), checkType); + exemptPermanently(player.getUniqueId(), checkType); } - /** - * This should be registered before all other listeners of NoCheatPlus. - * - * NOTE: For internal use only, DO NOT CALL FROM OUTSIDE. - * - * @return the listener - */ - public static Listener getListener() { - return new NCPListener() { - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerJoin(final PlayerJoinEvent event) { - NCPExemptionManager.registerPlayer(event.getPlayer()); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerQuit(final PlayerQuitEvent event) { - NCPExemptionManager.tryToRemove(event.getPlayer()); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerKick(final PlayerKickEvent event) { - NCPExemptionManager.tryToRemove(event.getPlayer()); - } - }; - } - /** * Check if an entity is exempted from a check right now by entity id. *
@@ -137,8 +99,8 @@ public class NCPExemptionManager { * group like MOVING or ALL * @return if the entity is exempted from checks right now */ - public static final boolean isExempted(final int entityId, final CheckType checkType) { - return exempted.get(checkType).contains(entityId); + public static final boolean isExempted(final UUID id, final CheckType checkType) { + return exempted.get(checkType).contains(id); } /** @@ -152,74 +114,17 @@ public class NCPExemptionManager { * @return if the player is exempted from the check right now */ public static final boolean isExempted(final Player player, final CheckType checkType) { - return isExempted(player.getEntityId(), checkType); - } - - /** - * Check if a player is exempted from a check right now by player name. - * @param playerName - * The exact player name. - * @param checkType - * the type of check to exempt the player from. This can be individual check types, as well as a check - * group like MOVING or ALL - * @return if the player is exempted from the check right now - */ - public static final boolean isExempted(final String playerName, final CheckType checkType) { - final Integer entityId = registeredPlayers.get(playerName); - if (entityId == null) return false; - return isExempted(entityId, checkType); - } - - /** - * Register current entity id for the player. - * - * @param player - * the player - */ - public static final void registerPlayer(final Player player) { - final int entityId = player.getEntityId(); - final String name = player.getName(); - - final Integer registeredId = registeredPlayers.get(name); - if (registeredId == null) - // Player wasn't registered. - registeredPlayers.put(name, entityId); - else if (entityId != registeredId.intValue()) { - // Player was registered under another id (needs exchange). - for (final Set set : exempted.values()) - if (set.remove(registeredId)) - // Replace. - set.add(entityId); - registeredPlayers.put(name, entityId); - } - } - - /** - * Check if the registeredPlayers mapping can be removed for a player, i.e. no exemptions are present. - * - * @param player - * the player - */ - protected static final void tryToRemove(final Player player) { - if (!registeredPlayers.containsKey(player.getName())) - return; - final Integer entityId = player.getEntityId(); - for (final CheckType checkType : CheckType.values()) - // Check if player is exempted from something. - if (isExempted(entityId, checkType)) - // If they are, we can't remove them so we return. - return; - registeredPlayers.remove(player.getName()); + return isExempted(player.getUniqueId(), checkType); } /** * Undo exempting an entity from all checks. * - * @param entityId - * the entity id + * @param id + * Unique id of a player to exempt. */ - public static final void unexempt(final int entityId) { - unexempt(entityId, CheckType.ALL); + public static final void unexempt(final UUID id) { + unexempt(id, CheckType.ALL); } /** @@ -230,11 +135,11 @@ public class NCPExemptionManager { * @param checkType * the check type */ - public static final void unexempt(final int entityId, final CheckType checkType) { - final Integer id = entityId; + public static final void unexempt(final UUID id, final CheckType checkType) { exempted.get(checkType).remove(id); - for (final CheckType child : APIUtils.getChildren(checkType)) + for (final CheckType child : APIUtils.getChildren(checkType)) { exempted.get(child).remove(id); + } } /** @@ -246,16 +151,6 @@ public class NCPExemptionManager { public static final void unexempt(final Player player) { unexempt(player, CheckType.ALL); } - - /** - * Undo exempting a player from all checks. - * - * @param playerName - * the players exact name - */ - public static final void unexempt(final String playerName) { - unexempt(playerName, CheckType.ALL); - } /** * Undo exempting a player form a certain check, or check group, as given. @@ -266,49 +161,7 @@ public class NCPExemptionManager { * the check type */ public static final void unexempt(final Player player, final CheckType checkType) { - unexempt(player.getEntityId(), checkType); - } - - /** - * Undo exempting a player form a certain check, or check group, as given. - * - * @param playerName - * the exact player name. - * @param checkType - * the check type - */ - public static final void unexempt(final String playerName, final CheckType checkType) { - final Integer entityId = registeredPlayers.get(playerName); - if (entityId != null) unexempt(entityId, checkType); - } - - /** - * Check Entity-id mappings, for internal use. - * @param onlinePlayers - */ - public static void checkConsistency(final Player[] onlinePlayers){ - int wrong = 0; - for (int i = 0; i < onlinePlayers.length; i++){ - final Player player = onlinePlayers[i]; - final int id = player.getEntityId(); - final String name = player.getName(); - final Integer presentId = registeredPlayers.get(name); - if (presentId == null){ - // TODO: Could complain. - } - else if (id != presentId.intValue()){ - wrong ++; - registerPlayer(player); - } - // TODO: Consider also checking if numbers don't match. - } - if (wrong != 0){ - final List details = new LinkedList(); - if (wrong != 0){ - details.add("wrong entity-ids (" + wrong + ")"); - } - StaticLog.logWarning("[NoCheatPlus] ExemptionManager inconsistencies: " + StringUtil.join(details, " | ")); - } + unexempt(player.getUniqueId(), checkType); } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/players/DataManager.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/players/DataManager.java index 6c294b35..a4a014d8 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/players/DataManager.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/players/DataManager.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -51,6 +52,7 @@ import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigManager; import fr.neatmonster.nocheatplus.hooks.APIUtils; import fr.neatmonster.nocheatplus.logging.StaticLog; +import fr.neatmonster.nocheatplus.utilities.IdUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil; /** @@ -301,7 +303,7 @@ public class DataManager implements Listener, INotifyReload, INeedConfig, Compon instance.playerData.clear(); // TODO } } - + /** * Restore the default debug flags within player data, as given in * corresponding configurations. This only yields the correct result, if the @@ -428,6 +430,23 @@ public class DataManager implements Listener, INotifyReload, INeedConfig, Compon return instance.onlinePlayers.get(playerName); } + /** + * Retrieve the UUID for a given input (name or UUID string of with or + * without '-'). Might later also query a cache, if appropriate. Convenience + * method for use with commands. + * + * @param input + * @return + */ + public static UUID getUUID(final String input) { + // TODO: Maintain a name-UUID mapping? + final Player player = getPlayer(input); + if (player != null) { + return player.getUniqueId(); + } + return IdUtil.UUIDFromStringSafe(input); + } + /** * This gets the online player with the exact name, but transforms the input to lower case. * @param playerName diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java index cb658f6b..6d3aac3a 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java @@ -833,13 +833,6 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { getCoreListener(), // Put ReloadListener first, because Checks could also listen to it. new ReloadHook(), - NCPExemptionManager.getListener(), - new ConsistencyChecker() { - @Override - public void checkConsistency(final Player[] onlinePlayers) { - NCPExemptionManager.checkConsistency(onlinePlayers); - } - }, dataMan, }){ addComponent(obj); @@ -945,7 +938,6 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { } for (final Player player : onlinePlayers){ updatePermStateReceivers(player); - NCPExemptionManager.registerPlayer(player); if (player.isSleeping()) { CombinedData.getData(player).wasInBed = true; }