Rebuild default and child permission lookup maps live instead of only once when the plugin first enables
This commit is contained in:
parent
fd937e3209
commit
173286d404
@ -129,6 +129,14 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- caffeine -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
<artifactId>caffeine</artifactId>
|
||||||
|
<version>2.6.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spigot -->
|
<!-- Spigot -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
|
@ -34,14 +34,15 @@ import me.lucko.luckperms.bukkit.contexts.WorldCalculator;
|
|||||||
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
|
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
|
||||||
import me.lucko.luckperms.bukkit.listeners.BukkitPlatformListener;
|
import me.lucko.luckperms.bukkit.listeners.BukkitPlatformListener;
|
||||||
import me.lucko.luckperms.bukkit.messaging.BukkitMessagingFactory;
|
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.LPPermissible;
|
||||||
import me.lucko.luckperms.bukkit.model.permissible.PermissibleInjector;
|
import me.lucko.luckperms.bukkit.model.permissible.PermissibleInjector;
|
||||||
import me.lucko.luckperms.bukkit.model.permissible.PermissibleMonitoringInjector;
|
import me.lucko.luckperms.bukkit.model.permissible.PermissibleMonitoringInjector;
|
||||||
import me.lucko.luckperms.bukkit.processors.BukkitProcessorsSetupTask;
|
import me.lucko.luckperms.bukkit.model.server.InjectorDefaultsMap;
|
||||||
import me.lucko.luckperms.bukkit.processors.ChildPermissionProvider;
|
import me.lucko.luckperms.bukkit.model.server.InjectorPermissionMap;
|
||||||
import me.lucko.luckperms.bukkit.processors.DefaultsProvider;
|
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.bukkit.vault.VaultHookManager;
|
||||||
import me.lucko.luckperms.common.actionlog.LogDispatcher;
|
import me.lucko.luckperms.common.actionlog.LogDispatcher;
|
||||||
import me.lucko.luckperms.common.api.ApiRegistrationUtil;
|
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.command.PluginCommand;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.permissions.Permission;
|
||||||
import org.bukkit.permissions.PermissionDefault;
|
import org.bukkit.permissions.PermissionDefault;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.ServicePriority;
|
import org.bukkit.plugin.ServicePriority;
|
||||||
@ -123,8 +125,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
private LuckPermsApiProvider apiProvider;
|
private LuckPermsApiProvider apiProvider;
|
||||||
private EventFactory eventFactory;
|
private EventFactory eventFactory;
|
||||||
private Logger log;
|
private Logger log;
|
||||||
private DefaultsProvider defaultsProvider;
|
private LPSubscriptionMap subscriptionMap;
|
||||||
private ChildPermissionProvider childPermissionProvider;
|
private LPPermissionMap permissionMap;
|
||||||
|
private LPDefaultsMap defaultPermissionMap;
|
||||||
private LocaleManager localeManager;
|
private LocaleManager localeManager;
|
||||||
private PluginClassLoader pluginClassLoader;
|
private PluginClassLoader pluginClassLoader;
|
||||||
private DependencyManager dependencyManager;
|
private DependencyManager dependencyManager;
|
||||||
@ -197,10 +200,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
Set<StorageType> storageTypes = storageFactory.getRequiredTypes(StorageType.H2);
|
Set<StorageType> storageTypes = storageFactory.getRequiredTypes(StorageType.H2);
|
||||||
this.dependencyManager.loadStorageDependencies(storageTypes);
|
this.dependencyManager.loadStorageDependencies(storageTypes);
|
||||||
|
|
||||||
// init the Bukkit model providers
|
|
||||||
this.defaultsProvider = new DefaultsProvider();
|
|
||||||
this.childPermissionProvider = new ChildPermissionProvider();
|
|
||||||
|
|
||||||
// register events
|
// register events
|
||||||
BukkitConnectionListener connectionListener = new BukkitConnectionListener(this);
|
BukkitConnectionListener connectionListener = new BukkitConnectionListener(this);
|
||||||
getServer().getPluginManager().registerEvents(connectionListener, this);
|
getServer().getPluginManager().registerEvents(connectionListener, this);
|
||||||
@ -246,21 +245,19 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
this.contextManager.registerStaticCalculator(new LuckPermsCalculator(getConfiguration()));
|
this.contextManager.registerStaticCalculator(new LuckPermsCalculator(getConfiguration()));
|
||||||
|
|
||||||
// inject our own custom permission maps
|
// inject our own custom permission maps
|
||||||
SubscriptionMapInjector subscriptionMapInjector = new SubscriptionMapInjector(this);
|
Runnable[] injectors = new Runnable[]{
|
||||||
subscriptionMapInjector.run();
|
new InjectorSubscriptionMap(this),
|
||||||
|
new InjectorPermissionMap(this),
|
||||||
|
new InjectorDefaultsMap(this)
|
||||||
|
};
|
||||||
|
|
||||||
PermissionMapInjector permissionMapInjector = new PermissionMapInjector(this);
|
for (Runnable injector : injectors) {
|
||||||
permissionMapInjector.run();
|
injector.run();
|
||||||
|
|
||||||
// setup the bukkit processors
|
// schedule another injection after all plugins have loaded
|
||||||
BukkitProcessorsSetupTask bukkitProcessorsSetupTask = new BukkitProcessorsSetupTask(this);
|
// the entire pluginmanager instance is replaced by some plugins :(
|
||||||
bukkitProcessorsSetupTask.run();
|
this.scheduler.asyncLater(injector, 1L);
|
||||||
|
}
|
||||||
// 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);
|
|
||||||
|
|
||||||
// inject verbose handlers into internal bukkit objects
|
// inject verbose handlers into internal bukkit objects
|
||||||
new PermissibleMonitoringInjector(this).run();
|
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;
|
PermissionDefault permDefault = getConfiguration().get(ConfigKeys.COMMANDS_ALLOW_OP) ? PermissionDefault.OP : PermissionDefault.FALSE;
|
||||||
|
|
||||||
for (CommandPermission p : CommandPermission.values()) {
|
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) {
|
} catch (Exception e) {
|
||||||
// this throws an exception if the plugin is /reloaded, grr
|
// 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
|
// Switch back to the fallback executor, the bukkit one won't allow new tasks
|
||||||
this.scheduler.setUseFallback(true);
|
this.scheduler.setUseFallback(true);
|
||||||
|
|
||||||
this.defaultsProvider.close();
|
|
||||||
this.permissionVault.shutdown();
|
this.permissionVault.shutdown();
|
||||||
this.verboseHandler.shutdown();
|
this.verboseHandler.shutdown();
|
||||||
|
|
||||||
@ -375,8 +371,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// uninject custom maps
|
// uninject custom maps
|
||||||
SubscriptionMapInjector.uninject();
|
InjectorSubscriptionMap.uninject();
|
||||||
PermissionMapInjector.uninject();
|
InjectorPermissionMap.uninject();
|
||||||
|
InjectorDefaultsMap.uninject();
|
||||||
|
|
||||||
getLog().info("Closing storage...");
|
getLog().info("Closing storage...");
|
||||||
this.storage.shutdown();
|
this.storage.shutdown();
|
||||||
@ -447,6 +444,30 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
return configFile;
|
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
|
@Override
|
||||||
public Optional<InternalMessagingService> getMessagingService() {
|
public Optional<InternalMessagingService> getMessagingService() {
|
||||||
return Optional.ofNullable(this.messagingService);
|
return Optional.ofNullable(this.messagingService);
|
||||||
@ -627,14 +648,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
return this.log;
|
return this.log;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultsProvider getDefaultsProvider() {
|
|
||||||
return this.defaultsProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChildPermissionProvider getChildPermissionProvider() {
|
|
||||||
return this.childPermissionProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocaleManager getLocaleManager() {
|
public LocaleManager getLocaleManager() {
|
||||||
return this.localeManager;
|
return this.localeManager;
|
||||||
|
@ -55,7 +55,7 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
|||||||
processors.add(new MapProcessor());
|
processors.add(new MapProcessor());
|
||||||
|
|
||||||
if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_CHILD_PERMISSIONS)) {
|
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)) {
|
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) {
|
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()));
|
return registerCalculator(new PermissionCalculator(this.plugin, metadata, processors.build()));
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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<String, Permission> {
|
|
||||||
final LuckPermsPlugin plugin;
|
|
||||||
|
|
||||||
public LPPermissionMap(LuckPermsPlugin plugin, Map<String, Permission> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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<PermissionAttachmentInfo> 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) {}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* 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<Boolean, Set<Permission>> castedMap = (Map<Boolean, Set<Permission>>) 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.bukkit.model;
|
package me.lucko.luckperms.bukkit.model.server;
|
||||||
|
|
||||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ import java.util.Objects;
|
|||||||
/**
|
/**
|
||||||
* Injects a {@link LPPermissionMap} into the {@link PluginManager}.
|
* Injects a {@link LPPermissionMap} into the {@link PluginManager}.
|
||||||
*/
|
*/
|
||||||
public class PermissionMapInjector implements Runnable {
|
public class InjectorPermissionMap implements Runnable {
|
||||||
private static final Field PERMISSIONS_FIELD;
|
private static final Field PERMISSIONS_FIELD;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -56,43 +56,45 @@ public class PermissionMapInjector implements Runnable {
|
|||||||
|
|
||||||
private final LPBukkitPlugin plugin;
|
private final LPBukkitPlugin plugin;
|
||||||
|
|
||||||
public PermissionMapInjector(LPBukkitPlugin plugin) {
|
public InjectorPermissionMap(LPBukkitPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
inject();
|
LPPermissionMap ret = inject();
|
||||||
|
if (ret != null) {
|
||||||
|
this.plugin.setPermissionMap(ret);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission map.");
|
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission map.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void inject() throws Exception {
|
private LPPermissionMap inject() throws Exception {
|
||||||
Objects.requireNonNull(PERMISSIONS_FIELD, "PERMISSIONS_FIELD");
|
Objects.requireNonNull(PERMISSIONS_FIELD, "PERMISSIONS_FIELD");
|
||||||
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
|
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
|
||||||
|
|
||||||
if (!(pluginManager instanceof SimplePluginManager)) {
|
if (!(pluginManager instanceof SimplePluginManager)) {
|
||||||
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||||
this.plugin.getLog().severe("Unable to inject LuckPerms Permission map.");
|
this.plugin.getLog().severe("Unable to inject LuckPerms Permission map.");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object map = PERMISSIONS_FIELD.get(pluginManager);
|
Object map = PERMISSIONS_FIELD.get(pluginManager);
|
||||||
if (map instanceof LPPermissionMap && ((LPPermissionMap) map).plugin == this.plugin) {
|
if (map instanceof LPPermissionMap && ((LPPermissionMap) map).plugin == this.plugin) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
Map<String, Permission> castedMap = (Map<String, Permission>) map;
|
Map<String, Permission> castedMap = (Map<String, Permission>) map;
|
||||||
|
|
||||||
// make a new map
|
// make a new map & inject it
|
||||||
LPPermissionMap newMap = new LPPermissionMap(this.plugin, castedMap);
|
LPPermissionMap newMap = new LPPermissionMap(this.plugin, castedMap);
|
||||||
|
|
||||||
// inject it
|
|
||||||
PERMISSIONS_FIELD.set(pluginManager, newMap);
|
PERMISSIONS_FIELD.set(pluginManager, newMap);
|
||||||
|
return newMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void uninject() {
|
public static void uninject() {
|
@ -23,7 +23,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.bukkit.model;
|
package me.lucko.luckperms.bukkit.model.server;
|
||||||
|
|
||||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ import java.util.Objects;
|
|||||||
/**
|
/**
|
||||||
* Injects a {@link LPSubscriptionMap} into the {@link PluginManager}.
|
* 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;
|
private static final Field PERM_SUBS_FIELD;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -55,34 +55,37 @@ public class SubscriptionMapInjector implements Runnable {
|
|||||||
|
|
||||||
private final LPBukkitPlugin plugin;
|
private final LPBukkitPlugin plugin;
|
||||||
|
|
||||||
public SubscriptionMapInjector(LPBukkitPlugin plugin) {
|
public InjectorSubscriptionMap(LPBukkitPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
inject();
|
LPSubscriptionMap ret = inject();
|
||||||
|
if (ret != null) {
|
||||||
|
this.plugin.setSubscriptionMap(ret);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission Subscription map.");
|
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission Subscription map.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void inject() throws Exception {
|
private LPSubscriptionMap inject() throws Exception {
|
||||||
Objects.requireNonNull(PERM_SUBS_FIELD, "PERM_SUBS_FIELD");
|
Objects.requireNonNull(PERM_SUBS_FIELD, "PERM_SUBS_FIELD");
|
||||||
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
|
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
|
||||||
|
|
||||||
if (!(pluginManager instanceof SimplePluginManager)) {
|
if (!(pluginManager instanceof SimplePluginManager)) {
|
||||||
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||||
this.plugin.getLog().severe("Unable to inject LuckPerms Permission Subscription map.");
|
this.plugin.getLog().severe("Unable to inject LuckPerms Permission Subscription map.");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object map = PERM_SUBS_FIELD.get(pluginManager);
|
Object map = PERM_SUBS_FIELD.get(pluginManager);
|
||||||
if (map instanceof LPSubscriptionMap) {
|
if (map instanceof LPSubscriptionMap) {
|
||||||
if (((LPSubscriptionMap) map).plugin == this.plugin) {
|
if (((LPSubscriptionMap) map).plugin == this.plugin) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
map = ((LPSubscriptionMap) map).detach();
|
map = ((LPSubscriptionMap) map).detach();
|
||||||
@ -91,11 +94,10 @@ public class SubscriptionMapInjector implements Runnable {
|
|||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
Map<String, Map<Permissible, Boolean>> castedMap = (Map<String, Map<Permissible, Boolean>>) map;
|
Map<String, Map<Permissible, Boolean>> castedMap = (Map<String, Map<Permissible, Boolean>>) map;
|
||||||
|
|
||||||
// make a new subscription map
|
// make a new subscription map & inject it
|
||||||
LPSubscriptionMap newMap = new LPSubscriptionMap(this.plugin, castedMap);
|
LPSubscriptionMap newMap = new LPSubscriptionMap(this.plugin, castedMap);
|
||||||
|
|
||||||
// inject it
|
|
||||||
PERM_SUBS_FIELD.set(pluginManager, newMap);
|
PERM_SUBS_FIELD.set(pluginManager, newMap);
|
||||||
|
return newMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void uninject() {
|
public static void uninject() {
|
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* 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<Boolean, Set<Permission>> {
|
||||||
|
// keyset for all instances
|
||||||
|
private static final Set<Boolean> KEY_SET = ImmutableSet.of(Boolean.TRUE, Boolean.FALSE);
|
||||||
|
|
||||||
|
// the plugin
|
||||||
|
final LPBukkitPlugin plugin;
|
||||||
|
|
||||||
|
// the two values in the map
|
||||||
|
private final Set<Permission> opSet = new DefaultPermissionSet(true);
|
||||||
|
private final Set<Permission> nonOpSet = new DefaultPermissionSet(false);
|
||||||
|
|
||||||
|
// fully resolved defaults (accounts for child permissions too)
|
||||||
|
private Map<String, Boolean> resolvedOpDefaults = ImmutableMap.of();
|
||||||
|
private Map<String, Boolean> resolvedNonOpDefaults = ImmutableMap.of();
|
||||||
|
|
||||||
|
// #values and #entrySet results - both immutable
|
||||||
|
private final Collection<Set<Permission>> values = ImmutableList.of(this.opSet, this.nonOpSet);
|
||||||
|
private final Set<Entry<Boolean, Set<Permission>>> entrySet = ImmutableSet.of(
|
||||||
|
Maps.immutableEntry(Boolean.TRUE, this.opSet),
|
||||||
|
Maps.immutableEntry(Boolean.FALSE, this.nonOpSet)
|
||||||
|
);
|
||||||
|
|
||||||
|
public LPDefaultsMap(LPBukkitPlugin plugin, Map<Boolean, Set<Permission>> 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<Permission> getOpPermissions() {
|
||||||
|
return this.opSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Permission> 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<String, Boolean> 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<String, Boolean> builder = new HashMap<>();
|
||||||
|
for (Permission perm : getOpPermissions()) {
|
||||||
|
String name = perm.getName().toLowerCase();
|
||||||
|
builder.put(name, true);
|
||||||
|
for (Map.Entry<String, Boolean> 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<String, Boolean> builder = new HashMap<>();
|
||||||
|
for (Permission perm : getNonOpPermissions()) {
|
||||||
|
String name = perm.getName().toLowerCase();
|
||||||
|
builder.put(name, true);
|
||||||
|
for (Map.Entry<String, Boolean> child : this.plugin.getPermissionMap().getChildPermissions(name, true).entrySet()) {
|
||||||
|
builder.putIfAbsent(child.getKey(), child.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.resolvedNonOpDefaults = ImmutableMap.copyOf(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Permission> get(Object key) {
|
||||||
|
boolean b = (boolean) key;
|
||||||
|
return b ? this.opSet : this.nonOpSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return wrappers around this map impl
|
||||||
|
@Nonnull @Override public Collection<Set<Permission>> values() { return this.values; }
|
||||||
|
@Nonnull @Override public Set<Entry<Boolean, Set<Permission>>> entrySet() { return this.entrySet; }
|
||||||
|
@Nonnull @Override public Set<Boolean> 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<Permission> put(Boolean key, Set<Permission> value) { throw new UnsupportedOperationException(); }
|
||||||
|
@Override public Set<Permission> remove(Object key) { throw new UnsupportedOperationException(); }
|
||||||
|
@Override public void putAll(@Nonnull Map<? extends Boolean, ? extends Set<Permission>> m) { throw new UnsupportedOperationException(); }
|
||||||
|
@Override public void clear() { throw new UnsupportedOperationException(); }
|
||||||
|
|
||||||
|
private final class DefaultPermissionSet extends ForwardingSet<Permission> {
|
||||||
|
private final Set<Permission> delegate = ConcurrentHashMap.newKeySet();
|
||||||
|
private final boolean op;
|
||||||
|
|
||||||
|
private DefaultPermissionSet(boolean op) {
|
||||||
|
this.op = op;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<Permission> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* 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<String, Permission> {
|
||||||
|
|
||||||
|
// Uses perm.getName().toLowerCase(java.util.Locale.ENGLISH); to determine the key
|
||||||
|
private final Map<String, Permission> delegate = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
// cache from permission --> children
|
||||||
|
private final LoadingCache<String, Map<String, Boolean>> trueChildPermissions = Caffeine.newBuilder()
|
||||||
|
.build(new ChildPermissionResolver(true));
|
||||||
|
|
||||||
|
private final LoadingCache<String, Map<String, Boolean>> falseChildPermissions = Caffeine.newBuilder()
|
||||||
|
.build(new ChildPermissionResolver(false));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The plugin instance
|
||||||
|
*/
|
||||||
|
final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
|
public LPPermissionMap(LuckPermsPlugin plugin, Map<String, Permission> existingData) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
putAll(existingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Boolean> 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<String, Permission> 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<String, Map<String, Boolean>> {
|
||||||
|
private final boolean value;
|
||||||
|
|
||||||
|
private ChildPermissionResolver(boolean value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@CheckForNull
|
||||||
|
@Override
|
||||||
|
public Map<String, Boolean> load(@Nonnull String key) {
|
||||||
|
Map<String, Boolean> children = new HashMap<>();
|
||||||
|
resolveChildren(children, Collections.singletonMap(key, this.value), false);
|
||||||
|
children.remove(key, this.value);
|
||||||
|
return ImmutableMap.copyOf(children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveChildren(Map<String, Boolean> accumulator, Map<String, Boolean> 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<String, Boolean> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
* SOFTWARE.
|
* 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.Maps;
|
||||||
import com.google.common.collect.Sets;
|
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
|
* 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<String, Map<Permissible, Boolean>> {
|
public class LPSubscriptionMap extends HashMap<String, Map<Permissible, Boolean>> {
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> permissions = ImmutableMap.of();
|
|
||||||
|
|
||||||
public void setup() {
|
|
||||||
ImmutableMap.Builder<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> 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<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> accumulator, Permission permission, boolean value) {
|
|
||||||
|
|
||||||
// accumulator for the child permissions being looked up
|
|
||||||
Map<String, Boolean> 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<String, Boolean> accumulator, Map<String, Boolean> 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<String, Boolean> 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<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> getPermissions() {
|
|
||||||
return this.permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -25,9 +25,8 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.bukkit.processors;
|
package me.lucko.luckperms.bukkit.processors;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Tristate;
|
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.AbstractPermissionProcessor;
|
||||||
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
||||||
|
|
||||||
@ -39,11 +38,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
* Permission Processor for Bukkits "child" permission system.
|
* Permission Processor for Bukkits "child" permission system.
|
||||||
*/
|
*/
|
||||||
public class ChildProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
|
public class ChildProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
|
||||||
private final ChildPermissionProvider provider;
|
private final LPBukkitPlugin plugin;
|
||||||
private Map<String, Boolean> childPermissions = Collections.emptyMap();
|
private Map<String, Boolean> childPermissions = Collections.emptyMap();
|
||||||
|
|
||||||
public ChildProcessor(ChildPermissionProvider provider) {
|
public ChildProcessor(LPBukkitPlugin plugin) {
|
||||||
this.provider = provider;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -55,7 +54,7 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi
|
|||||||
public void refresh() {
|
public void refresh() {
|
||||||
Map<String, Boolean> builder = new ConcurrentHashMap<>();
|
Map<String, Boolean> builder = new ConcurrentHashMap<>();
|
||||||
for (Map.Entry<String, Boolean> e : this.sourceMap.entrySet()) {
|
for (Map.Entry<String, Boolean> e : this.sourceMap.entrySet()) {
|
||||||
Map<String, Boolean> children = this.provider.getPermissions().get(Maps.immutableEntry(e.getKey(), e.getValue()));
|
Map<String, Boolean> children = this.plugin.getPermissionMap().getChildPermissions(e.getKey(), e.getValue());
|
||||||
if (children != null) {
|
if (children != null) {
|
||||||
builder.putAll(children);
|
builder.putAll(children);
|
||||||
}
|
}
|
||||||
|
@ -26,31 +26,31 @@
|
|||||||
package me.lucko.luckperms.bukkit.processors;
|
package me.lucko.luckperms.bukkit.processors;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Tristate;
|
import me.lucko.luckperms.api.Tristate;
|
||||||
|
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||||
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.permissions.Permission;
|
import org.bukkit.permissions.Permission;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission Processor for Bukkits "default" permission system.
|
* Permission Processor for Bukkits "default" permission system.
|
||||||
*/
|
*/
|
||||||
public class DefaultsProcessor implements PermissionProcessor {
|
public class DefaultsProcessor implements PermissionProcessor {
|
||||||
|
private final LPBukkitPlugin plugin;
|
||||||
private final boolean isOp;
|
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.isOp = isOp;
|
||||||
this.defaultsProvider = defaultsProvider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Tristate hasPermission(String permission) {
|
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) {
|
if (t != Tristate.UNDEFINED) {
|
||||||
return t;
|
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));
|
return defPerm == null ? Tristate.UNDEFINED : Tristate.fromBoolean(defPerm.getDefault().getValue(this.isOp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,169 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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<String, Boolean> opDefaults = ImmutableMap.of();
|
|
||||||
private final DummyPermissible opDummy = new DummyPermissible(this::refreshOp);
|
|
||||||
|
|
||||||
// defaults for non-opped players
|
|
||||||
private Map<String, Boolean> 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<String, Boolean> 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<String, Boolean> 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<String, Boolean> 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<String, Boolean> map, DummyPermissible p, boolean op) {
|
|
||||||
Set<String> perms = map.keySet();
|
|
||||||
|
|
||||||
for (String name : perms) {
|
|
||||||
pm().unsubscribeFromPermission(name, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
pm().unsubscribeFromDefaultPerms(op, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void calculateDefaults(Map<String, Boolean> map, DummyPermissible p, boolean op) {
|
|
||||||
pm().subscribeToDefaultPerms(op, p);
|
|
||||||
|
|
||||||
Set<Permission> 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<String, Boolean> accumulator, DummyPermissible p, Map<String, Boolean> children, boolean invert) {
|
|
||||||
for (Map.Entry<String, Boolean> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -8,16 +8,15 @@ main: me.lucko.luckperms.bukkit.LPBukkitPlugin
|
|||||||
load: STARTUP
|
load: STARTUP
|
||||||
|
|
||||||
# This means that all plugins that (soft-)depend on Vault, depend on LuckPerms too.
|
# 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
|
# It in turn fixes issues where plugins using Vault cache the provided instance
|
||||||
# when they check for the presence of a service provider, before LuckPerms has enabled.
|
# when their plugin enables, or when they check for the presence of a service
|
||||||
|
# provider, before LuckPerms has enabled.
|
||||||
loadbefore: [Vault]
|
loadbefore: [Vault]
|
||||||
|
|
||||||
|
# Soft depend on LilyPad for messaging service impl
|
||||||
softdepend: [LilyPad-Connect]
|
softdepend: [LilyPad-Connect]
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
luckperms:
|
luckperms:
|
||||||
description: Manage permissions
|
description: Manage permissions
|
||||||
aliases: [lp, perm, perms, permission, permissions]
|
aliases: [lp, perm, perms, permission, permissions]
|
||||||
|
|
||||||
|
|
||||||
# Permissions are registered programmatically instead of here.
|
|
||||||
# See the last method in me.lucko.luckperms.bukkit.LPBukkitPlugin
|
|
||||||
|
Loading…
Reference in New Issue
Block a user