mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Listen for changes in data files and automatically update
This commit is contained in:
parent
9dc2278083
commit
b9fc5c39ae
@ -71,6 +71,7 @@ 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.BufferedRequest;
|
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||||
|
import me.lucko.luckperms.common.utils.FileWatcher;
|
||||||
import me.lucko.luckperms.common.utils.LoggerImpl;
|
import me.lucko.luckperms.common.utils.LoggerImpl;
|
||||||
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@ -106,6 +107,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
private GroupManager groupManager;
|
private GroupManager groupManager;
|
||||||
private TrackManager trackManager;
|
private TrackManager trackManager;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
|
private FileWatcher fileWatcher = null;
|
||||||
private InternalMessagingService messagingService = null;
|
private InternalMessagingService messagingService = null;
|
||||||
private UuidCache uuidCache;
|
private UuidCache uuidCache;
|
||||||
private BukkitListener listener;
|
private BukkitListener listener;
|
||||||
@ -168,6 +170,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
listener = new BukkitListener(this);
|
listener = new BukkitListener(this);
|
||||||
pm.registerEvents(listener, this);
|
pm.registerEvents(listener, this);
|
||||||
|
|
||||||
|
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
|
||||||
|
fileWatcher = new FileWatcher(this);
|
||||||
|
getScheduler().doAsyncRepeating(fileWatcher, 30L);
|
||||||
|
}
|
||||||
|
|
||||||
// initialise datastore
|
// initialise datastore
|
||||||
storage = StorageFactory.getInstance(this, StorageType.H2);
|
storage = StorageFactory.getInstance(this, StorageType.H2);
|
||||||
|
|
||||||
@ -336,6 +343,10 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
getLog().info("Closing datastore...");
|
getLog().info("Closing datastore...");
|
||||||
storage.shutdown();
|
storage.shutdown();
|
||||||
|
|
||||||
|
if (fileWatcher != null) {
|
||||||
|
fileWatcher.close();
|
||||||
|
}
|
||||||
|
|
||||||
if (messagingService != null) {
|
if (messagingService != null) {
|
||||||
getLog().info("Closing messaging service...");
|
getLog().info("Closing messaging service...");
|
||||||
messagingService.close();
|
messagingService.close();
|
||||||
@ -363,6 +374,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
groupManager = null;
|
groupManager = null;
|
||||||
trackManager = null;
|
trackManager = null;
|
||||||
storage = null;
|
storage = null;
|
||||||
|
fileWatcher = null;
|
||||||
messagingService = null;
|
messagingService = null;
|
||||||
uuidCache = null;
|
uuidCache = null;
|
||||||
listener = null;
|
listener = null;
|
||||||
|
@ -192,6 +192,12 @@ group-name-rewrite:
|
|||||||
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
|
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
|
||||||
storage-method: h2
|
storage-method: h2
|
||||||
|
|
||||||
|
# When using a file-based storage type, LuckPerms can monitor the data files for changes, and then schedule automatic
|
||||||
|
# updates when changes are detected.
|
||||||
|
#
|
||||||
|
# If you don't want this to happen, set this option to false.
|
||||||
|
watch-files: true
|
||||||
|
|
||||||
# This block enables support for split datastores.
|
# This block enables support for split datastores.
|
||||||
split-storage:
|
split-storage:
|
||||||
enabled: false
|
enabled: false
|
||||||
@ -217,9 +223,14 @@ data:
|
|||||||
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
|
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
|
||||||
table_prefix: 'luckperms_'
|
table_prefix: 'luckperms_'
|
||||||
|
|
||||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
# This option controls how frequently LuckPerms will perform a sync task.
|
||||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
# A sync task will refresh all data from the storage, and ensure that the most up-to-date data is being used by the plugin.
|
||||||
sync-minutes: 3
|
#
|
||||||
|
# This is disabled by default, as most users will not need it. However, if you're using a remote storage type
|
||||||
|
# without a messaging service setup, you may wish to set this value to something like 3.
|
||||||
|
#
|
||||||
|
# Set to -1 to disable the task completely.
|
||||||
|
sync-minutes: -1
|
||||||
|
|
||||||
# Settings for the messaging service
|
# Settings for the messaging service
|
||||||
#
|
#
|
||||||
|
@ -64,6 +64,7 @@ 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.BufferedRequest;
|
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||||
|
import me.lucko.luckperms.common.utils.FileWatcher;
|
||||||
import me.lucko.luckperms.common.utils.LoggerImpl;
|
import me.lucko.luckperms.common.utils.LoggerImpl;
|
||||||
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
@ -88,6 +89,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
private GroupManager groupManager;
|
private GroupManager groupManager;
|
||||||
private TrackManager trackManager;
|
private TrackManager trackManager;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
|
private FileWatcher fileWatcher = null;
|
||||||
private InternalMessagingService messagingService = null;
|
private InternalMessagingService messagingService = null;
|
||||||
private UuidCache uuidCache;
|
private UuidCache uuidCache;
|
||||||
private ApiProvider apiProvider;
|
private ApiProvider apiProvider;
|
||||||
@ -122,6 +124,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
// register events
|
// register events
|
||||||
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
|
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
|
||||||
|
|
||||||
|
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
|
||||||
|
fileWatcher = new FileWatcher(this);
|
||||||
|
getScheduler().doAsyncRepeating(fileWatcher, 30L);
|
||||||
|
}
|
||||||
|
|
||||||
// initialise datastore
|
// initialise datastore
|
||||||
storage = StorageFactory.getInstance(this, StorageType.H2);
|
storage = StorageFactory.getInstance(this, StorageType.H2);
|
||||||
|
|
||||||
@ -226,6 +233,10 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
|||||||
getLog().info("Closing datastore...");
|
getLog().info("Closing datastore...");
|
||||||
storage.shutdown();
|
storage.shutdown();
|
||||||
|
|
||||||
|
if (fileWatcher != null) {
|
||||||
|
fileWatcher.close();
|
||||||
|
}
|
||||||
|
|
||||||
if (messagingService != null) {
|
if (messagingService != null) {
|
||||||
getLog().info("Closing messaging service...");
|
getLog().info("Closing messaging service...");
|
||||||
messagingService.close();
|
messagingService.close();
|
||||||
|
@ -134,6 +134,12 @@ meta-formatting:
|
|||||||
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
|
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
|
||||||
storage-method: h2
|
storage-method: h2
|
||||||
|
|
||||||
|
# When using a file-based storage type, LuckPerms can monitor the data files for changes, and then schedule automatic
|
||||||
|
# updates when changes are detected.
|
||||||
|
#
|
||||||
|
# If you don't want this to happen, set this option to false.
|
||||||
|
watch-files: true
|
||||||
|
|
||||||
# This block enables support for split datastores.
|
# This block enables support for split datastores.
|
||||||
split-storage:
|
split-storage:
|
||||||
enabled: false
|
enabled: false
|
||||||
@ -159,9 +165,14 @@ data:
|
|||||||
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
|
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
|
||||||
table_prefix: 'luckperms_'
|
table_prefix: 'luckperms_'
|
||||||
|
|
||||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
# This option controls how frequently LuckPerms will perform a sync task.
|
||||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
# A sync task will refresh all data from the storage, and ensure that the most up-to-date data is being used by the plugin.
|
||||||
sync-minutes: 3
|
#
|
||||||
|
# This is disabled by default, as most users will not need it. However, if you're using a remote storage type
|
||||||
|
# without a messaging service setup, you may wish to set this value to something like 3.
|
||||||
|
#
|
||||||
|
# Set to -1 to disable the task completely.
|
||||||
|
sync-minutes: -1
|
||||||
|
|
||||||
# Settings for the messaging service
|
# Settings for the messaging service
|
||||||
#
|
#
|
||||||
|
@ -51,7 +51,7 @@ import java.util.Map;
|
|||||||
public class ConfigKeys {
|
public class ConfigKeys {
|
||||||
|
|
||||||
public static final ConfigKey<String> SERVER = StringKey.of("server", "global");
|
public static final ConfigKey<String> SERVER = StringKey.of("server", "global");
|
||||||
public static final ConfigKey<Integer> SYNC_TIME = EnduringKey.wrap(IntegerKey.of("data.sync-minutes", 3));
|
public static final ConfigKey<Integer> SYNC_TIME = EnduringKey.wrap(IntegerKey.of("data.sync-minutes", -1));
|
||||||
public static final ConfigKey<String> DEFAULT_GROUP_NODE = StaticKey.of("group.default"); // constant since 2.6
|
public static final ConfigKey<String> DEFAULT_GROUP_NODE = StaticKey.of("group.default"); // constant since 2.6
|
||||||
public static final ConfigKey<String> DEFAULT_GROUP_NAME = StaticKey.of("default"); // constant since 2.6
|
public static final ConfigKey<String> DEFAULT_GROUP_NAME = StaticKey.of("default"); // constant since 2.6
|
||||||
public static final ConfigKey<Boolean> INCLUDING_GLOBAL_PERMS = BooleanKey.of("include-global", true);
|
public static final ConfigKey<Boolean> INCLUDING_GLOBAL_PERMS = BooleanKey.of("include-global", true);
|
||||||
@ -140,6 +140,7 @@ public class ConfigKeys {
|
|||||||
}));
|
}));
|
||||||
public static final ConfigKey<String> SQL_TABLE_PREFIX = EnduringKey.wrap(StringKey.of("data.table_prefix", "luckperms_"));
|
public static final ConfigKey<String> SQL_TABLE_PREFIX = EnduringKey.wrap(StringKey.of("data.table_prefix", "luckperms_"));
|
||||||
public static final ConfigKey<String> STORAGE_METHOD = EnduringKey.wrap(StringKey.of("storage-method", "h2"));
|
public static final ConfigKey<String> STORAGE_METHOD = EnduringKey.wrap(StringKey.of("storage-method", "h2"));
|
||||||
|
public static final ConfigKey<Boolean> WATCH_FILES = BooleanKey.of("watch-files", true);
|
||||||
public static final ConfigKey<Boolean> SPLIT_STORAGE = EnduringKey.wrap(BooleanKey.of("split-storage.enabled", false));
|
public static final ConfigKey<Boolean> SPLIT_STORAGE = EnduringKey.wrap(BooleanKey.of("split-storage.enabled", false));
|
||||||
public static final ConfigKey<Map<String, String>> SPLIT_STORAGE_OPTIONS = EnduringKey.wrap(AbstractKey.of(c -> {
|
public static final ConfigKey<Map<String, String>> SPLIT_STORAGE_OPTIONS = EnduringKey.wrap(AbstractKey.of(c -> {
|
||||||
return ImmutableMap.<String, String>builder()
|
return ImmutableMap.<String, String>builder()
|
||||||
|
@ -46,6 +46,7 @@ import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
|||||||
import me.lucko.luckperms.common.storage.Storage;
|
import me.lucko.luckperms.common.storage.Storage;
|
||||||
import me.lucko.luckperms.common.treeview.PermissionVault;
|
import me.lucko.luckperms.common.treeview.PermissionVault;
|
||||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||||
|
import me.lucko.luckperms.common.utils.FileWatcher;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -54,6 +55,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main internal interface for LuckPerms plugins, providing the base for abstraction throughout the project.
|
* Main internal interface for LuckPerms plugins, providing the base for abstraction throughout the project.
|
||||||
@ -216,6 +218,20 @@ public interface LuckPermsPlugin {
|
|||||||
*/
|
*/
|
||||||
String getServerVersion();
|
String getServerVersion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the file watcher running on the platform, or null if it's not enabled.
|
||||||
|
*
|
||||||
|
* @return the file watcher, or null
|
||||||
|
*/
|
||||||
|
FileWatcher getFileWatcher();
|
||||||
|
|
||||||
|
default void applyToFileWatcher(Consumer<FileWatcher> consumer) {
|
||||||
|
FileWatcher fw = getFileWatcher();
|
||||||
|
if (fw != null) {
|
||||||
|
consumer.accept(fw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the plugins main data storage directory
|
* Gets the plugins main data storage directory
|
||||||
*
|
*
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
package me.lucko.luckperms.common.storage.backing;
|
package me.lucko.luckperms.common.storage.backing;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.LogEntry;
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
|
import me.lucko.luckperms.common.commands.utils.Util;
|
||||||
import me.lucko.luckperms.common.constants.Constants;
|
import me.lucko.luckperms.common.constants.Constants;
|
||||||
|
import me.lucko.luckperms.common.core.model.User;
|
||||||
import me.lucko.luckperms.common.data.Log;
|
import me.lucko.luckperms.common.data.Log;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
@ -49,23 +51,27 @@ abstract class FlatfileBacking extends AbstractBacking {
|
|||||||
private static final String LOG_FORMAT = "%s(%s): [%s] %s(%s) --> %s";
|
private static final String LOG_FORMAT = "%s(%s): [%s] %s(%s) --> %s";
|
||||||
|
|
||||||
private final Logger actionLogger = Logger.getLogger("lp_actions");
|
private final Logger actionLogger = Logger.getLogger("lp_actions");
|
||||||
|
private Map<String, String> uuidCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final File pluginDir;
|
private final File pluginDir;
|
||||||
|
private final String fileExtension;
|
||||||
|
|
||||||
|
private File uuidData;
|
||||||
|
private File actionLog;
|
||||||
File usersDir;
|
File usersDir;
|
||||||
File groupsDir;
|
File groupsDir;
|
||||||
File tracksDir;
|
File tracksDir;
|
||||||
private Map<String, String> uuidCache = new ConcurrentHashMap<>();
|
|
||||||
private File uuidData;
|
|
||||||
private File actionLog;
|
|
||||||
|
|
||||||
FlatfileBacking(LuckPermsPlugin plugin, String name, File pluginDir) {
|
FlatfileBacking(LuckPermsPlugin plugin, String name, File pluginDir, String fileExtension) {
|
||||||
super(plugin, name);
|
super(plugin, name);
|
||||||
this.pluginDir = pluginDir;
|
this.pluginDir = pluginDir;
|
||||||
|
this.fileExtension = fileExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
try {
|
try {
|
||||||
makeFiles();
|
setupFiles();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return;
|
return;
|
||||||
@ -93,7 +99,7 @@ abstract class FlatfileBacking extends AbstractBacking {
|
|||||||
setAcceptingLogins(true);
|
setAcceptingLogins(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeFiles() throws IOException {
|
private void setupFiles() throws IOException {
|
||||||
File data = new File(pluginDir, "data");
|
File data = new File(pluginDir, "data");
|
||||||
data.mkdirs();
|
data.mkdirs();
|
||||||
|
|
||||||
@ -111,6 +117,45 @@ abstract class FlatfileBacking extends AbstractBacking {
|
|||||||
|
|
||||||
actionLog = new File(data, "actions.log");
|
actionLog = new File(data, "actions.log");
|
||||||
actionLog.createNewFile();
|
actionLog.createNewFile();
|
||||||
|
|
||||||
|
// Listen for file changes.
|
||||||
|
plugin.applyToFileWatcher(watcher -> {
|
||||||
|
watcher.subscribe("users", usersDir.toPath(), s -> {
|
||||||
|
if (!s.endsWith(fileExtension)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String user = s.substring(0, s.length() - fileExtension.length());
|
||||||
|
UUID uuid = Util.parseUuid(user);
|
||||||
|
if (uuid == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
User u = plugin.getUserManager().get(uuid);
|
||||||
|
if (u != null) {
|
||||||
|
plugin.getLog().info("[FileWatcher] Refreshing user " + u.getName());
|
||||||
|
plugin.getStorage().loadUser(uuid, "null");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
watcher.subscribe("groups", groupsDir.toPath(), s -> {
|
||||||
|
if (!s.endsWith(fileExtension)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String groupName = s.substring(0, s.length() - fileExtension.length());
|
||||||
|
plugin.getLog().info("[FileWatcher] Refreshing group " + groupName);
|
||||||
|
plugin.getUpdateTaskBuffer().request();
|
||||||
|
});
|
||||||
|
watcher.subscribe("tracks", tracksDir.toPath(), s -> {
|
||||||
|
if (!s.endsWith(fileExtension)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String trackName = s.substring(0, s.length() - fileExtension.length());
|
||||||
|
plugin.getLog().info("[FileWatcher] Refreshing track " + trackName);
|
||||||
|
plugin.getStorage().loadAllTracks();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -118,6 +163,10 @@ abstract class FlatfileBacking extends AbstractBacking {
|
|||||||
saveUUIDCache(uuidCache);
|
saveUUIDCache(uuidCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void registerFileAction(String type, File file) {
|
||||||
|
plugin.applyToFileWatcher(fileWatcher -> fileWatcher.registerChange(type, file.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean logAction(LogEntry entry) {
|
public boolean logAction(LogEntry entry) {
|
||||||
actionLogger.info(String.format(LOG_FORMAT,
|
actionLogger.info(String.format(LOG_FORMAT,
|
||||||
|
@ -70,7 +70,7 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JSONBacking(LuckPermsPlugin plugin, File pluginDir) {
|
public JSONBacking(LuckPermsPlugin plugin, File pluginDir) {
|
||||||
super(plugin, "JSON", pluginDir);
|
super(plugin, "JSON", pluginDir, ".json");
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fileToWriter(File file, ThrowingFunction<JsonWriter, Boolean> writeOperation) {
|
private boolean fileToWriter(File file, ThrowingFunction<JsonWriter, Boolean> writeOperation) {
|
||||||
@ -108,6 +108,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File userFile = new File(usersDir, uuid.toString() + ".json");
|
File userFile = new File(usersDir, uuid.toString() + ".json");
|
||||||
|
registerFileAction("users", userFile);
|
||||||
|
|
||||||
if (userFile.exists()) {
|
if (userFile.exists()) {
|
||||||
return fileToReader(userFile, reader -> {
|
return fileToReader(userFile, reader -> {
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
@ -178,6 +180,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
|
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
|
||||||
|
registerFileAction("users", userFile);
|
||||||
|
|
||||||
if (!GenericUserManager.shouldSave(user)) {
|
if (!GenericUserManager.shouldSave(user)) {
|
||||||
if (userFile.exists()) {
|
if (userFile.exists()) {
|
||||||
userFile.delete();
|
userFile.delete();
|
||||||
@ -221,6 +225,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
if (files == null) return false;
|
if (files == null) return false;
|
||||||
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
registerFileAction("users", file);
|
||||||
|
|
||||||
Map<String, Boolean> nodes = new HashMap<>();
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
fileToReader(file, reader -> {
|
fileToReader(file, reader -> {
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
@ -277,6 +283,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
if (files == null) return false;
|
if (files == null) return false;
|
||||||
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
registerFileAction("users", file);
|
||||||
|
|
||||||
UUID holder = UUID.fromString(file.getName().substring(0, file.getName().length() - 5));
|
UUID holder = UUID.fromString(file.getName().substring(0, file.getName().length() - 5));
|
||||||
Map<String, Boolean> nodes = new HashMap<>();
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
fileToReader(file, reader -> {
|
fileToReader(file, reader -> {
|
||||||
@ -321,6 +329,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, name + ".json");
|
File groupFile = new File(groupsDir, name + ".json");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
|
|
||||||
if (groupFile.exists()) {
|
if (groupFile.exists()) {
|
||||||
return fileToReader(groupFile, reader -> {
|
return fileToReader(groupFile, reader -> {
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
@ -374,6 +384,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, name + ".json");
|
File groupFile = new File(groupsDir, name + ".json");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
|
|
||||||
return groupFile.exists() && fileToReader(groupFile, reader -> {
|
return groupFile.exists() && fileToReader(groupFile, reader -> {
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
reader.nextName(); // name record
|
reader.nextName(); // name record
|
||||||
@ -420,6 +432,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
|
|
||||||
if (!groupFile.exists()) {
|
if (!groupFile.exists()) {
|
||||||
try {
|
try {
|
||||||
groupFile.createNewFile();
|
groupFile.createNewFile();
|
||||||
@ -453,6 +467,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
|
|
||||||
if (groupFile.exists()) {
|
if (groupFile.exists()) {
|
||||||
groupFile.delete();
|
groupFile.delete();
|
||||||
}
|
}
|
||||||
@ -471,6 +487,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
if (files == null) return false;
|
if (files == null) return false;
|
||||||
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
registerFileAction("groups", file);
|
||||||
|
|
||||||
String holder = file.getName().substring(0, file.getName().length() - 5);
|
String holder = file.getName().substring(0, file.getName().length() - 5);
|
||||||
Map<String, Boolean> nodes = new HashMap<>();
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
fileToReader(file, reader -> {
|
fileToReader(file, reader -> {
|
||||||
@ -511,6 +529,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, name + ".json");
|
File trackFile = new File(tracksDir, name + ".json");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
if (trackFile.exists()) {
|
if (trackFile.exists()) {
|
||||||
return fileToReader(trackFile, reader -> {
|
return fileToReader(trackFile, reader -> {
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
@ -561,6 +581,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, name + ".json");
|
File trackFile = new File(tracksDir, name + ".json");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
return trackFile.exists() && fileToReader(trackFile, reader -> {
|
return trackFile.exists() && fileToReader(trackFile, reader -> {
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
reader.nextName(); // name record
|
reader.nextName(); // name record
|
||||||
@ -606,6 +628,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
if (!trackFile.exists()) {
|
if (!trackFile.exists()) {
|
||||||
try {
|
try {
|
||||||
trackFile.createNewFile();
|
trackFile.createNewFile();
|
||||||
@ -639,6 +663,8 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
if (trackFile.exists()) {
|
if (trackFile.exists()) {
|
||||||
trackFile.delete();
|
trackFile.delete();
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public YAMLBacking(LuckPermsPlugin plugin, File pluginDir) {
|
public YAMLBacking(LuckPermsPlugin plugin, File pluginDir) {
|
||||||
super(plugin, "YAML", pluginDir);
|
super(plugin, "YAML", pluginDir, ".yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean writeMapToFile(File file, Map<String, Object> values) {
|
private boolean writeMapToFile(File file, Map<String, Object> values) {
|
||||||
@ -110,6 +110,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File userFile = new File(usersDir, uuid.toString() + ".yml");
|
File userFile = new File(usersDir, uuid.toString() + ".yml");
|
||||||
|
registerFileAction("users", userFile);
|
||||||
if (userFile.exists()) {
|
if (userFile.exists()) {
|
||||||
return readMapFromFile(userFile, values -> {
|
return readMapFromFile(userFile, values -> {
|
||||||
// User exists, let's load.
|
// User exists, let's load.
|
||||||
@ -159,6 +160,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File userFile = new File(usersDir, user.getUuid().toString() + ".yml");
|
File userFile = new File(usersDir, user.getUuid().toString() + ".yml");
|
||||||
|
registerFileAction("users", userFile);
|
||||||
if (!GenericUserManager.shouldSave(user)) {
|
if (!GenericUserManager.shouldSave(user)) {
|
||||||
if (userFile.exists()) {
|
if (userFile.exists()) {
|
||||||
userFile.delete();
|
userFile.delete();
|
||||||
@ -194,6 +196,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
if (files == null) return false;
|
if (files == null) return false;
|
||||||
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
registerFileAction("users", file);
|
||||||
Map<String, Boolean> nodes = new HashMap<>();
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
readMapFromFile(file, values -> {
|
readMapFromFile(file, values -> {
|
||||||
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||||
@ -235,6 +238,8 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
if (files == null) return false;
|
if (files == null) return false;
|
||||||
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
registerFileAction("users", file);
|
||||||
|
|
||||||
UUID holder = UUID.fromString(file.getName().substring(0, file.getName().length() - 4));
|
UUID holder = UUID.fromString(file.getName().substring(0, file.getName().length() - 4));
|
||||||
Map<String, Boolean> nodes = new HashMap<>();
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
readMapFromFile(file, values -> {
|
readMapFromFile(file, values -> {
|
||||||
@ -264,6 +269,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, name + ".yml");
|
File groupFile = new File(groupsDir, name + ".yml");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
if (groupFile.exists()) {
|
if (groupFile.exists()) {
|
||||||
return readMapFromFile(groupFile, values -> {
|
return readMapFromFile(groupFile, values -> {
|
||||||
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||||
@ -296,6 +302,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, name + ".yml");
|
File groupFile = new File(groupsDir, name + ".yml");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
return groupFile.exists() && readMapFromFile(groupFile, values -> {
|
return groupFile.exists() && readMapFromFile(groupFile, values -> {
|
||||||
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||||
group.setNodes(perms);
|
group.setNodes(perms);
|
||||||
@ -331,6 +338,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
if (!groupFile.exists()) {
|
if (!groupFile.exists()) {
|
||||||
try {
|
try {
|
||||||
groupFile.createNewFile();
|
groupFile.createNewFile();
|
||||||
@ -356,6 +364,7 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
||||||
|
registerFileAction("groups", groupFile);
|
||||||
if (groupFile.exists()) {
|
if (groupFile.exists()) {
|
||||||
groupFile.delete();
|
groupFile.delete();
|
||||||
}
|
}
|
||||||
@ -374,6 +383,8 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
if (files == null) return false;
|
if (files == null) return false;
|
||||||
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
registerFileAction("groups", file);
|
||||||
|
|
||||||
String holder = file.getName().substring(0, file.getName().length() - 4);
|
String holder = file.getName().substring(0, file.getName().length() - 4);
|
||||||
Map<String, Boolean> nodes = new HashMap<>();
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
readMapFromFile(file, values -> {
|
readMapFromFile(file, values -> {
|
||||||
@ -403,6 +414,8 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, name + ".yml");
|
File trackFile = new File(tracksDir, name + ".yml");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
if (trackFile.exists()) {
|
if (trackFile.exists()) {
|
||||||
return readMapFromFile(trackFile, values -> {
|
return readMapFromFile(trackFile, values -> {
|
||||||
track.setGroups((List<String>) values.get("groups"));
|
track.setGroups((List<String>) values.get("groups"));
|
||||||
@ -435,6 +448,8 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, name + ".yml");
|
File trackFile = new File(tracksDir, name + ".yml");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
return trackFile.exists() && readMapFromFile(trackFile, values -> {
|
return trackFile.exists() && readMapFromFile(trackFile, values -> {
|
||||||
track.setGroups((List<String>) values.get("groups"));
|
track.setGroups((List<String>) values.get("groups"));
|
||||||
return true;
|
return true;
|
||||||
@ -468,6 +483,8 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
if (!trackFile.exists()) {
|
if (!trackFile.exists()) {
|
||||||
try {
|
try {
|
||||||
trackFile.createNewFile();
|
trackFile.createNewFile();
|
||||||
@ -493,6 +510,8 @@ public class YAMLBacking extends FlatfileBacking {
|
|||||||
try {
|
try {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
||||||
|
registerFileAction("tracks", trackFile);
|
||||||
|
|
||||||
if (trackFile.exists()) {
|
if (trackFile.exists()) {
|
||||||
trackFile.delete();
|
trackFile.delete();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||||
|
*
|
||||||
|
* 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 lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardWatchEventKinds;
|
||||||
|
import java.nio.file.WatchEvent;
|
||||||
|
import java.nio.file.WatchKey;
|
||||||
|
import java.nio.file.WatchService;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class FileWatcher implements Runnable {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
|
private final Map<String, WatchedLocation> keyMap;
|
||||||
|
private final Map<String, Long> internalChanges;
|
||||||
|
private WatchService watchService = null;
|
||||||
|
|
||||||
|
public FileWatcher(LuckPermsPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.keyMap = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
this.internalChanges = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
try {
|
||||||
|
this.watchService = plugin.getDataDirectory().toPath().getFileSystem().newWatchService();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subscribe(String id, Path path, Consumer<String> consumer) {
|
||||||
|
if (watchService == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register with a delay to ignore changes made at startup
|
||||||
|
plugin.getScheduler().doAsyncLater(() -> {
|
||||||
|
try {
|
||||||
|
// doesn't need to be atomic
|
||||||
|
if (keyMap.containsKey(id)) {
|
||||||
|
throw new IllegalArgumentException("id already registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
|
||||||
|
keyMap.put(id, new WatchedLocation(path, key, consumer));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, 40L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerChange(String id, String filename) {
|
||||||
|
internalChanges.put(id + "/" + filename, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if (watchService == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
watchService.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long expireTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(4);
|
||||||
|
// was either processed last time, or recently modified by the system.
|
||||||
|
internalChanges.values().removeIf(lastChange -> lastChange < expireTime);
|
||||||
|
|
||||||
|
List<String> expired = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map.Entry<String, WatchedLocation> ent : keyMap.entrySet()) {
|
||||||
|
String id = ent.getKey();
|
||||||
|
Path path = ent.getValue().getPath();
|
||||||
|
WatchKey key = ent.getValue().getKey();
|
||||||
|
|
||||||
|
List<WatchEvent<?>> watchEvents = key.pollEvents();
|
||||||
|
|
||||||
|
for (WatchEvent<?> event : watchEvents) {
|
||||||
|
Path name = (Path) event.context();
|
||||||
|
Path file = path.resolve(name);
|
||||||
|
|
||||||
|
String fileName = name.toString();
|
||||||
|
|
||||||
|
if (internalChanges.containsKey(id + "/" + fileName)) {
|
||||||
|
// This file was modified by the system.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerChange(id, fileName);
|
||||||
|
|
||||||
|
plugin.getLog().info("[FileWatcher] Detected change in file: " + file.toString());
|
||||||
|
|
||||||
|
// Process the change
|
||||||
|
ent.getValue().getFileConsumer().accept(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean valid = key.reset();
|
||||||
|
if (!valid) {
|
||||||
|
new RuntimeException("WatchKey no longer valid: " + key.toString()).printStackTrace();
|
||||||
|
expired.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expired.forEach(keyMap::remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
private static class WatchedLocation {
|
||||||
|
private final Path path;
|
||||||
|
private final WatchKey key;
|
||||||
|
private final Consumer<String> fileConsumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -62,6 +62,7 @@ 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.BufferedRequest;
|
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||||
|
import me.lucko.luckperms.common.utils.FileWatcher;
|
||||||
import me.lucko.luckperms.common.utils.LoggerImpl;
|
import me.lucko.luckperms.common.utils.LoggerImpl;
|
||||||
import me.lucko.luckperms.sponge.commands.SpongeMainCommand;
|
import me.lucko.luckperms.sponge.commands.SpongeMainCommand;
|
||||||
import me.lucko.luckperms.sponge.contexts.WorldCalculator;
|
import me.lucko.luckperms.sponge.contexts.WorldCalculator;
|
||||||
@ -146,6 +147,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
private SpongeGroupManager groupManager;
|
private SpongeGroupManager groupManager;
|
||||||
private TrackManager trackManager;
|
private TrackManager trackManager;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
|
private FileWatcher fileWatcher = null;
|
||||||
private InternalMessagingService messagingService = null;
|
private InternalMessagingService messagingService = null;
|
||||||
private UuidCache uuidCache;
|
private UuidCache uuidCache;
|
||||||
private ApiProvider apiProvider;
|
private ApiProvider apiProvider;
|
||||||
@ -183,6 +185,11 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
// register events
|
// register events
|
||||||
game.getEventManager().registerListeners(this, new SpongeListener(this));
|
game.getEventManager().registerListeners(this, new SpongeListener(this));
|
||||||
|
|
||||||
|
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
|
||||||
|
fileWatcher = new FileWatcher(this);
|
||||||
|
getScheduler().doAsyncRepeating(fileWatcher, 30L);
|
||||||
|
}
|
||||||
|
|
||||||
// initialise datastore
|
// initialise datastore
|
||||||
storage = StorageFactory.getInstance(this, StorageType.H2);
|
storage = StorageFactory.getInstance(this, StorageType.H2);
|
||||||
|
|
||||||
@ -309,6 +316,10 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
|||||||
getLog().info("Closing datastore...");
|
getLog().info("Closing datastore...");
|
||||||
storage.shutdown();
|
storage.shutdown();
|
||||||
|
|
||||||
|
if (fileWatcher != null) {
|
||||||
|
fileWatcher.close();
|
||||||
|
}
|
||||||
|
|
||||||
if (messagingService != null) {
|
if (messagingService != null) {
|
||||||
getLog().info("Closing messaging service...");
|
getLog().info("Closing messaging service...");
|
||||||
messagingService.close();
|
messagingService.close();
|
||||||
|
@ -138,6 +138,12 @@ meta-formatting {
|
|||||||
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
|
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
|
||||||
storage-method="h2"
|
storage-method="h2"
|
||||||
|
|
||||||
|
# When using a file-based storage type, LuckPerms can monitor the data files for changes, and then schedule automatic
|
||||||
|
# updates when changes are detected.
|
||||||
|
#
|
||||||
|
# If you don't want this to happen, set this option to false.
|
||||||
|
watch-files=true
|
||||||
|
|
||||||
# This block enables support for split datastores.
|
# This block enables support for split datastores.
|
||||||
split-storage {
|
split-storage {
|
||||||
enabled=false
|
enabled=false
|
||||||
@ -165,9 +171,14 @@ data {
|
|||||||
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
|
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
|
||||||
table_prefix="luckperms_"
|
table_prefix="luckperms_"
|
||||||
|
|
||||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
# This option controls how frequently LuckPerms will perform a sync task.
|
||||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
# A sync task will refresh all data from the storage, and ensure that the most up-to-date data is being used by the plugin.
|
||||||
sync-minutes=3
|
#
|
||||||
|
# This is disabled by default, as most users will not need it. However, if you're using a remote storage type
|
||||||
|
# without a messaging service setup, you may wish to set this value to something like 3.
|
||||||
|
#
|
||||||
|
# Set to -1 to disable the task completely.
|
||||||
|
sync-minutes=-1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Settings for the messaging service
|
# Settings for the messaging service
|
||||||
|
Loading…
Reference in New Issue
Block a user