diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index d00f901f3..c1f999162 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -50,7 +50,6 @@ import fr.xephi.authme.util.BukkitService; import fr.xephi.authme.util.FileUtils; import fr.xephi.authme.util.GeoLiteAPI; import fr.xephi.authme.util.MigrationService; -import fr.xephi.authme.util.ServerUtils; import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.ValidationService; @@ -307,13 +306,6 @@ public class AuthMe extends JavaPlugin { && settings.getProperty(PluginSettings.SESSIONS_ENABLED)) { ConsoleLogger.warning("WARNING!!! You set session timeout to 0, this may cause security issues!"); } - - // Single session not possible on CraftBukkit - if (settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION) - && !Bukkit.getOnlineMode() && !ServerUtils.isSpigot()) { - ConsoleLogger.warning("WARNING: You have force single session enabled but are not running on Spigot. " - + "This feature is not supported on CraftBukkit in offline mode"); - } } /** diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index 39be7bb4e..c0f851a26 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -14,7 +14,6 @@ import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.util.BukkitService; import fr.xephi.authme.util.TeleportationService; import fr.xephi.authme.util.ValidationService; - import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -194,12 +193,24 @@ public class PlayerListener implements Listener { } } - @EventHandler(priority = EventPriority.NORMAL) + @EventHandler(priority = EventPriority.LOW) + public void onPlayerJoin(PlayerJoinEvent event) { + final Player player = event.getPlayer(); + teleportationService.teleportNewPlayerToFirstSpawn(player); + management.performJoin(player); + } + + // Note #831: AsyncPlayerPreLoginEvent is not fired by all servers in offline mode + // e.g. CraftBukkit does not fire it. So we need to run crucial things with PlayerLoginEvent. + // Single session feature can be implemented for Spigot and CraftBukkit by canceling a kick + // event caused by "logged in from another location". The nicer way, but only for Spigot, would be + // to check in the AsyncPlayerPreLoginEvent. To support all servers, we use the less nice way. + + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerLogin(PlayerLoginEvent event) { final Player player = event.getPlayer(); final String name = player.getName(); - - if (validationService.isUnrestricted(name)) { + if (validationService.isUnrestricted(player.getName())) { return; } else if (onJoinVerifier.refusePlayerForFullServer(event)) { return; @@ -231,13 +242,6 @@ public class PlayerListener implements Listener { teleportationService.teleportOnJoin(player); } - @EventHandler(priority = EventPriority.LOW) - public void onPlayerJoin(PlayerJoinEvent event) { - final Player player = event.getPlayer(); - teleportationService.teleportNewPlayerToFirstSpawn(player); - management.performJoin(player); - } - @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); @@ -255,8 +259,15 @@ public class PlayerListener implements Listener { @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onPlayerKick(PlayerKickEvent event) { - Player player = event.getPlayer(); + // Note #831: Especially for offline CraftBukkit, we need to catch players being kicked because of + // "logged in from another location" and to cancel their kick + if (settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION) + && event.getReason().contains("You logged in from another location")) { + event.setCancelled(true); + return; + } + final Player player = event.getPlayer(); if (!antiBot.wasPlayerKicked(player.getName())) { management.performQuit(player); } diff --git a/src/main/java/fr/xephi/authme/util/ServerUtils.java b/src/main/java/fr/xephi/authme/util/ServerUtils.java deleted file mode 100644 index ae5306b85..000000000 --- a/src/main/java/fr/xephi/authme/util/ServerUtils.java +++ /dev/null @@ -1,21 +0,0 @@ -package fr.xephi.authme.util; - -public final class ServerUtils { - - private ServerUtils() { - } - - /** - * Check if the server implementation is based on Spigot - * - * @return true if the implementation is based on Spigot - */ - public static boolean isSpigot() { - try { - Class.forName("org.spigotmc.CustomTimingsHandler"); - return true; - } catch (ClassNotFoundException ignored) { - } - return false; - } -} diff --git a/src/test/java/fr/xephi/authme/util/ServerUtilsTest.java b/src/test/java/fr/xephi/authme/util/ServerUtilsTest.java deleted file mode 100644 index 04aaf88b0..000000000 --- a/src/test/java/fr/xephi/authme/util/ServerUtilsTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package fr.xephi.authme.util; - -import org.junit.Test; - -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; - -/** - * Test for {@link ServerUtils}. - */ -public class ServerUtilsTest { - - @Test - public void shouldReturnTrueForSpigotImplementation() { - // Spigot is a provided dependency of the project, so the ClassLoader knows about it - assertThat(ServerUtils.isSpigot(), equalTo(true)); - } - -}