From 04e511026d07208e766e084bbdeffe73153d3d1a Mon Sep 17 00:00:00 2001 From: Luck Date: Thu, 20 Sep 2018 11:07:20 +0100 Subject: [PATCH] Detach from permissible objects with a 1 tick delay after player quit to allow plugins listening on monitor to still access data (#1220) --- .../listeners/BukkitConnectionListener.java | 41 ++++++++---------- .../listeners/BungeeConnectionListener.java | 14 +------ .../BungeePermissionCheckListener.java | 4 +- .../util/AbstractConnectionListener.java | 14 +++++++ .../listeners/NukkitConnectionListener.java | 42 ++++++++----------- .../listeners/SpongeConnectionListener.java | 14 +------ .../listeners/VelocityConnectionListener.java | 14 +------ 7 files changed, 54 insertions(+), 89 deletions(-) diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java index 69dc3607..146a49be 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java @@ -186,33 +186,26 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme @EventHandler(priority = EventPriority.MONITOR) public void onPlayerQuit(PlayerQuitEvent e) { final Player player = e.getPlayer(); + handleDisconnect(player.getUniqueId()); - // Remove the custom permissible - try { - PermissibleInjector.unInject(player, true); - } catch (Exception ex) { - ex.printStackTrace(); - } - - // Handle auto op - if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) { - player.setOp(false); - } - - // Register with the housekeeper, so the User's instance will stick - // around for a bit after they disconnect - this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId()); - - // force a clear of transient nodes - this.plugin.getBootstrap().getScheduler().executeAsync(() -> { - User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); - if (user != null) { - user.clearTransientNodes(); + // perform unhooking from bukkit objects 1 tick later. + // this allows plugins listening after us on MONITOR to still have intact permissions data + this.plugin.getBootstrap().getServer().getScheduler().runTaskLaterAsynchronously(this.plugin.getBootstrap(), () -> { + // Remove the custom permissible + try { + PermissibleInjector.unInject(player, true); + } catch (Exception ex) { + ex.printStackTrace(); } - }); - // remove their contexts cache - this.plugin.getContextManager().onPlayerQuit(player); + // Handle auto op + if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) { + player.setOp(false); + } + + // remove their contexts cache + this.plugin.getContextManager().onPlayerQuit(player); + }, 1L); } } diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeeConnectionListener.java b/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeeConnectionListener.java index edc2c18d..6d4c7b8c 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeeConnectionListener.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeeConnectionListener.java @@ -138,19 +138,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme // Wait until the last priority to unload, so plugins can still perform permission checks on this event @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerQuit(PlayerDisconnectEvent e) { - ProxiedPlayer player = e.getPlayer(); - - // Register with the housekeeper, so the User's instance will stick - // around for a bit after they disconnect - this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId()); - - // force a clear of transient nodes - this.plugin.getBootstrap().getScheduler().executeAsync(() -> { - User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); - if (user != null) { - user.clearTransientNodes(); - } - }); + handleDisconnect(e.getPlayer().getUniqueId()); } } diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java b/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java index 75f85d8c..1c0ff96d 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java @@ -63,7 +63,7 @@ public class BungeePermissionCheckListener implements Listener { User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); if (user == null) { e.setHasPermission(false); - return; + throw new IllegalStateException("No permissions data present for player: " + player.getName() + " - " + player.getUniqueId()); } Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player); @@ -89,7 +89,7 @@ public class BungeePermissionCheckListener implements Listener { User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); if (user == null) { e.setResult(Tristate.UNDEFINED); - return; + throw new IllegalStateException("No permissions data present for player: " + player.getName() + " - " + player.getUniqueId()); } Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player); diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java b/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java index 4bca9849..307f768b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java +++ b/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java @@ -124,4 +124,18 @@ public abstract class AbstractConnectionListener { return user; } + public void handleDisconnect(UUID uuid) { + // Register with the housekeeper, so the User's instance will stick + // around for a bit after they disconnect + this.plugin.getUserManager().getHouseKeeper().registerUsage(uuid); + + // force a clear of transient nodes + this.plugin.getBootstrap().getScheduler().executeAsync(() -> { + User user = this.plugin.getUserManager().getIfLoaded(uuid); + if (user != null) { + user.clearTransientNodes(); + } + }); + } + } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java index 4870db1e..77d809f3 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java @@ -40,6 +40,7 @@ import cn.nukkit.event.Listener; import cn.nukkit.event.player.PlayerAsyncPreLoginEvent; import cn.nukkit.event.player.PlayerLoginEvent; import cn.nukkit.event.player.PlayerQuitEvent; +import cn.nukkit.scheduler.Task; import java.util.Collections; import java.util.HashSet; @@ -179,33 +180,26 @@ public class NukkitConnectionListener extends AbstractConnectionListener impleme @EventHandler(priority = EventPriority.MONITOR) public void onPlayerQuit(PlayerQuitEvent e) { final Player player = e.getPlayer(); + handleDisconnect(player.getUniqueId()); - // Remove the custom permissible - try { - PermissibleInjector.unInject(player, true); - } catch (Exception ex) { - ex.printStackTrace(); - } - - // Handle auto op - if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) { - player.setOp(false); - } - - // Register with the housekeeper, so the User's instance will stick - // around for a bit after they disconnect - this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId()); - - // force a clear of transient nodes - this.plugin.getBootstrap().getScheduler().executeAsync(() -> { - User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); - if (user != null) { - user.clearTransientNodes(); + // perform unhooking from nukkit objects 1 tick later. + // this allows plugins listening after us on MONITOR to still have intact permissions data + this.plugin.getBootstrap().getServer().getScheduler().scheduleDelayedTask(this.plugin.getBootstrap(), () -> { + // Remove the custom permissible + try { + PermissibleInjector.unInject(player, true); + } catch (Exception ex) { + ex.printStackTrace(); } - }); - // remove their contexts cache - this.plugin.getContextManager().onPlayerQuit(player); + // Handle auto op + if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) { + player.setOp(false); + } + + // remove their contexts cache + this.plugin.getContextManager().onPlayerQuit(player); + }, 1, true); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java b/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java index c3677a13..cc936147 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java @@ -166,19 +166,7 @@ public class SpongeConnectionListener extends AbstractConnectionListener { @Listener(order = Order.POST) public void onClientLeave(ClientConnectionEvent.Disconnect e) { - Player player = e.getTargetEntity(); - - // Register with the housekeeper, so the User's instance will stick - // around for a bit after they disconnect - this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId()); - - // force a clear of transient nodes - this.plugin.getBootstrap().getScheduler().executeAsync(() -> { - User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); - if (user != null) { - user.clearTransientNodes(); - } - }); + handleDisconnect(e.getTargetEntity().getUniqueId()); } } diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java b/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java index b5a2c7af..34cc9b12 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java @@ -151,19 +151,7 @@ public class VelocityConnectionListener extends AbstractConnectionListener { // Wait until the last priority to unload, so plugins can still perform permission checks on this event @Subscribe(order = PostOrder.LAST) public void onPlayerQuit(DisconnectEvent e) { - Player player = e.getPlayer(); - - // Register with the housekeeper, so the User's instance will stick - // around for a bit after they disconnect - this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId()); - - // force a clear of transient nodes - this.plugin.getBootstrap().getScheduler().executeAsync(() -> { - User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); - if (user != null) { - user.clearTransientNodes(); - } - }); + handleDisconnect(e.getPlayer().getUniqueId()); } }