Extract common plugin behaviour into an abstract class

This commit is contained in:
Luck
2018-03-03 16:26:27 +00:00
Unverified
parent cd5447de38
commit 68e4d36f40
98 changed files with 2310 additions and 2177 deletions
@@ -0,0 +1,298 @@
/*
* 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.sponge;
import com.google.inject.Inject;
import me.lucko.luckperms.api.platform.PlatformType;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
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.sponge.utils.VersionData;
import org.slf4j.Logger;
import org.spongepowered.api.Game;
import org.spongepowered.api.Platform;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.Order;
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.scheduler.AsynchronousExecutor;
import org.spongepowered.api.scheduler.Scheduler;
import org.spongepowered.api.scheduler.SpongeExecutorService;
import org.spongepowered.api.scheduler.SynchronousExecutor;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Stream;
import javax.annotation.Nullable;
/**
* Bootstrap plugin for LuckPerms running on Sponge.
*/
@Plugin(
id = "luckperms",
name = "LuckPerms",
version = VersionData.VERSION,
authors = "Luck",
description = "A permissions plugin",
url = "https://github.com/lucko/LuckPerms"
)
public class LPSpongeBootstrap implements LuckPermsBootstrap {
/**
* A scheduler adapter for the platform
*/
private final SchedulerAdapter schedulerAdapter;
/**
* The plugin classloader
*/
private final PluginClassLoader classLoader;
/**
* The plugin instance
*/
private final LPSpongePlugin plugin;
/**
* The time when the plugin was enabled
*/
private long startTime;
// load/enable latches
private final CountDownLatch loadLatch = new CountDownLatch(1);
private final CountDownLatch enableLatch = new CountDownLatch(1);
/**
* Injected plugin logger
*/
@Inject
private Logger logger;
/**
* Reference to the central {@link Game} instance in the API
*/
@Inject
private Game game;
/**
* Reference to the sponge scheduler
*/
private final Scheduler spongeScheduler;
/**
* Injected configuration directory for the plugin
*/
@Inject
@ConfigDir(sharedRoot = false)
private Path configDirectory;
/**
* Injected plugin container for the plugin
*/
@Inject
private PluginContainer pluginContainer;
@Inject
public LPSpongeBootstrap(@SynchronousExecutor SpongeExecutorService syncExecutor, @AsynchronousExecutor SpongeExecutorService asyncExecutor) {
this.spongeScheduler = Sponge.getScheduler();
this.schedulerAdapter = new SpongeSchedulerAdapter(this, this.spongeScheduler, syncExecutor, asyncExecutor);
this.classLoader = new ReflectionClassLoader(this);
this.plugin = new LPSpongePlugin(this);
}
// provide adapters
@Override
public SchedulerAdapter getScheduler() {
return this.schedulerAdapter;
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.classLoader;
}
// lifecycle
@Listener(order = Order.FIRST)
public void onEnable(GamePreInitializationEvent event) {
this.startTime = System.currentTimeMillis();
try {
this.plugin.load();
} finally {
this.loadLatch.countDown();
}
try {
this.plugin.enable();
} finally {
this.enableLatch.countDown();
}
}
@Listener(order = Order.LATE)
public void onLateEnable(GamePreInitializationEvent event) {
this.plugin.lateEnable();
}
@Listener
public void onDisable(GameStoppingServerEvent event) {
this.plugin.disable();
}
@Override
public CountDownLatch getEnableLatch() {
return this.enableLatch;
}
@Override
public CountDownLatch getLoadLatch() {
return this.loadLatch;
}
// getters for the injected sponge instances
public Logger getLogger() {
return this.logger;
}
public Game getGame() {
return this.game;
}
public Scheduler getSpongeScheduler() {
return this.spongeScheduler;
}
public Path getConfigPath() {
return this.configDirectory;
}
public PluginContainer getPluginContainer() {
return this.pluginContainer;
}
// provide information about the plugin
@Override
public String getVersion() {
return VersionData.VERSION;
}
@Override
public long getStartupTime() {
return this.startTime;
}
// provide information about the platform
@Override
public PlatformType getType() {
return PlatformType.SPONGE;
}
@Override
public String getServerBrand() {
return getGame().getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getName();
}
@Override
public String getServerVersion() {
return getGame().getPlatform().getContainer(Platform.Component.API).getName() + ": " +
getGame().getPlatform().getContainer(Platform.Component.API).getVersion().orElse("null") + " - " +
getGame().getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getName() + ": " +
getGame().getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getVersion().orElse("null");
}
@Override
public File getDataDirectory() {
File serverRoot = getConfigPath().toFile().getParentFile().getParentFile();
File dataDirectory = new File(serverRoot, "luckperms");
dataDirectory.mkdirs();
return dataDirectory;
}
@Override
public InputStream getResourceStream(String path) {
return getClass().getClassLoader().getResourceAsStream(path);
}
@Nullable
@Override
public Player getPlayer(UUID uuid) {
if (!getGame().isServerAvailable()) {
return null;
}
return getGame().getServer().getPlayer(uuid).orElse(null);
}
@Override
public Optional<UUID> lookupUuid(String username) {
if (!getGame().isServerAvailable()) {
return Optional.empty();
}
return getGame().getServer().getGameProfileManager().get(username)
.thenApply(p -> Optional.of(p.getUniqueId()))
.exceptionally(x -> Optional.empty())
.join();
}
@Override
public int getPlayerCount() {
return getGame().isServerAvailable() ? getGame().getServer().getOnlinePlayers().size() : 0;
}
@Override
public Stream<String> getPlayerList() {
return getGame().isServerAvailable() ? getGame().getServer().getOnlinePlayers().stream().map(Player::getName) : Stream.empty();
}
@Override
public Stream<UUID> getOnlinePlayers() {
return getGame().isServerAvailable() ? getGame().getServer().getOnlinePlayers().stream().map(Player::getUniqueId) : Stream.empty();
}
@Override
public boolean isPlayerOnline(UUID uuid) {
return getGame().isServerAvailable() ? getGame().getServer().getPlayer(uuid).map(Player::isOnline).orElse(false) : false;
}
}
@@ -25,50 +25,22 @@
package me.lucko.luckperms.sponge;
import com.google.inject.Inject;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.platform.PlatformType;
import me.lucko.luckperms.common.actionlog.LogDispatcher;
import me.lucko.luckperms.common.api.ApiRegistrationUtil;
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
import me.lucko.luckperms.common.buffers.BufferedRequest;
import me.lucko.luckperms.common.buffers.UpdateTaskBuffer;
import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.commands.CommandManager;
import me.lucko.luckperms.common.commands.CommandPermission;
import me.lucko.luckperms.common.commands.abstraction.Command;
import me.lucko.luckperms.common.commands.sender.DummySender;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.config.AbstractConfiguration;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.config.LuckPermsConfiguration;
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.contexts.LuckPermsCalculator;
import me.lucko.luckperms.common.dependencies.DependencyManager;
import me.lucko.luckperms.common.dependencies.DependencyRegistry;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
import me.lucko.luckperms.common.event.EventFactory;
import me.lucko.luckperms.common.inheritance.InheritanceHandler;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.NoopLocaleManager;
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
import me.lucko.luckperms.common.logging.SenderLogger;
import me.lucko.luckperms.common.managers.track.StandardTrackManager;
import me.lucko.luckperms.common.messaging.InternalMessagingService;
import me.lucko.luckperms.common.messaging.MessagingFactory;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.storage.dao.file.FileWatcher;
import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin;
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
import me.lucko.luckperms.common.tasks.UpdateTask;
import me.lucko.luckperms.common.treeview.PermissionVault;
import me.lucko.luckperms.common.verbose.VerboseHandler;
import me.lucko.luckperms.sponge.calculators.SpongeCalculatorFactory;
import me.lucko.luckperms.sponge.commands.SpongeMainCommand;
import me.lucko.luckperms.sponge.contexts.SpongeContextManager;
@@ -83,33 +55,13 @@ import me.lucko.luckperms.sponge.service.event.UpdateEventHandler;
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.model.LuckPermsSpongePlugin;
import me.lucko.luckperms.sponge.service.persisted.PersistedCollection;
import me.lucko.luckperms.sponge.tasks.ServiceCacheHousekeepingTask;
import me.lucko.luckperms.sponge.utils.VersionData;
import org.slf4j.Logger;
import org.spongepowered.api.Game;
import org.spongepowered.api.Platform;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandManager;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.Order;
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.profile.GameProfile;
import org.spongepowered.api.scheduler.AsynchronousExecutor;
import org.spongepowered.api.scheduler.Scheduler;
import org.spongepowered.api.scheduler.SpongeExecutorService;
import org.spongepowered.api.scheduler.SynchronousExecutor;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@@ -117,233 +69,127 @@ import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;
/**
* LuckPerms implementation for the Sponge API.
*/
@Plugin(
id = "luckperms",
name = "LuckPerms",
version = VersionData.VERSION,
authors = "Luck",
description = "A permissions plugin",
url = "https://github.com/lucko/LuckPerms"
)
public class LPSpongePlugin implements LuckPermsSpongePlugin {
public class LPSpongePlugin extends AbstractLuckPermsPlugin {
private final LPSpongeBootstrap bootstrap;
@Inject
private Logger logger;
@Inject
private Game game;
@Inject
@ConfigDir(sharedRoot = false)
private Path configDirectory;
private Scheduler spongeScheduler = Sponge.getScheduler();
@Inject
@SynchronousExecutor
private SpongeExecutorService syncExecutorService;
@Inject
@AsynchronousExecutor
private SpongeExecutorService asyncExecutorService;
@Inject
private PluginContainer pluginContainer;
private boolean lateLoad = false;
private long startTime;
private SchedulerAdapter scheduler;
private SpongeSenderFactory senderFactory;
private SpongeConnectionListener connectionListener;
private SpongeCommandExecutor commandManager;
private LuckPermsConfiguration configuration;
private SpongeUserManager userManager;
private SpongeGroupManager groupManager;
private StandardTrackManager trackManager;
private Storage storage;
private FileWatcher fileWatcher = null;
private InternalMessagingService messagingService = null;
private LuckPermsApiProvider apiProvider;
private EventFactory eventFactory;
private UpdateEventHandler updateEventHandler;
private me.lucko.luckperms.common.logging.Logger log;
private LuckPermsService service;
private LocaleManager localeManager;
private PluginClassLoader pluginClassLoader;
private DependencyManager dependencyManager;
private InheritanceHandler inheritanceHandler;
private CachedStateManager cachedStateManager;
private ContextManager<Subject> contextManager;
private CalculatorFactory calculatorFactory;
private BufferedRequest<Void> updateTaskBuffer;
private VerboseHandler verboseHandler;
private SpongeSenderFactory senderFactory;
private PermissionVault permissionVault;
private LogDispatcher logDispatcher;
private Set<UUID> uniqueConnections = ConcurrentHashMap.newKeySet();
private LuckPermsService service;
private UpdateEventHandler updateEventHandler;
@Listener(order = Order.FIRST)
public void onEnable(GamePreInitializationEvent event) {
this.startTime = System.currentTimeMillis();
this.scheduler = new SpongeSchedulerAdapter(this);
this.localeManager = new NoopLocaleManager();
private boolean lateLoad = false;
public LPSpongePlugin(LPSpongeBootstrap bootstrap) {
this.bootstrap = bootstrap;
}
@Override
public LPSpongeBootstrap getBootstrap() {
return this.bootstrap;
}
@Override
protected void setupSenderFactory() {
this.senderFactory = new SpongeSenderFactory(this);
this.log = new SenderLogger(this, getConsoleSender());
this.pluginClassLoader = new ReflectionClassLoader(this);
this.dependencyManager = new DependencyManager(this);
this.dependencyManager.loadDependencies(DependencyRegistry.GLOBAL_DEPENDENCIES);
}
sendStartupBanner(getConsoleSender());
this.verboseHandler = new VerboseHandler(this.scheduler.async());
this.permissionVault = new PermissionVault(this.scheduler.async());
this.logDispatcher = new LogDispatcher(this);
@Override
protected ConfigurationAdapter provideConfigurationAdapter() {
return new SpongeConfigAdapter(this, resolveConfig());
}
getLog().info("Loading configuration...");
this.configuration = new AbstractConfiguration(this, new SpongeConfigAdapter(this, resolveConfig("luckperms.conf")));
this.configuration.loadAll();
@Override
protected void registerPlatformListeners() {
this.connectionListener = new SpongeConnectionListener(this);
this.bootstrap.getGame().getEventManager().registerListeners(this, this.connectionListener);
this.bootstrap.getGame().getEventManager().registerListeners(this, new SpongePlatformListener(this));
}
StorageFactory storageFactory = new StorageFactory(this);
Set<StorageType> storageTypes = storageFactory.getRequiredTypes(StorageType.H2);
this.dependencyManager.loadStorageDependencies(storageTypes);
@Override
protected MessagingFactory<?> provideMessagingFactory() {
return new SpongeMessagingFactory(this);
}
// register events
this.game.getEventManager().registerListeners(this, new SpongeConnectionListener(this));
this.game.getEventManager().registerListeners(this, new SpongePlatformListener(this));
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
this.fileWatcher = new FileWatcher(this);
getScheduler().asyncRepeating(this.fileWatcher, 30L);
}
// initialise datastore
this.storage = storageFactory.getInstance(StorageType.H2);
// initialise messaging
this.messagingService = new SpongeMessagingFactory(this).getInstance();
// setup the update task buffer
this.updateTaskBuffer = new UpdateTaskBuffer(this);
// load locale
this.localeManager = new SimpleLocaleManager();
this.localeManager.tryLoad(this, new File(getDataDirectory(), "lang.yml"));
// register commands
CommandManager cmdService = this.game.getCommandManager();
@Override
protected void registerCommands() {
this.commandManager = new SpongeCommandExecutor(this);
cmdService.register(this, this.commandManager, "luckperms", "lp", "perm", "perms", "permission", "permissions");
this.bootstrap.getGame().getCommandManager().register(this, this.commandManager, "luckperms", "lp", "perm", "perms", "permission", "permissions");
}
// load internal managers
getLog().info("Loading internal permission managers...");
this.inheritanceHandler = new InheritanceHandler(this);
@Override
protected void setupManagers() {
this.userManager = new SpongeUserManager(this);
this.groupManager = new SpongeGroupManager(this);
this.trackManager = new StandardTrackManager(this);
this.calculatorFactory = new SpongeCalculatorFactory(this);
this.cachedStateManager = new CachedStateManager();
}
// setup context manager
@Override
protected CalculatorFactory provideCalculatorFactory() {
return new SpongeCalculatorFactory(this);
}
@Override
protected void setupContextManager() {
this.contextManager = new SpongeContextManager(this);
this.contextManager.registerCalculator(new WorldCalculator(this));
this.contextManager.registerStaticCalculator(new LuckPermsCalculator(getConfiguration()));
}
// register the PermissionService with Sponge
getLog().info("Registering PermissionService...");
@Override
protected void setupPlatformHooks() {
getLogger().info("Registering PermissionService...");
this.updateEventHandler = UpdateEventHandler.obtain(this);
this.service = new LuckPermsService(this);
if (this.game.getPluginManager().getPlugin("permissionsex").isPresent()) {
getLog().warn("Detected PermissionsEx - assuming it's loaded for migration.");
getLog().warn("Delaying LuckPerms PermissionService registration.");
if (this.bootstrap.getGame().getPluginManager().getPlugin("permissionsex").isPresent()) {
getLogger().warn("Detected PermissionsEx - assuming it's loaded for migration.");
getLogger().warn("Delaying LuckPerms PermissionService registration.");
this.lateLoad = true;
} else {
this.game.getServiceManager().setProvider(this, LPPermissionService.class, this.service);
this.game.getServiceManager().setProvider(this, PermissionService.class, this.service.sponge());
this.game.getServiceManager().setProvider(this, LuckPermsService.class, this.service);
this.bootstrap.getGame().getServiceManager().setProvider(this, LPPermissionService.class, this.service);
this.bootstrap.getGame().getServiceManager().setProvider(this, PermissionService.class, this.service.sponge());
this.bootstrap.getGame().getServiceManager().setProvider(this, LuckPermsService.class, this.service);
}
}
// register with the LP API
this.apiProvider = new LuckPermsApiProvider(this);
@Override
protected void registerApiOnPlatform(LuckPermsApi api) {
this.bootstrap.getGame().getServiceManager().setProvider(this, LuckPermsApi.class, api);
}
// setup event factory
this.eventFactory = new EventFactory(this, this.apiProvider);
ApiRegistrationUtil.registerProvider(this.apiProvider);
this.game.getServiceManager().setProvider(this, LuckPermsApi.class, this.apiProvider);
// schedule update tasks
int mins = getConfiguration().get(ConfigKeys.SYNC_TIME);
if (mins > 0) {
long ticks = mins * 60 * 20;
this.scheduler.asyncRepeating(() -> this.updateTaskBuffer.request(), ticks);
}
this.scheduler.asyncLater(() -> this.updateTaskBuffer.request(), 40L);
// run an update instantly.
getLog().info("Performing initial data load...");
try {
new UpdateTask(this, true).run();
} catch (Exception e) {
e.printStackTrace();
}
// register tasks
this.scheduler.asyncRepeating(new ExpireTemporaryTask(this), 60L);
this.scheduler.asyncRepeating(new CacheHousekeepingTask(this), 2400L);
this.scheduler.asyncRepeating(new ServiceCacheHousekeepingTask(this.service), 2400L);
@Override
protected void registerHousekeepingTasks() {
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 60L);
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2400L);
this.bootstrap.getScheduler().asyncRepeating(new ServiceCacheHousekeepingTask(this.service), 2400L);
}
@Override
protected void performFinalSetup() {
// register permissions
for (CommandPermission perm : CommandPermission.values()) {
this.service.registerPermissionDescription(perm.getPermission(), null, this.pluginContainer);
this.service.registerPermissionDescription(perm.getPermission(), null, this.bootstrap.getPluginContainer());
}
getLog().info("Successfully enabled. (took " + (System.currentTimeMillis() - this.startTime) + "ms)");
}
@Listener(order = Order.LATE)
public void onLateEnable(GamePreInitializationEvent event) {
public void lateEnable() {
if (this.lateLoad) {
getLog().info("Providing late registration of PermissionService...");
this.game.getServiceManager().setProvider(this, LPPermissionService.class, this.service);
this.game.getServiceManager().setProvider(this, PermissionService.class, this.service.sponge());
this.game.getServiceManager().setProvider(this, LuckPermsService.class, this.service);
getLogger().info("Providing late registration of PermissionService...");
this.bootstrap.getGame().getServiceManager().setProvider(this, LPPermissionService.class, this.service);
this.bootstrap.getGame().getServiceManager().setProvider(this, PermissionService.class, this.service.sponge());
this.bootstrap.getGame().getServiceManager().setProvider(this, LuckPermsService.class, this.service);
}
}
@Listener
public void onDisable(GameStoppingServerEvent event) {
this.permissionVault.shutdown();
this.verboseHandler.shutdown();
getLog().info("Closing storage...");
this.storage.shutdown();
if (this.fileWatcher != null) {
this.fileWatcher.close();
}
if (this.messagingService != null) {
getLog().info("Closing messaging service...");
this.messagingService.close();
}
ApiRegistrationUtil.unregisterProvider();
getLog().info("Shutting down internal scheduler...");
this.scheduler.shutdown();
getLog().info("Goodbye!");
}
@Override
public void onPostUpdate() {
for (LPSubjectCollection collection : this.service.getLoadedCollections().values()) {
@@ -354,13 +200,12 @@ public class LPSpongePlugin implements LuckPermsSpongePlugin {
this.service.invalidateAllCaches(LPSubject.CacheLevel.PARENT);
}
private Path resolveConfig(String file) {
Path path = this.configDirectory.resolve(file);
private Path resolveConfig() {
Path path = this.bootstrap.getConfigPath().resolve("luckperms.conf");
if (!Files.exists(path)) {
try {
Files.createDirectories(this.configDirectory);
try (InputStream is = getClass().getClassLoader().getResourceAsStream(file)) {
Files.createDirectories(this.bootstrap.getConfigPath());
try (InputStream is = getClass().getClassLoader().getResourceAsStream("luckperms.conf")) {
Files.copy(is, path);
}
} catch (IOException e) {
@@ -371,140 +216,38 @@ public class LPSpongePlugin implements LuckPermsSpongePlugin {
return path;
}
@Override
public Optional<InternalMessagingService> getMessagingService() {
return Optional.ofNullable(this.messagingService);
}
@Override
public void setMessagingService(InternalMessagingService messagingService) {
if (this.messagingService == null) {
this.messagingService = messagingService;
}
}
@Override
public Optional<FileWatcher> getFileWatcher() {
return Optional.ofNullable(this.fileWatcher);
}
@Override
public File getDataDirectory() {
File serverRoot = this.configDirectory.toFile().getParentFile().getParentFile();
File dataDirectory = new File(serverRoot, "luckperms");
dataDirectory.mkdirs();
return dataDirectory;
}
@Override
public File getConfigDirectory() {
return this.configDirectory.toFile();
}
@Override
public InputStream getResourceStream(String path) {
return getClass().getClassLoader().getResourceAsStream(path);
}
@Override
public Player getPlayer(User user) {
if (!this.game.isServerAvailable()) {
return null;
}
return this.game.getServer().getPlayer(user.getUuid()).orElse(null);
}
@Override
public Optional<UUID> lookupUuid(String username) {
if (!this.game.isServerAvailable()) {
return Optional.empty();
}
CompletableFuture<GameProfile> fut = this.game.getServer().getGameProfileManager().get(username);
try {
return Optional.of(fut.get().getUniqueId());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return Optional.empty();
}
}
@Override
public Optional<Contexts> getContextForUser(User user) {
Player player = getPlayer(user);
Player player = this.bootstrap.getPlayer(user.getUuid());
if (player == null) {
return Optional.empty();
}
return Optional.of(this.contextManager.getApplicableContexts(player));
}
@Override
public String getVersion() {
return VersionData.VERSION;
}
@Override
public PlatformType getServerType() {
return PlatformType.SPONGE;
}
@Override
public String getServerBrand() {
return getGame().getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getName();
}
@Override
public String getServerVersion() {
return getGame().getPlatform().getContainer(Platform.Component.API).getName() + ": " +
getGame().getPlatform().getContainer(Platform.Component.API).getVersion().orElse("null") + " - " +
getGame().getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getName() + ": " +
getGame().getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getVersion().orElse("null");
}
@Override
public int getPlayerCount() {
return this.game.isServerAvailable() ? this.game.getServer().getOnlinePlayers().size() : 0;
}
@Override
public Stream<String> getPlayerList() {
return this.game.isServerAvailable() ? this.game.getServer().getOnlinePlayers().stream().map(Player::getName) : Stream.empty();
}
@Override
public Stream<UUID> getOnlinePlayers() {
return this.game.isServerAvailable() ? this.game.getServer().getOnlinePlayers().stream().map(Player::getUniqueId) : Stream.empty();
}
@Override
public boolean isPlayerOnline(UUID external) {
return this.game.isServerAvailable() ? this.game.getServer().getPlayer(external).map(Player::isOnline).orElse(false) : false;
}
@Override
public Stream<Sender> getOnlineSenders() {
if (!this.game.isServerAvailable()) {
if (!this.bootstrap.getGame().isServerAvailable()) {
return Stream.empty();
}
return Stream.concat(
Stream.of(getConsoleSender()),
this.game.getServer().getOnlinePlayers().stream().map(s -> getSenderFactory().wrap(s))
this.bootstrap.getGame().getServer().getOnlinePlayers().stream().map(s -> this.senderFactory.wrap(s))
);
}
@Override
public Sender getConsoleSender() {
if (!this.game.isServerAvailable()) {
return new DummySender(this, me.lucko.luckperms.common.commands.CommandManager.CONSOLE_UUID, me.lucko.luckperms.common.commands.CommandManager.CONSOLE_NAME) {
if (!this.bootstrap.getGame().isServerAvailable()) {
return new DummySender(this, CommandManager.CONSOLE_UUID, CommandManager.CONSOLE_NAME) {
@Override
protected void consumeMessage(String s) {
LPSpongePlugin.this.logger.info(s);
LPSpongePlugin.this.bootstrap.getLogger().info(s);
}
};
}
return getSenderFactory().wrap(this.game.getServer().getConsole());
return this.senderFactory.wrap(this.bootstrap.getGame().getServer().getConsole());
}
@Override
@@ -512,38 +255,13 @@ public class LPSpongePlugin implements LuckPermsSpongePlugin {
return Collections.singletonList(new SpongeMainCommand(this));
}
public Game getGame() {
return this.game;
}
public PluginContainer getPluginContainer() {
return this.pluginContainer;
}
public Scheduler getSpongeScheduler() {
return this.spongeScheduler;
}
public UpdateEventHandler getUpdateEventHandler() {
return this.updateEventHandler;
}
public SpongeExecutorService getSyncExecutorService() {
return this.syncExecutorService;
}
public SpongeExecutorService getAsyncExecutorService() {
return this.asyncExecutorService;
public SpongeSenderFactory getSenderFactory() {
return this.senderFactory;
}
@Override
public long getStartTime() {
return this.startTime;
}
@Override
public SchedulerAdapter getScheduler() {
return this.scheduler;
public SpongeConnectionListener getConnectionListener() {
return this.connectionListener;
}
@Override
@@ -551,11 +269,6 @@ public class LPSpongePlugin implements LuckPermsSpongePlugin {
return this.commandManager;
}
@Override
public LuckPermsConfiguration getConfiguration() {
return this.configuration;
}
@Override
public SpongeUserManager getUserManager() {
return this.userManager;
@@ -572,90 +285,16 @@ public class LPSpongePlugin implements LuckPermsSpongePlugin {
}
@Override
public Storage getStorage() {
return this.storage;
}
@Override
public LuckPermsApiProvider getApiProvider() {
return this.apiProvider;
}
@Override
public EventFactory getEventFactory() {
return this.eventFactory;
}
@Override
public me.lucko.luckperms.common.logging.Logger getLog() {
return this.log;
public ContextManager<Subject> getContextManager() {
return this.contextManager;
}
public LuckPermsService getService() {
return this.service;
}
@Override
public LocaleManager getLocaleManager() {
return this.localeManager;
public UpdateEventHandler getUpdateEventHandler() {
return this.updateEventHandler;
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.pluginClassLoader;
}
@Override
public DependencyManager getDependencyManager() {
return this.dependencyManager;
}
@Override
public CachedStateManager getCachedStateManager() {
return this.cachedStateManager;
}
@Override
public ContextManager<Subject> getContextManager() {
return this.contextManager;
}
@Override
public InheritanceHandler getInheritanceHandler() {
return this.inheritanceHandler;
}
@Override
public CalculatorFactory getCalculatorFactory() {
return this.calculatorFactory;
}
@Override
public BufferedRequest<Void> getUpdateTaskBuffer() {
return this.updateTaskBuffer;
}
@Override
public VerboseHandler getVerboseHandler() {
return this.verboseHandler;
}
public SpongeSenderFactory getSenderFactory() {
return this.senderFactory;
}
@Override
public PermissionVault getPermissionVault() {
return this.permissionVault;
}
@Override
public LogDispatcher getLogDispatcher() {
return this.logDispatcher;
}
@Override
public Set<UUID> getUniqueConnections() {
return this.uniqueConnections;
}
}
@@ -30,6 +30,7 @@ import me.lucko.luckperms.common.plugin.SchedulerTask;
import me.lucko.luckperms.common.utils.SafeIteration;
import org.spongepowered.api.scheduler.Scheduler;
import org.spongepowered.api.scheduler.SpongeExecutorService;
import org.spongepowered.api.scheduler.Task;
import java.util.Set;
@@ -37,45 +38,49 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
public class SpongeSchedulerAdapter implements SchedulerAdapter {
private final LPSpongePlugin plugin;
private final LPSpongeBootstrap bootstrap;
private final Scheduler scheduler;
private final SpongeExecutorService sync;
private final SpongeExecutorService async;
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
public SpongeSchedulerAdapter(LPSpongePlugin plugin) {
this.plugin = plugin;
}
private Scheduler scheduler() {
return this.plugin.getSpongeScheduler();
public SpongeSchedulerAdapter(LPSpongeBootstrap bootstrap, Scheduler scheduler, SpongeExecutorService sync, SpongeExecutorService async) {
this.bootstrap = bootstrap;
this.scheduler = scheduler;
this.sync = sync;
this.async = async;
}
@Override
public Executor async() {
return this.plugin.getAsyncExecutorService();
return this.async;
}
@Override
public Executor sync() {
return this.plugin.getSyncExecutorService();
return this.sync;
}
@Override
public void doAsync(Runnable runnable) {
this.plugin.getSpongeScheduler().createTaskBuilder().async().execute(runnable).submit(this.plugin);
this.scheduler.createTaskBuilder().async().execute(runnable).submit(this.bootstrap);
}
@Override
public void doSync(Runnable runnable) {
this.plugin.getSpongeScheduler().createTaskBuilder().execute(runnable).submit(this.plugin);
this.scheduler.createTaskBuilder().execute(runnable).submit(this.bootstrap);
}
@Override
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
Task task = scheduler().createTaskBuilder()
Task task = this.scheduler.createTaskBuilder()
.async()
.intervalTicks(intervalTicks)
.delayTicks(intervalTicks)
.execute(runnable)
.submit(this.plugin);
.submit(this.bootstrap);
SchedulerTask wrapped = new SpongeSchedulerTask(task);
this.tasks.add(wrapped);
@@ -84,11 +89,11 @@ public class SpongeSchedulerAdapter implements SchedulerAdapter {
@Override
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
Task task = scheduler().createTaskBuilder()
Task task = this.scheduler.createTaskBuilder()
.intervalTicks(intervalTicks)
.delayTicks(intervalTicks)
.execute(runnable)
.submit(this.plugin);
.submit(this.bootstrap);
SchedulerTask wrapped = new SpongeSchedulerTask(task);
this.tasks.add(wrapped);
@@ -97,11 +102,11 @@ public class SpongeSchedulerAdapter implements SchedulerAdapter {
@Override
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
Task task = scheduler().createTaskBuilder()
Task task = this.scheduler.createTaskBuilder()
.async()
.delayTicks(delayTicks)
.execute(runnable)
.submit(this.plugin);
.submit(this.bootstrap);
SchedulerTask wrapped = new SpongeSchedulerTask(task);
this.tasks.add(wrapped);
@@ -110,10 +115,10 @@ public class SpongeSchedulerAdapter implements SchedulerAdapter {
@Override
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
Task task = scheduler().createTaskBuilder()
Task task = this.scheduler.createTaskBuilder()
.delayTicks(delayTicks)
.execute(runnable)
.submit(this.plugin);
.submit(this.bootstrap);
SchedulerTask wrapped = new SpongeSchedulerTask(task);
this.tasks.add(wrapped);
@@ -26,9 +26,9 @@
package me.lucko.luckperms.sponge.listeners;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.listener.AbstractConnectionListener;
import me.lucko.luckperms.common.locale.Message;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.utils.AbstractLoginListener;
import me.lucko.luckperms.sponge.LPSpongePlugin;
import org.spongepowered.api.entity.living.player.Player;
@@ -45,7 +45,7 @@ import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class SpongeConnectionListener extends AbstractLoginListener {
public class SpongeConnectionListener extends AbstractConnectionListener {
private final LPSpongePlugin plugin;
private final Set<UUID> deniedAsyncLogin = Collections.synchronizedSet(new HashSet<>());
@@ -66,10 +66,10 @@ public class SpongeConnectionListener extends AbstractLoginListener {
final String username = profile.getName().orElseThrow(() -> new RuntimeException("No username present for user " + profile.getUniqueId()));
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
this.plugin.getLog().info("Processing auth event for " + profile.getUniqueId() + " - " + profile.getName());
this.plugin.getLogger().info("Processing auth event for " + profile.getUniqueId() + " - " + profile.getName());
}
this.plugin.getUniqueConnections().add(profile.getUniqueId());
recordConnection(profile.getUniqueId());
/* Actually process the login for the connection.
We do this here to delay the login until the data is ready.
@@ -84,7 +84,7 @@ public class SpongeConnectionListener extends AbstractLoginListener {
User user = loadUser(profile.getUniqueId(), username);
this.plugin.getEventFactory().handleUserLoginProcess(profile.getUniqueId(), username, user);
} catch (Exception ex) {
this.plugin.getLog().severe("Exception occurred whilst loading data for " + profile.getUniqueId() + " - " + profile.getName());
this.plugin.getLogger().severe("Exception occurred whilst loading data for " + profile.getUniqueId() + " - " + profile.getName());
ex.printStackTrace();
this.deniedAsyncLogin.add(profile.getUniqueId());
@@ -107,7 +107,7 @@ public class SpongeConnectionListener extends AbstractLoginListener {
// This is a problem, as they were denied at low priority, but are now being allowed.
if (e.isCancelled()) {
this.plugin.getLog().severe("Player connection was re-allowed for " + e.getProfile().getUniqueId());
this.plugin.getLogger().severe("Player connection was re-allowed for " + e.getProfile().getUniqueId());
e.setCancelled(true);
}
}
@@ -123,7 +123,7 @@ public class SpongeConnectionListener extends AbstractLoginListener {
final GameProfile profile = e.getProfile();
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
this.plugin.getLog().info("Processing login event for " + profile.getUniqueId() + " - " + profile.getName());
this.plugin.getLogger().info("Processing login event for " + profile.getUniqueId() + " - " + profile.getName());
}
final User user = this.plugin.getUserManager().getIfLoaded(profile.getUniqueId());
@@ -132,7 +132,7 @@ public class SpongeConnectionListener extends AbstractLoginListener {
if (user == null) {
this.deniedLogin.add(profile.getUniqueId());
this.plugin.getLog().warn("User " + profile.getUniqueId() + " - " + profile.getName() + " doesn't have data pre-loaded. - denying login.");
this.plugin.getLogger().warn("User " + profile.getUniqueId() + " - " + profile.getName() + " doesn't have data pre-loaded. - denying login.");
e.setCancelled(true);
e.setMessageCancelled(false);
//noinspection deprecation
@@ -150,7 +150,7 @@ public class SpongeConnectionListener extends AbstractLoginListener {
if (this.deniedLogin.remove(e.getProfile().getUniqueId())) {
// This is a problem, as they were denied at low priority, but are now being allowed.
if (!e.isCancelled()) {
this.plugin.getLog().severe("Player connection was re-allowed for " + e.getProfile().getUniqueId());
this.plugin.getLogger().severe("Player connection was re-allowed for " + e.getProfile().getUniqueId());
e.setCancelled(true);
}
}
@@ -165,7 +165,7 @@ public class SpongeConnectionListener extends AbstractLoginListener {
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
// force a clear of transient nodes
this.plugin.getScheduler().doAsync(() -> {
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
if (user != null) {
user.clearTransientNodes();
@@ -82,7 +82,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
group = getIfLoaded(s);
if (group == null) {
getPlugin().getLog().severe("Error whilst loading group '" + s + "'.");
getPlugin().getLogger().severe("Error whilst loading group '" + s + "'.");
throw new RuntimeException();
}
@@ -137,7 +137,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
return CompletableFuture.completedFuture(present);
}
return CompletableFuture.supplyAsync(() -> this.subjectLoadingCache.get(identifier.toLowerCase()), this.plugin.getScheduler().async());
return CompletableFuture.supplyAsync(() -> this.subjectLoadingCache.get(identifier.toLowerCase()), this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -170,7 +170,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
}
return ret.build();
}, this.plugin.getScheduler().async());
}, this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -196,7 +196,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
}
return ret.build();
}, this.plugin.getScheduler().async());
}, this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -212,7 +212,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
}
return ret.build();
}, this.plugin.getScheduler().async());
}, this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -89,7 +89,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
getPlugin().getStorage().loadUser(u, null).join();
user = getIfLoaded(u);
if (user == null) {
getPlugin().getLog().severe("Error whilst loading user '" + u + "'.");
getPlugin().getLogger().severe("Error whilst loading user '" + u + "'.");
throw new RuntimeException();
}
@@ -149,7 +149,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
return CompletableFuture.completedFuture(present);
}
return CompletableFuture.supplyAsync(() -> this.subjectLoadingCache.get(uuid), this.plugin.getScheduler().async());
return CompletableFuture.supplyAsync(() -> this.subjectLoadingCache.get(uuid), this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -188,7 +188,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
}
return ret.build();
}, this.plugin.getScheduler().async());
}, this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -205,7 +205,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
this.plugin.getStorage().getUniqueUsers().join().forEach(uuid -> ids.add(uuid.toString()));
return ids.build();
}, this.plugin.getScheduler().async());
}, this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -221,7 +221,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
}
return ret.build();
}, this.plugin.getScheduler().async());
}, this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -237,7 +237,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
}
return ret.build();
}, this.plugin.getScheduler().async());
}, this.plugin.getBootstrap().getScheduler().async());
}
@Override
@@ -61,25 +61,25 @@ public class BungeeMessenger implements Messenger, RawDataListener {
}
public void init() {
this.channel = this.plugin.getGame().getChannelRegistrar().createRawChannel(this.plugin, CHANNEL);
this.channel = this.plugin.getBootstrap().getGame().getChannelRegistrar().createRawChannel(this.plugin, CHANNEL);
this.channel.addListener(Platform.Type.SERVER, this);
}
@Override
public void close() {
if (this.channel != null) {
this.plugin.getGame().getChannelRegistrar().unbindChannel(this.channel);
this.plugin.getBootstrap().getGame().getChannelRegistrar().unbindChannel(this.channel);
}
}
@Override
public void sendOutgoingMessage(@Nonnull OutgoingMessage outgoingMessage) {
this.plugin.getSpongeScheduler().createTaskBuilder().interval(10, TimeUnit.SECONDS).execute(task -> {
if (!this.plugin.getGame().isServerAvailable()) {
this.plugin.getBootstrap().getSpongeScheduler().createTaskBuilder().interval(10, TimeUnit.SECONDS).execute(task -> {
if (!this.plugin.getBootstrap().getGame().isServerAvailable()) {
return;
}
Collection<Player> players = this.plugin.getGame().getServer().getOnlinePlayers();
Collection<Player> players = this.plugin.getBootstrap().getGame().getServer().getOnlinePlayers();
Player p = Iterables.getFirst(players, null);
if (p == null) {
return;
@@ -31,6 +31,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.sponge.LPSpongePlugin;
@@ -88,7 +89,7 @@ public class LuckPermsService implements LPPermissionService {
this.referenceFactory = new SubjectReferenceFactory(this);
this.spongeProxy = ProxyFactory.toSponge(this);
this.storage = new SubjectStorage(this, new File(plugin.getDataDirectory(), "sponge-data"));
this.storage = new SubjectStorage(this, new File(plugin.getBootstrap().getDataDirectory(), "sponge-data"));
this.userSubjects = plugin.getUserManager();
this.groupSubjects = plugin.getGroupManager();
@@ -122,6 +123,11 @@ public class LuckPermsService implements LPPermissionService {
return this.plugin;
}
@Override
public ContextManager<Subject> getContextManager() {
return this.plugin.getContextManager();
}
@Override
public SubjectReferenceFactory getReferenceFactory() {
return this.referenceFactory;
@@ -59,7 +59,7 @@ public class LPSubjectDataUpdateEvent extends AbstractEvent implements SubjectDa
@Override
public Cause getCause() {
EventContext eventContext = EventContext.builder()
.add(EventContextKeys.PLUGIN, this.plugin.getPluginContainer())
.add(EventContextKeys.PLUGIN, this.plugin.getBootstrap().getPluginContainer())
.build();
return Cause.builder().build(eventContext);
@@ -40,6 +40,6 @@ public class UpdateEventHandlerImpl implements UpdateEventHandler {
@Override
public void fireUpdateEvent(LPSubjectData subjectData) {
SubjectDataUpdateEvent event = new LPSubjectDataUpdateEvent(this.plugin, subjectData);
this.plugin.getGame().getEventManager().post(event);
this.plugin.getBootstrap().getGame().getEventManager().post(event);
}
}
@@ -465,7 +465,7 @@ public class HolderSubjectData implements LPSubjectData {
}
user.getRefreshBuffer().request().thenAccept(fut::complete);
}, this.service.getPlugin().getScheduler().async());
}, this.service.getPlugin().getBootstrap().getScheduler().async());
return fut;
} else {
Group group = ((Group) t);
@@ -476,7 +476,7 @@ public class HolderSubjectData implements LPSubjectData {
}
this.service.getPlugin().getUpdateTaskBuffer().request().thenAccept(fut::complete);
}, this.service.getPlugin().getScheduler().async());
}, this.service.getPlugin().getBootstrap().getScheduler().async());
return fut;
}
}
@@ -77,7 +77,7 @@ public class PersistedSubject implements LPSubject {
.expireAfterAccess(20, TimeUnit.MINUTES)
.build(lookup -> lookupOptionValue(lookup.contexts, lookup.key));
private final BufferedRequest<Void> saveBuffer = new BufferedRequest<Void>(1000L, 500L, r -> PersistedSubject.this.service.getPlugin().getScheduler().doAsync(r)) {
private final BufferedRequest<Void> saveBuffer = new BufferedRequest<Void>(1000L, 500L, r -> PersistedSubject.this.service.getPlugin().getBootstrap().getScheduler().doAsync(r)) {
@Override
protected Void perform() {
try {