Listeners name refactor + Fix #831 for both Spigot and CraftBukkit

This commit is contained in:
Gabriele C 2016-08-03 01:02:25 +02:00
parent bff99902b0
commit 75421fd156
16 changed files with 167 additions and 41 deletions

View File

@ -20,12 +20,14 @@ import fr.xephi.authme.hooks.BungeeCordMessage;
import fr.xephi.authme.hooks.PluginHooks; import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.initialization.MetricsStarter; import fr.xephi.authme.initialization.MetricsStarter;
import fr.xephi.authme.listener.AuthMeBlockListener; import fr.xephi.authme.listener.AsyncSingleSessionListener;
import fr.xephi.authme.listener.AuthMeEntityListener; import fr.xephi.authme.listener.BlockListener;
import fr.xephi.authme.listener.AuthMePlayerListener; import fr.xephi.authme.listener.EntityListener;
import fr.xephi.authme.listener.AuthMePlayerListener16; import fr.xephi.authme.listener.PlayerListener;
import fr.xephi.authme.listener.AuthMePlayerListener18; import fr.xephi.authme.listener.PlayerListener16;
import fr.xephi.authme.listener.AuthMeServerListener; import fr.xephi.authme.listener.PlayerListener18;
import fr.xephi.authme.listener.ServerListener;
import fr.xephi.authme.listener.SyncSingleSessionListener;
import fr.xephi.authme.output.ConsoleFilter; import fr.xephi.authme.output.ConsoleFilter;
import fr.xephi.authme.output.Log4JFilter; import fr.xephi.authme.output.Log4JFilter;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
@ -53,6 +55,8 @@ import fr.xephi.authme.util.MigrationService;
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;
import tools.utils.ServerUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -316,24 +320,31 @@ public class AuthMe extends JavaPlugin {
PluginManager pluginManager = getServer().getPluginManager(); PluginManager pluginManager = getServer().getPluginManager();
// Register event listeners // Register event listeners
pluginManager.registerEvents(injector.getSingleton(AuthMePlayerListener.class), this); pluginManager.registerEvents(injector.getSingleton(PlayerListener.class), this);
pluginManager.registerEvents(injector.getSingleton(AuthMeBlockListener.class), this); pluginManager.registerEvents(injector.getSingleton(BlockListener.class), this);
pluginManager.registerEvents(injector.getSingleton(AuthMeEntityListener.class), this); pluginManager.registerEvents(injector.getSingleton(EntityListener.class), this);
pluginManager.registerEvents(injector.getSingleton(AuthMeServerListener.class), this); pluginManager.registerEvents(injector.getSingleton(ServerListener.class), this);
// Try to register 1.6 player listeners // Try to register 1.6 player listeners
try { try {
Class.forName("org.bukkit.event.player.PlayerEditBookEvent"); Class.forName("org.bukkit.event.player.PlayerEditBookEvent");
pluginManager.registerEvents(injector.getSingleton(AuthMePlayerListener16.class), this); pluginManager.registerEvents(injector.getSingleton(PlayerListener16.class), this);
} catch (ClassNotFoundException ignore) { } catch (ClassNotFoundException ignore) {
} }
// Try to register 1.8 player listeners // Try to register 1.8 player listeners
try { try {
Class.forName("org.bukkit.event.player.PlayerInteractAtEntityEvent"); Class.forName("org.bukkit.event.player.PlayerInteractAtEntityEvent");
pluginManager.registerEvents(injector.getSingleton(AuthMePlayerListener18.class), this); pluginManager.registerEvents(injector.getSingleton(PlayerListener18.class), this);
} catch (ClassNotFoundException ignore) { } catch (ClassNotFoundException ignore) {
} }
// Choose the right SingleSessionListener
if(Bukkit.getOnlineMode() || ServerUtils.isSpigot()) {
pluginManager.registerEvents(injector.getSingleton(AsyncSingleSessionListener.class), this);
} else {
pluginManager.registerEvents(injector.getSingleton(SyncSingleSessionListener.class), this);
}
} }
private void reloadSupportHook() { private void reloadSupportHook() {

View File

@ -0,0 +1,39 @@
package fr.xephi.authme.listener;
import javax.inject.Inject;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import fr.xephi.authme.output.Messages;
/*
* This listener is registered only if the server is in online-mode or the implementation is Spigot.
* The reason is that only Spigot fires the Async version of the event on an offline-mode server!
*/
public class AsyncSingleSessionListener implements Listener {
@Inject
private Messages m;
@Inject
private OnJoinVerifier onJoinVerifier;
@EventHandler(priority = EventPriority.LOWEST)
public void onSyncPreLogin(AsyncPlayerPreLoginEvent event) {
if(event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
return;
}
final String name = event.getName();
try {
onJoinVerifier.checkSingleSession(name);
} catch (FailedVerificationException e) {
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
return;
}
}
}

View File

@ -7,7 +7,7 @@ import org.bukkit.event.block.BlockPlaceEvent;
import javax.inject.Inject; import javax.inject.Inject;
public class AuthMeBlockListener implements Listener { public class BlockListener implements Listener {
@Inject @Inject
private ListenerService listenerService; private ListenerService listenerService;

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.listener; package fr.xephi.authme.listener;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile; import org.bukkit.entity.Projectile;
@ -20,14 +21,14 @@ import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public class AuthMeEntityListener implements Listener { public class EntityListener implements Listener {
private final ListenerService listenerService; private final ListenerService listenerService;
private Method getShooter; private Method getShooter;
private boolean shooterIsLivingEntity; private boolean shooterIsLivingEntity;
@Inject @Inject
AuthMeEntityListener(ListenerService listenerService) { EntityListener(ListenerService listenerService) {
this.listenerService = listenerService; this.listenerService = listenerService;
try { try {
getShooter = Projectile.class.getDeclaredMethod("getShooter"); getShooter = Projectile.class.getDeclaredMethod("getShooter");

View File

@ -1,7 +1,6 @@
package fr.xephi.authme.listener; package fr.xephi.authme.listener;
import fr.xephi.authme.AntiBot; import fr.xephi.authme.AntiBot;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
@ -15,6 +14,7 @@ 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;
@ -25,6 +25,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerBedEnterEvent; import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerDropItemEvent;
@ -52,7 +53,7 @@ import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAU
/** /**
* Listener class for player events. * Listener class for player events.
*/ */
public class AuthMePlayerListener implements Listener { public class PlayerListener implements Listener {
public static final ConcurrentHashMap<String, String> joinMessage = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<String, String> joinMessage = new ConcurrentHashMap<>();
@ -201,26 +202,27 @@ public class AuthMePlayerListener implements Listener {
management.performJoin(player); management.performJoin(player);
} }
// Note: AsyncPlayerPreLoginEvent is not fired by all servers in offline mode
// e.g. CraftBukkit does not. So we need to run crucial things in onPlayerLogin, too
// We have no performance improvements if we do the same thing on two different events
// Important: the single session feature works if we use the low priority to the sync handler
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onLoginSingleSession(PlayerLoginEvent event) { public void onAsyncPreLogin(AsyncPlayerPreLoginEvent event) {
if(event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
// Spigot only
try {
Class.forName("org.spigotmc.CustomTimingsHandler");
} catch(Exception e) {
return;
}
if(event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
return; return;
} }
final Player player = event.getPlayer(); final String name = event.getName();
final String name = player.getName();
try { try {
onJoinVerifier.checkSingleSession(name); onJoinVerifier.checkSingleSession(name);
} catch (FailedVerificationException e) { } catch (FailedVerificationException e) {
ConsoleLogger.warning("DEBUG: " + name + " tried to join the game but an user with the same name was already online!" );
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs())); event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));
event.setResult(PlayerLoginEvent.Result.KICK_OTHER); event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
return; return;
} }
} }

View File

@ -10,7 +10,7 @@ import javax.inject.Inject;
/** /**
* Listener of player events for events introduced in Minecraft 1.6. * Listener of player events for events introduced in Minecraft 1.6.
*/ */
public class AuthMePlayerListener16 implements Listener { public class PlayerListener16 implements Listener {
@Inject @Inject
private ListenerService listenerService; private ListenerService listenerService;

View File

@ -10,7 +10,7 @@ import javax.inject.Inject;
/** /**
* Listener of player events for events introduced in Minecraft 1.8. * Listener of player events for events introduced in Minecraft 1.8.
*/ */
public class AuthMePlayerListener18 implements Listener { public class PlayerListener18 implements Listener {
@Inject @Inject
private ListenerService listenerService; private ListenerService listenerService;

View File

@ -14,7 +14,7 @@ import javax.inject.Inject;
/** /**
*/ */
public class AuthMeServerListener implements Listener { public class ServerListener implements Listener {
@Inject @Inject
private PluginHooks pluginHooks; private PluginHooks pluginHooks;

View File

@ -0,0 +1,41 @@
package fr.xephi.authme.listener;
import javax.inject.Inject;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerPreLoginEvent;
import fr.xephi.authme.output.Messages;
/*
* This listener is registered only if the server is in offline-mode and the implementation is not Spigot.
* The reason is that only Spigot fires the Async version of this event on an offline-mode server!
*/
public class SyncSingleSessionListener implements Listener {
@Inject
private Messages m;
@Inject
private OnJoinVerifier onJoinVerifier;
// Note: the PlayerPreLoginEvent causes the login thread to synchronize with the main thread
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.LOWEST)
public void onSyncPreLogin(PlayerPreLoginEvent event) {
if(event.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
return;
}
final String name = event.getName();
try {
onJoinVerifier.checkSingleSession(name);
} catch (FailedVerificationException e) {
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));
event.setResult(PlayerPreLoginEvent.Result.KICK_OTHER);
return;
}
}
}

View File

@ -7,7 +7,7 @@ import fr.xephi.authme.cache.limbo.PlayerData;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.events.LoginEvent; import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.RestoreInventoryEvent; import fr.xephi.authme.events.RestoreInventoryEvent;
import fr.xephi.authme.listener.AuthMePlayerListener; import fr.xephi.authme.listener.PlayerListener;
import fr.xephi.authme.process.ProcessService; import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.process.SynchronousProcess; import fr.xephi.authme.process.SynchronousProcess;
import fr.xephi.authme.service.BungeeService; import fr.xephi.authme.service.BungeeService;
@ -100,7 +100,7 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
teleportationService.teleportOnLogin(player, auth, limbo); teleportationService.teleportOnLogin(player, auth, limbo);
// We can now display the join message (if delayed) // We can now display the join message (if delayed)
String jm = AuthMePlayerListener.joinMessage.get(name); String jm = PlayerListener.joinMessage.get(name);
if (jm != null) { if (jm != null) {
if (!jm.isEmpty()) { if (!jm.isEmpty()) {
for (Player p : bukkitService.getOnlinePlayers()) { for (Player p : bukkitService.getOnlinePlayers()) {
@ -109,7 +109,7 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
} }
} }
} }
AuthMePlayerListener.joinMessage.remove(name); PlayerListener.joinMessage.remove(name);
} }
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) { if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {

View File

@ -7,7 +7,7 @@ import fr.xephi.authme.api.NewAPI;
import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.command.CommandHandler;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.listener.AuthMeBlockListener; import fr.xephi.authme.listener.BlockListener;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.process.Management; import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.login.ProcessSyncPlayerLogin; import fr.xephi.authme.process.login.ProcessSyncPlayerLogin;
@ -113,7 +113,7 @@ public class AuthMeInitializationTest {
// then // then
// Take a few samples and ensure that they are not null // Take a few samples and ensure that they are not null
assertThat(injector.getIfAvailable(AuthMeBlockListener.class), not(nullValue())); assertThat(injector.getIfAvailable(BlockListener.class), not(nullValue()));
assertThat(injector.getIfAvailable(CommandHandler.class), not(nullValue())); assertThat(injector.getIfAvailable(CommandHandler.class), not(nullValue()));
assertThat(injector.getIfAvailable(Management.class), not(nullValue())); assertThat(injector.getIfAvailable(Management.class), not(nullValue()));
assertThat(injector.getIfAvailable(NewAPI.class), not(nullValue())); assertThat(injector.getIfAvailable(NewAPI.class), not(nullValue()));

View File

@ -9,19 +9,22 @@ import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import fr.xephi.authme.listener.BlockListener;
import fr.xephi.authme.listener.ListenerService;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
/** /**
* Test for {@link AuthMeBlockListener}. * Test for {@link BlockListener}.
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class AuthMeBlockListenerTest { public class AuthMeBlockListenerTest {
@InjectMocks @InjectMocks
private AuthMeBlockListener listener; private BlockListener listener;
@Mock @Mock
private ListenerService listenerService; private ListenerService listenerService;

View File

@ -1,6 +1,14 @@
package fr.xephi.authme.listener; package fr.xephi.authme.listener;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import fr.xephi.authme.listener.BlockListener;
import fr.xephi.authme.listener.EntityListener;
import fr.xephi.authme.listener.PlayerListener;
import fr.xephi.authme.listener.PlayerListener16;
import fr.xephi.authme.listener.PlayerListener18;
import fr.xephi.authme.listener.ServerListener;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.junit.Test; import org.junit.Test;
@ -20,9 +28,9 @@ import static org.junit.Assert.fail;
*/ */
public final class ListenerConsistencyTest { public final class ListenerConsistencyTest {
private static final Class<?>[] LISTENERS = { AuthMeBlockListener.class, AuthMeEntityListener.class, private static final Class<?>[] LISTENERS = { BlockListener.class, EntityListener.class,
AuthMePlayerListener.class, AuthMePlayerListener16.class, AuthMePlayerListener18.class, PlayerListener.class, PlayerListener16.class, PlayerListener18.class,
AuthMeServerListener.class }; ServerListener.class };
private static final Set<String> CANCELED_EXCEPTIONS = Sets.newHashSet("AuthMePlayerListener#onPlayerJoin", private static final Set<String> CANCELED_EXCEPTIONS = Sets.newHashSet("AuthMePlayerListener#onPlayerJoin",
"AuthMePlayerListener#onPreLogin", "AuthMePlayerListener#onPlayerLogin", "AuthMePlayerListener#onPreLogin", "AuthMePlayerListener#onPlayerLogin",

View File

@ -6,6 +6,7 @@ import ch.jalu.injector.testing.InjectDelayed;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.hooks.PluginHooks; import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.listener.ListenerService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.ValidationService; import fr.xephi.authme.util.ValidationService;

View File

@ -4,6 +4,8 @@ import fr.xephi.authme.AntiBot;
import fr.xephi.authme.TestHelper; import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.listener.FailedVerificationException;
import fr.xephi.authme.listener.OnJoinVerifier;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;

View File

@ -0,0 +1,18 @@
package tools.utils;
public class 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;
}
}