From cd856208d26dfb215335da40a29644612c438e93 Mon Sep 17 00:00:00 2001 From: asofold Date: Mon, 10 Sep 2012 10:10:45 +0200 Subject: [PATCH] Add ncp tempkick command + API do deny logins [missing: persist]. --- .../neatmonster/nocheatplus/NoCheatPlus.java | 82 ++++++++++++++++++- .../nocheatplus/command/CommandHandler.java | 19 ++++- .../nocheatplus/command/DelayableCommand.java | 16 +++- .../nocheatplus/command/NCPCommand.java | 8 +- .../nocheatplus/command/TempKickCommand.java | 54 ++++++++++++ .../nocheatplus/players/Permissions.java | 4 + 6 files changed, 179 insertions(+), 4 deletions(-) create mode 100644 src/fr/neatmonster/nocheatplus/command/TempKickCommand.java diff --git a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java index 6ecec0e5..3310bc43 100644 --- a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java +++ b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java @@ -6,8 +6,12 @@ import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -16,6 +20,8 @@ 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.PlayerLoginEvent; +import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; @@ -55,8 +61,66 @@ import fr.neatmonster.nocheatplus.utilities.TickTask; * This is the main class of NoCheatPlus. The commands, events listeners and tasks are registered here. */ public class NoCheatPlus extends JavaPlugin implements Listener { + + /** Lower case player name to milliseconds point of time of release */ + private static final Map denyLoginNames = Collections.synchronizedMap(new HashMap()); + + /** + * Remove expired entries. + */ + private static void checkDenyLoginsNames() { + final long ts = System.currentTimeMillis(); + final List rem = new LinkedList(); + synchronized (denyLoginNames) { + for (final Entry entry : denyLoginNames.entrySet()){ + if (entry.getValue().longValue() < ts) rem.add(entry.getKey()); + } + for (final String name : rem){ + denyLoginNames.remove(name); + } + } + } + + /** + * Deny the player to login. This will also remove expired entries. + * @param playerName + * @param duration Duration from now on, in milliseconds. + */ + public static void denyLogin(String playerName, long duration){ + final long ts = System.currentTimeMillis() + duration; + playerName = playerName.trim().toLowerCase(); + synchronized (denyLoginNames) { + final Long oldTs = denyLoginNames.get(playerName); + if (oldTs != null && ts < oldTs.longValue()) return; + denyLoginNames.put(playerName, ts); + // TODO: later maybe save these ? + } + checkDenyLoginsNames(); + } + + /** + * Check if player is denied to login right now. + * @param playerName + * @return + */ + public static boolean isLoginDenied(String playerName){ + return isLoginDenied(playerName, System.currentTimeMillis()); + } - /** The event listeners. */ + /** + * Check if a player is denied to login at a certain point of time. + * @param playerName + * @param currentTimeMillis + * @return + */ + public static boolean isLoginDenied(String playerName, long currentTimeMillis) { + playerName = playerName.trim().toLowerCase(); + final Long oldTs = denyLoginNames.get(playerName); + if (oldTs == null) return false; + else return System.currentTimeMillis() < oldTs.longValue(); + } + + /** The event listeners. */ private final List listeners = new ArrayList(); /** Components that need notification on reloading. @@ -353,4 +417,20 @@ public class NoCheatPlus extends JavaPlugin implements Listener { player.sendMessage(message); } + @EventHandler(priority=EventPriority.HIGHEST) + public void onPlayerLogin(final PlayerLoginEvent event){ + // (HGHEST to give other plugins the possibility to add permissions or allow the player). + if (event.getResult() != Result.ALLOWED) return; + final Player player = event.getPlayer(); + // Check if login is denied: + checkDenyLoginsNames(); + if (player.hasPermission(Permissions.BYPASS_DENY_LOGIN)) return; + if (isLoginDenied(player.getName())){ + // TODO: display time for which the player is banned. + event.setResult(Result.KICK_OTHER); + // TODO: Make message configurable. + event.setKickMessage("You are temporarily denied to join server."); + } + } + } diff --git a/src/fr/neatmonster/nocheatplus/command/CommandHandler.java b/src/fr/neatmonster/nocheatplus/command/CommandHandler.java index a340601b..77de7653 100644 --- a/src/fr/neatmonster/nocheatplus/command/CommandHandler.java +++ b/src/fr/neatmonster/nocheatplus/command/CommandHandler.java @@ -2,7 +2,9 @@ package fr.neatmonster.nocheatplus.command; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import org.bukkit.ChatColor; import org.bukkit.command.Command; @@ -81,13 +83,28 @@ public class CommandHandler implements CommandExecutor { new BanCommand(plugin), new InfoCommand(plugin), new KickCommand(plugin), + new TempKickCommand(plugin), new ReloadCommand(plugin, notifyReload), new TellCommand(plugin), new DelayCommand(plugin), }){ - commands.put(cmd.label, cmd); + addCommand(cmd); } } + + public void addCommand(NCPCommand command){ + Set allLabels = new LinkedHashSet(); + allLabels.add(command.label); + if (command.aliases != null){ + for (String alias : command.aliases){ + allLabels.add(alias); + } + } + for (String label : allLabels){ + label = label.trim().toLowerCase(); // future. + if (!commands.containsKey(label)) commands.put(label, command); + } + } /* (non-Javadoc) * @see org.bukkit.command.CommandExecutor#onCommand(org.bukkit.command.CommandSender, org.bukkit.command.Command, diff --git a/src/fr/neatmonster/nocheatplus/command/DelayableCommand.java b/src/fr/neatmonster/nocheatplus/command/DelayableCommand.java index dd34248c..90af26ef 100644 --- a/src/fr/neatmonster/nocheatplus/command/DelayableCommand.java +++ b/src/fr/neatmonster/nocheatplus/command/DelayableCommand.java @@ -77,7 +77,21 @@ public abstract class DelayableCommand extends NCPCommand { * @param mustHaveDelay If specifying a delay is obligatory. */ public DelayableCommand(NoCheatPlus plugin, String label, String permission, int delayIndex, int delayPreset, boolean mustHaveDelay) { - super(plugin, label, permission); + this(plugin, label, permission, null, delayIndex, delayPreset, mustHaveDelay); + } + + /** + * + * @param plugin + * @param label + * @param permission + * @param aliases Sub command label aliases. + * @param delayIndex Index at which to look for the delay spec. + * @param delayPreset Preset if no delay is given. + * @param mustHaveDelay If delay must be specified. + */ + public DelayableCommand(NoCheatPlus plugin, String label, String permission, String[] aliases, int delayIndex, int delayPreset, boolean mustHaveDelay) { + super(plugin, label, permission, aliases); this.delayIndex = delayIndex; this.mustHaveDelay = mustHaveDelay; this.delayPreset = delayPreset; diff --git a/src/fr/neatmonster/nocheatplus/command/NCPCommand.java b/src/fr/neatmonster/nocheatplus/command/NCPCommand.java index fbb092cb..8ccecbba 100644 --- a/src/fr/neatmonster/nocheatplus/command/NCPCommand.java +++ b/src/fr/neatmonster/nocheatplus/command/NCPCommand.java @@ -46,15 +46,21 @@ public abstract class NCPCommand implements CommandExecutor{ /** The sub command label. */ public final String label; + + public final String[] aliases; /** The command permission */ public String permission; - public NCPCommand(NoCheatPlus plugin, String label, String permission){ + this(plugin, label, permission, null); + } + + public NCPCommand(NoCheatPlus plugin, String label, String permission, String[] aliases){ this.plugin = plugin; this.label = label; this.permission = permission; + this.aliases = aliases; } /** diff --git a/src/fr/neatmonster/nocheatplus/command/TempKickCommand.java b/src/fr/neatmonster/nocheatplus/command/TempKickCommand.java new file mode 100644 index 00000000..d5d0a758 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/command/TempKickCommand.java @@ -0,0 +1,54 @@ +package fr.neatmonster.nocheatplus.command; + +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.players.Permissions; + +public class TempKickCommand extends DelayableCommand { + + public TempKickCommand(NoCheatPlus plugin) { + super(plugin, "tempkick", Permissions.ADMINISTRATION_TEMPKICK, new String[]{ + "tkick", "tempban", "tban", + }, 1, -1, false); + } + + @Override + public boolean execute(final CommandSender sender, Command command, String label, + String[] alteredArgs, long delay) { + // Args contains sub command label as first arg. + if (alteredArgs.length < 3) return false; + long base = 60000; // minutes (!) + final String name = alteredArgs[1]; + long duration = -1; + try{ + // TODO: parse for abbreviations like 30s 30m 30h 30d, and set base... + duration = Integer.parseInt(alteredArgs[2]); + } + catch( NumberFormatException e){}; + if (duration <= 0) return false; + final long finalDuration = duration * base; + final String reason; + if (alteredArgs.length > 3) reason = join(alteredArgs, 3); + else reason = ""; + schedule(new Runnable() { + @Override + public void run() { + tempKick(sender, name, finalDuration, reason); + } + }, delay); + return true; + } + + + protected void tempKick(CommandSender sender, String name, long duration, String reason){ + Player player = Bukkit.getPlayerExact(name); + NoCheatPlus.denyLogin(name, duration); + if (player == null) return; + player.kickPlayer(reason); + System.out.println("[NoCheatPlus] (" + sender.getName() + ") Kicked " + player.getName() + " for " + duration/60000 +" minutes: " + reason); + } +} diff --git a/src/fr/neatmonster/nocheatplus/players/Permissions.java b/src/fr/neatmonster/nocheatplus/players/Permissions.java index a9e16234..cd4dd739 100644 --- a/src/fr/neatmonster/nocheatplus/players/Permissions.java +++ b/src/fr/neatmonster/nocheatplus/players/Permissions.java @@ -32,6 +32,10 @@ public class Permissions { public static final String ADMINISTRATION_PLUGINS = ADMINISTRATION + ".plugins"; public static final String ADMINISTRATION_RELOAD = ADMINISTRATION + ".reload"; public static final String ADMINISTRATION_TELL = ADMINISTRATION + ".tell"; + public static final String ADMINISTRATION_TEMPKICK = ADMINISTRATION + ".tempkick"; + + private final static String BYPASS = NOCHEATPLUS + ".bypass"; + public static final String BYPASS_DENY_LOGIN = BYPASS + "denylogin"; private static final String CHECKS = NOCHEATPLUS + ".checks";