Various performance optimizations
This commit is contained in:
parent
a0be1c7c48
commit
18f09f9862
@ -25,95 +25,16 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.bukkit;
|
package me.lucko.luckperms.bukkit;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
|
||||||
import me.lucko.luckperms.common.utils.Iterators;
|
|
||||||
|
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.SynchronousQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
public class BukkitSchedulerAdapter extends AbstractJavaScheduler implements SchedulerAdapter {
|
||||||
|
|
||||||
public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
|
||||||
private final LPBukkitBootstrap bootstrap;
|
|
||||||
|
|
||||||
private final ExecutorService asyncFallback;
|
|
||||||
private final Executor asyncBukkit;
|
|
||||||
private final Executor sync;
|
private final Executor sync;
|
||||||
private final Executor async;
|
|
||||||
|
|
||||||
private boolean useFallback = true;
|
|
||||||
|
|
||||||
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
|
||||||
|
|
||||||
public BukkitSchedulerAdapter(LPBukkitBootstrap bootstrap) {
|
public BukkitSchedulerAdapter(LPBukkitBootstrap bootstrap) {
|
||||||
this.bootstrap = bootstrap;
|
this.sync = r -> bootstrap.getServer().getScheduler().scheduleSyncDelayedTask(bootstrap, r);
|
||||||
|
|
||||||
this.sync = new SyncExecutor();
|
|
||||||
this.asyncFallback = new FallbackAsyncExecutor();
|
|
||||||
this.asyncBukkit = new BukkitAsyncExecutor();
|
|
||||||
this.async = new AsyncExecutor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private BukkitScheduler scheduler() {
|
|
||||||
return this.bootstrap.getServer().getScheduler();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doAsync(Runnable runnable) {
|
|
||||||
async().execute(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doSync(Runnable runnable) {
|
|
||||||
sync().execute(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
|
||||||
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimerAsynchronously(this.bootstrap, runnable, intervalTicks, intervalTicks));
|
|
||||||
this.tasks.add(task);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
|
||||||
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimer(this.bootstrap, runnable, intervalTicks, intervalTicks));
|
|
||||||
this.tasks.add(task);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
|
||||||
return new BukkitSchedulerTask(scheduler().runTaskLaterAsynchronously(this.bootstrap, runnable, delayTicks));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
|
||||||
return new BukkitSchedulerTask(scheduler().runTaskLater(this.bootstrap, runnable, delayTicks));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdown() {
|
|
||||||
Iterators.iterate(this.tasks, SchedulerTask::cancel);
|
|
||||||
|
|
||||||
// wait for executor
|
|
||||||
this.asyncFallback.shutdown();
|
|
||||||
try {
|
|
||||||
this.asyncFallback.awaitTermination(30, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,62 +42,4 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
|||||||
return this.sync;
|
return this.sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Executor async() {
|
|
||||||
return this.async;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Executor platformAsync() {
|
|
||||||
return this.asyncBukkit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUseFallback(boolean useFallback) {
|
|
||||||
this.useFallback = useFallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class SyncExecutor implements Executor {
|
|
||||||
@Override
|
|
||||||
public void execute(@Nonnull Runnable runnable) {
|
|
||||||
BukkitSchedulerAdapter.this.bootstrap.getServer().getScheduler().scheduleSyncDelayedTask(BukkitSchedulerAdapter.this.bootstrap, runnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class AsyncExecutor implements Executor {
|
|
||||||
@Override
|
|
||||||
public void execute(@Nonnull Runnable runnable) {
|
|
||||||
if (BukkitSchedulerAdapter.this.useFallback || !BukkitSchedulerAdapter.this.bootstrap.isEnabled()) {
|
|
||||||
BukkitSchedulerAdapter.this.asyncFallback.execute(runnable);
|
|
||||||
} else {
|
|
||||||
BukkitSchedulerAdapter.this.asyncBukkit.execute(runnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class BukkitAsyncExecutor implements Executor {
|
|
||||||
@Override
|
|
||||||
public void execute(@Nonnull Runnable runnable) {
|
|
||||||
BukkitSchedulerAdapter.this.bootstrap.getServer().getScheduler().runTaskAsynchronously(BukkitSchedulerAdapter.this.bootstrap, runnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class FallbackAsyncExecutor extends ThreadPoolExecutor {
|
|
||||||
private FallbackAsyncExecutor() {
|
|
||||||
super(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactoryBuilder().setNameFormat("luckperms-fallback-%d").build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class BukkitSchedulerTask implements SchedulerTask {
|
|
||||||
private final BukkitTask task;
|
|
||||||
|
|
||||||
private BukkitSchedulerTask(BukkitTask task) {
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancel() {
|
|
||||||
this.task.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, send the message sync
|
// otherwise, send the message sync
|
||||||
getPlugin().getBootstrap().getScheduler().doSync(new SyncMessengerAgent(sender, s));
|
getPlugin().getBootstrap().getScheduler().executeSync(new SyncMessengerAgent(sender, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,7 +46,7 @@ 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.api.LuckPermsApiProvider;
|
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||||
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
|
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
|
||||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
@ -78,6 +78,7 @@ import java.util.EnumSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,7 +153,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PlatformCalculatorFactory provideCalculatorFactory() {
|
protected CalculatorFactory provideCalculatorFactory() {
|
||||||
return new BukkitCalculatorFactory(this);
|
return new BukkitCalculatorFactory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +178,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
|
|
||||||
// schedule another injection after all plugins have loaded
|
// schedule another injection after all plugins have loaded
|
||||||
// the entire pluginmanager instance is replaced by some plugins :(
|
// the entire pluginmanager instance is replaced by some plugins :(
|
||||||
this.bootstrap.getScheduler().asyncLater(injector, 1L);
|
this.bootstrap.getServer().getScheduler().runTaskLaterAsynchronously(this.bootstrap, injector, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide vault support
|
// Provide vault support
|
||||||
@ -214,8 +215,8 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerHousekeepingTasks() {
|
protected void registerHousekeepingTasks() {
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 3, TimeUnit.SECONDS);
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -234,7 +235,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
|
|
||||||
// remove all operators on startup if they're disabled
|
// remove all operators on startup if they're disabled
|
||||||
if (!getConfiguration().get(ConfigKeys.OPS_ENABLED)) {
|
if (!getConfiguration().get(ConfigKeys.OPS_ENABLED)) {
|
||||||
this.bootstrap.getScheduler().platformAsync().execute(() -> {
|
this.bootstrap.getServer().getScheduler().runTaskAsynchronously(this.bootstrap, () -> {
|
||||||
for (OfflinePlayer player : this.bootstrap.getServer().getOperators()) {
|
for (OfflinePlayer player : this.bootstrap.getServer().getOperators()) {
|
||||||
player.setOp(false);
|
player.setOp(false);
|
||||||
}
|
}
|
||||||
@ -250,16 +251,13 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace the temporary executor when the Bukkit one starts
|
|
||||||
this.bootstrap.getServer().getScheduler().runTaskAsynchronously(this.bootstrap, () -> this.bootstrap.getScheduler().setUseFallback(false));
|
|
||||||
|
|
||||||
// Load any online users (in the case of a reload)
|
// Load any online users (in the case of a reload)
|
||||||
for (Player player : this.bootstrap.getServer().getOnlinePlayers()) {
|
for (Player player : this.bootstrap.getServer().getOnlinePlayers()) {
|
||||||
this.bootstrap.getScheduler().doAsync(() -> {
|
this.bootstrap.getScheduler().executeAsync(() -> {
|
||||||
try {
|
try {
|
||||||
User user = this.connectionListener.loadUser(player.getUniqueId(), player.getName());
|
User user = this.connectionListener.loadUser(player.getUniqueId(), player.getName());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
this.bootstrap.getScheduler().doSync(() -> {
|
this.bootstrap.getScheduler().executeSync(() -> {
|
||||||
try {
|
try {
|
||||||
LPPermissible lpPermissible = new LPPermissible(player, user, this);
|
LPPermissible lpPermissible = new LPPermissible(player, user, this);
|
||||||
PermissibleInjector.inject(player, lpPermissible);
|
PermissibleInjector.inject(player, lpPermissible);
|
||||||
@ -275,12 +273,6 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void performEarlyDisableTasks() {
|
|
||||||
// Switch back to the fallback executor, the bukkit one won't allow new tasks
|
|
||||||
this.bootstrap.getScheduler().setUseFallback(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void removePlatformHooks() {
|
protected void removePlatformHooks() {
|
||||||
// uninject from players
|
// uninject from players
|
||||||
|
@ -32,7 +32,7 @@ import me.lucko.luckperms.api.LookupSetting;
|
|||||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||||
import me.lucko.luckperms.bukkit.processors.ChildProcessor;
|
import me.lucko.luckperms.bukkit.processors.ChildProcessor;
|
||||||
import me.lucko.luckperms.bukkit.processors.DefaultsProcessor;
|
import me.lucko.luckperms.bukkit.processors.DefaultsProcessor;
|
||||||
import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
@ -42,7 +42,7 @@ import me.lucko.luckperms.common.processors.PermissionProcessor;
|
|||||||
import me.lucko.luckperms.common.processors.RegexProcessor;
|
import me.lucko.luckperms.common.processors.RegexProcessor;
|
||||||
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
||||||
|
|
||||||
public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
public class BukkitCalculatorFactory implements CalculatorFactory {
|
||||||
private final LPBukkitPlugin plugin;
|
private final LPBukkitPlugin plugin;
|
||||||
|
|
||||||
public BukkitCalculatorFactory(LPBukkitPlugin plugin) {
|
public BukkitCalculatorFactory(LPBukkitPlugin plugin) {
|
||||||
@ -71,6 +71,6 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
|||||||
processors.add(new DefaultsProcessor(this.plugin, contexts.hasSetting(LookupSetting.IS_OP)));
|
processors.add(new DefaultsProcessor(this.plugin, contexts.hasSetting(LookupSetting.IS_OP)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return registerCalculator(new PermissionCalculator(this.plugin, metadata, processors.build()));
|
return new PermissionCalculator(this.plugin, metadata, processors.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
|
|||||||
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||||
|
|
||||||
// force a clear of transient nodes
|
// force a clear of transient nodes
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.clearTransientNodes();
|
user.clearTransientNodes();
|
||||||
|
@ -87,7 +87,7 @@ public class LilyPadMessenger implements Messenger {
|
|||||||
|
|
||||||
@EventListener
|
@EventListener
|
||||||
public void onMessage(MessageEvent event) {
|
public void onMessage(MessageEvent event) {
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
try {
|
try {
|
||||||
String channel = event.getChannel();
|
String channel = event.getChannel();
|
||||||
|
|
||||||
|
@ -189,7 +189,6 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
|||||||
|
|
||||||
// remove transient permissions from the holder which were added by this attachment & equal the permission
|
// remove transient permissions from the holder which were added by this attachment & equal the permission
|
||||||
User user = this.permissible.getUser();
|
User user = this.permissible.getUser();
|
||||||
|
|
||||||
user.removeIfTransient(LocalizedNode.composedPredicate(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name)));
|
user.removeIfTransient(LocalizedNode.composedPredicate(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ 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.bukkit.LPBukkitPlugin;
|
||||||
|
import me.lucko.luckperms.common.buffers.Cache;
|
||||||
|
|
||||||
import org.bukkit.permissions.Permission;
|
import org.bukkit.permissions.Permission;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
@ -67,8 +68,8 @@ public final class LPDefaultsMap implements Map<Boolean, Set<Permission>> {
|
|||||||
private final Set<Permission> nonOpSet = new DefaultPermissionSet(false);
|
private final Set<Permission> nonOpSet = new DefaultPermissionSet(false);
|
||||||
|
|
||||||
// fully resolved defaults (accounts for child permissions too)
|
// fully resolved defaults (accounts for child permissions too)
|
||||||
private Map<String, Boolean> resolvedOpDefaults = ImmutableMap.of();
|
private DefaultsCache opCache = new DefaultsCache(true);
|
||||||
private Map<String, Boolean> resolvedNonOpDefaults = ImmutableMap.of();
|
private DefaultsCache nonOpCache = new DefaultsCache(false);
|
||||||
|
|
||||||
// #values and #entrySet results - both immutable
|
// #values and #entrySet results - both immutable
|
||||||
private final Collection<Set<Permission>> values = ImmutableList.of(this.opSet, this.nonOpSet);
|
private final Collection<Set<Permission>> values = ImmutableList.of(this.opSet, this.nonOpSet);
|
||||||
@ -81,16 +82,20 @@ public final class LPDefaultsMap implements Map<Boolean, Set<Permission>> {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.opSet.addAll(existingData.getOrDefault(Boolean.TRUE, Collections.emptySet()));
|
this.opSet.addAll(existingData.getOrDefault(Boolean.TRUE, Collections.emptySet()));
|
||||||
this.nonOpSet.addAll(existingData.getOrDefault(Boolean.FALSE, Collections.emptySet()));
|
this.nonOpSet.addAll(existingData.getOrDefault(Boolean.FALSE, Collections.emptySet()));
|
||||||
refreshOp();
|
|
||||||
refreshNonOp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Permission> getOpPermissions() {
|
@Override
|
||||||
return this.opSet;
|
public Set<Permission> get(Object key) {
|
||||||
|
boolean b = (boolean) key;
|
||||||
|
return b ? this.opSet : this.nonOpSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Permission> getNonOpPermissions() {
|
private DefaultsCache getCache(boolean op) {
|
||||||
return this.nonOpSet;
|
return op ? this.opCache : this.nonOpCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invalidate(boolean op) {
|
||||||
|
getCache(op).invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,54 +106,10 @@ public final class LPDefaultsMap implements Map<Boolean, Set<Permission>> {
|
|||||||
* @return a tristate result
|
* @return a tristate result
|
||||||
*/
|
*/
|
||||||
public Tristate lookupDefaultPermission(String permission, boolean isOp) {
|
public Tristate lookupDefaultPermission(String permission, boolean isOp) {
|
||||||
Map<String, Boolean> map = isOp ? this.resolvedOpDefaults : this.resolvedNonOpDefaults;
|
Map<String, Boolean> map = getCache(isOp).get();
|
||||||
return Tristate.fromNullableBoolean(map.get(permission));
|
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
|
// return wrappers around this map impl
|
||||||
@Nonnull @Override public Collection<Set<Permission>> values() { return this.values; }
|
@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<Entry<Boolean, Set<Permission>>> entrySet() { return this.entrySet; }
|
||||||
@ -166,11 +127,33 @@ public final class LPDefaultsMap implements Map<Boolean, Set<Permission>> {
|
|||||||
@Override public void putAll(@Nonnull Map<? extends Boolean, ? extends Set<Permission>> m) { 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(); }
|
@Override public void clear() { throw new UnsupportedOperationException(); }
|
||||||
|
|
||||||
|
private final class DefaultsCache extends Cache<Map<String, Boolean>> {
|
||||||
|
private final boolean op;
|
||||||
|
|
||||||
|
DefaultsCache(boolean op) {
|
||||||
|
this.op = op;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
protected Map<String, Boolean> supply() {
|
||||||
|
Map<String, Boolean> builder = new HashMap<>();
|
||||||
|
for (Permission perm : LPDefaultsMap.this.get(this.op)) {
|
||||||
|
String name = perm.getName().toLowerCase();
|
||||||
|
builder.put(name, true);
|
||||||
|
for (Map.Entry<String, Boolean> child : LPDefaultsMap.this.plugin.getPermissionMap().getChildPermissions(name, true).entrySet()) {
|
||||||
|
builder.putIfAbsent(child.getKey(), child.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ImmutableMap.copyOf(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class DefaultPermissionSet extends ForwardingSet<Permission> {
|
private final class DefaultPermissionSet extends ForwardingSet<Permission> {
|
||||||
private final Set<Permission> delegate = ConcurrentHashMap.newKeySet();
|
private final Set<Permission> delegate = ConcurrentHashMap.newKeySet();
|
||||||
private final boolean op;
|
private final boolean op;
|
||||||
|
|
||||||
private DefaultPermissionSet(boolean op) {
|
DefaultPermissionSet(boolean op) {
|
||||||
this.op = op;
|
this.op = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,14 +165,14 @@ public final class LPDefaultsMap implements Map<Boolean, Set<Permission>> {
|
|||||||
@Override
|
@Override
|
||||||
public boolean add(@Nonnull Permission element) {
|
public boolean add(@Nonnull Permission element) {
|
||||||
boolean ret = super.add(element);
|
boolean ret = super.add(element);
|
||||||
refresh(this.op);
|
invalidate(this.op);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(@Nonnull Collection<? extends Permission> collection) {
|
public boolean addAll(@Nonnull Collection<? extends Permission> collection) {
|
||||||
boolean ret = super.addAll(collection);
|
boolean ret = super.addAll(collection);
|
||||||
refresh(this.op);
|
invalidate(this.op);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,104 +25,56 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.bungee;
|
package me.lucko.luckperms.bungee;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
import me.lucko.luckperms.common.utils.Iterators;
|
import me.lucko.luckperms.common.utils.Iterators;
|
||||||
|
|
||||||
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
||||||
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class BungeeSchedulerAdapter implements SchedulerAdapter {
|
public class BungeeSchedulerAdapter implements SchedulerAdapter {
|
||||||
|
|
||||||
// the number of ticks which occur in a second - this is a server implementation detail
|
|
||||||
public static final int TICKS_PER_SECOND = 20;
|
|
||||||
// the number of milliseconds in a second - constant
|
|
||||||
public static final int MILLISECONDS_PER_SECOND = 1000;
|
|
||||||
// the number of milliseconds in a tick - assuming the server runs at a perfect tick rate
|
|
||||||
public static final int MILLISECONDS_PER_TICK = MILLISECONDS_PER_SECOND / TICKS_PER_SECOND;
|
|
||||||
|
|
||||||
private static long ticksToMillis(long ticks) {
|
|
||||||
return ticks * MILLISECONDS_PER_TICK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final LPBungeeBootstrap bootstrap;
|
private final LPBungeeBootstrap bootstrap;
|
||||||
|
|
||||||
private final Executor asyncExecutor;
|
private final Executor executor;
|
||||||
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
private final Set<ScheduledTask> tasks = Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
|
|
||||||
public BungeeSchedulerAdapter(LPBungeeBootstrap bootstrap) {
|
public BungeeSchedulerAdapter(LPBungeeBootstrap bootstrap) {
|
||||||
this.bootstrap = bootstrap;
|
this.bootstrap = bootstrap;
|
||||||
this.asyncExecutor = r -> bootstrap.getProxy().getScheduler().runAsync(bootstrap, r);
|
this.executor = r -> bootstrap.getProxy().getScheduler().runAsync(bootstrap, r);
|
||||||
}
|
|
||||||
|
|
||||||
private TaskScheduler scheduler() {
|
|
||||||
return this.bootstrap.getProxy().getScheduler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Executor async() {
|
public Executor async() {
|
||||||
return this.asyncExecutor;
|
return this.executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Executor sync() {
|
public Executor sync() {
|
||||||
return this.asyncExecutor;
|
return this.executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAsync(Runnable runnable) {
|
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
|
||||||
this.asyncExecutor.execute(runnable);
|
ScheduledTask t = this.bootstrap.getProxy().getScheduler().schedule(this.bootstrap, task, delay, unit);
|
||||||
|
this.tasks.add(t);
|
||||||
|
return t::cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doSync(Runnable runnable) {
|
public SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit) {
|
||||||
doAsync(runnable);
|
ScheduledTask t = this.bootstrap.getProxy().getScheduler().schedule(this.bootstrap, task, interval, interval, unit);
|
||||||
}
|
this.tasks.add(t);
|
||||||
|
return t::cancel;
|
||||||
@Override
|
|
||||||
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
|
||||||
long millis = ticksToMillis(intervalTicks);
|
|
||||||
SchedulerTask task = new BungeeSchedulerTask(scheduler().schedule(this.bootstrap, runnable, millis, millis, TimeUnit.MILLISECONDS));
|
|
||||||
this.tasks.add(task);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
|
||||||
return asyncRepeating(runnable, intervalTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
|
||||||
return new BungeeSchedulerTask(scheduler().schedule(this.bootstrap, runnable, ticksToMillis(delayTicks), TimeUnit.MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
|
||||||
return asyncLater(runnable, delayTicks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
Iterators.iterate(this.tasks, SchedulerTask::cancel);
|
Iterators.iterate(this.tasks, ScheduledTask::cancel);
|
||||||
}
|
|
||||||
|
|
||||||
private static final class BungeeSchedulerTask implements SchedulerTask {
|
|
||||||
private final ScheduledTask task;
|
|
||||||
|
|
||||||
private BungeeSchedulerTask(ScheduledTask task) {
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancel() {
|
|
||||||
this.task.cancel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ import me.lucko.luckperms.api.platform.PlatformType;
|
|||||||
import me.lucko.luckperms.bungee.util.RedisBungeeUtil;
|
import me.lucko.luckperms.bungee.util.RedisBungeeUtil;
|
||||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||||
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
|
||||||
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
@ -35,7 +35,7 @@ import me.lucko.luckperms.bungee.listeners.BungeeConnectionListener;
|
|||||||
import me.lucko.luckperms.bungee.listeners.BungeePermissionCheckListener;
|
import me.lucko.luckperms.bungee.listeners.BungeePermissionCheckListener;
|
||||||
import me.lucko.luckperms.bungee.messaging.BungeeMessagingFactory;
|
import me.lucko.luckperms.bungee.messaging.BungeeMessagingFactory;
|
||||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.command.CommandManager;
|
import me.lucko.luckperms.common.command.CommandManager;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
import me.lucko.luckperms.common.contexts.ContextManager;
|
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||||
@ -61,6 +61,7 @@ import java.nio.file.Files;
|
|||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,7 +131,7 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PlatformCalculatorFactory provideCalculatorFactory() {
|
protected CalculatorFactory provideCalculatorFactory() {
|
||||||
return new BungeeCalculatorFactory(this);
|
return new BungeeCalculatorFactory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +162,8 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerHousekeepingTasks() {
|
protected void registerHousekeepingTasks() {
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 3, TimeUnit.SECONDS);
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,7 +29,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
|
|
||||||
import me.lucko.luckperms.api.Contexts;
|
import me.lucko.luckperms.api.Contexts;
|
||||||
import me.lucko.luckperms.bungee.LPBungeePlugin;
|
import me.lucko.luckperms.bungee.LPBungeePlugin;
|
||||||
import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
@ -38,7 +38,7 @@ import me.lucko.luckperms.common.processors.PermissionProcessor;
|
|||||||
import me.lucko.luckperms.common.processors.RegexProcessor;
|
import me.lucko.luckperms.common.processors.RegexProcessor;
|
||||||
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
||||||
|
|
||||||
public class BungeeCalculatorFactory extends AbstractCalculatorFactory {
|
public class BungeeCalculatorFactory implements CalculatorFactory {
|
||||||
private final LPBungeePlugin plugin;
|
private final LPBungeePlugin plugin;
|
||||||
|
|
||||||
public BungeeCalculatorFactory(LPBungeePlugin plugin) {
|
public BungeeCalculatorFactory(LPBungeePlugin plugin) {
|
||||||
@ -59,6 +59,6 @@ public class BungeeCalculatorFactory extends AbstractCalculatorFactory {
|
|||||||
processors.add(new WildcardProcessor());
|
processors.add(new WildcardProcessor());
|
||||||
}
|
}
|
||||||
|
|
||||||
return registerCalculator(new PermissionCalculator(this.plugin, metadata, processors.build()));
|
return new PermissionCalculator(this.plugin, metadata, processors.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
|
|||||||
this.plugin.getLogger().info("Processing pre-login for " + c.getUniqueId() + " - " + c.getName());
|
this.plugin.getLogger().info("Processing pre-login for " + c.getUniqueId() + " - " + c.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
recordConnection(c.getUniqueId());
|
recordConnection(c.getUniqueId());
|
||||||
|
|
||||||
/* Actually process the login for the connection.
|
/* Actually process the login for the connection.
|
||||||
@ -139,7 +139,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
|
|||||||
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||||
|
|
||||||
// force a clear of transient nodes
|
// force a clear of transient nodes
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.clearTransientNodes();
|
user.clearTransientNodes();
|
||||||
|
@ -97,7 +97,7 @@ public class BungeeMessenger implements Messenger, Listener {
|
|||||||
|
|
||||||
if (this.consumer.consumeIncomingMessageAsString(msg)) {
|
if (this.consumer.consumeIncomingMessageAsString(msg)) {
|
||||||
// Forward to other servers
|
// Forward to other servers
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
||||||
server.sendData(CHANNEL, data, true);
|
server.sendData(CHANNEL, data, true);
|
||||||
}
|
}
|
||||||
|
@ -1,47 +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.common.calculators;
|
|
||||||
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public abstract class AbstractCalculatorFactory implements PlatformCalculatorFactory {
|
|
||||||
private final Set<PermissionCalculator> calculators = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
|
||||||
|
|
||||||
protected PermissionCalculator registerCalculator(PermissionCalculator calculator) {
|
|
||||||
this.calculators.add(calculator);
|
|
||||||
return calculator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invalidateAll() {
|
|
||||||
for (PermissionCalculator calculator : this.calculators) {
|
|
||||||
calculator.invalidateCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -44,7 +44,6 @@ import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
|
|||||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.sender.Sender;
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
|
||||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||||
import me.lucko.luckperms.common.utils.Iterators;
|
import me.lucko.luckperms.common.utils.Iterators;
|
||||||
import me.lucko.luckperms.common.utils.Predicates;
|
import me.lucko.luckperms.common.utils.Predicates;
|
||||||
@ -126,7 +125,7 @@ public class ParentInfo extends SharedSubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final Comparator<LocalizedNode> ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> {
|
private static final Comparator<LocalizedNode> ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> {
|
||||||
int i = CollationKeyCache.compareStrings(o1.getGroupName(), o2.getGroupName());
|
int i = o1.getGroupName().compareTo(o2.getGroupName());
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,6 @@ import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
|
|||||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.sender.Sender;
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
|
||||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||||
import me.lucko.luckperms.common.utils.Iterators;
|
import me.lucko.luckperms.common.utils.Iterators;
|
||||||
import me.lucko.luckperms.common.utils.Predicates;
|
import me.lucko.luckperms.common.utils.Predicates;
|
||||||
@ -129,7 +128,7 @@ public class PermissionInfo extends SharedSubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final Comparator<LocalizedNode> ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> {
|
private static final Comparator<LocalizedNode> ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> {
|
||||||
int i = CollationKeyCache.compareStrings(o1.getPermission(), o2.getPermission());
|
int i = o1.getPermission().compareTo(o2.getPermission());
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
package me.lucko.luckperms.common.commands.log;
|
package me.lucko.luckperms.common.commands.log;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Node;
|
import me.lucko.luckperms.api.Node;
|
||||||
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
import me.lucko.luckperms.common.actionlog.Log;
|
import me.lucko.luckperms.common.actionlog.Log;
|
||||||
import me.lucko.luckperms.common.command.CommandResult;
|
import me.lucko.luckperms.common.command.CommandResult;
|
||||||
import me.lucko.luckperms.common.command.abstraction.SubCommand;
|
import me.lucko.luckperms.common.command.abstraction.SubCommand;
|
||||||
@ -54,7 +55,7 @@ public class LogNotify extends SubCommand<Log> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<? extends Node> ret = user.getOwnNodes().stream()
|
Optional<? extends Node> ret = user.enduringData().immutable().get(ContextSet.empty()).stream()
|
||||||
.filter(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"))
|
.filter(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ public class LogNotify extends SubCommand<Log> {
|
|||||||
user.setPermission(NodeFactory.make("luckperms.log.notify.ignoring"));
|
user.setPermission(NodeFactory.make("luckperms.log.notify.ignoring"));
|
||||||
} else {
|
} else {
|
||||||
// remove the perm
|
// remove the perm
|
||||||
user.removeIf(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"));
|
user.removeIf(ContextSet.empty(), n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"));
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getStorage().saveUser(user).join();
|
plugin.getStorage().saveUser(user).join();
|
||||||
|
@ -85,7 +85,7 @@ public class ExportCommand extends SingleCommand {
|
|||||||
Exporter exporter = new Exporter(plugin, sender, path, includeUsers);
|
Exporter exporter = new Exporter(plugin, sender, path, includeUsers);
|
||||||
|
|
||||||
// Run the exporter in its own thread.
|
// Run the exporter in its own thread.
|
||||||
plugin.getBootstrap().getScheduler().doAsync(() -> {
|
plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
try {
|
try {
|
||||||
exporter.run();
|
exporter.run();
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -86,7 +86,7 @@ public class ImportCommand extends SingleCommand {
|
|||||||
Importer importer = new Importer(plugin.getCommandManager(), sender, commands);
|
Importer importer = new Importer(plugin.getCommandManager(), sender, commands);
|
||||||
|
|
||||||
// Run the importer in its own thread.
|
// Run the importer in its own thread.
|
||||||
plugin.getBootstrap().getScheduler().doAsync(() -> {
|
plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
try {
|
try {
|
||||||
importer.run();
|
importer.run();
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -25,34 +25,31 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.config;
|
package me.lucko.luckperms.common.config;
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.common.api.delegates.misc.ApiConfiguration;
|
import me.lucko.luckperms.common.api.delegates.misc.ApiConfiguration;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
import me.lucko.luckperms.common.config.keys.EnduringKey;
|
import me.lucko.luckperms.common.config.keys.EnduringKey;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract implementation of {@link LuckPermsConfiguration}, backed by a cache.
|
* An abstract implementation of {@link LuckPermsConfiguration}.
|
||||||
|
*
|
||||||
|
* <p>Values are loaded into memory on init.</p>
|
||||||
*/
|
*/
|
||||||
public class AbstractConfiguration implements LuckPermsConfiguration, CacheLoader<ConfigKey<?>, Optional<Object>> {
|
public class AbstractConfiguration implements LuckPermsConfiguration {
|
||||||
|
|
||||||
// the loading cache for config keys --> their value
|
/**
|
||||||
// the value is wrapped in an optional as null values don't get cached.
|
* The configurations loaded values.
|
||||||
private final LoadingCache<ConfigKey<?>, Optional<Object>> cache = Caffeine.newBuilder().build(this);
|
*
|
||||||
|
* <p>The value corresponding to each key is stored at the index defined
|
||||||
|
* by {@link ConfigKey#ordinal()}.</p>
|
||||||
|
*/
|
||||||
|
private Object[] values = null;
|
||||||
|
|
||||||
// the plugin instance
|
|
||||||
private final LuckPermsPlugin plugin;
|
private final LuckPermsPlugin plugin;
|
||||||
// the adapter used to read values
|
|
||||||
private final ConfigurationAdapter adapter;
|
private final ConfigurationAdapter adapter;
|
||||||
|
|
||||||
// the api delegate
|
// the api delegate
|
||||||
private final ApiConfiguration delegate = new ApiConfiguration(this);
|
private final ApiConfiguration delegate = new ApiConfiguration(this);
|
||||||
// the contextsfile handler
|
// the contextsfile handler
|
||||||
@ -61,6 +58,52 @@ public class AbstractConfiguration implements LuckPermsConfiguration, CacheLoade
|
|||||||
public AbstractConfiguration(LuckPermsPlugin plugin, ConfigurationAdapter adapter) {
|
public AbstractConfiguration(LuckPermsPlugin plugin, ConfigurationAdapter adapter) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.adapter = adapter;
|
this.adapter = adapter;
|
||||||
|
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public <T> T get(ConfigKey<T> key) {
|
||||||
|
return (T) this.values[key.ordinal()];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void load() {
|
||||||
|
// get the map of all keys
|
||||||
|
Map<String, ConfigKey<?>> keys = ConfigKeys.getAllKeys();
|
||||||
|
|
||||||
|
// if this is a reload operation
|
||||||
|
boolean reload = true;
|
||||||
|
|
||||||
|
// if values are null, must be loading for the first time
|
||||||
|
if (this.values == null) {
|
||||||
|
this.values = new Object[keys.size()];
|
||||||
|
reload = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load a value for each key.
|
||||||
|
for (ConfigKey<?> key : keys.values()) {
|
||||||
|
// don't reload enduring keys.
|
||||||
|
if (reload && key instanceof EnduringKey) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the value for the key
|
||||||
|
Object value = key.get(this.adapter);
|
||||||
|
this.values[key.ordinal()] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the contexts file
|
||||||
|
this.contextsFile.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
this.adapter.reload();
|
||||||
|
load();
|
||||||
|
|
||||||
|
getPlugin().getEventFactory().handleConfigReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationAdapter getAdapter() {
|
public ConfigurationAdapter getAdapter() {
|
||||||
@ -81,36 +124,4 @@ public class AbstractConfiguration implements LuckPermsConfiguration, CacheLoade
|
|||||||
public ContextsFile getContextsFile() {
|
public ContextsFile getContextsFile() {
|
||||||
return this.contextsFile;
|
return this.contextsFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public <T> T get(ConfigKey<T> key) {
|
|
||||||
Optional<Object> ret = this.cache.get(key);
|
|
||||||
if (ret == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (T) ret.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadAll() {
|
|
||||||
ConfigKeys.getAllKeys().values().forEach(this.cache::get);
|
|
||||||
this.contextsFile.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reload() {
|
|
||||||
this.adapter.reload();
|
|
||||||
|
|
||||||
Set<ConfigKey<?>> toInvalidate = this.cache.asMap().keySet().stream().filter(k -> !(k instanceof EnduringKey)).collect(Collectors.toSet());
|
|
||||||
this.cache.invalidateAll(toInvalidate);
|
|
||||||
|
|
||||||
loadAll();
|
|
||||||
getPlugin().getEventFactory().handleConfigReload();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Object> load(@Nonnull ConfigKey<?> key) {
|
|
||||||
return Optional.ofNullable(key.get(this.adapter));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,17 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.calculators;
|
package me.lucko.luckperms.common.config;
|
||||||
|
|
||||||
/**
|
public abstract class BaseConfigKey<T> implements ConfigKey<T> {
|
||||||
* Extension of {@link CalculatorFactory} which keeps a record of produced
|
int ordinal = -1;
|
||||||
* calculators and provides a means to invalidate them all in bulk.
|
|
||||||
*/
|
|
||||||
public interface PlatformCalculatorFactory extends CalculatorFactory {
|
|
||||||
|
|
||||||
/**
|
protected BaseConfigKey() {
|
||||||
* Invalidates all calculators build by this factory
|
|
||||||
*/
|
|
||||||
void invalidateAll();
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int ordinal() {
|
||||||
|
return this.ordinal;
|
||||||
|
}
|
||||||
}
|
}
|
@ -34,6 +34,16 @@ import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
|||||||
*/
|
*/
|
||||||
public interface ConfigKey<T> {
|
public interface ConfigKey<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the position of this key within the {@link ConfigKeys} enum.
|
||||||
|
*
|
||||||
|
* <p>This is lazily set when the configuration is loaded for the first time, during the
|
||||||
|
* execution of {@link ConfigKeys#getAllKeys()}.</p>
|
||||||
|
*
|
||||||
|
* @return the position
|
||||||
|
*/
|
||||||
|
int ordinal();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves and returns the value mapped to this key using the given config instance.
|
* Resolves and returns the value mapped to this key using the given config instance.
|
||||||
*
|
*
|
||||||
|
@ -33,8 +33,8 @@ import me.lucko.luckperms.api.LookupSetting;
|
|||||||
import me.lucko.luckperms.api.context.ContextSet;
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
|
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
|
||||||
import me.lucko.luckperms.common.assignments.AssignmentRule;
|
import me.lucko.luckperms.common.assignments.AssignmentRule;
|
||||||
import me.lucko.luckperms.common.config.keys.AbstractKey;
|
|
||||||
import me.lucko.luckperms.common.config.keys.BooleanKey;
|
import me.lucko.luckperms.common.config.keys.BooleanKey;
|
||||||
|
import me.lucko.luckperms.common.config.keys.CustomKey;
|
||||||
import me.lucko.luckperms.common.config.keys.EnduringKey;
|
import me.lucko.luckperms.common.config.keys.EnduringKey;
|
||||||
import me.lucko.luckperms.common.config.keys.LowercaseStringKey;
|
import me.lucko.luckperms.common.config.keys.LowercaseStringKey;
|
||||||
import me.lucko.luckperms.common.config.keys.MapKey;
|
import me.lucko.luckperms.common.config.keys.MapKey;
|
||||||
@ -64,13 +64,16 @@ import java.util.function.Function;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* All of the {@link ConfigKey}s used by LuckPerms.
|
* All of the {@link ConfigKey}s used by LuckPerms.
|
||||||
|
*
|
||||||
|
* <p>The {@link #getAllKeys()} method and associated behaviour allows this class to behave
|
||||||
|
* a bit like an enum with generics.</p>
|
||||||
*/
|
*/
|
||||||
public class ConfigKeys {
|
public final class ConfigKeys {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the server
|
* The name of the server
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<String> SERVER = AbstractKey.of(c -> {
|
public static final ConfigKey<String> SERVER = CustomKey.of(c -> {
|
||||||
if (c.getBoolean("use-server-properties-name", false)) {
|
if (c.getBoolean("use-server-properties-name", false)) {
|
||||||
String serverName = c.getPlugin().getBootstrap().getServerName();
|
String serverName = c.getPlugin().getBootstrap().getServerName();
|
||||||
if (serverName != null && !serverName.equals("Unknown Server")) {
|
if (serverName != null && !serverName.equals("Unknown Server")) {
|
||||||
@ -84,7 +87,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* How many minutes to wait between syncs. A value <= 0 will disable syncing.
|
* How many minutes to wait between syncs. A value <= 0 will disable syncing.
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<Integer> SYNC_TIME = EnduringKey.wrap(AbstractKey.of(c -> {
|
public static final ConfigKey<Integer> SYNC_TIME = EnduringKey.wrap(CustomKey.of(c -> {
|
||||||
int val = c.getInt("sync-minutes", -1);
|
int val = c.getInt("sync-minutes", -1);
|
||||||
if (val == -1) {
|
if (val == -1) {
|
||||||
val = c.getInt("data.sync-minutes", -1);
|
val = c.getInt("data.sync-minutes", -1);
|
||||||
@ -95,7 +98,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The lookup settings for contexts (care should be taken to not mutate this method)
|
* The lookup settings for contexts (care should be taken to not mutate this method)
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<EnumSet<LookupSetting>> LOOKUP_SETTINGS = AbstractKey.of(c -> {
|
public static final ConfigKey<EnumSet<LookupSetting>> LOOKUP_SETTINGS = CustomKey.of(c -> {
|
||||||
return EnumSet.copyOf(Contexts.of(
|
return EnumSet.copyOf(Contexts.of(
|
||||||
ContextSet.empty(),
|
ContextSet.empty(),
|
||||||
c.getBoolean("include-global", true),
|
c.getBoolean("include-global", true),
|
||||||
@ -130,7 +133,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* Controls how temporary add commands should behave
|
* Controls how temporary add commands should behave
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<TemporaryModifier> TEMPORARY_ADD_BEHAVIOUR = AbstractKey.of(c -> {
|
public static final ConfigKey<TemporaryModifier> TEMPORARY_ADD_BEHAVIOUR = CustomKey.of(c -> {
|
||||||
String option = c.getString("temporary-add-behaviour", "deny").toLowerCase();
|
String option = c.getString("temporary-add-behaviour", "deny").toLowerCase();
|
||||||
if (!option.equals("deny") && !option.equals("replace") && !option.equals("accumulate")) {
|
if (!option.equals("deny") && !option.equals("replace") && !option.equals("accumulate")) {
|
||||||
option = "deny";
|
option = "deny";
|
||||||
@ -142,7 +145,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* How primary groups should be calculated.
|
* How primary groups should be calculated.
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<String> PRIMARY_GROUP_CALCULATION_METHOD = EnduringKey.wrap(AbstractKey.of(c -> {
|
public static final ConfigKey<String> PRIMARY_GROUP_CALCULATION_METHOD = EnduringKey.wrap(CustomKey.of(c -> {
|
||||||
String option = c.getString("primary-group-calculation", "stored").toLowerCase();
|
String option = c.getString("primary-group-calculation", "stored").toLowerCase();
|
||||||
if (!option.equals("stored") && !option.equals("parents-by-weight") && !option.equals("all-parents-by-weight")) {
|
if (!option.equals("stored") && !option.equals("parents-by-weight") && !option.equals("all-parents-by-weight")) {
|
||||||
option = "stored";
|
option = "stored";
|
||||||
@ -154,7 +157,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* A function to create primary group holder instances based upon the {@link #PRIMARY_GROUP_CALCULATION_METHOD} setting.
|
* A function to create primary group holder instances based upon the {@link #PRIMARY_GROUP_CALCULATION_METHOD} setting.
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<Function<User, PrimaryGroupHolder>> PRIMARY_GROUP_CALCULATION = EnduringKey.wrap(AbstractKey.of(c -> {
|
public static final ConfigKey<Function<User, PrimaryGroupHolder>> PRIMARY_GROUP_CALCULATION = EnduringKey.wrap(CustomKey.of(c -> {
|
||||||
String option = PRIMARY_GROUP_CALCULATION_METHOD.get(c);
|
String option = PRIMARY_GROUP_CALCULATION_METHOD.get(c);
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case "stored":
|
case "stored":
|
||||||
@ -245,7 +248,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The algorithm LuckPerms should use when traversing the "inheritance tree"
|
* The algorithm LuckPerms should use when traversing the "inheritance tree"
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<TraversalAlgorithm> INHERITANCE_TRAVERSAL_ALGORITHM = AbstractKey.of(c -> {
|
public static final ConfigKey<TraversalAlgorithm> INHERITANCE_TRAVERSAL_ALGORITHM = CustomKey.of(c -> {
|
||||||
String value = c.getString("inheritance-traversal-algorithm", "depth-first-pre-order");
|
String value = c.getString("inheritance-traversal-algorithm", "depth-first-pre-order");
|
||||||
switch (value.toLowerCase()) {
|
switch (value.toLowerCase()) {
|
||||||
case "breadth-first":
|
case "breadth-first":
|
||||||
@ -260,7 +263,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The configured group weightings
|
* The configured group weightings
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<Map<String, Integer>> GROUP_WEIGHTS = AbstractKey.of(c -> {
|
public static final ConfigKey<Map<String, Integer>> GROUP_WEIGHTS = CustomKey.of(c -> {
|
||||||
return c.getMap("group-weight", ImmutableMap.of()).entrySet().stream().collect(ImmutableCollectors.toMap(
|
return c.getMap("group-weight", ImmutableMap.of()).entrySet().stream().collect(ImmutableCollectors.toMap(
|
||||||
e -> e.getKey().toLowerCase(),
|
e -> e.getKey().toLowerCase(),
|
||||||
e -> {
|
e -> {
|
||||||
@ -276,7 +279,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* Creates a new prefix MetaStack element based upon the configured values.
|
* Creates a new prefix MetaStack element based upon the configured values.
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<MetaStackDefinition> PREFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
public static final ConfigKey<MetaStackDefinition> PREFIX_FORMATTING_OPTIONS = CustomKey.of(l -> {
|
||||||
List<String> format = l.getList("meta-formatting.prefix.format", new ArrayList<>());
|
List<String> format = l.getList("meta-formatting.prefix.format", new ArrayList<>());
|
||||||
if (format.isEmpty()) {
|
if (format.isEmpty()) {
|
||||||
format.add("highest");
|
format.add("highest");
|
||||||
@ -291,7 +294,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* Creates a new suffix MetaStack element based upon the configured values.
|
* Creates a new suffix MetaStack element based upon the configured values.
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<MetaStackDefinition> SUFFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
public static final ConfigKey<MetaStackDefinition> SUFFIX_FORMATTING_OPTIONS = CustomKey.of(l -> {
|
||||||
List<String> format = l.getList("meta-formatting.suffix.format", new ArrayList<>());
|
List<String> format = l.getList("meta-formatting.suffix.format", new ArrayList<>());
|
||||||
if (format.isEmpty()) {
|
if (format.isEmpty()) {
|
||||||
format.add("highest");
|
format.add("highest");
|
||||||
@ -316,7 +319,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* If server operators should be enabled. Only used by the Bukkit platform.
|
* If server operators should be enabled. Only used by the Bukkit platform.
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<Boolean> OPS_ENABLED = EnduringKey.wrap(AbstractKey.of(c -> !AUTO_OP.get(c) && c.getBoolean("enable-ops", true)));
|
public static final ConfigKey<Boolean> OPS_ENABLED = EnduringKey.wrap(CustomKey.of(c -> !AUTO_OP.get(c) && c.getBoolean("enable-ops", true)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If server operators should be able to use LuckPerms commands by default. Only used by the Bukkit platform.
|
* If server operators should be able to use LuckPerms commands by default. Only used by the Bukkit platform.
|
||||||
@ -331,7 +334,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The name of the server to use for Vault.
|
* The name of the server to use for Vault.
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<String> VAULT_SERVER = AbstractKey.of(c -> {
|
public static final ConfigKey<String> VAULT_SERVER = CustomKey.of(c -> {
|
||||||
// default to true for backwards compatibility
|
// default to true for backwards compatibility
|
||||||
if (USE_VAULT_SERVER.get(c)) {
|
if (USE_VAULT_SERVER.get(c)) {
|
||||||
return c.getString("vault-server", "global").toLowerCase();
|
return c.getString("vault-server", "global").toLowerCase();
|
||||||
@ -358,7 +361,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The world rewrites map
|
* The world rewrites map
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<Map<String, String>> WORLD_REWRITES = AbstractKey.of(c -> {
|
public static final ConfigKey<Map<String, String>> WORLD_REWRITES = CustomKey.of(c -> {
|
||||||
return c.getMap("world-rewrite", ImmutableMap.of()).entrySet().stream()
|
return c.getMap("world-rewrite", ImmutableMap.of()).entrySet().stream()
|
||||||
.collect(ImmutableCollectors.toMap(
|
.collect(ImmutableCollectors.toMap(
|
||||||
e -> e.getKey().toLowerCase(),
|
e -> e.getKey().toLowerCase(),
|
||||||
@ -374,7 +377,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The default assignments being applied by the plugin
|
* The default assignments being applied by the plugin
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<List<AssignmentRule>> DEFAULT_ASSIGNMENTS = AbstractKey.of(c -> {
|
public static final ConfigKey<List<AssignmentRule>> DEFAULT_ASSIGNMENTS = CustomKey.of(c -> {
|
||||||
return c.getObjectList("default-assignments", ImmutableList.of()).stream().map(name -> {
|
return c.getObjectList("default-assignments", ImmutableList.of()).stream().map(name -> {
|
||||||
String hasTrue = c.getString("default-assignments." + name + ".if.has-true", null);
|
String hasTrue = c.getString("default-assignments." + name + ".if.has-true", null);
|
||||||
String hasFalse = c.getString("default-assignments." + name + ".if.has-false", null);
|
String hasFalse = c.getString("default-assignments." + name + ".if.has-false", null);
|
||||||
@ -389,7 +392,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The database settings, username, password, etc for use by any database
|
* The database settings, username, password, etc for use by any database
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<StorageCredentials> DATABASE_VALUES = EnduringKey.wrap(AbstractKey.of(c -> {
|
public static final ConfigKey<StorageCredentials> DATABASE_VALUES = EnduringKey.wrap(CustomKey.of(c -> {
|
||||||
int maxPoolSize = c.getInt("data.pool-settings.maximum-pool-size", c.getInt("data.pool-size", 10));
|
int maxPoolSize = c.getInt("data.pool-settings.maximum-pool-size", c.getInt("data.pool-size", 10));
|
||||||
int minIdle = c.getInt("data.pool-settings.minimum-idle", maxPoolSize);
|
int minIdle = c.getInt("data.pool-settings.minimum-idle", maxPoolSize);
|
||||||
int maxLifetime = c.getInt("data.pool-settings.maximum-lifetime", 1800000);
|
int maxLifetime = c.getInt("data.pool-settings.maximum-lifetime", 1800000);
|
||||||
@ -438,7 +441,7 @@ public class ConfigKeys {
|
|||||||
/**
|
/**
|
||||||
* The options for split storage
|
* The options for split storage
|
||||||
*/
|
*/
|
||||||
public static final ConfigKey<Map<SplitStorageType, String>> SPLIT_STORAGE_OPTIONS = EnduringKey.wrap(AbstractKey.of(c -> {
|
public static final ConfigKey<Map<SplitStorageType, String>> SPLIT_STORAGE_OPTIONS = EnduringKey.wrap(CustomKey.of(c -> {
|
||||||
EnumMap<SplitStorageType, String> map = new EnumMap<>(SplitStorageType.class);
|
EnumMap<SplitStorageType, String> map = new EnumMap<>(SplitStorageType.class);
|
||||||
map.put(SplitStorageType.USER, c.getString("split-storage.methods.user", "h2").toLowerCase());
|
map.put(SplitStorageType.USER, c.getString("split-storage.methods.user", "h2").toLowerCase());
|
||||||
map.put(SplitStorageType.GROUP, c.getString("split-storage.methods.group", "h2").toLowerCase());
|
map.put(SplitStorageType.GROUP, c.getString("split-storage.methods.group", "h2").toLowerCase());
|
||||||
@ -511,15 +514,25 @@ public class ConfigKeys {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Field[] values = ConfigKeys.class.getFields();
|
Field[] values = ConfigKeys.class.getFields();
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
for (Field f : values) {
|
for (Field f : values) {
|
||||||
|
// ignore non-static fields
|
||||||
if (!Modifier.isStatic(f.getModifiers())) {
|
if (!Modifier.isStatic(f.getModifiers())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object val = f.get(null);
|
// ignore fields that aren't configkeys
|
||||||
if (val instanceof ConfigKey<?>) {
|
if (!ConfigKey.class.equals(f.getType())) {
|
||||||
keys.put(f.getName(), (ConfigKey<?>) val);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the key instance
|
||||||
|
BaseConfigKey<?> key = (BaseConfigKey<?>) f.get(null);
|
||||||
|
// set the ordinal value of the key.
|
||||||
|
key.ordinal = counter++;
|
||||||
|
// add the key to the return map
|
||||||
|
keys.put(f.getName(), key);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -60,9 +60,9 @@ public interface LuckPermsConfiguration {
|
|||||||
void reload();
|
void reload();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pre-loads all configuration keys into the cache.
|
* Loads all configuration values.
|
||||||
*/
|
*/
|
||||||
void loadAll();
|
void load();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of a given context key.
|
* Gets the value of a given context key.
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.config.keys;
|
package me.lucko.luckperms.common.config.keys;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.config.ConfigKey;
|
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
|
||||||
public class BooleanKey implements ConfigKey<Boolean> {
|
public class BooleanKey extends BaseConfigKey<Boolean> {
|
||||||
public static BooleanKey of(String path, boolean def) {
|
public static BooleanKey of(String path, boolean def) {
|
||||||
return new BooleanKey(path, def);
|
return new BooleanKey(path, def);
|
||||||
}
|
}
|
||||||
|
@ -25,19 +25,19 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.config.keys;
|
package me.lucko.luckperms.common.config.keys;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.config.ConfigKey;
|
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class AbstractKey<T> implements ConfigKey<T> {
|
public class CustomKey<T> extends BaseConfigKey<T> {
|
||||||
public static <T> AbstractKey<T> of(Function<ConfigurationAdapter, T> function) {
|
public static <T> CustomKey<T> of(Function<ConfigurationAdapter, T> function) {
|
||||||
return new AbstractKey<>(function);
|
return new CustomKey<>(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Function<ConfigurationAdapter, T> function;
|
private final Function<ConfigurationAdapter, T> function;
|
||||||
|
|
||||||
private AbstractKey(Function<ConfigurationAdapter, T> function) {
|
private CustomKey(Function<ConfigurationAdapter, T> function) {
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.config.keys;
|
package me.lucko.luckperms.common.config.keys;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||||
import me.lucko.luckperms.common.config.ConfigKey;
|
import me.lucko.luckperms.common.config.ConfigKey;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
|||||||
* Wrapper class to mark a config key as enduring (doesn't change in the event of a reload)
|
* Wrapper class to mark a config key as enduring (doesn't change in the event of a reload)
|
||||||
* @param <T>
|
* @param <T>
|
||||||
*/
|
*/
|
||||||
public class EnduringKey<T> implements ConfigKey<T> {
|
public class EnduringKey<T> extends BaseConfigKey<T> {
|
||||||
|
|
||||||
public static <T> EnduringKey<T> wrap(ConfigKey<T> delegate) {
|
public static <T> EnduringKey<T> wrap(ConfigKey<T> delegate) {
|
||||||
return new EnduringKey<>(delegate);
|
return new EnduringKey<>(delegate);
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.config.keys;
|
package me.lucko.luckperms.common.config.keys;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.config.ConfigKey;
|
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
|
||||||
public class IntegerKey implements ConfigKey<Integer> {
|
public class IntegerKey extends BaseConfigKey<Integer> {
|
||||||
public static IntegerKey of(String path, int def) {
|
public static IntegerKey of(String path, int def) {
|
||||||
return new IntegerKey(path, def);
|
return new IntegerKey(path, def);
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.config.keys;
|
package me.lucko.luckperms.common.config.keys;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.config.ConfigKey;
|
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
|
||||||
public class LowercaseStringKey implements ConfigKey<String> {
|
public class LowercaseStringKey extends BaseConfigKey<String> {
|
||||||
public static LowercaseStringKey of(String path, String def) {
|
public static LowercaseStringKey of(String path, String def) {
|
||||||
return new LowercaseStringKey(path, def);
|
return new LowercaseStringKey(path, def);
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,12 @@ package me.lucko.luckperms.common.config.keys;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.config.ConfigKey;
|
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class MapKey implements ConfigKey<Map<String, String>> {
|
public class MapKey extends BaseConfigKey<Map<String, String>> {
|
||||||
public static MapKey of(String path) {
|
public static MapKey of(String path) {
|
||||||
return new MapKey(path);
|
return new MapKey(path);
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.config.keys;
|
package me.lucko.luckperms.common.config.keys;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.config.ConfigKey;
|
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
|
|
||||||
public class StringKey implements ConfigKey<String> {
|
public class StringKey extends BaseConfigKey<String> {
|
||||||
public static StringKey of(String path, String def) {
|
public static StringKey of(String path, String def) {
|
||||||
return new StringKey(path, def);
|
return new StringKey(path, def);
|
||||||
}
|
}
|
||||||
|
@ -221,6 +221,6 @@ public abstract class AbstractEventBus<P> implements EventBus, AutoCloseable {
|
|||||||
if (event instanceof Cancellable) {
|
if (event instanceof Cancellable) {
|
||||||
throw new IllegalArgumentException("cannot call Cancellable event async");
|
throw new IllegalArgumentException("cannot call Cancellable event async");
|
||||||
}
|
}
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> fireEvent(event));
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> fireEvent(event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,6 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.inheritance;
|
package me.lucko.luckperms.common.inheritance;
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Contexts;
|
import me.lucko.luckperms.api.Contexts;
|
||||||
import me.lucko.luckperms.api.LookupSetting;
|
import me.lucko.luckperms.api.LookupSetting;
|
||||||
import me.lucko.luckperms.api.Node;
|
import me.lucko.luckperms.api.Node;
|
||||||
@ -38,7 +35,6 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides {@link InheritanceGraph}s.
|
* Provides {@link InheritanceGraph}s.
|
||||||
@ -51,17 +47,15 @@ public class InheritanceHandler {
|
|||||||
*/
|
*/
|
||||||
private final InheritanceGraph nonContextualGraph;
|
private final InheritanceGraph nonContextualGraph;
|
||||||
|
|
||||||
/**
|
// some cached contextual graphs for common Contexts
|
||||||
* Cache of contextual inheritance graph instances
|
private final InheritanceGraph allowAllContextualGraph;
|
||||||
*/
|
private final InheritanceGraph globalContextualGraph;
|
||||||
private final LoadingCache<Contexts, InheritanceGraph> contextualGraphs;
|
|
||||||
|
|
||||||
public InheritanceHandler(LuckPermsPlugin plugin) {
|
public InheritanceHandler(LuckPermsPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.nonContextualGraph = new NonContextualGraph(plugin);
|
this.nonContextualGraph = new NonContextualGraph(plugin);
|
||||||
this.contextualGraphs = Caffeine.newBuilder()
|
this.allowAllContextualGraph = new ContextualGraph(plugin, Contexts.allowAll());
|
||||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
this.globalContextualGraph = new ContextualGraph(plugin, Contexts.global());
|
||||||
.build(key -> new ContextualGraph(this.plugin, key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public InheritanceGraph getGraph() {
|
public InheritanceGraph getGraph() {
|
||||||
@ -69,7 +63,14 @@ public class InheritanceHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public InheritanceGraph getGraph(Contexts contexts) {
|
public InheritanceGraph getGraph(Contexts contexts) {
|
||||||
return this.contextualGraphs.get(contexts);
|
if (contexts == Contexts.allowAll()) {
|
||||||
|
return this.allowAllContextualGraph;
|
||||||
|
}
|
||||||
|
if (contexts == Contexts.global()) {
|
||||||
|
return this.globalContextualGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ContextualGraph(this.plugin, contexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class NonContextualGraph implements InheritanceGraph {
|
private static final class NonContextualGraph implements InheritanceGraph {
|
||||||
|
@ -37,6 +37,7 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public abstract class AbstractUserManager<T extends User> extends AbstractManager<UserIdentifier, User, T> implements UserManager<T> {
|
public abstract class AbstractUserManager<T extends User> extends AbstractManager<UserIdentifier, User, T> implements UserManager<T> {
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
|
|||||||
public AbstractUserManager(LuckPermsPlugin plugin, UserHousekeeper.TimeoutSettings timeoutSettings) {
|
public AbstractUserManager(LuckPermsPlugin plugin, UserHousekeeper.TimeoutSettings timeoutSettings) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.housekeeper = new UserHousekeeper(plugin, this, timeoutSettings);
|
this.housekeeper = new UserHousekeeper(plugin, this, timeoutSettings);
|
||||||
this.plugin.getBootstrap().getScheduler().asyncRepeating(this.housekeeper, 200L); // every 10 seconds
|
this.plugin.getBootstrap().getScheduler().asyncRepeating(this.housekeeper, 10, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -102,7 +102,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushUpdate() {
|
public void pushUpdate() {
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
UUID requestId = generatePingId();
|
UUID requestId = generatePingId();
|
||||||
this.plugin.getLogger().info("[" + getName() + " Messaging] Sending ping with id: " + requestId);
|
this.plugin.getLogger().info("[" + getName() + " Messaging] Sending ping with id: " + requestId);
|
||||||
this.messenger.sendOutgoingMessage(new UpdateMessageImpl(requestId));
|
this.messenger.sendOutgoingMessage(new UpdateMessageImpl(requestId));
|
||||||
@ -111,7 +111,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushUserUpdate(User user) {
|
public void pushUserUpdate(User user) {
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
UUID requestId = generatePingId();
|
UUID requestId = generatePingId();
|
||||||
this.plugin.getLogger().info("[" + getName() + " Messaging] Sending user ping for '" + user.getFriendlyName() + "' with id: " + requestId);
|
this.plugin.getLogger().info("[" + getName() + " Messaging] Sending user ping for '" + user.getFriendlyName() + "' with id: " + requestId);
|
||||||
this.messenger.sendOutgoingMessage(new UserUpdateMessageImpl(requestId, user.getUuid()));
|
this.messenger.sendOutgoingMessage(new UserUpdateMessageImpl(requestId, user.getUuid()));
|
||||||
@ -120,7 +120,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushLog(LogEntry logEntry) {
|
public void pushLog(LogEntry logEntry) {
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
UUID requestId = generatePingId();
|
UUID requestId = generatePingId();
|
||||||
|
|
||||||
if (this.plugin.getEventFactory().handleLogNetworkPublish(!this.plugin.getConfiguration().get(ConfigKeys.PUSH_LOG_ENTRIES), requestId, logEntry)) {
|
if (this.plugin.getEventFactory().handleLogNetworkPublish(!this.plugin.getConfiguration().get(ConfigKeys.PUSH_LOG_ENTRIES), requestId, logEntry)) {
|
||||||
|
@ -65,7 +65,7 @@ public class RedisMessenger implements Messenger {
|
|||||||
this.jedisPool = new JedisPool(new JedisPoolConfig(), host, port, 0, password);
|
this.jedisPool = new JedisPool(new JedisPoolConfig(), host, port, 0, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
this.sub = new LPSub(this);
|
this.sub = new LPSub(this);
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||||
jedis.subscribe(this.sub, CHANNEL);
|
jedis.subscribe(this.sub, CHANNEL);
|
||||||
|
@ -27,12 +27,13 @@ package me.lucko.luckperms.common.messaging.sql;
|
|||||||
|
|
||||||
import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
|
import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
import me.lucko.luckperms.common.storage.dao.sql.SqlDao;
|
import me.lucko.luckperms.common.storage.dao.sql.SqlDao;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class SqlMessenger extends AbstractSqlMessenger {
|
public class SqlMessenger extends AbstractSqlMessenger {
|
||||||
private final LuckPermsPlugin plugin;
|
private final LuckPermsPlugin plugin;
|
||||||
@ -57,8 +58,8 @@ public class SqlMessenger extends AbstractSqlMessenger {
|
|||||||
|
|
||||||
// schedule poll tasks
|
// schedule poll tasks
|
||||||
SchedulerAdapter scheduler = this.plugin.getBootstrap().getScheduler();
|
SchedulerAdapter scheduler = this.plugin.getBootstrap().getScheduler();
|
||||||
this.pollTask = scheduler.asyncRepeating(this::pollMessages, 20L);
|
this.pollTask = scheduler.asyncRepeating(this::pollMessages, 1, TimeUnit.SECONDS);
|
||||||
this.housekeepingTask = scheduler.asyncRepeating(this::runHousekeeping, 20L * 30);
|
this.housekeepingTask = scheduler.asyncRepeating(this::runHousekeeping, 30, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
package me.lucko.luckperms.common.node.comparator;
|
package me.lucko.luckperms.common.node.comparator;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Node;
|
import me.lucko.luckperms.api.Node;
|
||||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
@ -65,6 +64,6 @@ public class NodeComparator implements Comparator<Node> {
|
|||||||
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
|
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CollationKeyCache.compareStrings(o1.getPermission(), o2.getPermission()) == 1 ? -1 : 1;
|
return o1.getPermission().compareTo(o2.getPermission()) > 0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
package me.lucko.luckperms.common.node.comparator;
|
package me.lucko.luckperms.common.node.comparator;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Node;
|
import me.lucko.luckperms.api.Node;
|
||||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
import me.lucko.luckperms.common.contexts.ContextSetComparator;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
@ -58,35 +58,16 @@ public class NodeWithContextComparator implements Comparator<Node> {
|
|||||||
return o1.isOverride() ? 1 : -1;
|
return o1.isOverride() ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o1.isServerSpecific() != o2.isServerSpecific()) {
|
int i = ContextSetComparator.normal().compare(
|
||||||
return o1.isServerSpecific() ? 1 : -1;
|
o1.getFullContexts().makeImmutable(),
|
||||||
|
o2.getFullContexts().makeImmutable()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o1.isWorldSpecific() != o2.isWorldSpecific()) {
|
return NodeComparator.normal().compare(o1, o2);
|
||||||
return o1.isWorldSpecific() ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o1.getContexts().size() != o2.getContexts().size()) {
|
|
||||||
return o1.getContexts().size() > o2.getContexts().size() ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o1.isTemporary() != o2.isTemporary()) {
|
|
||||||
return o1.isTemporary() ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o1.isWildcard() != o2.isWildcard()) {
|
|
||||||
return o1.isWildcard() ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o1.isTemporary()) {
|
|
||||||
return o1.getSecondsTilExpiry() < o2.getSecondsTilExpiry() ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o1.isWildcard()) {
|
|
||||||
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CollationKeyCache.compareStrings(o1.getPermission(), o2.getPermission()) == 1 ? -1 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ import javax.annotation.Nonnull;
|
|||||||
|
|
||||||
public abstract class ForwardingNode implements Node {
|
public abstract class ForwardingNode implements Node {
|
||||||
|
|
||||||
protected abstract Node delegate();
|
public abstract Node delegate();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -52,7 +52,7 @@ public final class ImmutableLocalizedNode extends ForwardingNode implements Loca
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node delegate() {
|
public Node delegate() {
|
||||||
return this.node;
|
return this.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,6 @@ public final class ImmutableNode implements Node {
|
|||||||
|
|
||||||
|
|
||||||
// cached state
|
// cached state
|
||||||
|
|
||||||
private final Optional<String> optServer;
|
private final Optional<String> optServer;
|
||||||
private final Optional<String> optWorld;
|
private final Optional<String> optWorld;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ public final class ImmutableTransientNode<O> extends ForwardingNode implements N
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node delegate() {
|
public Node delegate() {
|
||||||
return this.node;
|
return this.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import me.lucko.luckperms.common.api.ApiRegistrationUtil;
|
|||||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||||
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
||||||
import me.lucko.luckperms.common.buffers.UpdateTaskBuffer;
|
import me.lucko.luckperms.common.buffers.UpdateTaskBuffer;
|
||||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.command.utils.MessageUtils;
|
import me.lucko.luckperms.common.command.utils.MessageUtils;
|
||||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
@ -61,6 +61,7 @@ import me.lucko.luckperms.common.verbose.VerboseHandler;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||||||
private InternalMessagingService messagingService = null;
|
private InternalMessagingService messagingService = null;
|
||||||
private BufferedRequest<Void> updateTaskBuffer;
|
private BufferedRequest<Void> updateTaskBuffer;
|
||||||
private InheritanceHandler inheritanceHandler;
|
private InheritanceHandler inheritanceHandler;
|
||||||
private PlatformCalculatorFactory calculatorFactory;
|
private CalculatorFactory calculatorFactory;
|
||||||
private LuckPermsApiProvider apiProvider;
|
private LuckPermsApiProvider apiProvider;
|
||||||
private EventFactory eventFactory;
|
private EventFactory eventFactory;
|
||||||
|
|
||||||
@ -101,14 +102,13 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||||||
displayBanner(getConsoleSender());
|
displayBanner(getConsoleSender());
|
||||||
|
|
||||||
// load some utilities early
|
// load some utilities early
|
||||||
this.verboseHandler = new VerboseHandler();
|
this.verboseHandler = new VerboseHandler(getBootstrap().getScheduler());
|
||||||
this.permissionRegistry = new PermissionRegistry();
|
this.permissionRegistry = new PermissionRegistry(getBootstrap().getScheduler());
|
||||||
this.logDispatcher = new LogDispatcher(this);
|
this.logDispatcher = new LogDispatcher(this);
|
||||||
|
|
||||||
// load configuration
|
// load configuration
|
||||||
getLogger().info("Loading configuration...");
|
getLogger().info("Loading configuration...");
|
||||||
this.configuration = new AbstractConfiguration(this, provideConfigurationAdapter());
|
this.configuration = new AbstractConfiguration(this, provideConfigurationAdapter());
|
||||||
this.configuration.loadAll();
|
|
||||||
|
|
||||||
// load locale
|
// load locale
|
||||||
this.localeManager = new SimpleLocaleManager();
|
this.localeManager = new SimpleLocaleManager();
|
||||||
@ -168,10 +168,9 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||||||
// schedule update tasks
|
// schedule update tasks
|
||||||
int mins = getConfiguration().get(ConfigKeys.SYNC_TIME);
|
int mins = getConfiguration().get(ConfigKeys.SYNC_TIME);
|
||||||
if (mins > 0) {
|
if (mins > 0) {
|
||||||
long ticks = mins * 60 * 20;
|
getBootstrap().getScheduler().asyncRepeating(() -> this.updateTaskBuffer.request(), mins, TimeUnit.MINUTES);
|
||||||
getBootstrap().getScheduler().asyncRepeating(() -> this.updateTaskBuffer.request(), ticks);
|
|
||||||
}
|
}
|
||||||
getBootstrap().getScheduler().asyncLater(() -> this.updateTaskBuffer.request(), 40L);
|
getBootstrap().getScheduler().asyncLater(() -> this.updateTaskBuffer.request(), 2, TimeUnit.SECONDS);
|
||||||
|
|
||||||
// run an update instantly.
|
// run an update instantly.
|
||||||
getLogger().info("Performing initial data load...");
|
getLogger().info("Performing initial data load...");
|
||||||
@ -191,9 +190,6 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void disable() {
|
public final void disable() {
|
||||||
// perform initial disable tasks
|
|
||||||
performEarlyDisableTasks();
|
|
||||||
|
|
||||||
// shutdown permission vault and verbose handler tasks
|
// shutdown permission vault and verbose handler tasks
|
||||||
this.permissionRegistry.stop();
|
this.permissionRegistry.stop();
|
||||||
this.verboseHandler.stop();
|
this.verboseHandler.stop();
|
||||||
@ -233,7 +229,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||||||
protected abstract MessagingFactory<?> provideMessagingFactory();
|
protected abstract MessagingFactory<?> provideMessagingFactory();
|
||||||
protected abstract void registerCommands();
|
protected abstract void registerCommands();
|
||||||
protected abstract void setupManagers();
|
protected abstract void setupManagers();
|
||||||
protected abstract PlatformCalculatorFactory provideCalculatorFactory();
|
protected abstract CalculatorFactory provideCalculatorFactory();
|
||||||
protected abstract void setupContextManager();
|
protected abstract void setupContextManager();
|
||||||
protected abstract void setupPlatformHooks();
|
protected abstract void setupPlatformHooks();
|
||||||
protected abstract AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider);
|
protected abstract AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider);
|
||||||
@ -241,7 +237,6 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||||||
protected abstract void registerHousekeepingTasks();
|
protected abstract void registerHousekeepingTasks();
|
||||||
protected abstract void performFinalSetup();
|
protected abstract void performFinalSetup();
|
||||||
|
|
||||||
protected void performEarlyDisableTasks() {}
|
|
||||||
protected void removePlatformHooks() {}
|
protected void removePlatformHooks() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -312,7 +307,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlatformCalculatorFactory getCalculatorFactory() {
|
public CalculatorFactory getCalculatorFactory() {
|
||||||
return this.calculatorFactory;
|
return this.calculatorFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ package me.lucko.luckperms.common.plugin.bootstrap;
|
|||||||
|
|
||||||
import me.lucko.luckperms.api.platform.PlatformType;
|
import me.lucko.luckperms.api.platform.PlatformType;
|
||||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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.common.plugin.scheduler;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract implementation of {@link SchedulerAdapter} using a {@link ScheduledExecutorService}.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractJavaScheduler implements SchedulerAdapter {
|
||||||
|
private final ScheduledExecutorService asyncExecutor = new AsyncExecutor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Executor async() {
|
||||||
|
return this.asyncExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
|
||||||
|
ScheduledFuture<?> future = this.asyncExecutor.schedule(new WrappedRunnable(task), delay, unit);
|
||||||
|
return () -> future.cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit) {
|
||||||
|
ScheduledFuture<?> future = this.asyncExecutor.scheduleAtFixedRate(new WrappedRunnable(task), interval, interval, unit);
|
||||||
|
return () -> future.cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
this.asyncExecutor.shutdown();
|
||||||
|
try {
|
||||||
|
this.asyncExecutor.awaitTermination(1, TimeUnit.MINUTES);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class WrappedRunnable implements Runnable {
|
||||||
|
private final Runnable delegate;
|
||||||
|
|
||||||
|
WrappedRunnable(Runnable delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
this.delegate.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class AsyncExecutor extends ScheduledThreadPoolExecutor {
|
||||||
|
AsyncExecutor() {
|
||||||
|
super(4, new ThreadFactoryBuilder().setNameFormat("luckperms-%d").build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable command) {
|
||||||
|
super.execute(new WrappedRunnable(command));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,9 +23,12 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.plugin;
|
package me.lucko.luckperms.common.plugin.scheduler;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A scheduler for running tasks using the systems provided by the platform
|
* A scheduler for running tasks using the systems provided by the platform
|
||||||
@ -39,10 +42,6 @@ public interface SchedulerAdapter {
|
|||||||
*/
|
*/
|
||||||
Executor async();
|
Executor async();
|
||||||
|
|
||||||
default Executor platformAsync() {
|
|
||||||
return async();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a sync executor instance
|
* Gets a sync executor instance
|
||||||
*
|
*
|
||||||
@ -51,46 +50,42 @@ public interface SchedulerAdapter {
|
|||||||
Executor sync();
|
Executor sync();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a runnable async
|
* Executes a task async
|
||||||
*
|
*
|
||||||
* @param runnable the runnable
|
* @param task the task
|
||||||
*/
|
*/
|
||||||
void doAsync(Runnable runnable);
|
default void executeAsync(Runnable task) {
|
||||||
|
async().execute(task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a runnable sync
|
* Executes a task sync
|
||||||
*
|
*
|
||||||
* @param runnable the runnable
|
* @param task the task
|
||||||
*/
|
*/
|
||||||
void doSync(Runnable runnable);
|
default void executeSync(Runnable task) {
|
||||||
|
sync().execute(task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a runnable repeatedly until the plugin disables. Will wait for the interval before the first iteration of the task is ran.
|
* Executes the given task with a delay.
|
||||||
* @param runnable the runnable
|
*
|
||||||
* @param intervalTicks the interval in ticks.
|
* @param task the task
|
||||||
|
* @param delay the delay
|
||||||
|
* @param unit the unit of delay
|
||||||
|
* @return the resultant task instance
|
||||||
*/
|
*/
|
||||||
SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks);
|
SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a runnable repeatedly until the plugin disables. Will wait for the interval before the first iteration of the task is ran.
|
* Executes the given task repeatedly at a given interval.
|
||||||
* @param runnable the runnable
|
*
|
||||||
* @param intervalTicks the interval in ticks.
|
* @param task the task
|
||||||
|
* @param interval the interval
|
||||||
|
* @param unit the unit of interval
|
||||||
|
* @return the resultant task instance
|
||||||
*/
|
*/
|
||||||
SchedulerTask syncRepeating(Runnable runnable, long intervalTicks);
|
SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit);
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a runnable with a delay
|
|
||||||
* @param runnable the runnable
|
|
||||||
* @param delayTicks the delay in ticks
|
|
||||||
*/
|
|
||||||
SchedulerTask asyncLater(Runnable runnable, long delayTicks);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a runnable with a delay
|
|
||||||
* @param runnable the runnable
|
|
||||||
* @param delayTicks the delay in ticks
|
|
||||||
*/
|
|
||||||
SchedulerTask syncLater(Runnable runnable, long delayTicks);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuts down this executor instance
|
* Shuts down this executor instance
|
@ -61,8 +61,8 @@ public class FileWatcher {
|
|||||||
this.basePath = basePath;
|
this.basePath = basePath;
|
||||||
this.watchService = basePath.getFileSystem().newWatchService();
|
this.watchService = basePath.getFileSystem().newWatchService();
|
||||||
|
|
||||||
plugin.getBootstrap().getScheduler().asyncLater(this::initLocations, 25L);
|
plugin.getBootstrap().getScheduler().asyncLater(this::initLocations, 5, TimeUnit.SECONDS);
|
||||||
plugin.getBootstrap().getScheduler().asyncRepeating(this::tick, 10L);
|
plugin.getBootstrap().getScheduler().asyncRepeating(this::tick, 1, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WatchedLocation getWatcher(Path path) {
|
public WatchedLocation getWatcher(Path path) {
|
||||||
|
@ -28,6 +28,7 @@ package me.lucko.luckperms.common.treeview;
|
|||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
import me.lucko.luckperms.common.utils.RepeatingTask;
|
import me.lucko.luckperms.common.utils.RepeatingTask;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -55,8 +56,8 @@ public class PermissionRegistry extends RepeatingTask {
|
|||||||
// a queue of permission strings to be processed by the tree
|
// a queue of permission strings to be processed by the tree
|
||||||
private final Queue<String> queue;
|
private final Queue<String> queue;
|
||||||
|
|
||||||
public PermissionRegistry() {
|
public PermissionRegistry(SchedulerAdapter scheduler) {
|
||||||
super(1000, TimeUnit.MILLISECONDS, "luckperms-permission-vault");
|
super(scheduler, 1, TimeUnit.SECONDS);
|
||||||
this.rootNode = new TreeNode();
|
this.rootNode = new TreeNode();
|
||||||
this.knownPermissions = ConcurrentHashMap.newKeySet(3000);
|
this.knownPermissions = ConcurrentHashMap.newKeySet(3000);
|
||||||
this.queue = new ConcurrentLinkedQueue<>();
|
this.queue = new ConcurrentLinkedQueue<>();
|
||||||
|
@ -1,88 +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.common.utils;
|
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
|
||||||
|
|
||||||
import java.text.CollationKey;
|
|
||||||
import java.text.Collator;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public final class CollationKeyCache implements Comparator<String> {
|
|
||||||
private static final CollationKeyCache INSTANCE = new CollationKeyCache();
|
|
||||||
|
|
||||||
private static final Collator COLLATOR;
|
|
||||||
static {
|
|
||||||
COLLATOR = Collator.getInstance(Locale.ENGLISH);
|
|
||||||
COLLATOR.setStrength(Collator.IDENTICAL);
|
|
||||||
COLLATOR.setDecomposition(Collator.FULL_DECOMPOSITION);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final LoadingCache<String, CollationKey> CACHE = Caffeine.newBuilder()
|
|
||||||
.maximumSize(5000)
|
|
||||||
.expireAfterAccess(5, TimeUnit.MINUTES)
|
|
||||||
.build(COLLATOR::getCollationKey);
|
|
||||||
|
|
||||||
public static Comparator<String> comparator() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CollationKeyCache() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(String o1, String o2) {
|
|
||||||
return compareStrings(o1, o2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int compareStrings(String o1, String o2) {
|
|
||||||
//noinspection StringEquality
|
|
||||||
if (o1 == o2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
CollationKey o1c = CACHE.get(o1);
|
|
||||||
CollationKey o2c = CACHE.get(o2);
|
|
||||||
|
|
||||||
if (o1c != null && o2c != null) {
|
|
||||||
int i = o1c.compareTo(o2c);
|
|
||||||
if (i != 0) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback to standard string comparison
|
|
||||||
return o1.compareTo(o2);
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.utils;
|
package me.lucko.luckperms.common.utils;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
|
||||||
import com.google.common.collect.ForwardingSet;
|
import com.google.common.collect.ForwardingSet;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -36,22 +36,22 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bad expiring set implementation using Caffeine caches
|
* A simple expiring set implementation using Caffeine caches
|
||||||
*
|
*
|
||||||
* @param <E> element type
|
* @param <E> element type
|
||||||
*/
|
*/
|
||||||
public class ExpiringSet<E> extends ForwardingSet<E> {
|
public class ExpiringSet<E> extends ForwardingSet<E> {
|
||||||
private final LoadingCache<E, Boolean> cache;
|
private final Cache<E, Boolean> cache;
|
||||||
private final Set<E> setView;
|
private final Set<E> setView;
|
||||||
|
|
||||||
public ExpiringSet(long duration, TimeUnit unit) {
|
public ExpiringSet(long duration, TimeUnit unit) {
|
||||||
this.cache = Caffeine.newBuilder().expireAfterAccess(duration, unit).build(key -> Boolean.TRUE);
|
this.cache = Caffeine.newBuilder().expireAfterAccess(duration, unit).build();
|
||||||
this.setView = this.cache.asMap().keySet();
|
this.setView = this.cache.asMap().keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(E element) {
|
public boolean add(E element) {
|
||||||
this.cache.get(element); // simply requesting the element from the cache is sufficient.
|
this.cache.put(element, Boolean.TRUE);
|
||||||
|
|
||||||
// we don't care about the return value
|
// we don't care about the return value
|
||||||
return true;
|
return true;
|
||||||
|
@ -69,12 +69,12 @@ public final class PatternCache {
|
|||||||
private final Pattern instance;
|
private final Pattern instance;
|
||||||
private final PatternSyntaxException ex;
|
private final PatternSyntaxException ex;
|
||||||
|
|
||||||
public CachedPattern(Pattern instance) {
|
CachedPattern(Pattern instance) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.ex = null;
|
this.ex = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedPattern(PatternSyntaxException ex) {
|
CachedPattern(PatternSyntaxException ex) {
|
||||||
this.instance = null;
|
this.instance = null;
|
||||||
this.ex = ex;
|
this.ex = ex;
|
||||||
}
|
}
|
||||||
|
@ -25,20 +25,16 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.utils;
|
package me.lucko.luckperms.common.utils;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public abstract class RepeatingTask {
|
public abstract class RepeatingTask {
|
||||||
|
private final SchedulerTask task;
|
||||||
|
|
||||||
// the executor thread
|
protected RepeatingTask(SchedulerAdapter scheduler, long time, TimeUnit unit) {
|
||||||
private final ScheduledExecutorService executor;
|
this.task = scheduler.asyncRepeating(this::run, time, unit);
|
||||||
|
|
||||||
protected RepeatingTask(long time, TimeUnit unit, String nameFormat) {
|
|
||||||
this.executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat(nameFormat).build());
|
|
||||||
this.executor.scheduleAtFixedRate(this::run, time, time, unit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run() {
|
private void run() {
|
||||||
@ -52,11 +48,6 @@ public abstract class RepeatingTask {
|
|||||||
protected abstract void tick();
|
protected abstract void tick();
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
this.executor.shutdown();
|
this.task.cancel();
|
||||||
try {
|
|
||||||
this.executor.awaitTermination(10, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ package me.lucko.luckperms.common.verbose;
|
|||||||
|
|
||||||
import me.lucko.luckperms.api.Tristate;
|
import me.lucko.luckperms.api.Tristate;
|
||||||
import me.lucko.luckperms.api.context.ContextSet;
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
import me.lucko.luckperms.common.sender.Sender;
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
import me.lucko.luckperms.common.utils.RepeatingTask;
|
import me.lucko.luckperms.common.utils.RepeatingTask;
|
||||||
|
|
||||||
@ -51,8 +52,8 @@ public class VerboseHandler extends RepeatingTask {
|
|||||||
// if there are any listeners currently registered
|
// if there are any listeners currently registered
|
||||||
private boolean listening = false;
|
private boolean listening = false;
|
||||||
|
|
||||||
public VerboseHandler() {
|
public VerboseHandler(SchedulerAdapter scheduler) {
|
||||||
super(100, TimeUnit.MILLISECONDS, "luckperms-verbose");
|
super(scheduler, 100, TimeUnit.MILLISECONDS);
|
||||||
this.listeners = new ConcurrentHashMap<>();
|
this.listeners = new ConcurrentHashMap<>();
|
||||||
this.queue = new ConcurrentLinkedQueue<>();
|
this.queue = new ConcurrentLinkedQueue<>();
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ import me.lucko.luckperms.api.LuckPermsApi;
|
|||||||
import me.lucko.luckperms.api.event.user.UserDataRecalculateEvent;
|
import me.lucko.luckperms.api.event.user.UserDataRecalculateEvent;
|
||||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||||
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
|
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
|
||||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||||
@ -75,6 +75,7 @@ import java.util.EnumSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,7 +146,7 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PlatformCalculatorFactory provideCalculatorFactory() {
|
protected CalculatorFactory provideCalculatorFactory() {
|
||||||
return new NukkitCalculatorFactory(this);
|
return new NukkitCalculatorFactory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +171,7 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
|
|
||||||
// schedule another injection after all plugins have loaded
|
// schedule another injection after all plugins have loaded
|
||||||
// the entire pluginmanager instance is replaced by some plugins :(
|
// the entire pluginmanager instance is replaced by some plugins :(
|
||||||
this.bootstrap.getScheduler().asyncLater(injector, 1L);
|
this.bootstrap.getServer().getScheduler().scheduleDelayedTask(this.bootstrap, injector, 1, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,8 +187,8 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerHousekeepingTasks() {
|
protected void registerHousekeepingTasks() {
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 3, TimeUnit.SECONDS);
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -219,16 +220,13 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace the temporary executor when the Nukkit one starts
|
|
||||||
this.bootstrap.getServer().getScheduler().scheduleTask(this.bootstrap, () -> this.bootstrap.getScheduler().setUseFallback(false), true);
|
|
||||||
|
|
||||||
// Load any online users (in the case of a reload)
|
// Load any online users (in the case of a reload)
|
||||||
for (Player player : this.bootstrap.getServer().getOnlinePlayers().values()) {
|
for (Player player : this.bootstrap.getServer().getOnlinePlayers().values()) {
|
||||||
this.bootstrap.getScheduler().doAsync(() -> {
|
this.bootstrap.getScheduler().executeAsync(() -> {
|
||||||
try {
|
try {
|
||||||
User user = this.connectionListener.loadUser(player.getUniqueId(), player.getName());
|
User user = this.connectionListener.loadUser(player.getUniqueId(), player.getName());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
this.bootstrap.getScheduler().doSync(() -> {
|
this.bootstrap.getScheduler().executeSync(() -> {
|
||||||
try {
|
try {
|
||||||
LPPermissible lpPermissible = new LPPermissible(player, user, this);
|
LPPermissible lpPermissible = new LPPermissible(player, user, this);
|
||||||
PermissibleInjector.inject(player, lpPermissible);
|
PermissibleInjector.inject(player, lpPermissible);
|
||||||
@ -244,12 +242,6 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void performEarlyDisableTasks() {
|
|
||||||
// Switch back to the fallback executor, the nukkit one won't allow new tasks
|
|
||||||
this.bootstrap.getScheduler().setUseFallback(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void removePlatformHooks() {
|
protected void removePlatformHooks() {
|
||||||
// uninject from players
|
// uninject from players
|
||||||
|
@ -25,95 +25,16 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.nukkit;
|
package me.lucko.luckperms.nukkit;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
|
||||||
import me.lucko.luckperms.common.utils.Iterators;
|
|
||||||
|
|
||||||
import cn.nukkit.scheduler.ServerScheduler;
|
|
||||||
import cn.nukkit.scheduler.TaskHandler;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.SynchronousQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
public class NukkitSchedulerAdapter extends AbstractJavaScheduler implements SchedulerAdapter {
|
||||||
|
|
||||||
public class NukkitSchedulerAdapter implements SchedulerAdapter {
|
|
||||||
private final LPNukkitBootstrap bootstrap;
|
|
||||||
|
|
||||||
private final ExecutorService asyncFallback;
|
|
||||||
private final Executor asyncNukkit;
|
|
||||||
private final Executor sync;
|
private final Executor sync;
|
||||||
private final Executor async;
|
|
||||||
|
|
||||||
private boolean useFallback = true;
|
|
||||||
|
|
||||||
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
|
||||||
|
|
||||||
public NukkitSchedulerAdapter(LPNukkitBootstrap bootstrap) {
|
public NukkitSchedulerAdapter(LPNukkitBootstrap bootstrap) {
|
||||||
this.bootstrap = bootstrap;
|
this.sync = r -> bootstrap.getServer().getScheduler().scheduleTask(bootstrap, r, false);
|
||||||
|
|
||||||
this.sync = new SyncExecutor();
|
|
||||||
this.asyncFallback = new FallbackAsyncExecutor();
|
|
||||||
this.asyncNukkit = new NukkitAsyncExecutor();
|
|
||||||
this.async = new AsyncExecutor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ServerScheduler scheduler() {
|
|
||||||
return this.bootstrap.getServer().getScheduler();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doAsync(Runnable runnable) {
|
|
||||||
async().execute(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doSync(Runnable runnable) {
|
|
||||||
sync().execute(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
|
||||||
SchedulerTask task = new NukkitSchedulerTask(scheduler().scheduleDelayedRepeatingTask(this.bootstrap, runnable, (int) intervalTicks, (int) intervalTicks, true));
|
|
||||||
this.tasks.add(task);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
|
||||||
SchedulerTask task = new NukkitSchedulerTask(scheduler().scheduleDelayedRepeatingTask(this.bootstrap, runnable, (int) intervalTicks, (int) intervalTicks, false));
|
|
||||||
this.tasks.add(task);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
|
||||||
return new NukkitSchedulerTask(scheduler().scheduleDelayedTask(this.bootstrap, runnable, (int) delayTicks, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
|
||||||
return new NukkitSchedulerTask(scheduler().scheduleDelayedTask(this.bootstrap, runnable, (int) delayTicks, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdown() {
|
|
||||||
Iterators.iterate(this.tasks, SchedulerTask::cancel);
|
|
||||||
|
|
||||||
// wait for executor
|
|
||||||
this.asyncFallback.shutdown();
|
|
||||||
try {
|
|
||||||
this.asyncFallback.awaitTermination(30, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,62 +42,4 @@ public class NukkitSchedulerAdapter implements SchedulerAdapter {
|
|||||||
return this.sync;
|
return this.sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Executor async() {
|
|
||||||
return this.async;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Executor platformAsync() {
|
|
||||||
return this.asyncNukkit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUseFallback(boolean useFallback) {
|
|
||||||
this.useFallback = useFallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class SyncExecutor implements Executor {
|
|
||||||
@Override
|
|
||||||
public void execute(@Nonnull Runnable runnable) {
|
|
||||||
NukkitSchedulerAdapter.this.bootstrap.getServer().getScheduler().scheduleTask(NukkitSchedulerAdapter.this.bootstrap, runnable, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class AsyncExecutor implements Executor {
|
|
||||||
@Override
|
|
||||||
public void execute(@Nonnull Runnable runnable) {
|
|
||||||
if (NukkitSchedulerAdapter.this.useFallback || !NukkitSchedulerAdapter.this.bootstrap.isEnabled()) {
|
|
||||||
NukkitSchedulerAdapter.this.asyncFallback.execute(runnable);
|
|
||||||
} else {
|
|
||||||
NukkitSchedulerAdapter.this.asyncNukkit.execute(runnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class NukkitAsyncExecutor implements Executor {
|
|
||||||
@Override
|
|
||||||
public void execute(@Nonnull Runnable runnable) {
|
|
||||||
NukkitSchedulerAdapter.this.bootstrap.getServer().getScheduler().scheduleTask(NukkitSchedulerAdapter.this.bootstrap, runnable, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class FallbackAsyncExecutor extends ThreadPoolExecutor {
|
|
||||||
private FallbackAsyncExecutor() {
|
|
||||||
super(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactoryBuilder().setNameFormat("luckperms-fallback-%d").build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class NukkitSchedulerTask implements SchedulerTask {
|
|
||||||
private final TaskHandler task;
|
|
||||||
|
|
||||||
private NukkitSchedulerTask(TaskHandler task) {
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancel() {
|
|
||||||
this.task.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ public class NukkitSenderFactory extends SenderFactory<CommandSender> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, send the message sync
|
// otherwise, send the message sync
|
||||||
getPlugin().getBootstrap().getScheduler().doSync(new SyncMessengerAgent(sender, s));
|
getPlugin().getBootstrap().getScheduler().executeSync(new SyncMessengerAgent(sender, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,7 +29,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
|
|
||||||
import me.lucko.luckperms.api.Contexts;
|
import me.lucko.luckperms.api.Contexts;
|
||||||
import me.lucko.luckperms.api.LookupSetting;
|
import me.lucko.luckperms.api.LookupSetting;
|
||||||
import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
@ -42,7 +42,7 @@ import me.lucko.luckperms.nukkit.LPNukkitPlugin;
|
|||||||
import me.lucko.luckperms.nukkit.processors.ChildProcessor;
|
import me.lucko.luckperms.nukkit.processors.ChildProcessor;
|
||||||
import me.lucko.luckperms.nukkit.processors.DefaultsProcessor;
|
import me.lucko.luckperms.nukkit.processors.DefaultsProcessor;
|
||||||
|
|
||||||
public class NukkitCalculatorFactory extends AbstractCalculatorFactory {
|
public class NukkitCalculatorFactory implements CalculatorFactory {
|
||||||
private final LPNukkitPlugin plugin;
|
private final LPNukkitPlugin plugin;
|
||||||
|
|
||||||
public NukkitCalculatorFactory(LPNukkitPlugin plugin) {
|
public NukkitCalculatorFactory(LPNukkitPlugin plugin) {
|
||||||
@ -71,6 +71,6 @@ public class NukkitCalculatorFactory extends AbstractCalculatorFactory {
|
|||||||
processors.add(new DefaultsProcessor(this.plugin, contexts.hasSetting(LookupSetting.IS_OP)));
|
processors.add(new DefaultsProcessor(this.plugin, contexts.hasSetting(LookupSetting.IS_OP)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return registerCalculator(new PermissionCalculator(this.plugin, metadata, processors.build()));
|
return new PermissionCalculator(this.plugin, metadata, processors.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ public class NukkitConnectionListener extends AbstractConnectionListener impleme
|
|||||||
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||||
|
|
||||||
// force a clear of transient nodes
|
// force a clear of transient nodes
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.clearTransientNodes();
|
user.clearTransientNodes();
|
||||||
|
@ -29,6 +29,7 @@ import com.google.common.collect.ForwardingMap;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Tristate;
|
import me.lucko.luckperms.api.Tristate;
|
||||||
|
import me.lucko.luckperms.common.buffers.Cache;
|
||||||
import me.lucko.luckperms.nukkit.LPNukkitPlugin;
|
import me.lucko.luckperms.nukkit.LPNukkitPlugin;
|
||||||
|
|
||||||
import cn.nukkit.permission.Permission;
|
import cn.nukkit.permission.Permission;
|
||||||
@ -39,6 +40,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A replacement map for the 'defaultPerms' instance in Nukkit's SimplePluginManager.
|
* A replacement map for the 'defaultPerms' instance in Nukkit's SimplePluginManager.
|
||||||
*
|
*
|
||||||
@ -58,15 +61,13 @@ public final class LPDefaultsMap {
|
|||||||
private final Map<String, Permission> nonOpSet = new DefaultPermissionSet(false);
|
private final Map<String, Permission> nonOpSet = new DefaultPermissionSet(false);
|
||||||
|
|
||||||
// fully resolved defaults (accounts for child permissions too)
|
// fully resolved defaults (accounts for child permissions too)
|
||||||
private Map<String, Boolean> resolvedOpDefaults = ImmutableMap.of();
|
private DefaultsCache opCache = new DefaultsCache(true);
|
||||||
private Map<String, Boolean> resolvedNonOpDefaults = ImmutableMap.of();
|
private DefaultsCache nonOpCache = new DefaultsCache(false);
|
||||||
|
|
||||||
public LPDefaultsMap(LPNukkitPlugin plugin, Map<Boolean, Map<String, Permission>> existingData) {
|
public LPDefaultsMap(LPNukkitPlugin plugin, Map<Boolean, Map<String, Permission>> existingData) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.opSet.putAll(existingData.getOrDefault(Boolean.TRUE, Collections.emptyMap()));
|
this.opSet.putAll(existingData.getOrDefault(Boolean.TRUE, Collections.emptyMap()));
|
||||||
this.nonOpSet.putAll(existingData.getOrDefault(Boolean.FALSE, Collections.emptyMap()));
|
this.nonOpSet.putAll(existingData.getOrDefault(Boolean.FALSE, Collections.emptyMap()));
|
||||||
refreshOp();
|
|
||||||
refreshNonOp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Permission> getOpPermissions() {
|
public Map<String, Permission> getOpPermissions() {
|
||||||
@ -77,6 +78,18 @@ public final class LPDefaultsMap {
|
|||||||
return this.nonOpSet;
|
return this.nonOpSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, Permission> get(boolean op) {
|
||||||
|
return op ? this.opSet : this.nonOpSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefaultsCache getCache(boolean op) {
|
||||||
|
return op ? this.opCache : this.nonOpCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invalidate(boolean op) {
|
||||||
|
getCache(op).invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries whether a given permission should be granted by default.
|
* Queries whether a given permission should be granted by default.
|
||||||
*
|
*
|
||||||
@ -85,55 +98,17 @@ public final class LPDefaultsMap {
|
|||||||
* @return a tristate result
|
* @return a tristate result
|
||||||
*/
|
*/
|
||||||
public Tristate lookupDefaultPermission(String permission, boolean isOp) {
|
public Tristate lookupDefaultPermission(String permission, boolean isOp) {
|
||||||
Map<String, Boolean> map = isOp ? this.resolvedOpDefaults : this.resolvedNonOpDefaults;
|
Map<String, Boolean> map = getCache(isOp).get();
|
||||||
return Tristate.fromNullableBoolean(map.get(permission));
|
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().values()) {
|
|
||||||
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().values()) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
final class DefaultPermissionSet extends ForwardingMap<String, Permission> {
|
final class DefaultPermissionSet extends ForwardingMap<String, Permission> {
|
||||||
final LPDefaultsMap parent = LPDefaultsMap.this;
|
final LPDefaultsMap parent = LPDefaultsMap.this;
|
||||||
|
|
||||||
private final Map<String, Permission> delegate = new ConcurrentHashMap<>();
|
private final Map<String, Permission> delegate = new ConcurrentHashMap<>();
|
||||||
private final boolean op;
|
private final boolean op;
|
||||||
|
|
||||||
private DefaultPermissionSet(boolean op) {
|
DefaultPermissionSet(boolean op) {
|
||||||
this.op = op;
|
this.op = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,21 +120,43 @@ public final class LPDefaultsMap {
|
|||||||
@Override
|
@Override
|
||||||
public Permission put(String key, Permission value) {
|
public Permission put(String key, Permission value) {
|
||||||
Permission ret = super.put(key, value);
|
Permission ret = super.put(key, value);
|
||||||
refresh(this.op);
|
invalidate(this.op);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Permission putIfAbsent(String key, Permission value) {
|
public Permission putIfAbsent(String key, Permission value) {
|
||||||
Permission ret = super.putIfAbsent(key, value);
|
Permission ret = super.putIfAbsent(key, value);
|
||||||
refresh(this.op);
|
invalidate(this.op);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putAll(Map<? extends String, ? extends Permission> map) {
|
public void putAll(Map<? extends String, ? extends Permission> map) {
|
||||||
super.putAll(map);
|
super.putAll(map);
|
||||||
refresh(this.op);
|
invalidate(this.op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class DefaultsCache extends Cache<Map<String, Boolean>> {
|
||||||
|
private final boolean op;
|
||||||
|
|
||||||
|
DefaultsCache(boolean op) {
|
||||||
|
this.op = op;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
protected Map<String, Boolean> supply() {
|
||||||
|
Map<String, Boolean> builder = new HashMap<>();
|
||||||
|
for (Permission perm : LPDefaultsMap.this.get(this.op).values()) {
|
||||||
|
String name = perm.getName().toLowerCase();
|
||||||
|
builder.put(name, true);
|
||||||
|
for (Map.Entry<String, Boolean> child : LPDefaultsMap.this.plugin.getPermissionMap().getChildPermissions(name, true).entrySet()) {
|
||||||
|
builder.putIfAbsent(child.getKey(), child.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ImmutableMap.copyOf(builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.sponge.service;
|
package me.lucko.luckperms.sponge.service;
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Tristate;
|
import me.lucko.luckperms.api.Tristate;
|
||||||
@ -39,19 +37,12 @@ import org.spongepowered.api.service.context.Context;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for converting between Sponge and LuckPerms context and tristate classes
|
* Utility class for converting between Sponge and LuckPerms context and tristate classes
|
||||||
*/
|
*/
|
||||||
public final class CompatibilityUtil {
|
public final class CompatibilityUtil {
|
||||||
private static final LoadingCache<Set<Context>, ImmutableContextSet> SPONGE_TO_LP_CACHE = Caffeine.newBuilder()
|
private static final Set<Context> EMPTY = ImmutableSet.of();
|
||||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
|
||||||
.build(ImmutableContextSet::fromEntries);
|
|
||||||
|
|
||||||
private static final LoadingCache<ImmutableContextSet, Set<Context>> LP_TO_SPONGE_CACHE = Caffeine.newBuilder()
|
|
||||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
|
||||||
.build(DelegatingImmutableContextSet::new);
|
|
||||||
|
|
||||||
public static ImmutableContextSet convertContexts(Set<Context> contexts) {
|
public static ImmutableContextSet convertContexts(Set<Context> contexts) {
|
||||||
Objects.requireNonNull(contexts, "contexts");
|
Objects.requireNonNull(contexts, "contexts");
|
||||||
@ -60,12 +51,21 @@ public final class CompatibilityUtil {
|
|||||||
return ((DelegatingContextSet) contexts).getDelegate().makeImmutable();
|
return ((DelegatingContextSet) contexts).getDelegate().makeImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
return SPONGE_TO_LP_CACHE.get(ImmutableSet.copyOf(contexts));
|
if (contexts.isEmpty()) {
|
||||||
|
return ImmutableContextSet.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImmutableContextSet.fromEntries(contexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Context> convertContexts(ContextSet contexts) {
|
public static Set<Context> convertContexts(ContextSet contexts) {
|
||||||
Objects.requireNonNull(contexts, "contexts");
|
Objects.requireNonNull(contexts, "contexts");
|
||||||
return LP_TO_SPONGE_CACHE.get(contexts.makeImmutable());
|
|
||||||
|
if (contexts.isEmpty()) {
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DelegatingImmutableContextSet(contexts.makeImmutable());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static org.spongepowered.api.util.Tristate convertTristate(Tristate tristate) {
|
public static org.spongepowered.api.util.Tristate convertTristate(Tristate tristate) {
|
||||||
|
@ -60,12 +60,13 @@ public final class SubjectReferenceFactory {
|
|||||||
*
|
*
|
||||||
* It's perfectly ok if two instances of the same SubjectReference exist. (hence the 1 hour expiry)
|
* It's perfectly ok if two instances of the same SubjectReference exist. (hence the 1 hour expiry)
|
||||||
*/
|
*/
|
||||||
private final LoadingCache<SubjectReferenceAttributes, CachedSubjectReference> referenceCache = Caffeine.newBuilder()
|
private final LoadingCache<SubjectReferenceAttributes, CachedSubjectReference> referenceCache;
|
||||||
.expireAfterAccess(1, TimeUnit.HOURS)
|
|
||||||
.build(a -> new CachedSubjectReference(SubjectReferenceFactory.this.service, a.collectionId, a.id));
|
|
||||||
|
|
||||||
public SubjectReferenceFactory(LPPermissionService service) {
|
public SubjectReferenceFactory(LPPermissionService service) {
|
||||||
this.service = service;
|
this.service = service;
|
||||||
|
this.referenceCache = Caffeine.newBuilder()
|
||||||
|
.expireAfterAccess(1, TimeUnit.HOURS)
|
||||||
|
.build(a -> new CachedSubjectReference(this.service, a.collectionId, a.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -30,8 +30,8 @@ import com.google.inject.Inject;
|
|||||||
import me.lucko.luckperms.api.platform.PlatformType;
|
import me.lucko.luckperms.api.platform.PlatformType;
|
||||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||||
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
|
||||||
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
import me.lucko.luckperms.common.utils.MoreFiles;
|
import me.lucko.luckperms.common.utils.MoreFiles;
|
||||||
import me.lucko.luckperms.sponge.utils.VersionData;
|
import me.lucko.luckperms.sponge.utils.VersionData;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ package me.lucko.luckperms.sponge;
|
|||||||
import me.lucko.luckperms.api.Contexts;
|
import me.lucko.luckperms.api.Contexts;
|
||||||
import me.lucko.luckperms.api.LuckPermsApi;
|
import me.lucko.luckperms.api.LuckPermsApi;
|
||||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.command.CommandManager;
|
import me.lucko.luckperms.common.command.CommandManager;
|
||||||
import me.lucko.luckperms.common.command.abstraction.Command;
|
import me.lucko.luckperms.common.command.abstraction.Command;
|
||||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||||
@ -75,6 +75,7 @@ import java.util.EnumSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +147,7 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PlatformCalculatorFactory provideCalculatorFactory() {
|
protected CalculatorFactory provideCalculatorFactory() {
|
||||||
return new SpongeCalculatorFactory(this);
|
return new SpongeCalculatorFactory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,9 +190,9 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerHousekeepingTasks() {
|
protected void registerHousekeepingTasks() {
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 3, TimeUnit.SECONDS);
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2, TimeUnit.MINUTES);
|
||||||
this.bootstrap.getScheduler().asyncRepeating(new ServiceCacheHousekeepingTask(this.service), 2400L);
|
this.bootstrap.getScheduler().asyncRepeating(new ServiceCacheHousekeepingTask(this.service), 2, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,17 +25,19 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.sponge;
|
package me.lucko.luckperms.sponge;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||||
import me.lucko.luckperms.common.utils.Iterators;
|
import me.lucko.luckperms.common.utils.Iterators;
|
||||||
|
|
||||||
import org.spongepowered.api.scheduler.Scheduler;
|
import org.spongepowered.api.scheduler.Scheduler;
|
||||||
import org.spongepowered.api.scheduler.SpongeExecutorService;
|
import org.spongepowered.api.scheduler.SpongeExecutorService;
|
||||||
import org.spongepowered.api.scheduler.Task;
|
import org.spongepowered.api.scheduler.Task;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class SpongeSchedulerAdapter implements SchedulerAdapter {
|
public class SpongeSchedulerAdapter implements SchedulerAdapter {
|
||||||
private final LPSpongeBootstrap bootstrap;
|
private final LPSpongeBootstrap bootstrap;
|
||||||
@ -44,7 +46,7 @@ public class SpongeSchedulerAdapter implements SchedulerAdapter {
|
|||||||
private final SpongeExecutorService sync;
|
private final SpongeExecutorService sync;
|
||||||
private final SpongeExecutorService async;
|
private final SpongeExecutorService async;
|
||||||
|
|
||||||
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
private final Set<Task> tasks = Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
|
|
||||||
public SpongeSchedulerAdapter(LPSpongeBootstrap bootstrap, Scheduler scheduler, SpongeExecutorService sync, SpongeExecutorService async) {
|
public SpongeSchedulerAdapter(LPSpongeBootstrap bootstrap, Scheduler scheduler, SpongeExecutorService sync, SpongeExecutorService async) {
|
||||||
this.bootstrap = bootstrap;
|
this.bootstrap = bootstrap;
|
||||||
@ -64,82 +66,43 @@ public class SpongeSchedulerAdapter implements SchedulerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAsync(Runnable runnable) {
|
public void executeAsync(Runnable runnable) {
|
||||||
this.scheduler.createTaskBuilder().async().execute(runnable).submit(this.bootstrap);
|
this.scheduler.createTaskBuilder().async().execute(runnable).submit(this.bootstrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doSync(Runnable runnable) {
|
public void executeSync(Runnable runnable) {
|
||||||
this.scheduler.createTaskBuilder().execute(runnable).submit(this.bootstrap);
|
this.scheduler.createTaskBuilder().execute(runnable).submit(this.bootstrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
|
||||||
Task task = this.scheduler.createTaskBuilder()
|
Task t = this.scheduler.createTaskBuilder()
|
||||||
.async()
|
.async()
|
||||||
.intervalTicks(intervalTicks)
|
.delay(delay, unit)
|
||||||
.delayTicks(intervalTicks)
|
.execute(task)
|
||||||
.execute(runnable)
|
|
||||||
.submit(this.bootstrap);
|
.submit(this.bootstrap);
|
||||||
|
|
||||||
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
this.tasks.add(t);
|
||||||
this.tasks.add(wrapped);
|
return t::cancel;
|
||||||
return wrapped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit) {
|
||||||
Task task = this.scheduler.createTaskBuilder()
|
Task t = this.scheduler.createTaskBuilder()
|
||||||
.intervalTicks(intervalTicks)
|
|
||||||
.delayTicks(intervalTicks)
|
|
||||||
.execute(runnable)
|
|
||||||
.submit(this.bootstrap);
|
|
||||||
|
|
||||||
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
|
||||||
this.tasks.add(wrapped);
|
|
||||||
return wrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
|
||||||
Task task = this.scheduler.createTaskBuilder()
|
|
||||||
.async()
|
.async()
|
||||||
.delayTicks(delayTicks)
|
.interval(interval, unit)
|
||||||
.execute(runnable)
|
.delay(interval, unit)
|
||||||
|
.execute(task)
|
||||||
.submit(this.bootstrap);
|
.submit(this.bootstrap);
|
||||||
|
|
||||||
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
this.tasks.add(t);
|
||||||
this.tasks.add(wrapped);
|
return t::cancel;
|
||||||
return wrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
|
||||||
Task task = this.scheduler.createTaskBuilder()
|
|
||||||
.delayTicks(delayTicks)
|
|
||||||
.execute(runnable)
|
|
||||||
.submit(this.bootstrap);
|
|
||||||
|
|
||||||
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
|
||||||
this.tasks.add(wrapped);
|
|
||||||
return wrapped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
Iterators.iterate(this.tasks, SchedulerTask::cancel);
|
Iterators.iterate(this.tasks, Task::cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SpongeSchedulerTask implements SchedulerTask {
|
|
||||||
private final Task task;
|
|
||||||
|
|
||||||
private SpongeSchedulerTask(Task task) {
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancel() {
|
|
||||||
this.task.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ package me.lucko.luckperms.sponge.calculators;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Contexts;
|
import me.lucko.luckperms.api.Contexts;
|
||||||
import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
@ -41,7 +41,7 @@ import me.lucko.luckperms.sponge.processors.GroupDefaultsProcessor;
|
|||||||
import me.lucko.luckperms.sponge.processors.SpongeWildcardProcessor;
|
import me.lucko.luckperms.sponge.processors.SpongeWildcardProcessor;
|
||||||
import me.lucko.luckperms.sponge.processors.UserDefaultsProcessor;
|
import me.lucko.luckperms.sponge.processors.UserDefaultsProcessor;
|
||||||
|
|
||||||
public class SpongeCalculatorFactory extends AbstractCalculatorFactory {
|
public class SpongeCalculatorFactory implements CalculatorFactory {
|
||||||
private final LPSpongePlugin plugin;
|
private final LPSpongePlugin plugin;
|
||||||
|
|
||||||
public SpongeCalculatorFactory(LPSpongePlugin plugin) {
|
public SpongeCalculatorFactory(LPSpongePlugin plugin) {
|
||||||
@ -74,6 +74,6 @@ public class SpongeCalculatorFactory extends AbstractCalculatorFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return registerCalculator(new PermissionCalculator(this.plugin, metadata, processors.build()));
|
return new PermissionCalculator(this.plugin, metadata, processors.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ public class SpongeConnectionListener extends AbstractConnectionListener {
|
|||||||
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||||
|
|
||||||
// force a clear of transient nodes
|
// force a clear of transient nodes
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.clearTransientNodes();
|
user.clearTransientNodes();
|
||||||
|
@ -237,8 +237,6 @@ public class LuckPermsService implements LPPermissionService {
|
|||||||
subject.invalidateCaches();
|
subject.invalidateCaches();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.plugin.getCalculatorFactory().invalidateAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ public class UpdateEventHandlerImpl implements UpdateEventHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fireUpdateEvent(LPSubjectData subjectData) {
|
public void fireUpdateEvent(LPSubjectData subjectData) {
|
||||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||||
SubjectDataUpdateEvent event = new LPSubjectDataUpdateEvent(this.plugin, subjectData);
|
SubjectDataUpdateEvent event = new LPSubjectDataUpdateEvent(this.plugin, subjectData);
|
||||||
this.plugin.getBootstrap().getGame().getEventManager().post(event);
|
this.plugin.getBootstrap().getGame().getEventManager().post(event);
|
||||||
});
|
});
|
||||||
|
@ -161,7 +161,7 @@ public abstract class HolderSubject<T extends PermissionHolder> implements LPSub
|
|||||||
@Override
|
@Override
|
||||||
public void invalidateCaches() {
|
public void invalidateCaches() {
|
||||||
// invalidate for all changes
|
// invalidate for all changes
|
||||||
this.parent.getCachedData().invalidate();
|
this.parent.invalidateCachedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ import com.google.gson.JsonObject;
|
|||||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
import me.lucko.luckperms.common.contexts.ContextSetComparator;
|
import me.lucko.luckperms.common.contexts.ContextSetComparator;
|
||||||
import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
|
import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
|
||||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
|
||||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||||
@ -204,7 +203,7 @@ public class SubjectDataContainer {
|
|||||||
|
|
||||||
// sort alphabetically.
|
// sort alphabetically.
|
||||||
List<Map.Entry<String, Boolean>> perms = new ArrayList<>(e.getValue().entrySet());
|
List<Map.Entry<String, Boolean>> perms = new ArrayList<>(e.getValue().entrySet());
|
||||||
perms.sort(Map.Entry.comparingByKey(CollationKeyCache.comparator()));
|
perms.sort(Map.Entry.comparingByKey());
|
||||||
|
|
||||||
for (Map.Entry<String, Boolean> ent : perms) {
|
for (Map.Entry<String, Boolean> ent : perms) {
|
||||||
data.addProperty(ent.getKey(), ent.getValue());
|
data.addProperty(ent.getKey(), ent.getValue());
|
||||||
@ -228,7 +227,7 @@ public class SubjectDataContainer {
|
|||||||
|
|
||||||
// sort alphabetically.
|
// sort alphabetically.
|
||||||
List<Map.Entry<String, String>> opts = new ArrayList<>(e.getValue().entrySet());
|
List<Map.Entry<String, String>> opts = new ArrayList<>(e.getValue().entrySet());
|
||||||
opts.sort(Map.Entry.comparingByKey(CollationKeyCache.comparator()));
|
opts.sort(Map.Entry.comparingByKey());
|
||||||
|
|
||||||
for (Map.Entry<String, String> ent : opts) {
|
for (Map.Entry<String, String> ent : opts) {
|
||||||
data.addProperty(ent.getKey(), ent.getValue());
|
data.addProperty(ent.getKey(), ent.getValue());
|
||||||
|
Loading…
Reference in New Issue
Block a user