permissionMap = new HashMap<>();
+
+ public static void init(JavaPlugin plugin, String serverName) {
+ PandalibPaperPermissions.plugin = plugin;
+ PandalibPaperPermissions.serverName = serverName;
+ PermissionsInjectorBukkit.inject(Bukkit.getConsoleSender());
+ PermissionsInjectorVault.inject();
+ PermissionsInjectorWEPIF.inject();
+
+ Bukkit.getPluginManager().registerEvents(new PandalibPaperPermissions(), plugin);
+ }
+
+ /**
+ * Add the provided pair of permission into an internal permission map. This is used when a plugin asks the value of
+ * the sourcePerm, then the permission system actually check for the destPerm.
+ *
+ * This mapping is useful, for instance, when the bukkit dispatcher force the fake vanilla commands to have a
+ * permission starting with {@code minecraft.command.} even if we defined a custom permission in the plugin.
+ * @param sourcePerm the source permission to replace
+ * @param destPerm the replacement permission
+ */
+ public static void addPermissionMapping(String sourcePerm, String destPerm) {
+ Objects.requireNonNull(sourcePerm, "sourcePerm");
+ if (destPerm == null) {
+ permissionMap.remove(sourcePerm);
+ }
+ else {
+ permissionMap.put(sourcePerm, destPerm);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPlayerLogin(PlayerLoginEvent event) {
+ Permissions.clearPlayerCache(event.getPlayer().getUniqueId());
+ Permissions.precachePlayerAsync(event.getPlayer().getUniqueId());
+
+ PermissionsInjectorBukkit.inject(event.getPlayer());
+ }
+
+
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ PermissionsInjectorBukkit.uninject(event.getPlayer());
+ Permissions.clearPlayerCache(event.getPlayer().getUniqueId());
+ }
+
+
+
+
+ /* package */ static Function> SUPERPERMS_PARENT_PERMISSION_GETTER = childPerm -> {
+ return Bukkit.getPluginManager().getPermissions().stream()
+ .filter(p -> p.getChildren().containsKey(childPerm))
+ .collect(Collectors.toList());
+ };
+
+ /* package */ static ServerOperator dummyOperator(boolean isOp) {
+ return new ServerOperator() {
+ @Override public void setOp(boolean op) { }
+ @Override public boolean isOp() { return isOp; }
+ };
+ }
+
+ /* package */ static Boolean hasSuperPermsPermission(ServerOperator opable, String permission, Predicate parentPermissionChecker) {
+ if (opable instanceof CommandSender sender) {
+ Permissible permissible = PermissionsInjectorBukkit.getPermissible(sender);
+ if (permissible instanceof PermissionsInjectorBukkit.PandaPermissible pPerm)
+ return hasSuperPermsPermission(opable, permission, parentPermissionChecker, pPerm);
+ }
+ return hasSuperPermsPermission(opable, permission, parentPermissionChecker, null);
+ }
+
+ /* package */ static Boolean hasSuperPermsPermission(ServerOperator opable, String permission, Predicate parentPermissionChecker, PermissionsInjectorBukkit.PandaPermissible pandaPermissible) {
+
+ boolean reversed = permission.startsWith("-");
+ if (reversed) {
+ permission = permission.substring(1);
+ }
+
+ boolean defined = false;
+ Permission perm = Bukkit.getPluginManager().getPermission(permission);
+ if (perm != null) {
+ if (perm.getDefault().getValue(opable.isOp()))
+ return !reversed;
+ defined = true;
+ }
+
+ try {
+ List parents = pandaPermissible != null ? pandaPermissible.superPermsPermissionCache.get(permission) : SUPERPERMS_PARENT_PERMISSION_GETTER.apply(permission);
+
+ for (Permission parent : parents) {
+ Boolean childValue = parent.getChildren().get(permission);
+ if (childValue == null)
+ continue;
+ boolean parentPerm = parentPermissionChecker.test(parent.getName());
+ if (parentPerm == childValue)
+ return !reversed;
+ defined = true;
+ }
+ } catch (ExecutionException e) {
+ Log.severe("Unable to compute SuperPerms permission", e);
+ }
+
+ Boolean ret = defined ? reversed : null;
+ if (Log.isDebugEnabled()) {
+ String name = (opable instanceof CommandSender cs) ? cs.getName() : "unknown entity";
+ String actualPerm = permission;
+ if (reversed) actualPerm = "-" + permission;
+ Log.debug("[SuperPerms] For " + name + ", '" + actualPerm + "' is " + ret);
+ }
+ return ret;
+ }
+
+}
diff --git a/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorBukkit.java b/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorBukkit.java
new file mode 100644
index 0000000..754fe9b
--- /dev/null
+++ b/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorBukkit.java
@@ -0,0 +1,313 @@
+package fr.pandacube.lib.paper.permissions;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.permissions.Permissible;
+import org.bukkit.permissions.PermissibleBase;
+import org.bukkit.permissions.Permission;
+import org.bukkit.permissions.PermissionAttachment;
+import org.bukkit.permissions.PermissionAttachmentInfo;
+import org.bukkit.plugin.Plugin;
+
+import fr.pandacube.lib.permissions.Permissions;
+import fr.pandacube.lib.reflect.Reflect;
+import fr.pandacube.lib.util.Log;
+
+public class PermissionsInjectorBukkit
+{
+
+ // to be called : onEnable for console, onPlayerLogin (not Join) (Priority LOWEST) for players
+ public static void inject(CommandSender sender) {
+ Permissible oldP = getPermissible(sender);
+ if (oldP instanceof PandaPermissible)
+ return;
+ if (!oldP.getClass().equals(PermissibleBase.class)) {
+ Log.warning("Another plugin is already injecting permissions into Bukkit for " + sender.getName() + ": " + oldP.getClass().getName());
+ Log.warning("Not injecting our own permissions.");
+ }
+ PandaPermissible p = new PandaPermissible(sender, getPermissible(sender));
+ setPermissible(p.sender, p);
+ p.recalculatePermissions();
+ }
+
+
+
+ // to be called : onDisable for console, onPlayerQuit () and onDisable for players
+ public static void uninject(CommandSender sender)
+ {
+ Permissible perm = getPermissible(sender);
+ if (perm instanceof PandaPermissible p) {
+ setPermissible(sender, p.oldPermissible);
+ p.oldPermissible.recalculatePermissions();
+ }
+ }
+
+ private static void setPermissible(CommandSender sender, Permissible newpermissible)
+ {
+ try {
+ Field perm = getPermField(sender);
+ if (perm == null)
+ return;
+ perm.setAccessible(true);
+ perm.set(sender, newpermissible);
+ }
+ catch (Exception e) {
+ Log.severe(e);
+ }
+ }
+
+ /* package */ static Permissible getPermissible(CommandSender sender)
+ {
+ Field perm = getPermField(sender);
+ if (perm == null)
+ return null;
+ try {
+ perm.setAccessible(true);
+ Permissible p = (Permissible) perm.get(sender);
+ if (p == null) {
+ Log.warning("Null permissible instance found in provided CommandSender: " + sender, new Throwable());
+ }
+ return p;
+ }
+ catch (Exception e) {
+ Log.severe(e);
+ }
+ return null;
+ }
+
+ private static Field getPermField(CommandSender sender)
+ {
+ if (sender == null) {
+ throw new IllegalArgumentException("sender cannot be null");
+ }
+ try {
+ if (sender instanceof Player || sender instanceof ConsoleCommandSender)
+ return Reflect.ofClassOfInstance(sender).field("perm").get();
+ else
+ throw new IllegalArgumentException("Unsupported type for sender: " + sender.getClass());
+ }
+ catch (Exception e) {
+ Log.severe(e);
+ }
+ return null;
+ }
+
+ /* package */ static class PandaPermissible extends PermissibleBase
+ {
+ private final CommandSender sender;
+ private final Permissible oldPermissible;
+
+ /* package */ LoadingCache> superPermsPermissionCache = CacheBuilder.newBuilder()
+ .build(CacheLoader.from(PandalibPaperPermissions.SUPERPERMS_PARENT_PERMISSION_GETTER::apply));
+
+ private boolean init = false;
+
+ private PandaPermissible(CommandSender sender, Permissible oldPermissible)
+ {
+ super(sender);
+ this.sender = sender;
+ this.oldPermissible = oldPermissible;
+ init = true;
+ recalculatePermissions();
+ }
+
+ private Boolean hasPermissionOnServerInWorld(String permission) {
+ if (sender instanceof Player player) {
+ String world = player.getWorld().getName();
+ return Permissions.getPlayer(player.getUniqueId()).hasPermission(permission, PandalibPaperPermissions.serverName, world);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean hasPermission(String permission)
+ {
+ /*
+ * WARNING: don’t call PermissibleOnlinePlayer#hasPermission(String) here or it will result on a stack overflow
+ */
+
+ if (permission.toLowerCase().startsWith("minecraft.command."))
+ permission = PandalibPaperPermissions.permissionMap.getOrDefault(permission.toLowerCase(), permission);
+
+ Boolean res = hasPermissionOnServerInWorld(permission); // supports negative permission
+ if (res != null)
+ return res;
+
+ res = PandalibPaperPermissions.hasSuperPermsPermission(sender, permission, this::hasPermission, this); // supports negative permission
+ if (res != null)
+ return res;
+
+ boolean reversed = permission.startsWith("-");
+ if (reversed) {
+ permission = permission.substring(1);
+ }
+
+ return oldPermissible.hasPermission(permission) != reversed;
+ }
+
+ @Override
+ public boolean hasPermission(Permission permission)
+ {
+ if (permission.getName().toLowerCase().startsWith("minecraft.command.") && PandalibPaperPermissions.permissionMap.containsKey(permission.getName().toLowerCase())) {
+ return hasPermission(PandalibPaperPermissions.permissionMap.get(permission.getName().toLowerCase()));
+ }
+
+ Boolean res = hasPermissionOnServerInWorld(permission.getName()); // supports negative permission
+ if (res != null)
+ return res;
+
+ res = PandalibPaperPermissions.hasSuperPermsPermission(sender, permission.getName(), this::hasPermission, this); // supports negative permission
+ if (res != null)
+ return res;
+
+ return oldPermissible.hasPermission(permission); // doesn’t need to manage negative permission (should not happend)
+ }
+
+ @Override
+ public void recalculatePermissions()
+ {
+ // need this check because super class constructor calls this method,
+ // thus before oldPermissible has its value assigned
+ if (!init)
+ return;
+
+ oldPermissible.recalculatePermissions();
+
+ superPermsPermissionCache.invalidateAll();
+
+ effectivePermissionsListCache.invalidateAll();
+ }
+
+
+ private Map getEffectivePermissionsOnServerInWorld() {
+ if (sender instanceof Player player) {
+ String world = player.getWorld().getName();
+ return Permissions.getPlayer(player.getUniqueId()).listEffectivePermissions(PandalibPaperPermissions.serverName, world);
+ }
+ return new HashMap<>();
+ }
+
+
+ // key is world
+ private final Cache> effectivePermissionsListCache = CacheBuilder.newBuilder()
+ .expireAfterAccess(10, TimeUnit.MINUTES)
+ .build();
+
+ @Override
+ public Set getEffectivePermissions()
+ {
+ // PlotSquared uses this method to optimize permission range (plots.limit.10 for example)
+ // MobArena uses this method when a player leave the arena
+ // LibsDisguises uses this method (and only this one) to parse all the permissions
+
+ //Log.warning("There is a plugin calling CommandSender#getEffectivePermissions(). See the stacktrace to understand the reason for that.", new Throwable());
+
+ String world = null;
+ if (sender instanceof Player player) {
+ world = player.getWorld().getName();
+ }
+
+ try {
+ return effectivePermissionsListCache.get(world, () -> {
+ // first get the superperms effective permissions (taht take isOp into accound)
+ Map perms = oldPermissible.getEffectivePermissions().stream()
+ .collect(Collectors.toMap(PermissionAttachmentInfo::getPermission, Function.identity()));
+
+ // then override them with the permissions from our permission system (that has priority, and take current world into account)
+ for (Map.Entry permE : getEffectivePermissionsOnServerInWorld().entrySet()) {
+ perms.put(permE.getKey(), new PermissionAttachmentInfo(this, permE.getKey(), null, permE.getValue()));
+ }
+
+ return new LinkedHashSet<>(perms.values());
+ });
+ } catch (ExecutionException e) {
+ Log.severe(e);
+ return oldPermissible.getEffectivePermissions();
+ }
+
+ }
+
+ @Override
+ public boolean isOp()
+ {
+ return oldPermissible.isOp();
+ }
+
+ @Override
+ public void setOp(boolean value)
+ {
+ oldPermissible.setOp(value);
+ }
+
+ @Override
+ public boolean isPermissionSet(String permission)
+ {
+ Boolean res = hasPermissionOnServerInWorld(permission);
+ if (res != null)
+ return true;
+ return oldPermissible.isPermissionSet(permission);
+ }
+
+ @Override
+ public boolean isPermissionSet(Permission permission)
+ {
+ Boolean res = hasPermissionOnServerInWorld(permission.getName());
+ if (res != null)
+ return true;
+ return oldPermissible.isPermissionSet(permission);
+ }
+
+ @Override
+ public PermissionAttachment addAttachment(Plugin plugin)
+ {
+ return oldPermissible.addAttachment(plugin);
+ }
+
+ @Override
+ public PermissionAttachment addAttachment(Plugin plugin, int ticks)
+ {
+ return oldPermissible.addAttachment(plugin, ticks);
+ }
+
+ @Override
+ public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value)
+ {
+ return oldPermissible.addAttachment(plugin, name, value);
+ }
+
+ @Override
+ public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks)
+ {
+ return oldPermissible.addAttachment(plugin, name, value, ticks);
+ }
+
+ @Override
+ public void removeAttachment(PermissionAttachment attachment)
+ {
+ oldPermissible.removeAttachment(attachment);
+ }
+
+ @Override
+ public synchronized void clearPermissions()
+ {
+ if (oldPermissible instanceof PermissibleBase)
+ ((PermissibleBase) oldPermissible).clearPermissions();
+ }
+ }
+}
diff --git a/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorVault.java b/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorVault.java
new file mode 100644
index 0000000..970d3e4
--- /dev/null
+++ b/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorVault.java
@@ -0,0 +1,255 @@
+package fr.pandacube.lib.paper.permissions;
+
+import java.util.List;
+
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.plugin.ServicePriority;
+
+import fr.pandacube.lib.permissions.PermGroup;
+import fr.pandacube.lib.permissions.Permissions;
+import fr.pandacube.lib.util.Log;
+
+public class PermissionsInjectorVault {
+
+ public static PandaVaultPermission permInstance;
+
+ public static void inject() {
+ try {
+ permInstance = new PandaVaultPermission();
+ PandaVaultChat chat = new PandaVaultChat(permInstance);
+ Bukkit.getServicesManager().register(net.milkbowl.vault.permission.Permission.class, permInstance,
+ PandalibPaperPermissions.plugin, ServicePriority.High);
+ Bukkit.getServicesManager().register(net.milkbowl.vault.chat.Chat.class, chat,
+ PandalibPaperPermissions.plugin, ServicePriority.High);
+ Log.info("Providing permissions and chat prefix/suffix through Vault API.");
+ } catch (NoClassDefFoundError e) {
+ Log.warning("Vault plugin not detected. Not using it to provide permissions and prefix/suffix." + e.getMessage());
+ }
+ }
+
+
+
+
+
+ public static class PandaVaultPermission extends net.milkbowl.vault.permission.Permission {
+
+ private PandaVaultPermission() { }
+
+ @Override
+ public String getName() {
+ return "Pandalib";
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return PandalibPaperPermissions.plugin != null && PandalibPaperPermissions.plugin.isEnabled();
+ }
+
+ @Override
+ public boolean hasSuperPermsCompat() {
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean playerHas(String world, String player, String permission) {
+ return playerHas(world, Bukkit.getOfflinePlayer(player), permission);
+ }
+
+ @Override
+ public boolean playerHas(String world, OfflinePlayer player, String permission) {
+ Boolean res = Permissions.getPlayer(player.getUniqueId()).hasPermission(permission, PandalibPaperPermissions.serverName, world);
+ if (res != null)
+ return res;
+
+ res = PandalibPaperPermissions.hasSuperPermsPermission(player, permission, p -> playerHas(world, player, p));
+ if (res != null)
+ return res;
+
+ return permission.startsWith("-");
+ }
+
+ @Override
+ public boolean playerAdd(String world, String player, String permission) {
+ return false;
+ }
+
+ @Override
+ public boolean playerRemove(String world, String player, String permission) {
+ return false;
+ }
+
+ @Override
+ public boolean groupHas(String world, String group, String permission) {
+ Boolean res = Permissions.getGroup(group).hasPermission(permission, PandalibPaperPermissions.serverName, world);
+ if (res != null)
+ return res;
+
+ res = PandalibPaperPermissions.hasSuperPermsPermission(PandalibPaperPermissions.dummyOperator(false), permission, p -> groupHas(world, group, p), null);
+ if (res != null)
+ return res;
+
+ return permission.startsWith("-");
+ }
+
+ @Override
+ public boolean groupAdd(String world, String group, String permission) {
+ return false;
+ }
+
+ @Override
+ public boolean groupRemove(String world, String group, String permission) {
+ return false;
+ }
+
+ @Deprecated
+ @Override
+ public boolean playerInGroup(String world, String player, String group) {
+ return playerInGroup(world, Bukkit.getOfflinePlayer(player), group);
+ }
+
+ @Override
+ public boolean playerInGroup(String world, OfflinePlayer player, String group) {
+ return Permissions.getPlayer(player.getUniqueId()).isInGroup(group);
+ }
+
+ @Override
+ public boolean playerAddGroup(String world, String player, String group) {
+ return false;
+ }
+
+ @Override
+ public boolean playerRemoveGroup(String world, String player, String group) {
+ return false;
+ }
+
+ @Deprecated
+ @Override
+ public String[] getPlayerGroups(String world, String player) {
+ return getPlayerGroups(world, Bukkit.getOfflinePlayer(player));
+ }
+
+ @Override
+ public String[] getPlayerGroups(String world, OfflinePlayer player) {
+ List groups = Permissions.getPlayer(player.getUniqueId()).getGroupsString();
+ return groups.toArray(new String[0]);
+ }
+
+ @Deprecated
+ @Override
+ public String getPrimaryGroup(String world, String player) {
+ return getPrimaryGroup(world, Bukkit.getOfflinePlayer(player));
+ }
+
+ @Override
+ public String getPrimaryGroup(String world, OfflinePlayer player) {
+ return Permissions.getPlayer(player.getUniqueId()).getGroupsString().stream()
+ .findFirst().orElse(null);
+ }
+
+ @Override
+ public String[] getGroups() {
+ return Permissions.getGroups().stream()
+ .map(PermGroup::getName).toArray(String[]::new);
+ }
+
+ @Override
+ public boolean hasGroupSupport() {
+ return true;
+ }
+
+ }
+
+
+ private static class PandaVaultChat extends net.milkbowl.vault.chat.Chat {
+
+ public PandaVaultChat(net.milkbowl.vault.permission.Permission perms) {
+ super(perms);
+ }
+
+ @Override
+ public String getName() {
+ return "Pandalib";
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return PandalibPaperPermissions.plugin != null && PandalibPaperPermissions.plugin.isEnabled();
+ }
+
+ @Deprecated
+ @Override
+ public String getPlayerPrefix(String world, String player) {
+ return getPlayerPrefix(world, Bukkit.getOfflinePlayer(player));
+ }
+
+ @Override
+ public String getPlayerPrefix(String world, OfflinePlayer player) {
+ return Permissions.getPlayer(player.getUniqueId()).getPrefix();
+ }
+
+ @Deprecated
+ @Override
+ public String getPlayerSuffix(String world, String player) {
+ return getPlayerSuffix(world, Bukkit.getOfflinePlayer(player));
+ }
+
+ @Override
+ public String getPlayerSuffix(String world, OfflinePlayer player) {
+ return Permissions.getPlayer(player.getUniqueId()).getSuffix();
+ }
+
+ @Override
+ public String getGroupPrefix(String world, String group) {
+ return Permissions.getGroup(group).getPrefix();
+ }
+
+ @Override
+ public String getGroupSuffix(String world, String group) {
+ return Permissions.getGroup(group).getSuffix();
+ }
+
+ @Override
+ public void setPlayerPrefix(String world, String player, String prefix) { /* unsupported */ }
+ @Override
+ public void setPlayerSuffix(String world, String player, String suffix) { /* unsupported */ }
+ @Override
+ public void setGroupPrefix(String world, String group, String prefix) { /* unsupported */ }
+ @Override
+ public void setGroupSuffix(String world, String group, String suffix) { /* unsupported */ }
+ @Override
+ public int getPlayerInfoInteger(String world, String player, String node, int defaultValue) { return defaultValue; }
+ @Override
+ public void setPlayerInfoInteger(String world, String player, String node, int value) { /* unsupported */ }
+ @Override
+ public int getGroupInfoInteger(String world, String group, String node, int defaultValue) { return defaultValue; }
+ @Override
+ public void setGroupInfoInteger(String world, String group, String node, int value) { /* unsupported */ }
+ @Override
+ public double getPlayerInfoDouble(String world, String player, String node, double defaultValue) { return defaultValue; }
+ @Override
+ public void setPlayerInfoDouble(String world, String player, String node, double value) { /* unsupported */ }
+ @Override
+ public double getGroupInfoDouble(String world, String group, String node, double defaultValue) { return defaultValue; }
+ @Override
+ public void setGroupInfoDouble(String world, String group, String node, double value) { /* unsupported */ }
+ @Override
+ public boolean getPlayerInfoBoolean(String world, String player, String node, boolean defaultValue) { return defaultValue; }
+ @Override
+ public void setPlayerInfoBoolean(String world, String player, String node, boolean value) { /* unsupported */ }
+ @Override
+ public boolean getGroupInfoBoolean(String world, String group, String node, boolean defaultValue) { return defaultValue; }
+ @Override
+ public void setGroupInfoBoolean(String world, String group, String node, boolean value) { /* unsupported */ }
+ @Override
+ public String getPlayerInfoString(String world, String player, String node, String defaultValue) { return defaultValue; }
+ @Override
+ public void setPlayerInfoString(String world, String player, String node, String value) { /* unsupported */ }
+ @Override
+ public String getGroupInfoString(String world, String group, String node, String defaultValue) { return defaultValue; }
+ @Override
+ public void setGroupInfoString(String world, String group, String node, String value) { /* unsupported */ }
+ }
+
+}
diff --git a/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorWEPIF.java b/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorWEPIF.java
new file mode 100644
index 0000000..afb3af2
--- /dev/null
+++ b/pandalib-paper-permissions/src/main/java/fr/pandacube/lib/paper/permissions/PermissionsInjectorWEPIF.java
@@ -0,0 +1,93 @@
+package fr.pandacube.lib.paper.permissions;
+
+import java.util.List;
+
+import com.sk89q.worldedit.bukkit.WorldEditPlugin;
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.ServicePriority;
+
+import fr.pandacube.lib.permissions.PermPlayer;
+import fr.pandacube.lib.permissions.Permissions;
+import fr.pandacube.lib.util.Log;
+
+public class PermissionsInjectorWEPIF {
+
+ public static PandaWEPIFPermissionsProvider permInstance;
+
+ public static void inject() {
+ try {
+ permInstance = new PandaWEPIFPermissionsProvider();
+ Bukkit.getServicesManager().register(com.sk89q.wepif.PermissionsProvider.class, permInstance,
+ PandalibPaperPermissions.plugin, ServicePriority.Highest);
+ Log.info("Providing permissions through WEPIF");
+ Plugin pl = Bukkit.getPluginManager().getPlugin("WorldEdit");
+ if (pl == null || !pl.isEnabled())
+ return;
+ ((WorldEditPlugin) pl).getPermissionsResolver().findResolver();
+ } catch (NoClassDefFoundError e) {
+ Log.warning("WorldEdit plugin not detected. Not using WEPIF to provide permissions and prefix/suffix." + e.getMessage());
+ }
+ }
+
+
+
+
+
+ public static class PandaWEPIFPermissionsProvider implements com.sk89q.wepif.PermissionsProvider {
+ private PandaWEPIFPermissionsProvider() { }
+
+ private PermPlayer getPlayer(OfflinePlayer player) {
+ return Permissions.getPlayer(player.getUniqueId());
+ }
+
+ @Override
+ public String[] getGroups(OfflinePlayer player) {
+ List groups = getPlayer(player).getGroupsString();
+ return groups.toArray(new String[0]);
+ }
+ @Deprecated
+ @Override
+ public String[] getGroups(String player) {
+ return getGroups(Bukkit.getOfflinePlayer(player));
+ }
+ @Override
+ public boolean hasPermission(OfflinePlayer player, String permission) {
+ Player p = Bukkit.getPlayer(player.getUniqueId());
+ return hasPermission(p != null ? p.getWorld().getName() : null, player, permission);
+ }
+ @Deprecated
+ @Override
+ public boolean hasPermission(String player, String permission) {
+ return hasPermission(Bukkit.getOfflinePlayer(player), permission);
+ }
+ @Override
+ public boolean hasPermission(String worldName, OfflinePlayer player, String permission) {
+ Boolean res = Permissions.getPlayer(player.getUniqueId()).hasPermission(permission, PandalibPaperPermissions.serverName, worldName);
+ if (res != null)
+ return res;
+
+ res = PandalibPaperPermissions.hasSuperPermsPermission(player, permission, p -> hasPermission(worldName, player, p));
+ if (res != null)
+ return res;
+
+ return permission.startsWith("-");
+ }
+ @Deprecated
+ @Override
+ public boolean hasPermission(String worldName, String player, String permission) {
+ return hasPermission(worldName, Bukkit.getOfflinePlayer(player), permission);
+ }
+ @Override
+ public boolean inGroup(OfflinePlayer player, String group) {
+ return getPlayer(player).isInGroup(group);
+ }
+ @Deprecated
+ @Override
+ public boolean inGroup(String player, String group) {
+ return inGroup(Bukkit.getOfflinePlayer(player), group);
+ }
+ }
+}
diff --git a/pandalib-paper/pom.xml b/pandalib-paper/pom.xml
index 75e4937..652af6c 100644
--- a/pandalib-paper/pom.xml
+++ b/pandalib-paper/pom.xml
@@ -24,7 +24,7 @@
fr.pandacube.lib
- pandalib-core
+ pandalib-chat
${project.version}
@@ -37,17 +37,31 @@
+
+
+ fr.pandacube.lib
+ pandalib-reflect
+ ${project.version}
+
+
+
+ fr.pandacube.lib
+ pandalib-util
+ ${project.version}
+
io.papermc.paper
paper-api
${paper.version}-SNAPSHOT
+ provided
io.papermc.paper
paper-mojangapi
${paper.version}-SNAPSHOT
+ provided
diff --git a/pandalib-players-permissible/pom.xml b/pandalib-players-permissible/pom.xml
index 842c621..89e8c61 100644
--- a/pandalib-players-permissible/pom.xml
+++ b/pandalib-players-permissible/pom.xml
@@ -23,7 +23,6 @@
fr.pandacube.lib
pandalib-players-standalone
${project.version}
- provided
diff --git a/pom.xml b/pom.xml
index 453f81a..6f59487 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,6 +59,9 @@
pandalib-reflect
pandalib-util
pandalib-players-permissible
+ pandalib-bungee-permissions
+ pandalib-bungee-players
+ pandalib-paper-permissions