From 32f8e354df6083d07362fc7bf8a2a7f8c49d0255 Mon Sep 17 00:00:00 2001 From: sgdc3 Date: Wed, 27 Sep 2017 14:41:23 +0200 Subject: [PATCH] Should fix issues like #1336 and #592 The #592 fix will be effective only on 1.9+ servers --- .../xephi/authme/listener/PlayerListener.java | 32 +++++++++++++-- .../authme/service/TeleportationService.java | 41 ++++++++++++------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index e671d1bfb..f3539db93 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -12,7 +12,6 @@ import fr.xephi.authme.service.TeleportationService; import fr.xephi.authme.service.ValidationService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.SpawnLoader; -import fr.xephi.authme.settings.properties.DatabaseSettings; import fr.xephi.authme.settings.properties.HooksSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RestrictionSettings; @@ -43,6 +42,7 @@ import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerShearEntityEvent; +import org.spigotmc.event.player.PlayerSpawnLocationEvent; import javax.inject.Inject; @@ -80,6 +80,7 @@ public class PlayerListener implements Listener { private JoinMessageService joinMessageService; private boolean isAsyncPlayerPreLoginEventCalled = false; + private boolean isPlayerSpawnLocationEventCalled = false; @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { @@ -190,6 +191,9 @@ public class PlayerListener implements Listener { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerJoin(PlayerJoinEvent event) { final Player player = event.getPlayer(); + if (!isPlayerSpawnLocationEventCalled) { + teleportationService.teleportOnJoin(player); + } teleportationService.teleportNewPlayerToFirstSpawn(player); management.performJoin(player); } @@ -233,6 +237,9 @@ public class PlayerListener implements Listener { } } + //Note: We can't teleport the player in the PlayerLoginEvent listener + //as the new player location will be reverted by the server. + @EventHandler(priority = EventPriority.LOW) public void onPlayerLogin(PlayerLoginEvent event) { final Player player = event.getPlayer(); @@ -249,9 +256,7 @@ public class PlayerListener implements Listener { return; } - teleportationService.teleportOnJoin(player); - - if(!isAsyncPlayerPreLoginEventCalled) { + if (!isAsyncPlayerPreLoginEventCalled) { try { runOnJoinChecks(name, event.getAddress().getHostAddress()); } catch (FailedVerificationException e) { @@ -261,6 +266,25 @@ public class PlayerListener implements Listener { } } + // Note: the following event is called since MC1.9, in older versions we have to fallback on the PlayerJoinEvent + + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerSpawn(PlayerSpawnLocationEvent event) { + isPlayerSpawnLocationEventCalled = true; + + final Player player = event.getPlayer(); + final String name = player.getName(); + + if (validationService.isUnrestricted(name)) { + return; + } + + Location customSpawnLocation = teleportationService.prepareOnJoinSpawnLocation(player); + if (customSpawnLocation != null) { + event.setSpawnLocation(customSpawnLocation); + } + } + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); diff --git a/src/main/java/fr/xephi/authme/service/TeleportationService.java b/src/main/java/fr/xephi/authme/service/TeleportationService.java index a0f05ed93..38917d4d8 100644 --- a/src/main/java/fr/xephi/authme/service/TeleportationService.java +++ b/src/main/java/fr/xephi/authme/service/TeleportationService.java @@ -57,15 +57,8 @@ public class TeleportationService implements Reloadable { /** * Teleports the player according to the settings when he joins. - *

- * Note: this is triggered by Bukkit's PlayerLoginEvent, during which you cannot use - * {@link Player#hasPlayedBefore()}: it always returns {@code false}. We trigger teleportation - * from the PlayerLoginEvent and not the PlayerJoinEvent to ensure that the location is overridden - * as fast as possible (cf. AuthMe #682). * * @param player the player to process - * @see BUKKIT-3521: Player.hasPlayedBefore() - * always false */ public void teleportOnJoin(final Player player) { if (!settings.getProperty(RestrictionSettings.NO_TELEPORT) @@ -74,6 +67,29 @@ public class TeleportationService implements Reloadable { } } + /** + * Returns the player's custom on join location + * + * @param player the player to process + * + * @return the custom spawn location, null if the player should spawn at the original location + */ + public Location prepareOnJoinSpawnLocation(final Player player) { + if (!settings.getProperty(RestrictionSettings.NO_TELEPORT) + && settings.getProperty(TELEPORT_UNAUTHED_TO_SPAWN)) { + final Location location = spawnLoader.getSpawnLocation(player); + + SpawnTeleportEvent event = new SpawnTeleportEvent(player, location, playerCache.isAuthenticated(player.getName())); + bukkitService.callEvent(event); + if(!isEventValid(event)) { + return null; + } + + return location; + } + return null; + } + /** * Teleports the player to the first spawn if he is new and the first spawn is configured. * @@ -155,13 +171,10 @@ public class TeleportationService implements Reloadable { * @param event the event to emit and according to which to teleport */ private void performTeleportation(final Player player, final AbstractTeleportEvent event) { - bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(new Runnable() { - @Override - public void run() { - bukkitService.callEvent(event); - if (player.isOnline() && isEventValid(event)) { - player.teleport(event.getTo()); - } + bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> { + bukkitService.callEvent(event); + if (player.isOnline() && isEventValid(event)) { + player.teleport(event.getTo()); } }); }