Convert PermissionAttachment to use ConcurrentMap, and do refreshPermissions async

This commit is contained in:
Luck
2016-08-22 22:39:40 +01:00
Unverified
parent 41fca40a36
commit 7a4135319f
6 changed files with 63 additions and 43 deletions
@@ -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<String, Boolean> toApply = getLocalPermissions(getPlugin().getConfiguration().getServer(), plugin.getUserManager().getWorldCache().get(getUuid()), null);
// Calculate the permissions that should be applied
Map<String, Boolean> toApply = getLocalPermissions(getPlugin().getConfiguration().getServer(), player.getWorld().getName(), null);
try {
// Existing is thread-safe, hopefully
Map<String, Boolean> existing = (Map<String, Boolean>) getPermissionsField().get(attachment);
try {
Map<String, Boolean> existing = (Map<String, Boolean>) getPermissionsField().get(attachment);
boolean different = false;
if (toApply.size() != existing.size()) {
different = true;
} else {
for (Map.Entry<String, Boolean> 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<String, Boolean> 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)));
}
}
@@ -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<UUID, String> worldCache = new ConcurrentHashMap<>();
public BukkitUserManager(LPBukkitPlugin plugin) {
super(plugin);
this.plugin = plugin;