From 3791a158de118da26de5f3e07dad8414e1bdac15 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 16 Apr 2011 03:08:05 -0700 Subject: [PATCH] Added pre-login event for catching logins right after name verification has completed. This happens in a different thread from the server (and thus can also block). --- src/main/java/org/bukkit/event/Event.java | 7 + .../bukkit/event/player/PlayerListener.java | 8 ++ .../event/player/PlayerPreLoginEvent.java | 126 ++++++++++++++++++ .../bukkit/plugin/SimplePluginManager.java | 14 +- .../bukkit/plugin/java/JavaPluginLoader.java | 6 + 5 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java diff --git a/src/main/java/org/bukkit/event/Event.java b/src/main/java/org/bukkit/event/Event.java index 5476cc74..3c4a6a34 100644 --- a/src/main/java/org/bukkit/event/Event.java +++ b/src/main/java/org/bukkit/event/Event.java @@ -152,6 +152,13 @@ public abstract class Event implements Serializable { */ PLAYER_LOGIN (Category.PLAYER), + /** + * Called when a player has just been authenticated + * + * @see org.bukkit.event.player.PlayerPreLoginEvent + */ + PLAYER_PRELOGIN (Category.PLAYER), + /** * Called when a player respawns * diff --git a/src/main/java/org/bukkit/event/player/PlayerListener.java b/src/main/java/org/bukkit/event/player/PlayerListener.java index 1aff9ed1..c2381331 100644 --- a/src/main/java/org/bukkit/event/player/PlayerListener.java +++ b/src/main/java/org/bukkit/event/player/PlayerListener.java @@ -100,6 +100,14 @@ public class PlayerListener implements Listener { public void onPlayerLogin(PlayerLoginEvent event) { } + /** + * Called when a player has just been authenticated + * + * @param event Relevant event details + */ + public void onPlayerPreLogin(PlayerPreLoginEvent event) { + } + /** * Called when a player throws an egg and it might hatch * diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java new file mode 100644 index 00000000..a76d96a2 --- /dev/null +++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java @@ -0,0 +1,126 @@ + +package org.bukkit.event.player; + +import java.net.InetAddress; +import org.bukkit.event.Event; + +/** + * Stores details for players attempting to log in + */ +public class PlayerPreLoginEvent extends Event { + private Result result; + private String message; + private String name; + private InetAddress ipAddress; + + public PlayerPreLoginEvent(String name, InetAddress ipAddress) { + super(Type.PLAYER_PRELOGIN); + this.result = Result.ALLOWED; + this.message = ""; + this.name = name; + this.ipAddress = ipAddress; + } + + /** + * Gets the current result of the login, as an enum + * + * @return Current Result of the login + */ + public Result getResult() { + return result; + } + + /** + * Sets the new result of the login, as an enum + * + * @param result New result to set + */ + public void setResult(final Result result) { + this.result = result; + } + + /** + * Gets the current kick message that will be used if getResult() != Result.ALLOWED + * + * @return Current kick message + */ + public String getKickMessage() { + return message; + } + + /** + * Sets the kick message to display if getResult() != Result.ALLOWED + * + * @param message New kick message + */ + public void setKickMessage(final String message) { + this.message = message; + } + + /** + * Allows the player to log in + */ + public void allow() { + result = Result.ALLOWED; + message = ""; + } + + /** + * Disallows the player from logging in, with the given reason + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user + */ + public void disallow(final Result result, final String message) { + this.result = result; + this.message = message; + } + + /** + * Gets the player name. + * + * @return + */ + public String getName() { + return name; + } + + /** + * Gets the player IP address. + * + * @return + */ + public InetAddress getAddress() { + return ipAddress; + } + + /** + * Basic kick reasons for communicating to plugins + */ + public enum Result { + /** + * The player is allowed to log in + */ + ALLOWED, + + /** + * The player is not allowed to log in, due to the server being full + */ + KICK_FULL, + + /** + * The player is not allowed to log in, due to them being banned + */ + KICK_BANNED, + + /** + * The player is not allowed to log in, due to them not being on the white list + */ + KICK_WHITELIST, + + /** + * The player is not allowed to log in, for reasons undefined + */ + KICK_OTHER + } +} diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java index 6f9f71eb..5ab303ec 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -75,8 +75,10 @@ public final class SimplePluginManager implements PluginManager { Pattern[] patterns = instance.getPluginFileFilters(); - for (Pattern pattern : patterns) { - fileAssociations.put(pattern, instance); + synchronized (this) { + for (Pattern pattern : patterns) { + fileAssociations.put(pattern, instance); + } } } @@ -145,7 +147,7 @@ public final class SimplePluginManager implements PluginManager { * @throws InvalidPluginException Thrown when the specified file is not a valid plugin * @throws InvalidDescriptionException Thrown when the specified file contains an invalid description */ - public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException { + public synchronized Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException { Set filters = fileAssociations.keySet(); Plugin result = null; @@ -175,11 +177,11 @@ public final class SimplePluginManager implements PluginManager { * @param name Name of the plugin to check * @return Plugin if it exists, otherwise null */ - public Plugin getPlugin(String name) { + public synchronized Plugin getPlugin(String name) { return lookupNames.get(name); } - public Plugin[] getPlugins() { + public synchronized Plugin[] getPlugins() { return plugins.toArray(new Plugin[0]); } @@ -246,7 +248,7 @@ public final class SimplePluginManager implements PluginManager { * @param type Type of player related event to call * @param event Event details */ - public void callEvent(Event event) { + public synchronized void callEvent(Event event) { SortedSet eventListeners = listeners.get(event.getType()); if (eventListeners != null) { diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java index 10eaaaa2..1fca4b1d 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -258,6 +258,12 @@ public final class JavaPluginLoader implements PluginLoader { ((PlayerListener) listener).onPlayerLogin((PlayerLoginEvent) event); } }; + case PLAYER_PRELOGIN: + return new EventExecutor() { + public void execute(Listener listener, Event event) { + ((PlayerListener) listener).onPlayerPreLogin((PlayerPreLoginEvent) event); + } + }; case PLAYER_EGG_THROW: return new EventExecutor() { public void execute(Listener listener, Event event) {