#831 Implement single session by canceling kicks caused by same name joining

- A little less nice, but works on both CraftBukkit and Spigot
- Remove obsolete warning
This commit is contained in:
ljacqu 2016-08-03 21:31:40 +02:00
parent f4add64695
commit 4aad1d506c
4 changed files with 23 additions and 60 deletions

View File

@ -50,7 +50,6 @@ import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.FileUtils; import fr.xephi.authme.util.FileUtils;
import fr.xephi.authme.util.GeoLiteAPI; import fr.xephi.authme.util.GeoLiteAPI;
import fr.xephi.authme.util.MigrationService; import fr.xephi.authme.util.MigrationService;
import fr.xephi.authme.util.ServerUtils;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.ValidationService; import fr.xephi.authme.util.ValidationService;
@ -307,13 +306,6 @@ public class AuthMe extends JavaPlugin {
&& settings.getProperty(PluginSettings.SESSIONS_ENABLED)) { && settings.getProperty(PluginSettings.SESSIONS_ENABLED)) {
ConsoleLogger.warning("WARNING!!! You set session timeout to 0, this may cause security issues!"); 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");
}
} }
/** /**

View File

@ -14,7 +14,6 @@ import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.BukkitService; import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.TeleportationService; import fr.xephi.authme.util.TeleportationService;
import fr.xephi.authme.util.ValidationService; import fr.xephi.authme.util.ValidationService;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; 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) { public void onPlayerLogin(PlayerLoginEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final String name = player.getName(); final String name = player.getName();
if (validationService.isUnrestricted(player.getName())) {
if (validationService.isUnrestricted(name)) {
return; return;
} else if (onJoinVerifier.refusePlayerForFullServer(event)) { } else if (onJoinVerifier.refusePlayerForFullServer(event)) {
return; return;
@ -231,13 +242,6 @@ public class PlayerListener implements Listener {
teleportationService.teleportOnJoin(player); 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) @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
@ -255,8 +259,15 @@ public class PlayerListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onPlayerKick(PlayerKickEvent event) { 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())) { if (!antiBot.wasPlayerKicked(player.getName())) {
management.performQuit(player); management.performQuit(player);
} }

View File

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

View File

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