diff --git a/bukkit/pom.xml b/bukkit/pom.xml
index e210de9a..cca49154 100644
--- a/bukkit/pom.xml
+++ b/bukkit/pom.xml
@@ -129,6 +129,14 @@
provided
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+ 2.6.1
+ provided
+
+
org.spigotmc
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java
index 06220678..168ea852 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java
@@ -34,14 +34,15 @@ import me.lucko.luckperms.bukkit.contexts.WorldCalculator;
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
import me.lucko.luckperms.bukkit.listeners.BukkitPlatformListener;
import me.lucko.luckperms.bukkit.messaging.BukkitMessagingFactory;
-import me.lucko.luckperms.bukkit.model.PermissionMapInjector;
-import me.lucko.luckperms.bukkit.model.SubscriptionMapInjector;
import me.lucko.luckperms.bukkit.model.permissible.LPPermissible;
import me.lucko.luckperms.bukkit.model.permissible.PermissibleInjector;
import me.lucko.luckperms.bukkit.model.permissible.PermissibleMonitoringInjector;
-import me.lucko.luckperms.bukkit.processors.BukkitProcessorsSetupTask;
-import me.lucko.luckperms.bukkit.processors.ChildPermissionProvider;
-import me.lucko.luckperms.bukkit.processors.DefaultsProvider;
+import me.lucko.luckperms.bukkit.model.server.InjectorDefaultsMap;
+import me.lucko.luckperms.bukkit.model.server.InjectorPermissionMap;
+import me.lucko.luckperms.bukkit.model.server.InjectorSubscriptionMap;
+import me.lucko.luckperms.bukkit.model.server.LPDefaultsMap;
+import me.lucko.luckperms.bukkit.model.server.LPPermissionMap;
+import me.lucko.luckperms.bukkit.model.server.LPSubscriptionMap;
import me.lucko.luckperms.bukkit.vault.VaultHookManager;
import me.lucko.luckperms.common.actionlog.LogDispatcher;
import me.lucko.luckperms.common.api.ApiRegistrationUtil;
@@ -86,6 +87,7 @@ import me.lucko.luckperms.common.verbose.VerboseHandler;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
+import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicePriority;
@@ -123,8 +125,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private LuckPermsApiProvider apiProvider;
private EventFactory eventFactory;
private Logger log;
- private DefaultsProvider defaultsProvider;
- private ChildPermissionProvider childPermissionProvider;
+ private LPSubscriptionMap subscriptionMap;
+ private LPPermissionMap permissionMap;
+ private LPDefaultsMap defaultPermissionMap;
private LocaleManager localeManager;
private PluginClassLoader pluginClassLoader;
private DependencyManager dependencyManager;
@@ -197,10 +200,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
Set storageTypes = storageFactory.getRequiredTypes(StorageType.H2);
this.dependencyManager.loadStorageDependencies(storageTypes);
- // init the Bukkit model providers
- this.defaultsProvider = new DefaultsProvider();
- this.childPermissionProvider = new ChildPermissionProvider();
-
// register events
BukkitConnectionListener connectionListener = new BukkitConnectionListener(this);
getServer().getPluginManager().registerEvents(connectionListener, this);
@@ -246,21 +245,19 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
this.contextManager.registerStaticCalculator(new LuckPermsCalculator(getConfiguration()));
// inject our own custom permission maps
- SubscriptionMapInjector subscriptionMapInjector = new SubscriptionMapInjector(this);
- subscriptionMapInjector.run();
+ Runnable[] injectors = new Runnable[]{
+ new InjectorSubscriptionMap(this),
+ new InjectorPermissionMap(this),
+ new InjectorDefaultsMap(this)
+ };
- PermissionMapInjector permissionMapInjector = new PermissionMapInjector(this);
- permissionMapInjector.run();
+ for (Runnable injector : injectors) {
+ injector.run();
- // setup the bukkit processors
- BukkitProcessorsSetupTask bukkitProcessorsSetupTask = new BukkitProcessorsSetupTask(this);
- bukkitProcessorsSetupTask.run();
-
- // schedule another injection after all plugins have loaded - the entire pluginmanager instance
- // is replaced by some plugins :(
- this.scheduler.asyncLater(subscriptionMapInjector, 1L);
- this.scheduler.asyncLater(permissionMapInjector, 1L);
- this.scheduler.syncLater(bukkitProcessorsSetupTask, 1L);
+ // schedule another injection after all plugins have loaded
+ // the entire pluginmanager instance is replaced by some plugins :(
+ this.scheduler.asyncLater(injector, 1L);
+ }
// inject verbose handlers into internal bukkit objects
new PermissibleMonitoringInjector(this).run();
@@ -305,7 +302,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
PermissionDefault permDefault = getConfiguration().get(ConfigKeys.COMMANDS_ALLOW_OP) ? PermissionDefault.OP : PermissionDefault.FALSE;
for (CommandPermission p : CommandPermission.values()) {
- pm.addPermission(new org.bukkit.permissions.Permission(p.getPermission(), permDefault));
+ pm.addPermission(new Permission(p.getPermission(), permDefault));
}
} catch (Exception e) {
// this throws an exception if the plugin is /reloaded, grr
@@ -351,7 +348,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
// Switch back to the fallback executor, the bukkit one won't allow new tasks
this.scheduler.setUseFallback(true);
- this.defaultsProvider.close();
this.permissionVault.shutdown();
this.verboseHandler.shutdown();
@@ -375,8 +371,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
// uninject custom maps
- SubscriptionMapInjector.uninject();
- PermissionMapInjector.uninject();
+ InjectorSubscriptionMap.uninject();
+ InjectorPermissionMap.uninject();
+ InjectorDefaultsMap.uninject();
getLog().info("Closing storage...");
this.storage.shutdown();
@@ -447,6 +444,30 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return configFile;
}
+ public LPSubscriptionMap getSubscriptionMap() {
+ return this.subscriptionMap;
+ }
+
+ public void setSubscriptionMap(LPSubscriptionMap subscriptionMap) {
+ this.subscriptionMap = subscriptionMap;
+ }
+
+ public LPPermissionMap getPermissionMap() {
+ return this.permissionMap;
+ }
+
+ public void setPermissionMap(LPPermissionMap permissionMap) {
+ this.permissionMap = permissionMap;
+ }
+
+ public LPDefaultsMap getDefaultPermissionMap() {
+ return this.defaultPermissionMap;
+ }
+
+ public void setDefaultPermissionMap(LPDefaultsMap defaultPermissionMap) {
+ this.defaultPermissionMap = defaultPermissionMap;
+ }
+
@Override
public Optional getMessagingService() {
return Optional.ofNullable(this.messagingService);
@@ -627,14 +648,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return this.log;
}
- public DefaultsProvider getDefaultsProvider() {
- return this.defaultsProvider;
- }
-
- public ChildPermissionProvider getChildPermissionProvider() {
- return this.childPermissionProvider;
- }
-
@Override
public LocaleManager getLocaleManager() {
return this.localeManager;
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java
index 4f1704d7..2728c650 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java
@@ -55,7 +55,7 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
processors.add(new MapProcessor());
if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_CHILD_PERMISSIONS)) {
- processors.add(new ChildProcessor(this.plugin.getChildPermissionProvider()));
+ processors.add(new ChildProcessor(this.plugin));
}
if (this.plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) {
@@ -67,7 +67,7 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
}
if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_DEFAULT_PERMISSIONS) && metadata.getHolderType() == HolderType.USER) {
- processors.add(new DefaultsProcessor(contexts.isOp(), this.plugin.getDefaultsProvider()));
+ processors.add(new DefaultsProcessor(this.plugin, contexts.isOp()));
}
return registerCalculator(new PermissionCalculator(this.plugin, metadata, processors.build()));
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/LPPermissionMap.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/LPPermissionMap.java
deleted file mode 100644
index 71df573d..00000000
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/LPPermissionMap.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package me.lucko.luckperms.bukkit.model;
-
-import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-import me.lucko.luckperms.common.treeview.PermissionVault;
-
-import org.bukkit.permissions.Permission;
-import org.bukkit.plugin.PluginManager;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A replacement map for the 'permissions' instance in Bukkit's SimplePluginManager.
- *
- * This instance allows LuckPerms to intercept calls to
- * {@link PluginManager#addPermission(Permission)} and record permissions in the
- * {@link PermissionVault}.
- *
- * Injected by {@link PermissionMapInjector}.
- */
-public class LPPermissionMap extends HashMap {
- final LuckPermsPlugin plugin;
-
- public LPPermissionMap(LuckPermsPlugin plugin, Map existingData) {
- this.plugin = plugin;
- putAll(existingData);
- }
-
- @Override
- public Permission put(String key, Permission value) {
- this.plugin.getPermissionVault().offer(key);
- return super.put(key, value);
- }
-
- @Override
- public void putAll(Map extends String, ? extends Permission> m) {
- this.plugin.getPermissionVault().offerAll(m.keySet());
- super.putAll(m);
- }
-
- @Override
- public Permission putIfAbsent(String key, Permission value) {
- this.plugin.getPermissionVault().offer(key);
- return super.putIfAbsent(key, value);
- }
-
-}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/dummy/DummyPermissible.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/dummy/DummyPermissible.java
deleted file mode 100644
index 8135b607..00000000
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/dummy/DummyPermissible.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package me.lucko.luckperms.bukkit.model.dummy;
-
-import org.bukkit.permissions.Permissible;
-import org.bukkit.permissions.Permission;
-import org.bukkit.permissions.PermissionAttachment;
-import org.bukkit.permissions.PermissionAttachmentInfo;
-import org.bukkit.plugin.Plugin;
-
-import java.util.Collections;
-import java.util.Set;
-
-public class DummyPermissible implements Permissible {
- private final Runnable onRefresh;
-
- public DummyPermissible(Runnable onRefresh) {
- this.onRefresh = onRefresh;
- }
-
- @Override
- public void recalculatePermissions() {
- this.onRefresh.run();
- }
-
- @Override public Set getEffectivePermissions() { return Collections.emptySet(); }
- @Override public boolean isPermissionSet(String name) { return false; }
- @Override public boolean isPermissionSet(Permission perm) { return false; }
- @Override public boolean hasPermission(String name) { return false; }
- @Override public boolean hasPermission(Permission perm) { return false; }
- @Override public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { return null; }
- @Override public PermissionAttachment addAttachment(Plugin plugin) { return null; }
- @Override public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { return null; }
- @Override public PermissionAttachment addAttachment(Plugin plugin, int ticks) { return null; }
- @Override public void removeAttachment(PermissionAttachment attachment) {}
- @Override public boolean isOp() { return false; }
- @Override public void setOp(boolean value) {}
-
-}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorDefaultsMap.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorDefaultsMap.java
new file mode 100644
index 00000000..ad29c7c6
--- /dev/null
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorDefaultsMap.java
@@ -0,0 +1,119 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.bukkit.model.server;
+
+import me.lucko.luckperms.bukkit.LPBukkitPlugin;
+
+import org.bukkit.Bukkit;
+import org.bukkit.permissions.Permission;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.SimplePluginManager;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Injects a {@link LPDefaultsMap} info the {@link PluginManager}.
+ */
+public class InjectorDefaultsMap implements Runnable {
+ private static final Field DEFAULT_PERMISSIONS_FIELD;
+
+ static {
+ Field permissionsField = null;
+ try {
+ permissionsField = SimplePluginManager.class.getDeclaredField("defaultPerms");
+ permissionsField.setAccessible(true);
+ } catch (Exception e) {
+ // ignore
+ }
+ DEFAULT_PERMISSIONS_FIELD = permissionsField;
+ }
+
+ private final LPBukkitPlugin plugin;
+
+ public InjectorDefaultsMap(LPBukkitPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void run() {
+ try {
+ LPDefaultsMap ret = inject();
+ if (ret != null) {
+ this.plugin.setDefaultPermissionMap(ret);
+ }
+ } catch (Exception e) {
+ this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Default Permission map.");
+ e.printStackTrace();
+ }
+ }
+
+ private LPDefaultsMap inject() throws Exception {
+ Objects.requireNonNull(DEFAULT_PERMISSIONS_FIELD, "DEFAULT_PERMISSIONS_FIELD");
+ PluginManager pluginManager = this.plugin.getServer().getPluginManager();
+
+ if (!(pluginManager instanceof SimplePluginManager)) {
+ this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
+ this.plugin.getLog().severe("Unable to inject LuckPerms Default Permission map.");
+ return null;
+ }
+
+ Object map = DEFAULT_PERMISSIONS_FIELD.get(pluginManager);
+ if (map instanceof LPDefaultsMap && ((LPDefaultsMap) map).plugin == this.plugin) {
+ return null;
+ }
+
+ //noinspection unchecked
+ Map> castedMap = (Map>) map;
+
+ // make a new map & inject it
+ LPDefaultsMap newMap = new LPDefaultsMap(this.plugin, castedMap);
+ DEFAULT_PERMISSIONS_FIELD.set(pluginManager, newMap);
+ return newMap;
+ }
+
+ public static void uninject() {
+ try {
+ Objects.requireNonNull(DEFAULT_PERMISSIONS_FIELD, "DEFAULT_PERMISSIONS_FIELD");
+
+ PluginManager pluginManager = Bukkit.getServer().getPluginManager();
+ if (!(pluginManager instanceof SimplePluginManager)) {
+ return;
+ }
+
+ Object map = DEFAULT_PERMISSIONS_FIELD.get(pluginManager);
+ if (map instanceof LPDefaultsMap) {
+ LPDefaultsMap lpMap = (LPDefaultsMap) map;
+ DEFAULT_PERMISSIONS_FIELD.set(pluginManager, new HashMap<>(lpMap));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/PermissionMapInjector.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorPermissionMap.java
similarity index 89%
rename from bukkit/src/main/java/me/lucko/luckperms/bukkit/model/PermissionMapInjector.java
rename to bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorPermissionMap.java
index 505611f0..7b1959de 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/PermissionMapInjector.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorPermissionMap.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.bukkit.model;
+package me.lucko.luckperms.bukkit.model.server;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
@@ -40,7 +40,7 @@ import java.util.Objects;
/**
* Injects a {@link LPPermissionMap} into the {@link PluginManager}.
*/
-public class PermissionMapInjector implements Runnable {
+public class InjectorPermissionMap implements Runnable {
private static final Field PERMISSIONS_FIELD;
static {
@@ -56,43 +56,45 @@ public class PermissionMapInjector implements Runnable {
private final LPBukkitPlugin plugin;
- public PermissionMapInjector(LPBukkitPlugin plugin) {
+ public InjectorPermissionMap(LPBukkitPlugin plugin) {
this.plugin = plugin;
}
@Override
public void run() {
try {
- inject();
+ LPPermissionMap ret = inject();
+ if (ret != null) {
+ this.plugin.setPermissionMap(ret);
+ }
} catch (Exception e) {
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission map.");
e.printStackTrace();
}
}
- private void inject() throws Exception {
+ private LPPermissionMap inject() throws Exception {
Objects.requireNonNull(PERMISSIONS_FIELD, "PERMISSIONS_FIELD");
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
if (!(pluginManager instanceof SimplePluginManager)) {
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
this.plugin.getLog().severe("Unable to inject LuckPerms Permission map.");
- return;
+ return null;
}
Object map = PERMISSIONS_FIELD.get(pluginManager);
if (map instanceof LPPermissionMap && ((LPPermissionMap) map).plugin == this.plugin) {
- return;
+ return null;
}
//noinspection unchecked
Map castedMap = (Map) map;
- // make a new map
+ // make a new map & inject it
LPPermissionMap newMap = new LPPermissionMap(this.plugin, castedMap);
-
- // inject it
PERMISSIONS_FIELD.set(pluginManager, newMap);
+ return newMap;
}
public static void uninject() {
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/SubscriptionMapInjector.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorSubscriptionMap.java
similarity index 88%
rename from bukkit/src/main/java/me/lucko/luckperms/bukkit/model/SubscriptionMapInjector.java
rename to bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorSubscriptionMap.java
index dde49971..5493ffc2 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/SubscriptionMapInjector.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/InjectorSubscriptionMap.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.bukkit.model;
+package me.lucko.luckperms.bukkit.model.server;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
@@ -39,7 +39,7 @@ import java.util.Objects;
/**
* Injects a {@link LPSubscriptionMap} into the {@link PluginManager}.
*/
-public class SubscriptionMapInjector implements Runnable {
+public class InjectorSubscriptionMap implements Runnable {
private static final Field PERM_SUBS_FIELD;
static {
@@ -55,34 +55,37 @@ public class SubscriptionMapInjector implements Runnable {
private final LPBukkitPlugin plugin;
- public SubscriptionMapInjector(LPBukkitPlugin plugin) {
+ public InjectorSubscriptionMap(LPBukkitPlugin plugin) {
this.plugin = plugin;
}
@Override
public void run() {
try {
- inject();
+ LPSubscriptionMap ret = inject();
+ if (ret != null) {
+ this.plugin.setSubscriptionMap(ret);
+ }
} catch (Exception e) {
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission Subscription map.");
e.printStackTrace();
}
}
- private void inject() throws Exception {
+ private LPSubscriptionMap inject() throws Exception {
Objects.requireNonNull(PERM_SUBS_FIELD, "PERM_SUBS_FIELD");
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
if (!(pluginManager instanceof SimplePluginManager)) {
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
this.plugin.getLog().severe("Unable to inject LuckPerms Permission Subscription map.");
- return;
+ return null;
}
Object map = PERM_SUBS_FIELD.get(pluginManager);
if (map instanceof LPSubscriptionMap) {
if (((LPSubscriptionMap) map).plugin == this.plugin) {
- return;
+ return null;
}
map = ((LPSubscriptionMap) map).detach();
@@ -91,11 +94,10 @@ public class SubscriptionMapInjector implements Runnable {
//noinspection unchecked
Map> castedMap = (Map>) map;
- // make a new subscription map
+ // make a new subscription map & inject it
LPSubscriptionMap newMap = new LPSubscriptionMap(this.plugin, castedMap);
-
- // inject it
PERM_SUBS_FIELD.set(pluginManager, newMap);
+ return newMap;
}
public static void uninject() {
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPDefaultsMap.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPDefaultsMap.java
new file mode 100644
index 00000000..c434bb12
--- /dev/null
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPDefaultsMap.java
@@ -0,0 +1,197 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.bukkit.model.server;
+
+import com.google.common.collect.ForwardingSet;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+import me.lucko.luckperms.api.Tristate;
+import me.lucko.luckperms.bukkit.LPBukkitPlugin;
+
+import org.bukkit.permissions.Permission;
+import org.bukkit.plugin.PluginManager;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A replacement map for the 'defaultPerms' instance in Bukkit's SimplePluginManager.
+ *
+ * This instance allows LuckPerms to intercept calls to
+ * {@link PluginManager#addPermission(Permission)}, specifically regarding
+ * the default nature of the permission.
+ *
+ * Injected by {@link InjectorDefaultsMap}.
+ */
+public class LPDefaultsMap implements Map> {
+ // keyset for all instances
+ private static final Set KEY_SET = ImmutableSet.of(Boolean.TRUE, Boolean.FALSE);
+
+ // the plugin
+ final LPBukkitPlugin plugin;
+
+ // the two values in the map
+ private final Set opSet = new DefaultPermissionSet(true);
+ private final Set nonOpSet = new DefaultPermissionSet(false);
+
+ // fully resolved defaults (accounts for child permissions too)
+ private Map resolvedOpDefaults = ImmutableMap.of();
+ private Map resolvedNonOpDefaults = ImmutableMap.of();
+
+ // #values and #entrySet results - both immutable
+ private final Collection> values = ImmutableList.of(this.opSet, this.nonOpSet);
+ private final Set>> entrySet = ImmutableSet.of(
+ Maps.immutableEntry(Boolean.TRUE, this.opSet),
+ Maps.immutableEntry(Boolean.FALSE, this.nonOpSet)
+ );
+
+ public LPDefaultsMap(LPBukkitPlugin plugin, Map> existingData) {
+ this.plugin = plugin;
+ this.opSet.addAll(existingData.getOrDefault(Boolean.TRUE, Collections.emptySet()));
+ this.nonOpSet.addAll(existingData.getOrDefault(Boolean.FALSE, Collections.emptySet()));
+ refreshOp();
+ refreshNonOp();
+ }
+
+ public Set getOpPermissions() {
+ return this.opSet;
+ }
+
+ public Set getNonOpPermissions() {
+ return this.nonOpSet;
+ }
+
+ /**
+ * Queries whether a given permission should be granted by default.
+ *
+ * @param permission the permission to query
+ * @param isOp if the player is op
+ * @return a tristate result
+ */
+ public Tristate lookupDefaultPermission(String permission, boolean isOp) {
+ Map map = isOp ? this.resolvedOpDefaults : this.resolvedNonOpDefaults;
+ return Tristate.fromNullableBoolean(map.get(permission));
+ }
+
+ private void refresh(boolean op) {
+ if (op) {
+ refreshOp();
+ } else {
+ refreshNonOp();
+ }
+ }
+
+ /**
+ * Refreshes the op data in this provider.
+ */
+ private void refreshOp() {
+ Map builder = new HashMap<>();
+ for (Permission perm : getOpPermissions()) {
+ String name = perm.getName().toLowerCase();
+ builder.put(name, true);
+ for (Map.Entry child : this.plugin.getPermissionMap().getChildPermissions(name, true).entrySet()) {
+ builder.putIfAbsent(child.getKey(), child.getValue());
+ }
+ }
+ this.resolvedOpDefaults = ImmutableMap.copyOf(builder);
+ }
+
+ /**
+ * Refreshes the non op data in this provider.
+ */
+ private void refreshNonOp() {
+ Map builder = new HashMap<>();
+ for (Permission perm : getNonOpPermissions()) {
+ String name = perm.getName().toLowerCase();
+ builder.put(name, true);
+ for (Map.Entry child : this.plugin.getPermissionMap().getChildPermissions(name, true).entrySet()) {
+ builder.putIfAbsent(child.getKey(), child.getValue());
+ }
+ }
+ this.resolvedNonOpDefaults = ImmutableMap.copyOf(builder);
+ }
+
+ @Override
+ public Set get(Object key) {
+ boolean b = (boolean) key;
+ return b ? this.opSet : this.nonOpSet;
+ }
+
+ // return wrappers around this map impl
+ @Nonnull @Override public Collection> values() { return this.values; }
+ @Nonnull @Override public Set>> entrySet() { return this.entrySet; }
+ @Nonnull @Override public Set keySet() { return KEY_SET; }
+
+ // return accurate results for the Map spec
+ @Override public int size() { return 2; }
+ @Override public boolean isEmpty() { return false; }
+ @Override public boolean containsKey(Object key) { return key instanceof Boolean; }
+ @Override public boolean containsValue(Object value) { return value == this.opSet || value == this.nonOpSet; }
+
+ // throw unsupported operation exceptions
+ @Override public Set put(Boolean key, Set value) { throw new UnsupportedOperationException(); }
+ @Override public Set remove(Object key) { throw new UnsupportedOperationException(); }
+ @Override public void putAll(@Nonnull Map extends Boolean, ? extends Set> m) { throw new UnsupportedOperationException(); }
+ @Override public void clear() { throw new UnsupportedOperationException(); }
+
+ private final class DefaultPermissionSet extends ForwardingSet {
+ private final Set delegate = ConcurrentHashMap.newKeySet();
+ private final boolean op;
+
+ private DefaultPermissionSet(boolean op) {
+ this.op = op;
+ }
+
+ @Override
+ protected Set delegate() {
+ return this.delegate;
+ }
+
+ @Override
+ public boolean add(@Nonnull Permission element) {
+ boolean ret = super.add(element);
+ refresh(this.op);
+ return ret;
+ }
+
+ @Override
+ public boolean addAll(@Nonnull Collection extends Permission> collection) {
+ boolean ret = super.addAll(collection);
+ refresh(this.op);
+ return ret;
+ }
+ }
+
+}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPPermissionMap.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPPermissionMap.java
new file mode 100644
index 00000000..3998c94f
--- /dev/null
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPPermissionMap.java
@@ -0,0 +1,155 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.bukkit.model.server;
+
+import com.github.benmanes.caffeine.cache.CacheLoader;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import com.google.common.collect.ForwardingMap;
+import com.google.common.collect.ImmutableMap;
+
+import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
+import me.lucko.luckperms.common.treeview.PermissionVault;
+
+import org.bukkit.permissions.Permission;
+import org.bukkit.plugin.PluginManager;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+/**
+ * A replacement map for the 'permissions' instance in Bukkit's SimplePluginManager.
+ *
+ * This instance allows LuckPerms to intercept calls to
+ * {@link PluginManager#addPermission(Permission)} and record permissions in the
+ * {@link PermissionVault}.
+ *
+ * It also allows us to pre-determine child permission relationships.
+ *
+ * Injected by {@link InjectorPermissionMap}.
+ */
+public class LPPermissionMap extends ForwardingMap {
+
+ // Uses perm.getName().toLowerCase(java.util.Locale.ENGLISH); to determine the key
+ private final Map delegate = new ConcurrentHashMap<>();
+
+ // cache from permission --> children
+ private final LoadingCache> trueChildPermissions = Caffeine.newBuilder()
+ .build(new ChildPermissionResolver(true));
+
+ private final LoadingCache> falseChildPermissions = Caffeine.newBuilder()
+ .build(new ChildPermissionResolver(false));
+
+ /**
+ * The plugin instance
+ */
+ final LuckPermsPlugin plugin;
+
+ public LPPermissionMap(LuckPermsPlugin plugin, Map existingData) {
+ this.plugin = plugin;
+ putAll(existingData);
+ }
+
+ public Map getChildPermissions(String permission, boolean value) {
+ return value ? this.trueChildPermissions.get(permission) : this.falseChildPermissions.get(permission);
+ }
+
+ private void update() {
+ this.trueChildPermissions.invalidateAll();
+ this.falseChildPermissions.invalidateAll();
+ }
+
+ @Override
+ protected Map delegate() {
+ return this.delegate;
+ }
+
+ @Override
+ public Permission put(@Nonnull String key, @Nonnull Permission value) {
+ this.plugin.getPermissionVault().offer(key);
+ Permission ret = super.put(key, value);
+ update();
+ return ret;
+ }
+
+ @Override
+ public void putAll(@Nonnull Map extends String, ? extends Permission> m) {
+ this.plugin.getPermissionVault().offerAll(m.keySet());
+ super.putAll(m);
+ update();
+ }
+
+ @Override
+ public Permission putIfAbsent(String key, Permission value) {
+ this.plugin.getPermissionVault().offer(key);
+ Permission ret = super.putIfAbsent(key, value);
+ update();
+ return ret;
+ }
+
+ private final class ChildPermissionResolver implements CacheLoader> {
+ private final boolean value;
+
+ private ChildPermissionResolver(boolean value) {
+ this.value = value;
+ }
+
+ @CheckForNull
+ @Override
+ public Map load(@Nonnull String key) {
+ Map children = new HashMap<>();
+ resolveChildren(children, Collections.singletonMap(key, this.value), false);
+ children.remove(key, this.value);
+ return ImmutableMap.copyOf(children);
+ }
+ }
+
+ private void resolveChildren(Map accumulator, Map children, boolean invert) {
+ // iterate through the current known children.
+ // the first time this method is called for a given permission, the children map will contain only the permission itself.
+ for (Map.Entry e : children.entrySet()) {
+ if (accumulator.containsKey(e.getKey())) {
+ continue; // Prevent infinite loops
+ }
+
+ // xor the value using the parent (bukkit logic, not mine)
+ boolean value = e.getValue() ^ invert;
+ accumulator.put(e.getKey().toLowerCase(), value);
+
+ // lookup any deeper children & resolve if present
+ Permission perm = this.delegate.get(e.getKey());
+ if (perm != null) {
+ resolveChildren(accumulator, perm.getChildren(), !value);
+ }
+ }
+ }
+
+}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/LPSubscriptionMap.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPSubscriptionMap.java
similarity index 99%
rename from bukkit/src/main/java/me/lucko/luckperms/bukkit/model/LPSubscriptionMap.java
rename to bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPSubscriptionMap.java
index 1a86993e..64366f16 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/LPSubscriptionMap.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/model/server/LPSubscriptionMap.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.bukkit.model;
+package me.lucko.luckperms.bukkit.model.server;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -66,7 +66,7 @@ import javax.annotation.Nonnull;
*
* This class implements option 2 above. It is preferred because it is faster & uses less memory
*
- * Injected by {@link SubscriptionMapInjector}.
+ * Injected by {@link InjectorSubscriptionMap}.
*/
public class LPSubscriptionMap extends HashMap> {
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/BukkitProcessorsSetupTask.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/BukkitProcessorsSetupTask.java
deleted file mode 100644
index 3292be1e..00000000
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/BukkitProcessorsSetupTask.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package me.lucko.luckperms.bukkit.processors;
-
-import me.lucko.luckperms.bukkit.LPBukkitPlugin;
-
-/**
- * Performs the initial setup for Bukkit permission processors
- */
-public class BukkitProcessorsSetupTask implements Runnable {
- private final LPBukkitPlugin plugin;
-
- public BukkitProcessorsSetupTask(LPBukkitPlugin plugin) {
- this.plugin = plugin;
- }
-
- @Override
- public void run() {
- this.plugin.getDefaultsProvider().refresh();
- this.plugin.getChildPermissionProvider().setup();
- }
-}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/ChildPermissionProvider.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/ChildPermissionProvider.java
deleted file mode 100644
index 53916154..00000000
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/ChildPermissionProvider.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package me.lucko.luckperms.bukkit.processors;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
-import org.bukkit.Bukkit;
-import org.bukkit.permissions.Permission;
-import org.bukkit.plugin.PluginManager;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Holds child permissions registered on the platform.
- *
- * The data stored in this class is pulled from the data in {@link PluginManager#getPermissions()}.
- *
- * The former method is not thread safe, so we populate this class when the server starts to get all of the data
- * in a form which is easily queryable & thread safe.
- *
- * The data is resolved early, so the represented child permissions are a "deep" lookup of permissions.
- */
-public class ChildPermissionProvider {
-
- // in the format: permission+value ===> children (a map of child permissions)
- private ImmutableMap, ImmutableMap> permissions = ImmutableMap.of();
-
- public void setup() {
- ImmutableMap.Builder, ImmutableMap> permissions = ImmutableMap.builder();
-
- // iterate all permissions registered on the platform & resolve.
- for (Permission permission : Bukkit.getServer().getPluginManager().getPermissions()) {
- resolve(permissions, permission, true);
- resolve(permissions, permission, false);
- }
-
- this.permissions = permissions.build();
- }
-
- private static void resolve(ImmutableMap.Builder, ImmutableMap> accumulator, Permission permission, boolean value) {
-
- // accumulator for the child permissions being looked up
- Map children = new HashMap<>();
-
- // resolve children for the permission, so pass a map containing just the permission being looked up.
- resolveChildren(children, Collections.singletonMap(permission.getName(), value), false);
-
- // remove self
- children.remove(permission.getName(), value);
-
- // only register the children if there are any.
- if (!children.isEmpty()) {
- accumulator.put(Maps.immutableEntry(permission.getName().toLowerCase(), value), ImmutableMap.copyOf(children));
- }
- }
-
- private static void resolveChildren(Map accumulator, Map children, boolean invert) {
- // iterate through the current known children.
- // the first time this method is called for a given permission, the children map will contain only the permission itself.
- for (Map.Entry e : children.entrySet()) {
- if (accumulator.containsKey(e.getKey())) {
- continue; // Prevent infinite loops
- }
-
- // xor the value using the parent (bukkit logic, not mine)
- boolean value = e.getValue() ^ invert;
- accumulator.put(e.getKey().toLowerCase(), value);
-
- // lookup any deeper children & resolve if present
- Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
- if (perm != null) {
- resolveChildren(accumulator, perm.getChildren(), !value);
- }
- }
- }
-
- public ImmutableMap, ImmutableMap> getPermissions() {
- return this.permissions;
- }
-
-}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/ChildProcessor.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/ChildProcessor.java
index 7a29d356..147e3312 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/ChildProcessor.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/ChildProcessor.java
@@ -25,9 +25,8 @@
package me.lucko.luckperms.bukkit.processors;
-import com.google.common.collect.Maps;
-
import me.lucko.luckperms.api.Tristate;
+import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.processors.AbstractPermissionProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
@@ -39,11 +38,11 @@ import java.util.concurrent.ConcurrentHashMap;
* Permission Processor for Bukkits "child" permission system.
*/
public class ChildProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
- private final ChildPermissionProvider provider;
+ private final LPBukkitPlugin plugin;
private Map childPermissions = Collections.emptyMap();
- public ChildProcessor(ChildPermissionProvider provider) {
- this.provider = provider;
+ public ChildProcessor(LPBukkitPlugin plugin) {
+ this.plugin = plugin;
}
@Override
@@ -55,7 +54,7 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi
public void refresh() {
Map builder = new ConcurrentHashMap<>();
for (Map.Entry e : this.sourceMap.entrySet()) {
- Map children = this.provider.getPermissions().get(Maps.immutableEntry(e.getKey(), e.getValue()));
+ Map children = this.plugin.getPermissionMap().getChildPermissions(e.getKey(), e.getValue());
if (children != null) {
builder.putAll(children);
}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/DefaultsProcessor.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/DefaultsProcessor.java
index 818d13c5..49fee5d1 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/DefaultsProcessor.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/DefaultsProcessor.java
@@ -26,31 +26,31 @@
package me.lucko.luckperms.bukkit.processors;
import me.lucko.luckperms.api.Tristate;
+import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.processors.PermissionProcessor;
-import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
/**
* Permission Processor for Bukkits "default" permission system.
*/
public class DefaultsProcessor implements PermissionProcessor {
+ private final LPBukkitPlugin plugin;
private final boolean isOp;
- private final DefaultsProvider defaultsProvider;
- public DefaultsProcessor(boolean isOp, DefaultsProvider defaultsProvider) {
+ public DefaultsProcessor(LPBukkitPlugin plugin, boolean isOp) {
+ this.plugin = plugin;
this.isOp = isOp;
- this.defaultsProvider = defaultsProvider;
}
@Override
public Tristate hasPermission(String permission) {
- Tristate t = this.defaultsProvider.lookup(permission, this.isOp);
+ Tristate t = this.plugin.getDefaultPermissionMap().lookupDefaultPermission(permission, this.isOp);
if (t != Tristate.UNDEFINED) {
return t;
}
- Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
+ Permission defPerm = this.plugin.getPermissionMap().get(permission);
return defPerm == null ? Tristate.UNDEFINED : Tristate.fromBoolean(defPerm.getDefault().getValue(this.isOp));
}
}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/DefaultsProvider.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/DefaultsProvider.java
deleted file mode 100644
index 722bdc5a..00000000
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/processors/DefaultsProvider.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package me.lucko.luckperms.bukkit.processors;
-
-import com.google.common.collect.ImmutableMap;
-
-import me.lucko.luckperms.api.Tristate;
-import me.lucko.luckperms.bukkit.model.dummy.DummyPermissible;
-
-import org.bukkit.Bukkit;
-import org.bukkit.permissions.Permission;
-import org.bukkit.plugin.PluginManager;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Holds default permissions registered on the platform.
- *
- * The data stored in this class is pulled from the data in {@link PluginManager#getDefaultPermissions(boolean)}.
- *
- * The former method is not thread safe, so we populate this class when the server starts to get all of the data
- * in a form which is easily queryable & thread safe.
- *
- * The {@link DummyPermissible}s are registered with Bukkit, so we can listen for any
- * changes to default permissions.
- */
-public class DefaultsProvider {
-
- // defaults for opped players
- private Map opDefaults = ImmutableMap.of();
- private final DummyPermissible opDummy = new DummyPermissible(this::refreshOp);
-
- // defaults for non-opped players
- private Map nonOpDefaults = ImmutableMap.of();
- private final DummyPermissible nonOpDummy = new DummyPermissible(this::refreshNonOp);
-
- /**
- * Refreshes the data in this provider.
- */
- public void refresh() {
- refreshOp();
- refreshNonOp();
- }
-
- /**
- * Queries whether a given permission should be granted by default.
- *
- * @param permission the permission to query
- * @param isOp if the player is op
- * @return a tristate result
- */
- public Tristate lookup(String permission, boolean isOp) {
- Map map = isOp ? this.opDefaults : this.nonOpDefaults;
- return Tristate.fromNullableBoolean(map.get(permission));
- }
-
- /**
- * Refreshes the op data in this provider.
- */
- private void refreshOp() {
- unregisterDefaults(this.opDefaults, this.opDummy, true);
-
- Map builder = new HashMap<>();
- calculateDefaults(builder, this.opDummy, true);
-
- this.opDefaults = ImmutableMap.copyOf(builder);
- }
-
- /**
- * Refreshes the non op data in this provider.
- */
- private void refreshNonOp() {
- unregisterDefaults(this.nonOpDefaults, this.nonOpDummy, false);
-
- Map builder = new HashMap<>();
- calculateDefaults(builder, this.nonOpDummy, false);
-
- this.nonOpDefaults = ImmutableMap.copyOf(builder);
- }
-
- /**
- * Unregisters the dummy permissibles with Bukkit.
- */
- public void close() {
- unregisterDefaults(this.opDefaults, this.opDummy, true);
- unregisterDefaults(this.nonOpDefaults, this.nonOpDummy, false);
- }
-
- private static PluginManager pm() {
- return Bukkit.getServer().getPluginManager();
- }
-
- /**
- * Unregisters defaults for a given permissible.
- *
- * @param map the map of current defaults
- * @param p the permissible
- */
- private static void unregisterDefaults(Map map, DummyPermissible p, boolean op) {
- Set perms = map.keySet();
-
- for (String name : perms) {
- pm().unsubscribeFromPermission(name, p);
- }
-
- pm().unsubscribeFromDefaultPerms(op, p);
- }
-
- private static void calculateDefaults(Map map, DummyPermissible p, boolean op) {
- pm().subscribeToDefaultPerms(op, p);
-
- Set defaults = pm().getDefaultPermissions(op);
- for (Permission perm : defaults) {
- String name = perm.getName().toLowerCase();
-
- map.put(name, true);
- pm().subscribeToPermission(name, p);
-
- // register defaults for any children too
- calculateChildPermissions(map, p, perm.getChildren(), false);
- }
- }
-
- private static void calculateChildPermissions(Map accumulator, DummyPermissible p, Map children, boolean invert) {
- for (Map.Entry e : children.entrySet()) {
- if (accumulator.containsKey(e.getKey())) {
- continue; // Prevent infinite loops
- }
-
- // xor the value using the parent (bukkit logic, not mine)
- boolean value = e.getValue() ^ invert;
-
- accumulator.put(e.getKey().toLowerCase(), value);
- pm().subscribeToPermission(e.getKey(), p);
-
- // lookup any deeper children & resolve if present
- Permission perm = pm().getPermission(e.getKey());
- if (perm != null) {
- calculateChildPermissions(accumulator, p, perm.getChildren(), !value);
- }
- }
- }
-
-}
diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml
index 3d34d2f1..e83bb4ce 100644
--- a/bukkit/src/main/resources/plugin.yml
+++ b/bukkit/src/main/resources/plugin.yml
@@ -8,16 +8,15 @@ main: me.lucko.luckperms.bukkit.LPBukkitPlugin
load: STARTUP
# This means that all plugins that (soft-)depend on Vault, depend on LuckPerms too.
-# It in turn fixes issues where plugins using Vault cache the provided instance when their plugin enables, or
-# when they check for the presence of a service provider, before LuckPerms has enabled.
+# It in turn fixes issues where plugins using Vault cache the provided instance
+# when their plugin enables, or when they check for the presence of a service
+# provider, before LuckPerms has enabled.
loadbefore: [Vault]
+
+# Soft depend on LilyPad for messaging service impl
softdepend: [LilyPad-Connect]
commands:
luckperms:
description: Manage permissions
aliases: [lp, perm, perms, permission, permissions]
-
-
-# Permissions are registered programmatically instead of here.
-# See the last method in me.lucko.luckperms.bukkit.LPBukkitPlugin