Detach from permissible objects with a 1 tick delay after player quit to allow plugins listening on monitor to still access data (#1220)

This commit is contained in:
Luck 2018-09-20 11:07:20 +01:00
parent 11a3ecbba0
commit 04e511026d
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
7 changed files with 54 additions and 89 deletions

View File

@ -186,7 +186,11 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(PlayerQuitEvent e) { public void onPlayerQuit(PlayerQuitEvent e) {
final Player player = e.getPlayer(); final Player player = e.getPlayer();
handleDisconnect(player.getUniqueId());
// 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 // Remove the custom permissible
try { try {
PermissibleInjector.unInject(player, true); PermissibleInjector.unInject(player, true);
@ -199,20 +203,9 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
player.setOp(false); 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();
}
});
// remove their contexts cache // remove their contexts cache
this.plugin.getContextManager().onPlayerQuit(player); this.plugin.getContextManager().onPlayerQuit(player);
}, 1L);
} }
} }

View File

@ -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 // Wait until the last priority to unload, so plugins can still perform permission checks on this event
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerQuit(PlayerDisconnectEvent e) { public void onPlayerQuit(PlayerDisconnectEvent e) {
ProxiedPlayer player = e.getPlayer(); handleDisconnect(e.getPlayer().getUniqueId());
// 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();
}
});
} }
} }

View File

@ -63,7 +63,7 @@ public class BungeePermissionCheckListener implements Listener {
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
if (user == null) { if (user == null) {
e.setHasPermission(false); e.setHasPermission(false);
return; throw new IllegalStateException("No permissions data present for player: " + player.getName() + " - " + player.getUniqueId());
} }
Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player); Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player);
@ -89,7 +89,7 @@ public class BungeePermissionCheckListener implements Listener {
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
if (user == null) { if (user == null) {
e.setResult(Tristate.UNDEFINED); 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); Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player);

View File

@ -124,4 +124,18 @@ public abstract class AbstractConnectionListener {
return user; 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();
}
});
}
} }

View File

@ -40,6 +40,7 @@ import cn.nukkit.event.Listener;
import cn.nukkit.event.player.PlayerAsyncPreLoginEvent; import cn.nukkit.event.player.PlayerAsyncPreLoginEvent;
import cn.nukkit.event.player.PlayerLoginEvent; import cn.nukkit.event.player.PlayerLoginEvent;
import cn.nukkit.event.player.PlayerQuitEvent; import cn.nukkit.event.player.PlayerQuitEvent;
import cn.nukkit.scheduler.Task;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -179,7 +180,11 @@ public class NukkitConnectionListener extends AbstractConnectionListener impleme
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(PlayerQuitEvent e) { public void onPlayerQuit(PlayerQuitEvent e) {
final Player player = e.getPlayer(); final Player player = e.getPlayer();
handleDisconnect(player.getUniqueId());
// 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 // Remove the custom permissible
try { try {
PermissibleInjector.unInject(player, true); PermissibleInjector.unInject(player, true);
@ -192,20 +197,9 @@ public class NukkitConnectionListener extends AbstractConnectionListener impleme
player.setOp(false); 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();
}
});
// remove their contexts cache // remove their contexts cache
this.plugin.getContextManager().onPlayerQuit(player); this.plugin.getContextManager().onPlayerQuit(player);
}, 1, true);
} }
} }

View File

@ -166,19 +166,7 @@ public class SpongeConnectionListener extends AbstractConnectionListener {
@Listener(order = Order.POST) @Listener(order = Order.POST)
public void onClientLeave(ClientConnectionEvent.Disconnect e) { public void onClientLeave(ClientConnectionEvent.Disconnect e) {
Player player = e.getTargetEntity(); handleDisconnect(e.getTargetEntity().getUniqueId());
// 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();
}
});
} }
} }

View File

@ -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 // Wait until the last priority to unload, so plugins can still perform permission checks on this event
@Subscribe(order = PostOrder.LAST) @Subscribe(order = PostOrder.LAST)
public void onPlayerQuit(DisconnectEvent e) { public void onPlayerQuit(DisconnectEvent e) {
Player player = e.getPlayer(); handleDisconnect(e.getPlayer().getUniqueId());
// 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();
}
});
} }
} }