diff --git a/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java index cc3fd52e..a8fafb59 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java +++ b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java @@ -30,6 +30,9 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.*; +import org.bukkit.permissions.PermissionAttachment; + +import java.util.concurrent.ConcurrentHashMap; class BukkitListener extends AbstractListener implements Listener { private final LPBukkitPlugin plugin; @@ -62,7 +65,15 @@ class BukkitListener extends AbstractListener implements Listener { if (user instanceof BukkitUser) { BukkitUser u = (BukkitUser) user; - u.setAttachment(player.addAttachment(plugin)); + + PermissionAttachment attachment = player.addAttachment(plugin); + try { + BukkitUser.getPermissionsField().set(attachment, new ConcurrentHashMap<>()); + } catch (Throwable t) { + t.printStackTrace(); + } + + u.setAttachment(attachment); } user.refreshPermissions(); @@ -71,16 +82,19 @@ class BukkitListener extends AbstractListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent e) { // Refresh permissions again + plugin.getUserManager().getWorldCache().put(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName()); refreshPlayer(e.getPlayer().getUniqueId()); } @EventHandler public void onPlayerChangedWorld(PlayerChangedWorldEvent e) { + plugin.getUserManager().getWorldCache().put(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName()); refreshPlayer(e.getPlayer().getUniqueId()); } @EventHandler public void onPlayerQuit(PlayerQuitEvent e) { + plugin.getUserManager().getWorldCache().remove(e.getPlayer().getUniqueId()); onLeave(e.getPlayer().getUniqueId()); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java index 11949eb4..cc2bb9d6 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java @@ -39,7 +39,6 @@ import me.lucko.luckperms.storage.Datastore; import me.lucko.luckperms.storage.StorageFactory; import me.lucko.luckperms.tracks.TrackManager; import me.lucko.luckperms.users.BukkitUserManager; -import me.lucko.luckperms.users.UserManager; import me.lucko.luckperms.utils.LogFactory; import org.bukkit.command.PluginCommand; import org.bukkit.entity.Player; @@ -49,13 +48,14 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.File; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Getter public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { - private final Set ignoringLogs = new HashSet<>(); + private final Set ignoringLogs = ConcurrentHashMap.newKeySet(); private LPConfiguration configuration; - private UserManager userManager; + private BukkitUserManager userManager; private GroupManager groupManager; private TrackManager trackManager; private Datastore datastore; diff --git a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java index 4bbe03b6..13a28ccb 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java +++ b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java @@ -27,7 +27,6 @@ import lombok.Setter; import me.lucko.luckperms.LPBukkitPlugin; import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent; import me.lucko.luckperms.api.implementation.internal.UserLink; -import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionAttachment; import java.lang.reflect.Field; @@ -36,7 +35,7 @@ import java.util.UUID; public class BukkitUser extends User { private static Field permissionsField = null; - private static Field getPermissionsField() { + public static Field getPermissionsField() { if (permissionsField == null) { try { permissionsField = PermissionAttachment.class.getDeclaredField("permissions"); @@ -68,46 +67,42 @@ public class BukkitUser extends User { @SuppressWarnings("unchecked") @Override public void refreshPermissions() { - plugin.doSync(() -> { - final Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid())); - if (player == null) return; + if (attachment == null) { + getPlugin().getLog().severe("User " + getName() + " does not have a permissions attachment defined."); + } - if (attachment == null) { - getPlugin().getLog().warn("User " + getName() + " does not have a permissions attachment defined."); - setAttachment(player.addAttachment(plugin)); - } + // Calculate the permissions that should be applied + Map toApply = getLocalPermissions(getPlugin().getConfiguration().getServer(), plugin.getUserManager().getWorldCache().get(getUuid()), null); - // Calculate the permissions that should be applied - Map toApply = getLocalPermissions(getPlugin().getConfiguration().getServer(), player.getWorld().getName(), null); + try { + // Existing is thread-safe, hopefully + Map existing = (Map) getPermissionsField().get(attachment); - try { - Map existing = (Map) getPermissionsField().get(attachment); - - boolean different = false; - if (toApply.size() != existing.size()) { - different = true; - } else { - for (Map.Entry e : existing.entrySet()) { - if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) { - continue; - } - different = true; - break; + boolean different = false; + if (toApply.size() != existing.size()) { + different = true; + } else { + for (Map.Entry e : existing.entrySet()) { + if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) { + continue; } + different = true; + break; } - - if (!different) return; - - // Faster than recalculating permissions after each PermissionAttachment#setPermission - existing.clear(); - existing.putAll(toApply); - attachment.getPermissible().recalculatePermissions(); - - } catch (Exception e) { - e.printStackTrace(); } - plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this))); - }); + if (!different) return; + + // Faster than recalculating permissions after each PermissionAttachment#setPermission + existing.clear(); + existing.putAll(toApply); + + attachment.getPermissible().recalculatePermissions(); + + } catch (Exception e) { + e.printStackTrace(); + } + + plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this))); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java index e6eef2dc..e2d19f92 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java +++ b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java @@ -22,16 +22,22 @@ package me.lucko.luckperms.users; +import lombok.Getter; import me.lucko.luckperms.LPBukkitPlugin; import org.bukkit.entity.Player; +import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class BukkitUserManager extends UserManager { private final LPBukkitPlugin plugin; + @Getter + private final Map worldCache = new ConcurrentHashMap<>(); + public BukkitUserManager(LPBukkitPlugin plugin) { super(plugin); this.plugin = plugin; diff --git a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java index 00a5f0e6..4b1b71f8 100644 --- a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java +++ b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java @@ -44,13 +44,17 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.plugin.Plugin; import java.io.File; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Getter public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { - private final Set ignoringLogs = new HashSet<>(); + private final Set ignoringLogs = ConcurrentHashMap.newKeySet(); private LPConfiguration configuration; private UserManager userManager; private GroupManager groupManager; diff --git a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java index acd90a9a..83e905ba 100644 --- a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java @@ -60,6 +60,7 @@ import org.spongepowered.api.text.Text; import java.io.File; import java.nio.file.Path; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -79,7 +80,7 @@ public class LPSpongePlugin implements LuckPermsPlugin { private Scheduler scheduler = Sponge.getScheduler(); - private final Set ignoringLogs = new HashSet<>(); + private final Set ignoringLogs = ConcurrentHashMap.newKeySet(); private LPConfiguration configuration; private UserManager userManager; private GroupManager groupManager;