Improved info and remove commands to work with offline players. [Mind:

removing from history seems exact, removing data will most often remove
the whole check category data , like blockbreak.]
This commit is contained in:
asofold 2012-09-13 15:22:59 +02:00
parent 347b85c7b7
commit a34b772f8d
4 changed files with 117 additions and 36 deletions

View File

@ -54,6 +54,7 @@ public abstract class Check {
*/
public Check(final CheckType type) {
this.type = type;
ViolationHistory.checkTypeMap.put(getClass().getName(), type);
}
/**

View File

@ -1,13 +1,17 @@
package fr.neatmonster.nocheatplus.checks;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.hooks.APIUtils;
/*
* M""MMMMM""M oo dP dP oo
* M MMMMM M 88 88
@ -32,9 +36,21 @@ import org.bukkit.entity.Player;
public class ViolationHistory {
/**
* The class storing the violation level for a check and a player.
* The class storing the violation level for a check and a player.<br>
* (Comparable by time.)
*/
public class ViolationLevel {
public static class ViolationLevel{
/**
* Descending sort.
*/
public static Comparator<ViolationLevel> VLComparator = new Comparator<ViolationHistory.ViolationLevel>() {
@Override
public int compare(final ViolationLevel vl1, final ViolationLevel vl2) {
if (vl1.time == vl2.time) return 0;
else if (vl1.time < vl2.time) return 1;
else return -1;
}
};
/** The check. */
public final String check;
@ -43,7 +59,7 @@ public class ViolationHistory {
public double VL;
/** The last VL time. */
private long time;
public long time;
/**
* Instantiates a new violation level.
@ -69,8 +85,25 @@ public class ViolationHistory {
this.VL += VL;
time = System.currentTimeMillis();
}
}
@Override
public boolean equals(final Object obj) {
// Might add String.
if (obj instanceof ViolationLevel)
return this.check.equals(((ViolationLevel) obj).check);
else return false;
}
@Override
public int hashCode() {
return check.hashCode();
}
}
/** Map the check string names to check types (workaround, keep at default, set by Check)*/
static Map<String, CheckType> checkTypeMap = new HashMap<String, CheckType>();
// TODO: Maybe add to metrics: average length of violation histories (does it pay to use SkipListSet or so).
/** The histories of all the players. */
private static Map<String, ViolationHistory> violationHistories = new HashMap<String, ViolationHistory>();
@ -126,11 +159,11 @@ public class ViolationHistory {
*
* @return the violation levels
*/
public TreeMap<Long, ViolationLevel> getViolationLevels() {
final TreeMap<Long, ViolationLevel> violationLevels = new TreeMap<Long, ViolationLevel>();
for (final ViolationLevel violationLevel : this.violationLevels)
violationLevels.put(violationLevel.time, violationLevel);
return violationLevels;
public ViolationLevel[] getViolationLevels() {
final ViolationLevel[] sortedLevels = new ViolationLevel[violationLevels.size()];
violationLevels.toArray(sortedLevels);
Arrays.sort(sortedLevels, ViolationLevel.VLComparator); // Descending sort.;
return sortedLevels;
}
/**
@ -149,4 +182,29 @@ public class ViolationHistory {
}
violationLevels.add(new ViolationLevel(check, VL));
}
/**
* Remove entries for certain check types. Will also remove sub check entries, or all for heckType.ALL
* @param checkType
* @return If entries were removed.
*/
public boolean remove(final CheckType checkType) {
if (checkType == CheckType.ALL){
final boolean empty = violationLevels.isEmpty();
violationLevels.clear();
return !empty;
}
final Iterator<ViolationLevel> it = violationLevels.iterator();
boolean found = false;
while (it.hasNext()){
final ViolationLevel vl = it.next();
final CheckType refType = checkTypeMap.get(vl.check);
if (refType == null) continue;
if (refType == checkType || APIUtils.isParent(checkType, refType)){
found = true;
it.remove();
}
}
return found;
}
}

View File

@ -3,7 +3,6 @@ package fr.neatmonster.nocheatplus.command;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TreeMap;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@ -38,28 +37,33 @@ public class InfoCommand extends NCPCommand {
* the player name
* @return true, if successful
*/
private void handleInfoCommand(final CommandSender sender, final String playerName) {
final Player player = Bukkit.getPlayer(playerName);
if (player != null) {
final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
final TreeMap<Long, ViolationLevel> violations = ViolationHistory.getHistory(player).getViolationLevels();
if (violations.size() > 0) {
sender.sendMessage(TAG + "Displaying " + playerName + "'s violations...");
for (final long time : violations.descendingKeySet()) {
final ViolationLevel violationLevel = violations.get(time);
final String[] parts = violationLevel.check.split("\\.");
final String check = parts[parts.length - 1];
final String parent = parts[parts.length - 2];
final double VL = Math.round(violationLevel.VL);
sender.sendMessage(TAG + "[" + dateFormat.format(new Date(time)) + "] (" + parent + ".)" + check
+ " VL " + VL);
}
} else
sender.sendMessage(TAG + "Displaying " + playerName + "'s violations... nothing to display.");
} else {
sender.sendMessage(TAG + "404 Not Found");
sender.sendMessage(TAG + "The requested player was not found on this server.");
}
private void handleInfoCommand(final CommandSender sender, String playerName) {
final Player player = Bukkit.getPlayerExact(playerName);
if (player != null) playerName = player.getName();
final ViolationHistory history = ViolationHistory.getHistory(playerName, false);
final boolean known = player != null || history != null;
if (history == null){
sender.sendMessage(TAG + "No entries for " + playerName + "'s violations... " + (known?"":"(exact spelling?)") +".");
return;
}
final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
final ViolationLevel[] violations = history.getViolationLevels();
if (violations.length > 0) {
sender.sendMessage(TAG + "Displaying " + playerName + "'s violations...");
for (final ViolationLevel violationLevel : violations) {
final long time = violationLevel.time;
final String[] parts = violationLevel.check.split("\\.");
final String check = parts[parts.length - 1];
final String parent = parts[parts.length - 2];
final double VL = Math.round(violationLevel.VL);
sender.sendMessage(TAG + "[" + dateFormat.format(new Date(time)) + "] (" + parent + ".)" + check
+ " VL " + VL);
}
} else
sender.sendMessage(TAG + "Displaying " + playerName + "'s violations... nothing to display.");
}
}

View File

@ -2,11 +2,14 @@ package fr.neatmonster.nocheatplus.command;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationHistory;
import fr.neatmonster.nocheatplus.players.Permissions;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
@ -34,10 +37,25 @@ public class RemovePlayerCommand extends NCPCommand {
}
}
else checkType = CheckType.ALL;
if (CheckType.removeData(playerName, checkType))
sender.sendMessage(TAG + "Removed data (" + checkType + "): " + playerName);
final Player player = Bukkit.getPlayerExact(playerName);
if (player != null) playerName = player.getName();
ViolationHistory hist = ViolationHistory.getHistory(playerName, false);
boolean histRemoved = false;
if (hist != null) histRemoved = hist.remove(checkType);
final boolean dataRemoved = CheckType.removeData(playerName, checkType);
if (dataRemoved || histRemoved){
String which;
if (dataRemoved && histRemoved) which = "data and history";
else if (dataRemoved) which = "data";
else which = "history";
sender.sendMessage(TAG + "Removed " + which + " (" + checkType + "): " + playerName);
}
else
sender.sendMessage(TAG + "No data present (" + checkType + ", exact spelling): " + playerName);
sender.sendMessage(TAG + "Nothing found (" + checkType + ", exact spelling): " + playerName);
return true;
}