Rewrite the way user instances are cleaned up and unloaded - towards #674
This commit is contained in:
parent
ea94bd8696
commit
3201d10bdd
@ -28,7 +28,10 @@ package me.lucko.luckperms.bukkit;
|
|||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||||
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.utils.SafeIterator;
|
||||||
|
|
||||||
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -51,7 +54,7 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
|||||||
|
|
||||||
private boolean useFallback = true;
|
private boolean useFallback = true;
|
||||||
|
|
||||||
private final Set<BukkitTask> tasks = ConcurrentHashMap.newKeySet();
|
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public BukkitSchedulerAdapter(LPBukkitPlugin plugin) {
|
public BukkitSchedulerAdapter(LPBukkitPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@ -62,6 +65,10 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
|||||||
this.async = new AsyncExecutor();
|
this.async = new AsyncExecutor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BukkitScheduler scheduler() {
|
||||||
|
return this.plugin.getServer().getScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAsync(Runnable runnable) {
|
public void doAsync(Runnable runnable) {
|
||||||
async().execute(runnable);
|
async().execute(runnable);
|
||||||
@ -73,30 +80,32 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void asyncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
||||||
BukkitTask task = this.plugin.getServer().getScheduler().runTaskTimerAsynchronously(this.plugin, runnable, intervalTicks, intervalTicks);
|
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimerAsynchronously(this.plugin, runnable, intervalTicks, intervalTicks));
|
||||||
this.tasks.add(task);
|
this.tasks.add(task);
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
||||||
BukkitTask task = this.plugin.getServer().getScheduler().runTaskTimer(this.plugin, runnable, intervalTicks, intervalTicks);
|
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimer(this.plugin, runnable, intervalTicks, intervalTicks));
|
||||||
this.tasks.add(task);
|
this.tasks.add(task);
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void asyncLater(Runnable runnable, long delayTicks) {
|
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
||||||
this.plugin.getServer().getScheduler().runTaskLaterAsynchronously(this.plugin, runnable, delayTicks);
|
return new BukkitSchedulerTask(scheduler().runTaskLaterAsynchronously(this.plugin, runnable, delayTicks));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syncLater(Runnable runnable, long delayTicks) {
|
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
||||||
this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, runnable, delayTicks);
|
return new BukkitSchedulerTask(scheduler().runTaskLater(this.plugin, runnable, delayTicks));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
this.tasks.forEach(BukkitTask::cancel);
|
SafeIterator.iterate(this.tasks, SchedulerTask::cancel);
|
||||||
|
|
||||||
// wait for executor
|
// wait for executor
|
||||||
this.asyncFallback.shutdown();
|
this.asyncFallback.shutdown();
|
||||||
@ -161,4 +170,17 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,9 @@ import me.lucko.luckperms.common.locale.NoopLocaleManager;
|
|||||||
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
||||||
import me.lucko.luckperms.common.logging.Logger;
|
import me.lucko.luckperms.common.logging.Logger;
|
||||||
import me.lucko.luckperms.common.logging.SenderLogger;
|
import me.lucko.luckperms.common.logging.SenderLogger;
|
||||||
import me.lucko.luckperms.common.managers.GenericGroupManager;
|
import me.lucko.luckperms.common.managers.group.StandardGroupManager;
|
||||||
import me.lucko.luckperms.common.managers.GenericTrackManager;
|
import me.lucko.luckperms.common.managers.track.StandardTrackManager;
|
||||||
import me.lucko.luckperms.common.managers.GenericUserManager;
|
import me.lucko.luckperms.common.managers.user.StandardUserManager;
|
||||||
import me.lucko.luckperms.common.managers.GroupManager;
|
|
||||||
import me.lucko.luckperms.common.managers.TrackManager;
|
|
||||||
import me.lucko.luckperms.common.managers.UserManager;
|
|
||||||
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
@ -80,7 +77,6 @@ import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
|
|||||||
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
|
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
|
||||||
import me.lucko.luckperms.common.tasks.UpdateTask;
|
import me.lucko.luckperms.common.tasks.UpdateTask;
|
||||||
import me.lucko.luckperms.common.treeview.PermissionVault;
|
import me.lucko.luckperms.common.treeview.PermissionVault;
|
||||||
import me.lucko.luckperms.common.utils.LoginHelper;
|
|
||||||
import me.lucko.luckperms.common.utils.UuidCache;
|
import me.lucko.luckperms.common.utils.UuidCache;
|
||||||
import me.lucko.luckperms.common.verbose.VerboseHandler;
|
import me.lucko.luckperms.common.verbose.VerboseHandler;
|
||||||
|
|
||||||
@ -115,9 +111,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
private BukkitCommandExecutor commandManager;
|
private BukkitCommandExecutor commandManager;
|
||||||
private VaultHookManager vaultHookManager = null;
|
private VaultHookManager vaultHookManager = null;
|
||||||
private LuckPermsConfiguration configuration;
|
private LuckPermsConfiguration configuration;
|
||||||
private UserManager userManager;
|
private StandardUserManager userManager;
|
||||||
private GroupManager groupManager;
|
private StandardGroupManager groupManager;
|
||||||
private TrackManager trackManager;
|
private StandardTrackManager trackManager;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
private FileWatcher fileWatcher = null;
|
private FileWatcher fileWatcher = null;
|
||||||
private ExtendedMessagingService messagingService = null;
|
private ExtendedMessagingService messagingService = null;
|
||||||
@ -205,7 +201,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
this.scheduler.syncLater(new BukkitProcessorsSetupTask(this), 1L);
|
this.scheduler.syncLater(new BukkitProcessorsSetupTask(this), 1L);
|
||||||
|
|
||||||
// register events
|
// register events
|
||||||
getServer().getPluginManager().registerEvents(new BukkitConnectionListener(this), this);
|
BukkitConnectionListener connectionListener = new BukkitConnectionListener(this);
|
||||||
|
getServer().getPluginManager().registerEvents(connectionListener, this);
|
||||||
getServer().getPluginManager().registerEvents(new BukkitPlatformListener(this), this);
|
getServer().getPluginManager().registerEvents(new BukkitPlatformListener(this), this);
|
||||||
|
|
||||||
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
|
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
|
||||||
@ -237,9 +234,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
// load internal managers
|
// load internal managers
|
||||||
getLog().info("Loading internal permission managers...");
|
getLog().info("Loading internal permission managers...");
|
||||||
this.uuidCache = new UuidCache(this);
|
this.uuidCache = new UuidCache(this);
|
||||||
this.userManager = new GenericUserManager(this);
|
this.userManager = new StandardUserManager(this);
|
||||||
this.groupManager = new GenericGroupManager(this);
|
this.groupManager = new StandardGroupManager(this);
|
||||||
this.trackManager = new GenericTrackManager(this);
|
this.trackManager = new StandardTrackManager(this);
|
||||||
this.calculatorFactory = new BukkitCalculatorFactory(this);
|
this.calculatorFactory = new BukkitCalculatorFactory(this);
|
||||||
this.cachedStateManager = new CachedStateManager();
|
this.cachedStateManager = new CachedStateManager();
|
||||||
|
|
||||||
@ -312,7 +309,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
for (Player player : getServer().getOnlinePlayers()) {
|
for (Player player : getServer().getOnlinePlayers()) {
|
||||||
this.scheduler.doAsync(() -> {
|
this.scheduler.doAsync(() -> {
|
||||||
try {
|
try {
|
||||||
LoginHelper.loadUser(this, player.getUniqueId(), player.getName(), false);
|
connectionListener.loadUser(player.getUniqueId(), player.getName());
|
||||||
User user = getUserManager().getIfLoaded(getUuidCache().getUUID(player.getUniqueId()));
|
User user = getUserManager().getIfLoaded(getUuidCache().getUUID(player.getUniqueId()));
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
this.scheduler.doSync(() -> {
|
this.scheduler.doSync(() -> {
|
||||||
@ -584,17 +581,17 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserManager getUserManager() {
|
public StandardUserManager getUserManager() {
|
||||||
return this.userManager;
|
return this.userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GroupManager getGroupManager() {
|
public StandardGroupManager getGroupManager() {
|
||||||
return this.groupManager;
|
return this.groupManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackManager getTrackManager() {
|
public StandardTrackManager getTrackManager() {
|
||||||
return this.trackManager;
|
return this.trackManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import me.lucko.luckperms.bukkit.model.PermissibleInjector;
|
|||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
import me.lucko.luckperms.common.locale.Message;
|
import me.lucko.luckperms.common.locale.Message;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.utils.LoginHelper;
|
import me.lucko.luckperms.common.utils.AbstractLoginListener;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -47,13 +47,14 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class BukkitConnectionListener implements Listener {
|
public class BukkitConnectionListener extends AbstractLoginListener implements Listener {
|
||||||
private final LPBukkitPlugin plugin;
|
private final LPBukkitPlugin plugin;
|
||||||
|
|
||||||
private final Set<UUID> deniedAsyncLogin = Collections.synchronizedSet(new HashSet<>());
|
private final Set<UUID> deniedAsyncLogin = Collections.synchronizedSet(new HashSet<>());
|
||||||
private final Set<UUID> deniedLogin = Collections.synchronizedSet(new HashSet<>());
|
private final Set<UUID> deniedLogin = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
public BukkitConnectionListener(LPBukkitPlugin plugin) {
|
public BukkitConnectionListener(LPBukkitPlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ public class BukkitConnectionListener implements Listener {
|
|||||||
- creating a user instance in the UserManager for this connection.
|
- creating a user instance in the UserManager for this connection.
|
||||||
- setting up cached data. */
|
- setting up cached data. */
|
||||||
try {
|
try {
|
||||||
User user = LoginHelper.loadUser(this.plugin, e.getUniqueId(), e.getName(), false);
|
User user = loadUser(e.getUniqueId(), e.getName());
|
||||||
this.plugin.getEventFactory().handleUserLoginProcess(e.getUniqueId(), e.getName(), user);
|
this.plugin.getEventFactory().handleUserLoginProcess(e.getUniqueId(), e.getName(), user);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.plugin.getLog().severe("Exception occured whilst loading data for " + e.getUniqueId() + " - " + e.getName());
|
this.plugin.getLog().severe("Exception occured whilst loading data for " + e.getUniqueId() + " - " + e.getName());
|
||||||
@ -115,12 +116,6 @@ public class BukkitConnectionListener implements Listener {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login event was cancelled by another plugin, but it wasn't cancelled when we handled it at LOW
|
|
||||||
if (e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
|
||||||
// Schedule cleanup of this user.
|
|
||||||
this.plugin.getUserManager().scheduleUnload(e.getUniqueId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
@ -180,8 +175,6 @@ public class BukkitConnectionListener implements Listener {
|
|||||||
|
|
||||||
// Login event was cancelled by another plugin since we first loaded their data
|
// Login event was cancelled by another plugin since we first loaded their data
|
||||||
if (denied || e.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
if (denied || e.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||||
// Schedule cleanup of this user.
|
|
||||||
this.plugin.getUserManager().scheduleUnload(e.getPlayer().getUniqueId());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +199,9 @@ public class BukkitConnectionListener implements Listener {
|
|||||||
player.setOp(false);
|
player.setOp(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request that the users data is unloaded.
|
// Register with the housekeeper, so the User's instance will stick
|
||||||
this.plugin.getUserManager().scheduleUnload(player.getUniqueId());
|
// around for a bit after they disconnect
|
||||||
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,11 @@
|
|||||||
package me.lucko.luckperms.bungee;
|
package me.lucko.luckperms.bungee;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||||
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.utils.SafeIterator;
|
||||||
|
|
||||||
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.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -35,16 +38,32 @@ 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 LPBungeePlugin plugin;
|
private final LPBungeePlugin plugin;
|
||||||
|
|
||||||
private final Executor asyncExecutor;
|
private final Executor asyncExecutor;
|
||||||
private final Set<ScheduledTask> tasks = ConcurrentHashMap.newKeySet();
|
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public BungeeSchedulerAdapter(LPBungeePlugin plugin) {
|
public BungeeSchedulerAdapter(LPBungeePlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.asyncExecutor = r -> plugin.getProxy().getScheduler().runAsync(plugin, r);
|
this.asyncExecutor = r -> plugin.getProxy().getScheduler().runAsync(plugin, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TaskScheduler scheduler() {
|
||||||
|
return this.plugin.getProxy().getScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Executor async() {
|
public Executor async() {
|
||||||
return this.asyncExecutor;
|
return this.asyncExecutor;
|
||||||
@ -66,30 +85,44 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void asyncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
||||||
long millis = intervalTicks * 50L; // convert from ticks to milliseconds
|
long millis = ticksToMillis(intervalTicks);
|
||||||
ScheduledTask task = this.plugin.getProxy().getScheduler().schedule(this.plugin, runnable, millis, millis, TimeUnit.MILLISECONDS);
|
SchedulerTask task = new BungeeSchedulerTask(scheduler().schedule(this.plugin, runnable, millis, millis, TimeUnit.MILLISECONDS));
|
||||||
this.tasks.add(task);
|
this.tasks.add(task);
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
||||||
asyncRepeating(runnable, intervalTicks);
|
return asyncRepeating(runnable, intervalTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void asyncLater(Runnable runnable, long delayTicks) {
|
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
||||||
long millis = delayTicks * 50L; // convert from ticks to milliseconds
|
return new BungeeSchedulerTask(scheduler().schedule(this.plugin, runnable, ticksToMillis(delayTicks), TimeUnit.MILLISECONDS));
|
||||||
this.plugin.getProxy().getScheduler().schedule(this.plugin, runnable, millis, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syncLater(Runnable runnable, long delayTicks) {
|
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
||||||
asyncLater(runnable, delayTicks);
|
return asyncLater(runnable, delayTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
this.tasks.forEach(ScheduledTask::cancel);
|
SafeIterator.iterate(this.tasks, SchedulerTask::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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -57,12 +57,9 @@ import me.lucko.luckperms.common.locale.NoopLocaleManager;
|
|||||||
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
||||||
import me.lucko.luckperms.common.logging.Logger;
|
import me.lucko.luckperms.common.logging.Logger;
|
||||||
import me.lucko.luckperms.common.logging.SenderLogger;
|
import me.lucko.luckperms.common.logging.SenderLogger;
|
||||||
import me.lucko.luckperms.common.managers.GenericGroupManager;
|
import me.lucko.luckperms.common.managers.group.StandardGroupManager;
|
||||||
import me.lucko.luckperms.common.managers.GenericTrackManager;
|
import me.lucko.luckperms.common.managers.track.StandardTrackManager;
|
||||||
import me.lucko.luckperms.common.managers.GenericUserManager;
|
import me.lucko.luckperms.common.managers.user.StandardUserManager;
|
||||||
import me.lucko.luckperms.common.managers.GroupManager;
|
|
||||||
import me.lucko.luckperms.common.managers.TrackManager;
|
|
||||||
import me.lucko.luckperms.common.managers.UserManager;
|
|
||||||
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
@ -101,9 +98,9 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
private SchedulerAdapter scheduler;
|
private SchedulerAdapter scheduler;
|
||||||
private CommandManager commandManager;
|
private CommandManager commandManager;
|
||||||
private LuckPermsConfiguration configuration;
|
private LuckPermsConfiguration configuration;
|
||||||
private UserManager userManager;
|
private StandardUserManager userManager;
|
||||||
private GroupManager groupManager;
|
private StandardGroupManager groupManager;
|
||||||
private TrackManager trackManager;
|
private StandardTrackManager trackManager;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
private FileWatcher fileWatcher = null;
|
private FileWatcher fileWatcher = null;
|
||||||
private ExtendedMessagingService messagingService = null;
|
private ExtendedMessagingService messagingService = null;
|
||||||
@ -183,9 +180,9 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
// load internal managers
|
// load internal managers
|
||||||
getLog().info("Loading internal permission managers...");
|
getLog().info("Loading internal permission managers...");
|
||||||
this.uuidCache = new UuidCache(this);
|
this.uuidCache = new UuidCache(this);
|
||||||
this.userManager = new GenericUserManager(this);
|
this.userManager = new StandardUserManager(this);
|
||||||
this.groupManager = new GenericGroupManager(this);
|
this.groupManager = new StandardGroupManager(this);
|
||||||
this.trackManager = new GenericTrackManager(this);
|
this.trackManager = new StandardTrackManager(this);
|
||||||
this.calculatorFactory = new BungeeCalculatorFactory(this);
|
this.calculatorFactory = new BungeeCalculatorFactory(this);
|
||||||
this.cachedStateManager = new CachedStateManager();
|
this.cachedStateManager = new CachedStateManager();
|
||||||
|
|
||||||
@ -394,17 +391,17 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserManager getUserManager() {
|
public StandardUserManager getUserManager() {
|
||||||
return this.userManager;
|
return this.userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GroupManager getGroupManager() {
|
public StandardGroupManager getGroupManager() {
|
||||||
return this.groupManager;
|
return this.groupManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackManager getTrackManager() {
|
public StandardTrackManager getTrackManager() {
|
||||||
return this.trackManager;
|
return this.trackManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ import me.lucko.luckperms.bungee.LPBungeePlugin;
|
|||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
import me.lucko.luckperms.common.locale.Message;
|
import me.lucko.luckperms.common.locale.Message;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.utils.LoginHelper;
|
import me.lucko.luckperms.common.utils.AbstractLoginListener;
|
||||||
|
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
@ -43,10 +43,11 @@ import net.md_5.bungee.event.EventPriority;
|
|||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class BungeeConnectionListener implements Listener {
|
public class BungeeConnectionListener extends AbstractLoginListener implements Listener {
|
||||||
private final LPBungeePlugin plugin;
|
private final LPBungeePlugin plugin;
|
||||||
|
|
||||||
public BungeeConnectionListener(LPBungeePlugin plugin) {
|
public BungeeConnectionListener(LPBungeePlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ public class BungeeConnectionListener implements Listener {
|
|||||||
- creating a user instance in the UserManager for this connection.
|
- creating a user instance in the UserManager for this connection.
|
||||||
- setting up cached data. */
|
- setting up cached data. */
|
||||||
try {
|
try {
|
||||||
User user = LoginHelper.loadUser(this.plugin, c.getUniqueId(), c.getName(), true);
|
User user = loadUser(c.getUniqueId(), c.getName());
|
||||||
this.plugin.getEventFactory().handleUserLoginProcess(c.getUniqueId(), c.getName(), user);
|
this.plugin.getEventFactory().handleUserLoginProcess(c.getUniqueId(), c.getName(), user);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.plugin.getLog().severe("Exception occured whilst loading data for " + c.getUniqueId() + " - " + c.getName());
|
this.plugin.getLog().severe("Exception occured whilst loading data for " + c.getUniqueId() + " - " + c.getName());
|
||||||
@ -98,10 +99,6 @@ public class BungeeConnectionListener implements Listener {
|
|||||||
|
|
||||||
// finally, complete our intent to modify state, so the proxy can continue handling the connection.
|
// finally, complete our intent to modify state, so the proxy can continue handling the connection.
|
||||||
e.completeIntent(this.plugin);
|
e.completeIntent(this.plugin);
|
||||||
|
|
||||||
// schedule a cleanup of the users data in a few seconds.
|
|
||||||
// this should cover the eventuality that the login fails.
|
|
||||||
this.plugin.getUserManager().scheduleUnload(c.getUniqueId());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,8 +132,9 @@ public class BungeeConnectionListener implements Listener {
|
|||||||
// Wait until the last priority to unload, so plugins can still perform permission checks on this event
|
// Wait until the last priority to unload, so plugins can still perform permission checks on this event
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onPlayerQuit(PlayerDisconnectEvent e) {
|
public void onPlayerQuit(PlayerDisconnectEvent e) {
|
||||||
// Request that the users data is unloaded.
|
// Register with the housekeeper, so the User's instance will stick
|
||||||
this.plugin.getUserManager().scheduleUnload(e.getPlayer().getUniqueId());
|
// around for a bit after they disconnect
|
||||||
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(e.getPlayer().getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public class LuckPermsApiProvider implements LuckPermsApi {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
|
||||||
this.platformInfo = new ApiPlatformInfo(plugin);
|
this.platformInfo = new ApiPlatformInfo(plugin);
|
||||||
this.userManager = new ApiUserManager(plugin, plugin.getUserManager());
|
this.userManager = new ApiUserManager(plugin.getUserManager());
|
||||||
this.groupManager = new ApiGroupManager(plugin.getGroupManager());
|
this.groupManager = new ApiGroupManager(plugin.getGroupManager());
|
||||||
this.trackManager = new ApiTrackManager(plugin.getTrackManager());
|
this.trackManager = new ApiTrackManager(plugin.getTrackManager());
|
||||||
this.actionLogger = new ApiActionLogger(plugin);
|
this.actionLogger = new ApiActionLogger(plugin);
|
||||||
|
@ -35,9 +35,9 @@ import java.util.stream.Collectors;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class ApiGroupManager implements GroupManager {
|
public class ApiGroupManager implements GroupManager {
|
||||||
private final me.lucko.luckperms.common.managers.GroupManager handle;
|
private final me.lucko.luckperms.common.managers.group.GroupManager<?> handle;
|
||||||
|
|
||||||
public ApiGroupManager(me.lucko.luckperms.common.managers.GroupManager handle) {
|
public ApiGroupManager(me.lucko.luckperms.common.managers.group.GroupManager<?> handle) {
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ import java.util.stream.Collectors;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class ApiTrackManager implements TrackManager {
|
public class ApiTrackManager implements TrackManager {
|
||||||
private final me.lucko.luckperms.common.managers.TrackManager handle;
|
private final me.lucko.luckperms.common.managers.track.TrackManager<?> handle;
|
||||||
|
|
||||||
public ApiTrackManager(me.lucko.luckperms.common.managers.TrackManager handle) {
|
public ApiTrackManager(me.lucko.luckperms.common.managers.track.TrackManager<?> handle) {
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ package me.lucko.luckperms.common.api.delegates.manager;
|
|||||||
import me.lucko.luckperms.api.User;
|
import me.lucko.luckperms.api.User;
|
||||||
import me.lucko.luckperms.api.manager.UserManager;
|
import me.lucko.luckperms.api.manager.UserManager;
|
||||||
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
|
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
|
||||||
import me.lucko.luckperms.common.references.UserIdentifier;
|
import me.lucko.luckperms.common.references.UserIdentifier;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -39,11 +38,9 @@ import java.util.stream.Collectors;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class ApiUserManager implements UserManager {
|
public class ApiUserManager implements UserManager {
|
||||||
private final LuckPermsPlugin plugin;
|
private final me.lucko.luckperms.common.managers.user.UserManager<?> handle;
|
||||||
private final me.lucko.luckperms.common.managers.UserManager handle;
|
|
||||||
|
|
||||||
public ApiUserManager(LuckPermsPlugin plugin, me.lucko.luckperms.common.managers.UserManager handle) {
|
public ApiUserManager(me.lucko.luckperms.common.managers.user.UserManager<?> handle) {
|
||||||
this.plugin = plugin;
|
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +73,6 @@ public class ApiUserManager implements UserManager {
|
|||||||
@Override
|
@Override
|
||||||
public void cleanupUser(@Nonnull User user) {
|
public void cleanupUser(@Nonnull User user) {
|
||||||
Objects.requireNonNull(user, "user");
|
Objects.requireNonNull(user, "user");
|
||||||
this.handle.scheduleUnload(this.plugin.getUuidCache().getExternalUUID(ApiUser.cast(user).getUuid()));
|
this.handle.getHouseKeeper().clearApiUsage(ApiUser.cast(user).getUuid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,11 @@ public class ApiStorage implements Storage {
|
|||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> loadUser(@Nonnull UUID uuid, String username) {
|
public CompletableFuture<Boolean> loadUser(@Nonnull UUID uuid, String username) {
|
||||||
Objects.requireNonNull(uuid, "uuid");
|
Objects.requireNonNull(uuid, "uuid");
|
||||||
|
|
||||||
|
if (this.plugin.getUserManager().getIfLoaded(uuid) == null) {
|
||||||
|
this.plugin.getUserManager().getHouseKeeper().registerApiUsage(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
return this.handle.noBuffer().loadUser(uuid, username == null ? null : checkUsername(username)).thenApply(Objects::nonNull);
|
return this.handle.noBuffer().loadUser(uuid, username == null ? null : checkUsername(username)).thenApply(Objects::nonNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +40,10 @@ import javax.annotation.Nonnull;
|
|||||||
* An abstract manager class
|
* An abstract manager class
|
||||||
*
|
*
|
||||||
* @param <I> the class used to identify each object held in this manager
|
* @param <I> the class used to identify each object held in this manager
|
||||||
* @param <T> the class this manager is "managing"
|
* @param <C> the super class being managed
|
||||||
|
* @param <T> the implementation class this manager is "managing"
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractManager<I, T extends Identifiable<I>> implements Manager<I, T> {
|
public abstract class AbstractManager<I, C extends Identifiable<I>, T extends C> implements Manager<I, C, T> {
|
||||||
|
|
||||||
private final LoadingCache<I, T> objects = Caffeine.newBuilder()
|
private final LoadingCache<I, T> objects = Caffeine.newBuilder()
|
||||||
.build(new CacheLoader<I, T>() {
|
.build(new CacheLoader<I, T>() {
|
||||||
@ -85,9 +86,9 @@ public abstract class AbstractManager<I, T extends Identifiable<I>> implements M
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unload(T t) {
|
public void unload(C object) {
|
||||||
if (t != null) {
|
if (object != null) {
|
||||||
unload(t.getId());
|
unload(object.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,16 +34,17 @@ import java.util.function.Function;
|
|||||||
* A class which manages instances of a class
|
* A class which manages instances of a class
|
||||||
*
|
*
|
||||||
* @param <I> the class used to identify each object held in this manager
|
* @param <I> the class used to identify each object held in this manager
|
||||||
* @param <T> the class this manager is "managing"
|
* @param <C> the super class being managed
|
||||||
|
* @param <T> the implementation class this manager is "managing"
|
||||||
*/
|
*/
|
||||||
public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
|
public interface Manager<I, C extends Identifiable<I>, T extends C> extends Function<I, T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a map containing all cached instances held by this manager.
|
* Gets a map containing all cached instances held by this manager.
|
||||||
*
|
*
|
||||||
* @return all instances held in this manager
|
* @return all instances held in this manager
|
||||||
*/
|
*/
|
||||||
Map<I, ? extends T> getAll();
|
Map<I, T> getAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or creates an object by id
|
* Gets or creates an object by id
|
||||||
@ -81,9 +82,9 @@ public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
|
|||||||
/**
|
/**
|
||||||
* Removes and unloads the object from the manager
|
* Removes and unloads the object from the manager
|
||||||
*
|
*
|
||||||
* @param t The object to unload
|
* @param object The object to unload
|
||||||
*/
|
*/
|
||||||
void unload(T t);
|
void unload(C object);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unloads all objects from the manager
|
* Unloads all objects from the manager
|
||||||
|
@ -23,40 +23,30 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.managers;
|
package me.lucko.luckperms.common.managers.group;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.managers.AbstractManager;
|
||||||
import me.lucko.luckperms.common.model.Group;
|
import me.lucko.luckperms.common.model.Group;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
|
||||||
|
|
||||||
public class GenericGroupManager extends AbstractManager<String, Group> implements GroupManager {
|
public abstract class AbstractGroupManager<T extends Group> extends AbstractManager<String, Group, T> implements GroupManager<T> {
|
||||||
private final LuckPermsPlugin plugin;
|
|
||||||
|
|
||||||
public GenericGroupManager(LuckPermsPlugin plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Group apply(String name) {
|
public T getByDisplayName(String name) {
|
||||||
return new Group(name, this.plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Group getByDisplayName(String name) {
|
|
||||||
// try to get an exact match first
|
// try to get an exact match first
|
||||||
Group g = getIfLoaded(name);
|
T g = getIfLoaded(name);
|
||||||
if (g != null) {
|
if (g != null) {
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
// then try exact display name matches
|
// then try exact display name matches
|
||||||
for (Group group : getAll().values()) {
|
for (T group : getAll().values()) {
|
||||||
if (group.getDisplayName().isPresent() && group.getDisplayName().get().equals(name)) {
|
if (group.getDisplayName().isPresent() && group.getDisplayName().get().equals(name)) {
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// then try case insensitive name matches
|
// then try case insensitive name matches
|
||||||
for (Group group : getAll().values()) {
|
for (T group : getAll().values()) {
|
||||||
if (group.getDisplayName().isPresent() && group.getDisplayName().get().equalsIgnoreCase(name)) {
|
if (group.getDisplayName().isPresent() && group.getDisplayName().get().equalsIgnoreCase(name)) {
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
@ -23,11 +23,12 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.managers;
|
package me.lucko.luckperms.common.managers.group;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.managers.Manager;
|
||||||
import me.lucko.luckperms.common.model.Group;
|
import me.lucko.luckperms.common.model.Group;
|
||||||
|
|
||||||
public interface GroupManager extends Manager<String, Group> {
|
public interface GroupManager<T extends Group> extends Manager<String, Group, T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a group object by display name
|
* Get a group object by display name
|
||||||
@ -35,6 +36,6 @@ public interface GroupManager extends Manager<String, Group> {
|
|||||||
* @param name The name to search by
|
* @param name The name to search by
|
||||||
* @return a {@link Group} object if the group is loaded, returns null if the group is not loaded
|
* @return a {@link Group} object if the group is loaded, returns null if the group is not loaded
|
||||||
*/
|
*/
|
||||||
Group getByDisplayName(String name);
|
T getByDisplayName(String name);
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.managers.group;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.model.Group;
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
|
public class StandardGroupManager extends AbstractGroupManager<Group> {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
|
public StandardGroupManager(LuckPermsPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Group apply(String name) {
|
||||||
|
return new Group(name, this.plugin);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.managers.track;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.managers.AbstractManager;
|
||||||
|
import me.lucko.luckperms.common.model.Track;
|
||||||
|
|
||||||
|
public abstract class AbstractTrackManager<T extends Track> extends AbstractManager<String, Track, T> implements TrackManager<T> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String sanitizeIdentifier(String s) {
|
||||||
|
return s.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
@ -23,15 +23,15 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.managers;
|
package me.lucko.luckperms.common.managers.track;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.model.Track;
|
import me.lucko.luckperms.common.model.Track;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
public class GenericTrackManager extends AbstractManager<String, Track> implements TrackManager {
|
public class StandardTrackManager extends AbstractTrackManager<Track> {
|
||||||
private final LuckPermsPlugin plugin;
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
public GenericTrackManager(LuckPermsPlugin plugin) {
|
public StandardTrackManager(LuckPermsPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,9 +39,4 @@ public class GenericTrackManager extends AbstractManager<String, Track> implemen
|
|||||||
public Track apply(String name) {
|
public Track apply(String name) {
|
||||||
return new Track(name, this.plugin);
|
return new Track(name, this.plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String sanitizeIdentifier(String s) {
|
|
||||||
return s.toLowerCase();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -23,10 +23,11 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.managers;
|
package me.lucko.luckperms.common.managers.track;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.managers.Manager;
|
||||||
import me.lucko.luckperms.common.model.Track;
|
import me.lucko.luckperms.common.model.Track;
|
||||||
|
|
||||||
public interface TrackManager extends Manager<String, Track> {
|
public interface TrackManager<T extends Track> extends Manager<String, Track, T> {
|
||||||
|
|
||||||
}
|
}
|
@ -23,11 +23,12 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.managers;
|
package me.lucko.luckperms.common.managers.user;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Node;
|
import me.lucko.luckperms.api.Node;
|
||||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
|
import me.lucko.luckperms.common.managers.AbstractManager;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.node.NodeFactory;
|
import me.lucko.luckperms.common.node.NodeFactory;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
@ -37,17 +38,20 @@ import java.util.Optional;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class GenericUserManager extends AbstractManager<UserIdentifier, User> implements UserManager {
|
public abstract class AbstractUserManager<T extends User> extends AbstractManager<UserIdentifier, User, T> implements UserManager<T> {
|
||||||
|
|
||||||
private final LuckPermsPlugin plugin;
|
private final LuckPermsPlugin plugin;
|
||||||
|
private final UserHousekeeper housekeeper;
|
||||||
|
|
||||||
public GenericUserManager(LuckPermsPlugin plugin) {
|
public AbstractUserManager(LuckPermsPlugin plugin, UserHousekeeper.TimeoutSettings timeoutSettings) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
this.housekeeper = new UserHousekeeper(plugin, this, timeoutSettings);
|
||||||
|
this.plugin.getScheduler().asyncRepeating(this.housekeeper, 200L); // every 10 seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getOrMake(UserIdentifier id) {
|
public T getOrMake(UserIdentifier id) {
|
||||||
User ret = super.getOrMake(id);
|
T ret = super.getOrMake(id);
|
||||||
if (id.getUsername().isPresent()) {
|
if (id.getUsername().isPresent()) {
|
||||||
ret.setName(id.getUsername().get(), false);
|
ret.setName(id.getUsername().get(), false);
|
||||||
}
|
}
|
||||||
@ -55,15 +59,8 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User apply(UserIdentifier id) {
|
public T getByUsername(String name) {
|
||||||
return !id.getUsername().isPresent() ?
|
for (T user : getAll().values()) {
|
||||||
new User(id.getUuid(), this.plugin) :
|
|
||||||
new User(id.getUuid(), id.getUsername().get(), this.plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getByUsername(String name) {
|
|
||||||
for (User user : getAll().values()) {
|
|
||||||
Optional<String> n = user.getName();
|
Optional<String> n = user.getName();
|
||||||
if (n.isPresent() && n.get().equalsIgnoreCase(name)) {
|
if (n.isPresent() && n.get().equalsIgnoreCase(name)) {
|
||||||
return user;
|
return user;
|
||||||
@ -73,59 +70,16 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getIfLoaded(UUID uuid) {
|
public T getIfLoaded(UUID uuid) {
|
||||||
return getIfLoaded(UserIdentifier.of(uuid, null));
|
return getIfLoaded(UserIdentifier.of(uuid, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean giveDefaultIfNeeded(User user, boolean save) {
|
public boolean giveDefaultIfNeeded(User user, boolean save) {
|
||||||
return giveDefaultIfNeeded(user, save, this.plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean cleanup(User user) {
|
|
||||||
if (!this.plugin.isPlayerOnline(this.plugin.getUuidCache().getExternalUUID(user.getUuid()))) {
|
|
||||||
unload(user);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void scheduleUnload(UUID uuid) {
|
|
||||||
this.plugin.getScheduler().asyncLater(() -> {
|
|
||||||
// check once to see if the user can be unloaded.
|
|
||||||
if (getIfLoaded(this.plugin.getUuidCache().getUUID(uuid)) != null && !this.plugin.isPlayerOnline(uuid)) {
|
|
||||||
|
|
||||||
// check again in 40 ticks, we want to be sure the player won't have re-logged before we unload them.
|
|
||||||
this.plugin.getScheduler().asyncLater(() -> {
|
|
||||||
User user = getIfLoaded(this.plugin.getUuidCache().getUUID(uuid));
|
|
||||||
if (user != null && !this.plugin.isPlayerOnline(uuid)) {
|
|
||||||
user.getCachedData().invalidateCaches();
|
|
||||||
unload(user);
|
|
||||||
this.plugin.getUuidCache().clearCache(uuid);
|
|
||||||
}
|
|
||||||
}, 40L);
|
|
||||||
}
|
|
||||||
}, 40L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Void> updateAllUsers() {
|
|
||||||
return CompletableFuture.runAsync(
|
|
||||||
() -> this.plugin.getOnlinePlayers()
|
|
||||||
.map(u -> this.plugin.getUuidCache().getUUID(u))
|
|
||||||
.forEach(u -> this.plugin.getStorage().loadUser(u, null).join()),
|
|
||||||
this.plugin.getScheduler().async()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean giveDefaultIfNeeded(User user, boolean save, LuckPermsPlugin plugin) {
|
|
||||||
boolean work = false;
|
boolean work = false;
|
||||||
|
|
||||||
// check that they are actually a member of their primary group, otherwise remove it
|
// check that they are actually a member of their primary group, otherwise remove it
|
||||||
if (plugin.getConfiguration().get(ConfigKeys.PRIMARY_GROUP_CALCULATION_METHOD).equals("stored")) {
|
if (this.plugin.getConfiguration().get(ConfigKeys.PRIMARY_GROUP_CALCULATION_METHOD).equals("stored")) {
|
||||||
String pg = user.getPrimaryGroup().getValue();
|
String pg = user.getPrimaryGroup().getValue();
|
||||||
boolean has = false;
|
boolean has = false;
|
||||||
|
|
||||||
@ -174,19 +128,40 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (work && save) {
|
if (work && save) {
|
||||||
plugin.getStorage().saveUser(user);
|
this.plugin.getStorage().saveUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
return work;
|
return work;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserHousekeeper getHouseKeeper() {
|
||||||
|
return this.housekeeper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup(User user) {
|
||||||
|
this.housekeeper.cleanup(user.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> updateAllUsers() {
|
||||||
|
return CompletableFuture.runAsync(
|
||||||
|
() -> this.plugin.getOnlinePlayers()
|
||||||
|
.map(u -> this.plugin.getUuidCache().getUUID(u))
|
||||||
|
.forEach(u -> this.plugin.getStorage().loadUser(u, null).join()),
|
||||||
|
this.plugin.getScheduler().async()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the user's state indicates that they should be persisted to storage.
|
* Check whether the user's state indicates that they should be persisted to storage.
|
||||||
*
|
*
|
||||||
* @param user the user to check
|
* @param user the user to check
|
||||||
* @return true if the user should be saved
|
* @return true if the user should be saved
|
||||||
*/
|
*/
|
||||||
public static boolean shouldSave(User user) {
|
@Override
|
||||||
|
public boolean shouldSave(User user) {
|
||||||
if (user.getEnduringNodes().size() != 1) {
|
if (user.getEnduringNodes().size() != 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.managers.user;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.model.User;
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.common.references.UserIdentifier;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class StandardUserManager extends AbstractUserManager<User> {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
|
public StandardUserManager(LuckPermsPlugin plugin) {
|
||||||
|
super(plugin, UserHousekeeper.timeoutSettings(1, TimeUnit.MINUTES));
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User apply(UserIdentifier id) {
|
||||||
|
return !id.getUsername().isPresent() ?
|
||||||
|
new User(id.getUuid(), this.plugin) :
|
||||||
|
new User(id.getUuid(), id.getUsername().get(), this.plugin);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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.managers.user;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.common.references.UserIdentifier;
|
||||||
|
import me.lucko.luckperms.common.utils.ExpiringSet;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance responsible for unloading users which are no longer needed.
|
||||||
|
*/
|
||||||
|
public class UserHousekeeper implements Runnable {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
private final UserManager<?> userManager;
|
||||||
|
|
||||||
|
// contains the uuids of users who have recently logged in / out
|
||||||
|
private final ExpiringSet<UUID> recentlyUsed;
|
||||||
|
|
||||||
|
// contains the uuids of users who have recently been retrieved from the API
|
||||||
|
private final ExpiringSet<UUID> recentlyUsedApi;
|
||||||
|
|
||||||
|
public UserHousekeeper(LuckPermsPlugin plugin, UserManager<?> userManager, TimeoutSettings timeoutSettings) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.userManager = userManager;
|
||||||
|
this.recentlyUsed = new ExpiringSet<>(timeoutSettings.duration, timeoutSettings.unit);
|
||||||
|
this.recentlyUsedApi = new ExpiringSet<>(5, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
// called when a player attempts a connection or logs out
|
||||||
|
public void registerUsage(UUID uuid) {
|
||||||
|
this.recentlyUsed.add(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerApiUsage(UUID uuid) {
|
||||||
|
this.recentlyUsedApi.add(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearApiUsage(UUID uuid) {
|
||||||
|
this.recentlyUsedApi.remove(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (UserIdentifier entry : this.userManager.getAll().keySet()) {
|
||||||
|
cleanup(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup(UserIdentifier identifier) {
|
||||||
|
UUID uuid = identifier.getUuid();
|
||||||
|
|
||||||
|
// unload users which aren't online and who haven't been online (or tried to login) recently
|
||||||
|
if (this.recentlyUsed.contains(uuid) || this.recentlyUsedApi.contains(uuid) || this.plugin.isPlayerOnline(this.plugin.getUuidCache().getExternalUUID(uuid))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unload them
|
||||||
|
this.userManager.unload(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeoutSettings timeoutSettings(long duration, TimeUnit unit) {
|
||||||
|
return new TimeoutSettings(duration, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class TimeoutSettings {
|
||||||
|
private final long duration;
|
||||||
|
private final TimeUnit unit;
|
||||||
|
|
||||||
|
private TimeoutSettings(long duration, TimeUnit unit) {
|
||||||
|
this.duration = duration;
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,16 +23,16 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.common.managers;
|
package me.lucko.luckperms.common.managers.user;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.managers.Manager;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.references.Identifiable;
|
|
||||||
import me.lucko.luckperms.common.references.UserIdentifier;
|
import me.lucko.luckperms.common.references.UserIdentifier;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public interface UserManager extends Manager<UserIdentifier, User> {
|
public interface UserManager<T extends User> extends Manager<UserIdentifier, User, T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a user object by name
|
* Get a user object by name
|
||||||
@ -40,7 +40,7 @@ public interface UserManager extends Manager<UserIdentifier, User> {
|
|||||||
* @param name The name to search by
|
* @param name The name to search by
|
||||||
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
|
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
|
||||||
*/
|
*/
|
||||||
User getByUsername(String name);
|
T getByUsername(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a user object by uuid
|
* Get a user object by uuid
|
||||||
@ -48,7 +48,7 @@ public interface UserManager extends Manager<UserIdentifier, User> {
|
|||||||
* @param uuid The uuid to search by
|
* @param uuid The uuid to search by
|
||||||
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
|
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
|
||||||
*/
|
*/
|
||||||
User getIfLoaded(UUID uuid);
|
T getIfLoaded(UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives the user the default group if necessary.
|
* Gives the user the default group if necessary.
|
||||||
@ -58,18 +58,26 @@ public interface UserManager extends Manager<UserIdentifier, User> {
|
|||||||
boolean giveDefaultIfNeeded(User user, boolean save);
|
boolean giveDefaultIfNeeded(User user, boolean save);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if the user is online, and if they are not, runs {@link #unload(Identifiable)}
|
* Check whether the user's state indicates that they should be persisted to storage.
|
||||||
*
|
*
|
||||||
* @param user The user to be cleaned up
|
* @param user the user to check
|
||||||
|
* @return true if the user should be saved
|
||||||
*/
|
*/
|
||||||
boolean cleanup(User user);
|
boolean shouldSave(User user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a task to cleanup a user after a certain period of time, if they're not on the server anymore.
|
* Gets the instance responsible for unloading unneeded users.
|
||||||
*
|
*
|
||||||
* @param uuid external uuid of the player
|
* @return the housekeeper
|
||||||
*/
|
*/
|
||||||
void scheduleUnload(UUID uuid);
|
UserHousekeeper getHouseKeeper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads the user if a corresponding player is not online
|
||||||
|
*
|
||||||
|
* @param user the user
|
||||||
|
*/
|
||||||
|
void cleanup(User user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the data of all online users
|
* Reloads the data of all online users
|
@ -42,9 +42,9 @@ import me.lucko.luckperms.common.dependencies.DependencyManager;
|
|||||||
import me.lucko.luckperms.common.event.EventFactory;
|
import me.lucko.luckperms.common.event.EventFactory;
|
||||||
import me.lucko.luckperms.common.locale.LocaleManager;
|
import me.lucko.luckperms.common.locale.LocaleManager;
|
||||||
import me.lucko.luckperms.common.logging.Logger;
|
import me.lucko.luckperms.common.logging.Logger;
|
||||||
import me.lucko.luckperms.common.managers.GroupManager;
|
import me.lucko.luckperms.common.managers.group.GroupManager;
|
||||||
import me.lucko.luckperms.common.managers.TrackManager;
|
import me.lucko.luckperms.common.managers.track.TrackManager;
|
||||||
import me.lucko.luckperms.common.managers.UserManager;
|
import me.lucko.luckperms.common.managers.user.UserManager;
|
||||||
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.storage.Storage;
|
import me.lucko.luckperms.common.storage.Storage;
|
||||||
@ -75,21 +75,21 @@ public interface LuckPermsPlugin {
|
|||||||
*
|
*
|
||||||
* @return the user manager
|
* @return the user manager
|
||||||
*/
|
*/
|
||||||
UserManager getUserManager();
|
UserManager<?> getUserManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the group manager instance for the platform
|
* Gets the group manager instance for the platform
|
||||||
*
|
*
|
||||||
* @return the group manager
|
* @return the group manager
|
||||||
*/
|
*/
|
||||||
GroupManager getGroupManager();
|
GroupManager<?> getGroupManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the track manager instance for the platform
|
* Gets the track manager instance for the platform
|
||||||
*
|
*
|
||||||
* @return the track manager
|
* @return the track manager
|
||||||
*/
|
*/
|
||||||
TrackManager getTrackManager();
|
TrackManager<?> getTrackManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the plugin's configuration
|
* Gets the plugin's configuration
|
||||||
|
@ -65,28 +65,28 @@ public interface SchedulerAdapter {
|
|||||||
* @param runnable the runnable
|
* @param runnable the runnable
|
||||||
* @param intervalTicks the interval in ticks.
|
* @param intervalTicks the interval in ticks.
|
||||||
*/
|
*/
|
||||||
void asyncRepeating(Runnable runnable, long intervalTicks);
|
SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a runnable repeatedly until the plugin disables. Will wait for the interval before the first iteration of the task is ran.
|
* Runs a runnable repeatedly until the plugin disables. Will wait for the interval before the first iteration of the task is ran.
|
||||||
* @param runnable the runnable
|
* @param runnable the runnable
|
||||||
* @param intervalTicks the interval in ticks.
|
* @param intervalTicks the interval in ticks.
|
||||||
*/
|
*/
|
||||||
void syncRepeating(Runnable runnable, long intervalTicks);
|
SchedulerTask syncRepeating(Runnable runnable, long intervalTicks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a runnable with a delay
|
* Runs a runnable with a delay
|
||||||
* @param runnable the runnable
|
* @param runnable the runnable
|
||||||
* @param delayTicks the delay in ticks
|
* @param delayTicks the delay in ticks
|
||||||
*/
|
*/
|
||||||
void asyncLater(Runnable runnable, long delayTicks);
|
SchedulerTask asyncLater(Runnable runnable, long delayTicks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a runnable with a delay
|
* Runs a runnable with a delay
|
||||||
* @param runnable the runnable
|
* @param runnable the runnable
|
||||||
* @param delayTicks the delay in ticks
|
* @param delayTicks the delay in ticks
|
||||||
*/
|
*/
|
||||||
void syncLater(Runnable runnable, long delayTicks);
|
SchedulerTask syncLater(Runnable runnable, long delayTicks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuts down this executor instance
|
* Shuts down this executor instance
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a scheduled task
|
||||||
|
*/
|
||||||
|
public interface SchedulerTask {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the task.
|
||||||
|
*/
|
||||||
|
void cancel();
|
||||||
|
|
||||||
|
}
|
@ -37,9 +37,8 @@ import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
|||||||
import me.lucko.luckperms.common.commands.CommandManager;
|
import me.lucko.luckperms.common.commands.CommandManager;
|
||||||
import me.lucko.luckperms.common.commands.utils.CommandUtils;
|
import me.lucko.luckperms.common.commands.utils.CommandUtils;
|
||||||
import me.lucko.luckperms.common.contexts.ContextSetConfigurateSerializer;
|
import me.lucko.luckperms.common.contexts.ContextSetConfigurateSerializer;
|
||||||
import me.lucko.luckperms.common.managers.GenericUserManager;
|
import me.lucko.luckperms.common.managers.group.GroupManager;
|
||||||
import me.lucko.luckperms.common.managers.GroupManager;
|
import me.lucko.luckperms.common.managers.track.TrackManager;
|
||||||
import me.lucko.luckperms.common.managers.TrackManager;
|
|
||||||
import me.lucko.luckperms.common.model.Group;
|
import me.lucko.luckperms.common.model.Group;
|
||||||
import me.lucko.luckperms.common.model.Track;
|
import me.lucko.luckperms.common.model.Track;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
@ -400,7 +399,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
|||||||
saveUser(user);
|
saveUser(user);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (GenericUserManager.shouldSave(user)) {
|
if (this.plugin.getUserManager().shouldSave(user)) {
|
||||||
user.clearNodes();
|
user.clearNodes();
|
||||||
user.getPrimaryGroup().setStoredValue(null);
|
user.getPrimaryGroup().setStoredValue(null);
|
||||||
this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||||
@ -419,7 +418,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
|||||||
public void saveUser(User user) throws Exception {
|
public void saveUser(User user) throws Exception {
|
||||||
user.getIoLock().lock();
|
user.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
if (!GenericUserManager.shouldSave(user)) {
|
if (!this.plugin.getUserManager().shouldSave(user)) {
|
||||||
saveFile(StorageLocation.USER, user.getUuid().toString(), null);
|
saveFile(StorageLocation.USER, user.getUuid().toString(), null);
|
||||||
} else {
|
} else {
|
||||||
ConfigurationNode data = SimpleConfigurationNode.root();
|
ConfigurationNode data = SimpleConfigurationNode.root();
|
||||||
@ -562,7 +561,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
|||||||
throw new RuntimeException("Exception occurred whilst loading a group");
|
throw new RuntimeException("Exception occurred whilst loading a group");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupManager gm = this.plugin.getGroupManager();
|
GroupManager<?> gm = this.plugin.getGroupManager();
|
||||||
gm.getAll().values().stream()
|
gm.getAll().values().stream()
|
||||||
.filter(g -> !groups.contains(g.getName()))
|
.filter(g -> !groups.contains(g.getName()))
|
||||||
.forEach(gm::unload);
|
.forEach(gm::unload);
|
||||||
@ -718,7 +717,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
|||||||
throw new RuntimeException("Exception occurred whilst loading a track");
|
throw new RuntimeException("Exception occurred whilst loading a track");
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackManager tm = this.plugin.getTrackManager();
|
TrackManager<?> tm = this.plugin.getTrackManager();
|
||||||
tm.getAll().values().stream()
|
tm.getAll().values().stream()
|
||||||
.filter(t -> !tracks.contains(t.getName()))
|
.filter(t -> !tracks.contains(t.getName()))
|
||||||
.forEach(tm::unload);
|
.forEach(tm::unload);
|
||||||
|
@ -44,9 +44,8 @@ import me.lucko.luckperms.api.context.MutableContextSet;
|
|||||||
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
|
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
|
||||||
import me.lucko.luckperms.common.actionlog.Log;
|
import me.lucko.luckperms.common.actionlog.Log;
|
||||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
||||||
import me.lucko.luckperms.common.managers.GenericUserManager;
|
import me.lucko.luckperms.common.managers.group.GroupManager;
|
||||||
import me.lucko.luckperms.common.managers.GroupManager;
|
import me.lucko.luckperms.common.managers.track.TrackManager;
|
||||||
import me.lucko.luckperms.common.managers.TrackManager;
|
|
||||||
import me.lucko.luckperms.common.model.Group;
|
import me.lucko.luckperms.common.model.Group;
|
||||||
import me.lucko.luckperms.common.model.Track;
|
import me.lucko.luckperms.common.model.Track;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
@ -268,7 +267,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user));
|
c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (GenericUserManager.shouldSave(user)) {
|
if (this.plugin.getUserManager().shouldSave(user)) {
|
||||||
user.clearNodes();
|
user.clearNodes();
|
||||||
user.getPrimaryGroup().setStoredValue(null);
|
user.getPrimaryGroup().setStoredValue(null);
|
||||||
this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||||
@ -287,7 +286,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
user.getIoLock().lock();
|
user.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = this.database.getCollection(this.prefix + "users");
|
MongoCollection<Document> c = this.database.getCollection(this.prefix + "users");
|
||||||
if (!GenericUserManager.shouldSave(user)) {
|
if (!this.plugin.getUserManager().shouldSave(user)) {
|
||||||
c.deleteOne(new Document("_id", user.getUuid()));
|
c.deleteOne(new Document("_id", user.getUuid()));
|
||||||
} else {
|
} else {
|
||||||
c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user), new UpdateOptions().upsert(true));
|
c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user), new UpdateOptions().upsert(true));
|
||||||
@ -409,7 +408,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
throw new RuntimeException("Exception occurred whilst loading a group");
|
throw new RuntimeException("Exception occurred whilst loading a group");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupManager gm = this.plugin.getGroupManager();
|
GroupManager<?> gm = this.plugin.getGroupManager();
|
||||||
gm.getAll().values().stream()
|
gm.getAll().values().stream()
|
||||||
.filter(g -> !groups.contains(g.getName()))
|
.filter(g -> !groups.contains(g.getName()))
|
||||||
.forEach(gm::unload);
|
.forEach(gm::unload);
|
||||||
@ -535,7 +534,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
throw new RuntimeException("Exception occurred whilst loading a track");
|
throw new RuntimeException("Exception occurred whilst loading a track");
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackManager tm = this.plugin.getTrackManager();
|
TrackManager<?> tm = this.plugin.getTrackManager();
|
||||||
tm.getAll().values().stream()
|
tm.getAll().values().stream()
|
||||||
.filter(t -> !tracks.contains(t.getName()))
|
.filter(t -> !tracks.contains(t.getName()))
|
||||||
.forEach(tm::unload);
|
.forEach(tm::unload);
|
||||||
|
@ -37,9 +37,8 @@ import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
|
|||||||
import me.lucko.luckperms.common.actionlog.Log;
|
import me.lucko.luckperms.common.actionlog.Log;
|
||||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
||||||
import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
|
import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
|
||||||
import me.lucko.luckperms.common.managers.GenericUserManager;
|
import me.lucko.luckperms.common.managers.group.GroupManager;
|
||||||
import me.lucko.luckperms.common.managers.GroupManager;
|
import me.lucko.luckperms.common.managers.track.TrackManager;
|
||||||
import me.lucko.luckperms.common.managers.TrackManager;
|
|
||||||
import me.lucko.luckperms.common.model.Group;
|
import me.lucko.luckperms.common.model.Group;
|
||||||
import me.lucko.luckperms.common.model.Track;
|
import me.lucko.luckperms.common.model.Track;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
@ -364,7 +363,7 @@ public class SqlDao extends AbstractDao {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// User has no data in storage.
|
// User has no data in storage.
|
||||||
if (GenericUserManager.shouldSave(user)) {
|
if (this.plugin.getUserManager().shouldSave(user)) {
|
||||||
user.clearNodes();
|
user.clearNodes();
|
||||||
user.getPrimaryGroup().setStoredValue(null);
|
user.getPrimaryGroup().setStoredValue(null);
|
||||||
this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||||
@ -382,7 +381,7 @@ public class SqlDao extends AbstractDao {
|
|||||||
user.getIoLock().lock();
|
user.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
// Empty data - just delete from the DB.
|
// Empty data - just delete from the DB.
|
||||||
if (!GenericUserManager.shouldSave(user)) {
|
if (!this.plugin.getUserManager().shouldSave(user)) {
|
||||||
try (Connection c = this.provider.getConnection()) {
|
try (Connection c = this.provider.getConnection()) {
|
||||||
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(USER_PERMISSIONS_DELETE))) {
|
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(USER_PERMISSIONS_DELETE))) {
|
||||||
ps.setString(1, user.getUuid().toString());
|
ps.setString(1, user.getUuid().toString());
|
||||||
@ -643,7 +642,7 @@ public class SqlDao extends AbstractDao {
|
|||||||
throw new RuntimeException("Exception occurred whilst loading a group");
|
throw new RuntimeException("Exception occurred whilst loading a group");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupManager gm = this.plugin.getGroupManager();
|
GroupManager<?> gm = this.plugin.getGroupManager();
|
||||||
gm.getAll().values().stream()
|
gm.getAll().values().stream()
|
||||||
.filter(g -> !groups.contains(g.getName()))
|
.filter(g -> !groups.contains(g.getName()))
|
||||||
.forEach(gm::unload);
|
.forEach(gm::unload);
|
||||||
@ -880,7 +879,7 @@ public class SqlDao extends AbstractDao {
|
|||||||
throw new RuntimeException("Exception occurred whilst loading a track");
|
throw new RuntimeException("Exception occurred whilst loading a track");
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackManager tm = this.plugin.getTrackManager();
|
TrackManager<?> tm = this.plugin.getTrackManager();
|
||||||
tm.getAll().values().stream()
|
tm.getAll().values().stream()
|
||||||
.filter(t -> !tracks.contains(t.getName()))
|
.filter(t -> !tracks.contains(t.getName()))
|
||||||
.forEach(tm::unload);
|
.forEach(tm::unload);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.utils;
|
package me.lucko.luckperms.common.utils;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.platform.PlatformType;
|
||||||
import me.lucko.luckperms.common.assignments.AssignmentRule;
|
import me.lucko.luckperms.common.assignments.AssignmentRule;
|
||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
@ -34,47 +35,61 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for use in platform listeners
|
* Abstract listener utility for handling new player connections
|
||||||
*/
|
*/
|
||||||
public final class LoginHelper {
|
public abstract class AbstractLoginListener {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
public static User loadUser(LuckPermsPlugin plugin, UUID u, String username, boolean joinUuidSave) {
|
// if we should #join the uuid save future.
|
||||||
|
// this is only really necessary on BungeeCord, as the data may be needed
|
||||||
|
// on the backend, depending on uuid config options
|
||||||
|
private final boolean joinUuidSave;
|
||||||
|
|
||||||
|
protected AbstractLoginListener(LuckPermsPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.joinUuidSave = plugin.getServerType() == PlatformType.BUNGEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User loadUser(UUID u, String username) {
|
||||||
final long startTime = System.currentTimeMillis();
|
final long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
final UuidCache cache = plugin.getUuidCache();
|
// register with the housekeeper to avoid accidental unloads
|
||||||
if (!plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS)) {
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(u);
|
||||||
UUID uuid = plugin.getStorage().noBuffer().getUUID(username).join();
|
|
||||||
|
final UuidCache cache = this.plugin.getUuidCache();
|
||||||
|
if (!this.plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS)) {
|
||||||
|
UUID uuid = this.plugin.getStorage().noBuffer().getUUID(username).join();
|
||||||
if (uuid != null) {
|
if (uuid != null) {
|
||||||
cache.addToCache(u, uuid);
|
cache.addToCache(u, uuid);
|
||||||
} else {
|
} else {
|
||||||
// No previous data for this player
|
// No previous data for this player
|
||||||
plugin.getEventFactory().handleUserFirstLogin(u, username);
|
this.plugin.getEventFactory().handleUserFirstLogin(u, username);
|
||||||
cache.addToCache(u, u);
|
cache.addToCache(u, u);
|
||||||
CompletableFuture<Void> future = plugin.getStorage().noBuffer().saveUUIDData(u, username);
|
CompletableFuture<Void> future = this.plugin.getStorage().noBuffer().saveUUIDData(u, username);
|
||||||
if (joinUuidSave) {
|
if (this.joinUuidSave) {
|
||||||
future.join();
|
future.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String name = plugin.getStorage().noBuffer().getName(u).join();
|
String name = this.plugin.getStorage().noBuffer().getName(u).join();
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
plugin.getEventFactory().handleUserFirstLogin(u, username);
|
this.plugin.getEventFactory().handleUserFirstLogin(u, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Online mode, no cache needed. This is just for name -> uuid lookup.
|
// Online mode, no cache needed. This is just for name -> uuid lookup.
|
||||||
CompletableFuture<Void> future = plugin.getStorage().noBuffer().saveUUIDData(u, username);
|
CompletableFuture<Void> future = this.plugin.getStorage().noBuffer().saveUUIDData(u, username);
|
||||||
if (joinUuidSave) {
|
if (this.joinUuidSave) {
|
||||||
future.join();
|
future.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
User user = plugin.getStorage().noBuffer().loadUser(cache.getUUID(u), username).join();
|
User user = this.plugin.getStorage().noBuffer().loadUser(cache.getUUID(u), username).join();
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new NullPointerException("User is null");
|
throw new NullPointerException("User is null");
|
||||||
} else {
|
} else {
|
||||||
// Setup defaults for the user
|
// Setup defaults for the user
|
||||||
boolean save = false;
|
boolean save = false;
|
||||||
for (AssignmentRule rule : plugin.getConfiguration().get(ConfigKeys.DEFAULT_ASSIGNMENTS)) {
|
for (AssignmentRule rule : this.plugin.getConfiguration().get(ConfigKeys.DEFAULT_ASSIGNMENTS)) {
|
||||||
if (rule.apply(user)) {
|
if (rule.apply(user)) {
|
||||||
save = true;
|
save = true;
|
||||||
}
|
}
|
||||||
@ -82,7 +97,7 @@ public final class LoginHelper {
|
|||||||
|
|
||||||
// If they were given a default, persist the new assignments back to the storage.
|
// If they were given a default, persist the new assignments back to the storage.
|
||||||
if (save) {
|
if (save) {
|
||||||
plugin.getStorage().noBuffer().saveUser(user).join();
|
this.plugin.getStorage().noBuffer().saveUser(user).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does some minimum pre-calculations to (maybe) speed things up later.
|
// Does some minimum pre-calculations to (maybe) speed things up later.
|
||||||
@ -91,12 +106,10 @@ public final class LoginHelper {
|
|||||||
|
|
||||||
final long time = System.currentTimeMillis() - startTime;
|
final long time = System.currentTimeMillis() - startTime;
|
||||||
if (time >= 1000) {
|
if (time >= 1000) {
|
||||||
plugin.getLog().warn("Processing login for " + username + " took " + time + "ms.");
|
this.plugin.getLog().warn("Processing login for " + username + " took " + time + "ms.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoginHelper() {}
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.common.collect.ForwardingSet;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bad expiring set implementation using Caffeine caches
|
||||||
|
*
|
||||||
|
* @param <E> element type
|
||||||
|
*/
|
||||||
|
public class ExpiringSet<E> extends ForwardingSet<E> {
|
||||||
|
private final LoadingCache<E, Boolean> cache;
|
||||||
|
private final Set<E> setView;
|
||||||
|
|
||||||
|
public ExpiringSet(long duration, TimeUnit unit) {
|
||||||
|
this.cache = Caffeine.newBuilder().expireAfterAccess(duration, unit).build(key -> Boolean.TRUE);
|
||||||
|
this.setView = this.cache.asMap().keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(E element) {
|
||||||
|
this.cache.get(element); // simply requesting the element from the cache is sufficient.
|
||||||
|
|
||||||
|
// we don't care about the return value
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(@Nonnull Collection<? extends E> collection) {
|
||||||
|
for (E element : collection) {
|
||||||
|
add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't care about the return value
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object key) {
|
||||||
|
this.cache.invalidate(key);
|
||||||
|
|
||||||
|
// we don't care about the return value
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(@Nonnull Collection<?> keys) {
|
||||||
|
this.cache.invalidateAll(keys);
|
||||||
|
|
||||||
|
// we don't care about the return value
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<E> delegate() {
|
||||||
|
return this.setView;
|
||||||
|
}
|
||||||
|
}
|
@ -52,8 +52,7 @@ import me.lucko.luckperms.common.locale.LocaleManager;
|
|||||||
import me.lucko.luckperms.common.locale.NoopLocaleManager;
|
import me.lucko.luckperms.common.locale.NoopLocaleManager;
|
||||||
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
||||||
import me.lucko.luckperms.common.logging.SenderLogger;
|
import me.lucko.luckperms.common.logging.SenderLogger;
|
||||||
import me.lucko.luckperms.common.managers.GenericTrackManager;
|
import me.lucko.luckperms.common.managers.track.StandardTrackManager;
|
||||||
import me.lucko.luckperms.common.managers.TrackManager;
|
|
||||||
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
import me.lucko.luckperms.common.messaging.ExtendedMessagingService;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
@ -168,7 +167,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
private LuckPermsConfiguration configuration;
|
private LuckPermsConfiguration configuration;
|
||||||
private SpongeUserManager userManager;
|
private SpongeUserManager userManager;
|
||||||
private SpongeGroupManager groupManager;
|
private SpongeGroupManager groupManager;
|
||||||
private TrackManager trackManager;
|
private StandardTrackManager trackManager;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
private FileWatcher fileWatcher = null;
|
private FileWatcher fileWatcher = null;
|
||||||
private ExtendedMessagingService messagingService = null;
|
private ExtendedMessagingService messagingService = null;
|
||||||
@ -243,7 +242,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
this.uuidCache = new UuidCache(this);
|
this.uuidCache = new UuidCache(this);
|
||||||
this.userManager = new SpongeUserManager(this);
|
this.userManager = new SpongeUserManager(this);
|
||||||
this.groupManager = new SpongeGroupManager(this);
|
this.groupManager = new SpongeGroupManager(this);
|
||||||
this.trackManager = new GenericTrackManager(this);
|
this.trackManager = new StandardTrackManager(this);
|
||||||
this.calculatorFactory = new SpongeCalculatorFactory(this);
|
this.calculatorFactory = new SpongeCalculatorFactory(this);
|
||||||
this.cachedStateManager = new CachedStateManager();
|
this.cachedStateManager = new CachedStateManager();
|
||||||
|
|
||||||
@ -561,7 +560,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackManager getTrackManager() {
|
public StandardTrackManager getTrackManager() {
|
||||||
return this.trackManager;
|
return this.trackManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,10 @@
|
|||||||
package me.lucko.luckperms.sponge;
|
package me.lucko.luckperms.sponge;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||||
|
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||||
|
import me.lucko.luckperms.common.utils.SafeIterator;
|
||||||
|
|
||||||
|
import org.spongepowered.api.scheduler.Scheduler;
|
||||||
import org.spongepowered.api.scheduler.Task;
|
import org.spongepowered.api.scheduler.Task;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -35,12 +38,16 @@ import java.util.concurrent.Executor;
|
|||||||
|
|
||||||
public class SpongeSchedulerAdapter implements SchedulerAdapter {
|
public class SpongeSchedulerAdapter implements SchedulerAdapter {
|
||||||
private final LPSpongePlugin plugin;
|
private final LPSpongePlugin plugin;
|
||||||
private final Set<Task> tasks = ConcurrentHashMap.newKeySet();
|
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public SpongeSchedulerAdapter(LPSpongePlugin plugin) {
|
public SpongeSchedulerAdapter(LPSpongePlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Scheduler scheduler() {
|
||||||
|
return this.plugin.getSpongeScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Executor async() {
|
public Executor async() {
|
||||||
return this.plugin.getAsyncExecutorService();
|
return this.plugin.getAsyncExecutorService();
|
||||||
@ -62,29 +69,72 @@ public class SpongeSchedulerAdapter implements SchedulerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void asyncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
||||||
Task task = this.plugin.getSpongeScheduler().createTaskBuilder().async().intervalTicks(intervalTicks).delayTicks(intervalTicks).execute(runnable).submit(this.plugin);
|
Task task = scheduler().createTaskBuilder()
|
||||||
this.tasks.add(task);
|
.async()
|
||||||
|
.intervalTicks(intervalTicks)
|
||||||
|
.delayTicks(intervalTicks)
|
||||||
|
.execute(runnable)
|
||||||
|
.submit(this.plugin);
|
||||||
|
|
||||||
|
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
||||||
|
this.tasks.add(wrapped);
|
||||||
|
return wrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syncRepeating(Runnable runnable, long intervalTicks) {
|
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
||||||
Task task = this.plugin.getSpongeScheduler().createTaskBuilder().intervalTicks(intervalTicks).delayTicks(intervalTicks).execute(runnable).submit(this.plugin);
|
Task task = scheduler().createTaskBuilder()
|
||||||
this.tasks.add(task);
|
.intervalTicks(intervalTicks)
|
||||||
|
.delayTicks(intervalTicks)
|
||||||
|
.execute(runnable)
|
||||||
|
.submit(this.plugin);
|
||||||
|
|
||||||
|
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
||||||
|
this.tasks.add(wrapped);
|
||||||
|
return wrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void asyncLater(Runnable runnable, long delayTicks) {
|
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
||||||
this.plugin.getSpongeScheduler().createTaskBuilder().async().delayTicks(delayTicks).execute(runnable).submit(this.plugin);
|
Task task = scheduler().createTaskBuilder()
|
||||||
|
.async()
|
||||||
|
.delayTicks(delayTicks)
|
||||||
|
.execute(runnable)
|
||||||
|
.submit(this.plugin);
|
||||||
|
|
||||||
|
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
||||||
|
this.tasks.add(wrapped);
|
||||||
|
return wrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syncLater(Runnable runnable, long delayTicks) {
|
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
||||||
this.plugin.getSpongeScheduler().createTaskBuilder().delayTicks(delayTicks).execute(runnable).submit(this.plugin);
|
Task task = scheduler().createTaskBuilder()
|
||||||
|
.delayTicks(delayTicks)
|
||||||
|
.execute(runnable)
|
||||||
|
.submit(this.plugin);
|
||||||
|
|
||||||
|
SchedulerTask wrapped = new SpongeSchedulerTask(task);
|
||||||
|
this.tasks.add(wrapped);
|
||||||
|
return wrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
this.tasks.forEach(Task::cancel);
|
SafeIterator.iterate(this.tasks, SchedulerTask::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.listeners;
|
|||||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
import me.lucko.luckperms.common.locale.Message;
|
import me.lucko.luckperms.common.locale.Message;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.utils.LoginHelper;
|
import me.lucko.luckperms.common.utils.AbstractLoginListener;
|
||||||
import me.lucko.luckperms.common.utils.UuidCache;
|
import me.lucko.luckperms.common.utils.UuidCache;
|
||||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||||
|
|
||||||
@ -45,13 +45,14 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class SpongeConnectionListener {
|
public class SpongeConnectionListener extends AbstractLoginListener {
|
||||||
private final LPSpongePlugin plugin;
|
private final LPSpongePlugin plugin;
|
||||||
|
|
||||||
private final Set<UUID> deniedAsyncLogin = Collections.synchronizedSet(new HashSet<>());
|
private final Set<UUID> deniedAsyncLogin = Collections.synchronizedSet(new HashSet<>());
|
||||||
private final Set<UUID> deniedLogin = Collections.synchronizedSet(new HashSet<>());
|
private final Set<UUID> deniedLogin = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
public SpongeConnectionListener(LPSpongePlugin plugin) {
|
public SpongeConnectionListener(LPSpongePlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ public class SpongeConnectionListener {
|
|||||||
- creating a user instance in the UserManager for this connection.
|
- creating a user instance in the UserManager for this connection.
|
||||||
- setting up cached data. */
|
- setting up cached data. */
|
||||||
try {
|
try {
|
||||||
User user = LoginHelper.loadUser(this.plugin, p.getUniqueId(), username, false);
|
User user = loadUser(p.getUniqueId(), username);
|
||||||
this.plugin.getEventFactory().handleUserLoginProcess(p.getUniqueId(), username, user);
|
this.plugin.getEventFactory().handleUserLoginProcess(p.getUniqueId(), username, user);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.plugin.getLog().severe("Exception occured whilst loading data for " + p.getUniqueId() + " - " + p.getName());
|
this.plugin.getLog().severe("Exception occured whilst loading data for " + p.getUniqueId() + " - " + p.getName());
|
||||||
@ -165,6 +166,10 @@ public class SpongeConnectionListener {
|
|||||||
|
|
||||||
// Unload the user from memory when they disconnect
|
// Unload the user from memory when they disconnect
|
||||||
cache.clearCache(e.getTargetEntity().getUniqueId());
|
cache.clearCache(e.getTargetEntity().getUniqueId());
|
||||||
|
|
||||||
|
// Register with the housekeeper, so the User's instance will stick
|
||||||
|
// around for a bit after they disconnect
|
||||||
|
this.plugin.getUserManager().getHouseKeeper().registerUsage(e.getTargetEntity().getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,7 @@ import me.lucko.luckperms.api.HeldPermission;
|
|||||||
import me.lucko.luckperms.api.Tristate;
|
import me.lucko.luckperms.api.Tristate;
|
||||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||||
import me.lucko.luckperms.common.managers.GroupManager;
|
import me.lucko.luckperms.common.managers.group.AbstractGroupManager;
|
||||||
import me.lucko.luckperms.common.model.Group;
|
|
||||||
import me.lucko.luckperms.common.storage.DataConstraints;
|
import me.lucko.luckperms.common.storage.DataConstraints;
|
||||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||||
@ -61,15 +60,10 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implements LPSubjectCollection {
|
||||||
|
|
||||||
private final LPSpongePlugin plugin;
|
private final LPSpongePlugin plugin;
|
||||||
|
|
||||||
private SubjectCollection spongeProxy = null;
|
private SubjectCollection spongeProxy = null;
|
||||||
|
|
||||||
private final LoadingCache<String, SpongeGroup> objects = Caffeine.newBuilder()
|
|
||||||
.build(this::apply);
|
|
||||||
|
|
||||||
private final LoadingCache<String, LPSubject> subjectLoadingCache = Caffeine.newBuilder()
|
private final LoadingCache<String, LPSubject> subjectLoadingCache = Caffeine.newBuilder()
|
||||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||||
.build(s -> {
|
.build(s -> {
|
||||||
@ -104,53 +98,6 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
|||||||
return new SpongeGroup(name, this.plugin);
|
return new SpongeGroup(name, this.plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------
|
|
||||||
* Manager methods
|
|
||||||
* ------------------------------------------ */
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, SpongeGroup> getAll() {
|
|
||||||
return ImmutableMap.copyOf(this.objects.asMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpongeGroup getOrMake(String id) {
|
|
||||||
return this.objects.get(id.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpongeGroup getIfLoaded(String id) {
|
|
||||||
return this.objects.getIfPresent(id.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoaded(String id) {
|
|
||||||
return this.objects.asMap().containsKey(id.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unload(String id) {
|
|
||||||
if (id != null) {
|
|
||||||
this.objects.invalidate(id.toLowerCase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unload(Group t) {
|
|
||||||
if (t != null) {
|
|
||||||
unload(t.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unloadAll() {
|
|
||||||
this.objects.invalidateAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------
|
|
||||||
* SubjectCollection methods
|
|
||||||
* ------------------------------------------ */
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized SubjectCollection sponge() {
|
public synchronized SubjectCollection sponge() {
|
||||||
if (this.spongeProxy == null) {
|
if (this.spongeProxy == null) {
|
||||||
@ -160,6 +107,10 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
|||||||
return this.spongeProxy;
|
return this.spongeProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LPSpongePlugin getPlugin() {
|
||||||
|
return this.plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LuckPermsService getService() {
|
public LuckPermsService getService() {
|
||||||
return this.plugin.getService();
|
return this.plugin.getService();
|
||||||
@ -261,7 +212,7 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission) {
|
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission) {
|
||||||
return this.objects.asMap().values().stream()
|
return getAll().values().stream()
|
||||||
.map(SpongeGroup::sponge)
|
.map(SpongeGroup::sponge)
|
||||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(ImmutableContextSet.empty(), permission)))
|
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(ImmutableContextSet.empty(), permission)))
|
||||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||||
@ -270,7 +221,7 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission) {
|
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission) {
|
||||||
return this.objects.asMap().values().stream()
|
return getAll().values().stream()
|
||||||
.map(SpongeGroup::sponge)
|
.map(SpongeGroup::sponge)
|
||||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(contexts, permission)))
|
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(contexts, permission)))
|
||||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||||
@ -282,33 +233,4 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
|||||||
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
|
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Group getByDisplayName(String name) {
|
|
||||||
// try to get an exact match first
|
|
||||||
Group g = getIfLoaded(name);
|
|
||||||
if (g != null) {
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
// then try exact display name matches
|
|
||||||
for (Group group : getAll().values()) {
|
|
||||||
if (group.getDisplayName().isPresent() && group.getDisplayName().get().equals(name)) {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// then try case insensitive name matches
|
|
||||||
for (Group group : getAll().values()) {
|
|
||||||
if (group.getDisplayName().isPresent() && group.getDisplayName().get().equalsIgnoreCase(name)) {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LPSpongePlugin getPlugin() {
|
|
||||||
return this.plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,8 @@ import com.google.common.collect.Maps;
|
|||||||
import me.lucko.luckperms.api.HeldPermission;
|
import me.lucko.luckperms.api.HeldPermission;
|
||||||
import me.lucko.luckperms.api.Tristate;
|
import me.lucko.luckperms.api.Tristate;
|
||||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
import me.lucko.luckperms.common.managers.GenericUserManager;
|
import me.lucko.luckperms.common.managers.user.AbstractUserManager;
|
||||||
import me.lucko.luckperms.common.managers.UserManager;
|
import me.lucko.luckperms.common.managers.user.UserHousekeeper;
|
||||||
import me.lucko.luckperms.common.model.User;
|
|
||||||
import me.lucko.luckperms.common.references.UserIdentifier;
|
import me.lucko.luckperms.common.references.UserIdentifier;
|
||||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||||
@ -62,18 +61,16 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
public class SpongeUserManager extends AbstractUserManager<SpongeUser> implements LPSubjectCollection {
|
||||||
|
|
||||||
private final LPSpongePlugin plugin;
|
private final LPSpongePlugin plugin;
|
||||||
|
|
||||||
private SubjectCollection spongeProxy = null;
|
private SubjectCollection spongeProxy = null;
|
||||||
|
|
||||||
private final LoadingCache<UserIdentifier, SpongeUser> objects = Caffeine.newBuilder()
|
|
||||||
.build(this::apply);
|
|
||||||
|
|
||||||
private final LoadingCache<UUID, LPSubject> subjectLoadingCache = Caffeine.<UUID, LPSubject>newBuilder()
|
private final LoadingCache<UUID, LPSubject> subjectLoadingCache = Caffeine.<UUID, LPSubject>newBuilder()
|
||||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||||
.build(u -> {
|
.build(u -> {
|
||||||
|
// clock in with the housekeeper
|
||||||
|
getHouseKeeper().registerUsage(u);
|
||||||
|
|
||||||
// check if the user instance is already loaded.
|
// check if the user instance is already loaded.
|
||||||
SpongeUser user = getIfLoaded(u);
|
SpongeUser user = getIfLoaded(u);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
@ -100,6 +97,7 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
|||||||
});
|
});
|
||||||
|
|
||||||
public SpongeUserManager(LPSpongePlugin plugin) {
|
public SpongeUserManager(LPSpongePlugin plugin) {
|
||||||
|
super(plugin, UserHousekeeper.timeoutSettings(10, TimeUnit.MINUTES));
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,103 +108,6 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
|||||||
new SpongeUser(id.getUuid(), id.getUsername().get(), this.plugin);
|
new SpongeUser(id.getUuid(), id.getUsername().get(), this.plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------
|
|
||||||
* Manager methods
|
|
||||||
* ------------------------------------------ */
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<UserIdentifier, SpongeUser> getAll() {
|
|
||||||
return ImmutableMap.copyOf(this.objects.asMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpongeUser getOrMake(UserIdentifier id) {
|
|
||||||
SpongeUser ret = this.objects.get(id);
|
|
||||||
if (id.getUsername().isPresent()) {
|
|
||||||
ret.setName(id.getUsername().get(), false);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpongeUser getIfLoaded(UserIdentifier id) {
|
|
||||||
return this.objects.getIfPresent(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoaded(UserIdentifier id) {
|
|
||||||
return this.objects.asMap().containsKey(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unload(UserIdentifier id) {
|
|
||||||
if (id != null) {
|
|
||||||
this.objects.invalidate(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unload(User t) {
|
|
||||||
if (t != null) {
|
|
||||||
unload(t.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unloadAll() {
|
|
||||||
this.objects.invalidateAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------
|
|
||||||
* UserManager methods
|
|
||||||
* ------------------------------------------ */
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpongeUser getByUsername(String name) {
|
|
||||||
for (SpongeUser user : getAll().values()) {
|
|
||||||
Optional<String> n = user.getName();
|
|
||||||
if (n.isPresent() && n.get().equalsIgnoreCase(name)) {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpongeUser getIfLoaded(UUID uuid) {
|
|
||||||
return getIfLoaded(UserIdentifier.of(uuid, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean giveDefaultIfNeeded(User user, boolean save) {
|
|
||||||
return GenericUserManager.giveDefaultIfNeeded(user, save, this.plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean cleanup(User user) {
|
|
||||||
// Do nothing - this instance uses other means in order to cleanup
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void scheduleUnload(UUID uuid) {
|
|
||||||
// Do nothing - this instance uses other means in order to cleanup
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Void> updateAllUsers() {
|
|
||||||
return CompletableFuture.runAsync(
|
|
||||||
() -> this.plugin.getOnlinePlayers()
|
|
||||||
.map(u -> this.plugin.getUuidCache().getUUID(u))
|
|
||||||
.forEach(u -> this.plugin.getStorage().loadUser(u, null).join()),
|
|
||||||
this.plugin.getScheduler().async()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------
|
|
||||||
* SubjectCollection methods
|
|
||||||
* ------------------------------------------ */
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized SubjectCollection sponge() {
|
public synchronized SubjectCollection sponge() {
|
||||||
if (this.spongeProxy == null) {
|
if (this.spongeProxy == null) {
|
||||||
@ -216,6 +117,10 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
|||||||
return this.spongeProxy;
|
return this.spongeProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LPSpongePlugin getPlugin() {
|
||||||
|
return this.plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LuckPermsService getService() {
|
public LuckPermsService getService() {
|
||||||
return this.plugin.getService();
|
return this.plugin.getService();
|
||||||
@ -358,7 +263,7 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission) {
|
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission) {
|
||||||
return this.objects.asMap().values().stream()
|
return getAll().values().stream()
|
||||||
.map(SpongeUser::sponge)
|
.map(SpongeUser::sponge)
|
||||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(ImmutableContextSet.empty(), permission)))
|
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(ImmutableContextSet.empty(), permission)))
|
||||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||||
@ -367,7 +272,7 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission) {
|
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission) {
|
||||||
return this.objects.asMap().values().stream()
|
return getAll().values().stream()
|
||||||
.map(SpongeUser::sponge)
|
.map(SpongeUser::sponge)
|
||||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(contexts, permission)))
|
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(contexts, permission)))
|
||||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||||
@ -379,8 +284,4 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
|||||||
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
|
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LPSpongePlugin getPlugin() {
|
|
||||||
return this.plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user