[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.
This commit is contained in:
asofold 2015-01-19 17:19:30 +01:00
parent e6e8bf7222
commit 33cd10826d
5 changed files with 153 additions and 259 deletions

View File

@ -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<String> entries = new LinkedList<String>();
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<String> entries = new LinkedList<String>();
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<String> 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<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
// Fill in players.
return null;
}
}

View File

@ -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<String> 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<String> 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");
}
}

View File

@ -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<CheckType, Set<Integer>> exempted = new HashMap<CheckType, Set<Integer>>();
/** A map associating the registered player with their entity id. */
private static final Map<String, Integer> registeredPlayers = new HashMap<String, Integer>();
/** A map associating a check type with the unique ids of its exempted players. */
private static final Map<CheckType, Set<UUID>> exempted = new HashMap<CheckType, Set<UUID>>();
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<Integer>()));
else
exempted.put(checkType, new HashSet<Integer>());
if (APIUtils.needsSynchronization(checkType)) {
exempted.put(checkType, Collections.synchronizedSet(new HashSet<UUID>()));
}
else {
exempted.put(checkType, new HashSet<UUID>());
}
}
/**
@ -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.
* <hr>
@ -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<Integer> 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<String> details = new LinkedList<String>();
if (wrong != 0){
details.add("wrong entity-ids (" + wrong + ")");
}
StaticLog.logWarning("[NoCheatPlus] ExemptionManager inconsistencies: " + StringUtil.join(details, " | "));
}
unexempt(player.getUniqueId(), checkType);
}
}

View File

@ -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

View File

@ -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;
}