diff --git a/commandapi-core/pom.xml b/commandapi-core/pom.xml
index 25f7e2958f..099f1a69a5 100644
--- a/commandapi-core/pom.xml
+++ b/commandapi-core/pom.xml
@@ -65,12 +65,20 @@
${project.version}
provided
+
+
org.jetbrains
annotations
24.1.0
provided
+
+ org.spongepowered
+ configurate-yaml
+ 4.1.2
+ provided
+
diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/config/ConfigGenerator.java b/commandapi-core/src/main/java/dev/jorel/commandapi/config/ConfigGenerator.java
new file mode 100644
index 0000000000..53dd09ec99
--- /dev/null
+++ b/commandapi-core/src/main/java/dev/jorel/commandapi/config/ConfigGenerator.java
@@ -0,0 +1,79 @@
+package dev.jorel.commandapi.config;
+
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+
+@ApiStatus.Internal
+public class ConfigGenerator {
+
+ private final DefaultedConfig defaultedConfig;
+
+ private ConfigGenerator(DefaultedConfig defaultedConfig) {
+ this.defaultedConfig = defaultedConfig;
+ }
+
+ public static ConfigGenerator createNew(DefaultedConfig defaultedConfig) {
+ return new ConfigGenerator(defaultedConfig);
+ }
+
+ public void populateDefaultConfig(ConfigurationAdapter adapter) {
+ for (Map.Entry> commentedConfigOption : defaultedConfig.getAllOptions().entrySet()) {
+ adapter.setValue(commentedConfigOption.getKey(), commentedConfigOption.getValue().option());
+ adapter.setComment(commentedConfigOption.getKey(), commentedConfigOption.getValue().comment().toArray(new String[0]));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public ConfigurationAdapter generateWithNewValues(ConfigurationAdapter existingConfig) {
+ ConfigurationAdapter updatedConfig = existingConfig.createNew();
+
+ boolean shouldRemoveValues = shouldRemoveOptions(existingConfig);
+
+ boolean wasConfigUpdated = false;
+ for (Map.Entry> commentedConfigOption : defaultedConfig.getAllOptions().entrySet()) {
+ String path = commentedConfigOption.getKey();
+
+ // Update config option
+ if (existingConfig.contains(path)) {
+ updatedConfig.tryCreateSection(path, (C) defaultedConfig);
+ updatedConfig.setValue(path, existingConfig.getValue(path));
+ } else {
+ wasConfigUpdated = true;
+ updatedConfig.tryCreateSection(path, (C) defaultedConfig);
+ updatedConfig.setValue(path, commentedConfigOption.getValue().option());
+ }
+
+ // Update config option comment
+ String[] defaultComment = commentedConfigOption.getValue().comment().toArray(new String[0]);
+ String[] configComment = existingConfig.getComment(path);
+
+ if (!Arrays.equals(defaultComment, configComment)) {
+ wasConfigUpdated = true;
+ }
+
+ updatedConfig.setComment(path, commentedConfigOption.getValue().comment().toArray(new String[0]));
+ }
+ if (shouldRemoveValues) {
+ wasConfigUpdated = true;
+ }
+ return (wasConfigUpdated) ? updatedConfig : null;
+ }
+
+ private boolean shouldRemoveOptions(ConfigurationAdapter config) {
+ Set configOptions = config.getKeys();
+ Set defaultConfigOptions = defaultedConfig.getAllOptions().keySet();
+
+ boolean shouldRemoveOptions = false;
+ for (String option : configOptions) {
+ if (!defaultConfigOptions.contains(option)) {
+ shouldRemoveOptions = true;
+ break;
+ }
+ }
+ return shouldRemoveOptions;
+ }
+
+}
diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/config/ConfigurationAdapter.java b/commandapi-core/src/main/java/dev/jorel/commandapi/config/ConfigurationAdapter.java
new file mode 100644
index 0000000000..1815a8d219
--- /dev/null
+++ b/commandapi-core/src/main/java/dev/jorel/commandapi/config/ConfigurationAdapter.java
@@ -0,0 +1,28 @@
+package dev.jorel.commandapi.config;
+
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.Set;
+
+@ApiStatus.Internal
+public interface ConfigurationAdapter {
+
+ void setValue(String key, Object value);
+
+ void setComment(String key, String[] comment);
+
+ Object getValue(String key);
+
+ String[] getComment(String key);
+
+ Set getKeys();
+
+ boolean contains(String key);
+
+ void tryCreateSection(String key, DefaultConfiguration defaultConfiguration);
+
+ Configuration config();
+
+ ConfigurationAdapter createNew();
+
+}
diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/config/DefaultedConfig.java b/commandapi-core/src/main/java/dev/jorel/commandapi/config/DefaultedConfig.java
index a1c1105233..c8cc709c1b 100644
--- a/commandapi-core/src/main/java/dev/jorel/commandapi/config/DefaultedConfig.java
+++ b/commandapi-core/src/main/java/dev/jorel/commandapi/config/DefaultedConfig.java
@@ -10,8 +10,8 @@
@ApiStatus.Internal
public abstract class DefaultedConfig {
- final Map> allOptions = new LinkedHashMap<>();
- final Map allSections = new LinkedHashMap<>();
+ protected final Map> allOptions = new LinkedHashMap<>();
+ protected final Map allSections = new LinkedHashMap<>();
public static final CommentedConfigOption VERBOSE_OUTPUTS = new CommentedConfigOption<>(
List.of(
@@ -46,4 +46,19 @@ public abstract class DefaultedConfig {
), false
);
+ public static final CommentedSection SECTION_MESSAGE = new CommentedSection(
+ List.of(
+ "Messages",
+ "Controls messages that the CommandAPI displays to players"
+ )
+ );
+
+ public final Map> getAllOptions() {
+ return allOptions;
+ }
+
+ public final Map getAllSections() {
+ return allSections;
+ }
+
}
diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/BukkitConfigurationAdapter.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/BukkitConfigurationAdapter.java
new file mode 100644
index 0000000000..888c087ec5
--- /dev/null
+++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/BukkitConfigurationAdapter.java
@@ -0,0 +1,103 @@
+package dev.jorel.commandapi.config;
+
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+@ApiStatus.Internal
+public record BukkitConfigurationAdapter(YamlConfiguration config) implements ConfigurationAdapter {
+
+ @Override
+ public void setValue(String key, Object value) {
+ config.set(key, value);
+ }
+
+ @Override
+ public void setComment(String key, String[] comment) {
+ config.setComments(key, Arrays.asList(comment));
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return config.get(key);
+ }
+
+ @Override
+ public String[] getComment(String key) {
+ List comments = config.getStringList(key);
+ comments.removeIf(Objects::isNull);
+ return comments.toArray(new String[0]);
+ }
+
+ @Override
+ public Set getKeys() {
+ return config.getKeys(false);
+ }
+
+ @Override
+ public boolean contains(String key) {
+ return config.contains(key);
+ }
+
+ @Override
+ public void tryCreateSection(String key, DefaultedBukkitConfig defaultedBukkitConfig) {
+ if (!key.contains(".")) {
+ return;
+ }
+
+ // Collect config keys
+ Set keys = getKeys();
+ keys.removeIf(k -> !config.isConfigurationSection(k));
+
+ // Collect sections
+ String[] paths = key.split("\\.");
+ List sectionCandidates = new ArrayList<>(Arrays.asList(paths).subList(0, paths.length - 1));
+
+ // Create new sections
+ ConfigurationSection root = null;
+ StringBuilder pathSoFar = new StringBuilder();
+ for (String sectionCandidate : sectionCandidates) {
+ if (pathSoFar.isEmpty()) {
+ pathSoFar.append(sectionCandidate);
+ } else {
+ pathSoFar.append(".").append(sectionCandidate);
+ }
+ if (keys.contains(sectionCandidate) && root == null) {
+ root = config.getConfigurationSection(sectionCandidate);
+ } else if (root == null) {
+ root = config.createSection(sectionCandidate);
+ root.setComments(sectionCandidate, defaultedBukkitConfig.getAllSections().get(pathSoFar.toString()).comment());
+ } else {
+ ConfigurationSection section = root.getConfigurationSection(sectionCandidate);
+ if (section == null) {
+ root = root.createSection(sectionCandidate);
+ root.setComments(sectionCandidate, defaultedBukkitConfig.getAllSections().get(pathSoFar.toString()).comment());
+ } else {
+ root = section;
+ }
+ }
+ }
+ }
+
+ @Override
+ public ConfigurationAdapter createNew() {
+ return new BukkitConfigurationAdapter(new YamlConfiguration());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ BukkitConfigurationAdapter that = (BukkitConfigurationAdapter) o;
+ String thisConfigString = config.saveToString();
+ String thatConfigString = that.config.saveToString();
+ return thisConfigString.equals(thatConfigString);
+ }
+
+}
diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/ConfigGenerator.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/ConfigGenerator.java
deleted file mode 100644
index 38e7925757..0000000000
--- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/ConfigGenerator.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package dev.jorel.commandapi.config;
-
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.jetbrains.annotations.ApiStatus;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-@ApiStatus.Internal
-public class ConfigGenerator {
-
- private final DefaultedBukkitConfig defaultedBukkitConfig;
-
- private ConfigGenerator() {
- this.defaultedBukkitConfig = DefaultedBukkitConfig.createDefault();
- }
-
- private ConfigGenerator(DefaultedBukkitConfig defaultedBukkitConfig) {
- this.defaultedBukkitConfig = defaultedBukkitConfig;
- }
-
- public static ConfigGenerator createNew() {
- return new ConfigGenerator();
- }
-
- public static ConfigGenerator createNew(DefaultedBukkitConfig defaultedBukkitConfig) {
- return new ConfigGenerator(defaultedBukkitConfig);
- }
-
- public YamlConfiguration generateDefaultConfig() throws InvalidConfigurationException {
- YamlConfiguration config = new YamlConfiguration();
- Set sections = new HashSet<>();
- for (Map.Entry> commentedConfigOption : defaultedBukkitConfig.getAllOptions().entrySet()) {
- String path = commentedConfigOption.getKey();
-
- tryCreateSection(config, path, sections);
-
- config.set(path, commentedConfigOption.getValue().option());
- config.setComments(path, commentedConfigOption.getValue().comment());
- }
- return process(config.saveToString());
- }
-
- public YamlConfiguration generateWithNewValues(YamlConfiguration existingConfig) throws InvalidConfigurationException {
- YamlConfiguration config = new YamlConfiguration();
-
- boolean shouldRemoveValues = shouldRemoveOptions(existingConfig);
-
- boolean wasConfigUpdated = false;
- Set sections = new HashSet<>();
- for (Map.Entry> commentedConfigOption : defaultedBukkitConfig.getAllOptions().entrySet()) {
- String path = commentedConfigOption.getKey();
-
- // Update config option
- if (existingConfig.contains(path)) {
- tryCreateSection(config, path, sections);
- config.set(path, existingConfig.get(path));
- } else {
- wasConfigUpdated = true;
- tryCreateSection(config, path, sections);
- config.set(path, commentedConfigOption.getValue().option());
- }
-
- // Update config option comments
- // Comments are kinda stupid, some elements are apparently null elements
- // Also, both, YamlConfiguration#getComments(String) and CommentedConfigOption#comments() return unmodifiable list
- // which by itself apparently aren't able to be checked for equality by the equals() method
- // As a result, we wrap them in new ArrayLists first to be able to compare them
- List existingComment = new ArrayList<>(existingConfig.getComments(path));
- existingComment.removeIf(Objects::isNull);
- List defaultComment = new ArrayList<>(commentedConfigOption.getValue().comment());
-
- if (!existingComment.equals(defaultComment)) {
- wasConfigUpdated = true;
- }
- config.setComments(path, commentedConfigOption.getValue().comment());
- }
- if (shouldRemoveValues) {
- wasConfigUpdated = true;
- }
- return (wasConfigUpdated) ? process(config.saveToString()) : null;
- }
-
- private YamlConfiguration process(String configAsString) throws InvalidConfigurationException {
- String[] configStrings = configAsString.split("\n");
- StringBuilder configBuilder = new StringBuilder();
- for (String configString : configStrings) {
- configBuilder.append(configString).append("\n");
- if (!configString.contains("#")) {
- configBuilder.append("\n");
- }
- }
- YamlConfiguration config = new YamlConfiguration();
- config.loadFromString(configBuilder.toString());
- return config;
- }
-
- private void tryCreateSection(YamlConfiguration config, String path, Set existingSections) {
- if (path.contains(".")) {
- // We have to create a section, or multiple if applicable, first, if it doesn't exist already
- String[] sectionNames = path.split("\\.");
- // The last value is the config option
- for (int i = 0; i < sectionNames.length - 1; i++) {
- String sectionName = sectionNames[i];
- if (!existingSections.contains(sectionName)) {
- config.createSection(sectionName);
- List comment = defaultedBukkitConfig.getAllSections().get(sectionName).comment();
- if (comment != null) {
- config.setComments(sectionName, comment);
- }
- }
- existingSections.add(sectionName);
- }
- }
- }
-
- private boolean shouldRemoveOptions(YamlConfiguration config) {
- Set configOptions = config.getKeys(true);
- configOptions.removeIf(config::isConfigurationSection);
-
- Set defaultConfigOptions = defaultedBukkitConfig.getAllOptions().keySet();
-
- boolean shouldRemoveOptions = false;
- for (String option : configOptions) {
- if (!defaultConfigOptions.contains(option)) {
- shouldRemoveOptions = true;
- break;
- }
- }
- return shouldRemoveOptions;
- }
-
-}
diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/DefaultedBukkitConfig.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/DefaultedBukkitConfig.java
index 847873168a..2f21db861e 100644
--- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/DefaultedBukkitConfig.java
+++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/config/DefaultedBukkitConfig.java
@@ -78,32 +78,28 @@ public class DefaultedBukkitConfig extends DefaultedConfig {
), new ArrayList<>()
);
- public static final CommentedSection SECTION_MESSAGE = new CommentedSection(
- List.of(
- "Messages",
- "Controls messages that the CommandAPI displays to players"
- )
- );
-
- private DefaultedBukkitConfig() {}
+ private DefaultedBukkitConfig() {
+ }
public static DefaultedBukkitConfig createDefault() {
- DefaultedBukkitConfig config = new DefaultedBukkitConfig();
- config.allOptions.put("verbose-outputs", VERBOSE_OUTPUTS);
- config.allOptions.put("silent-logs", SILENT_LOGS);
- config.allOptions.put("messages.missing-executor-implementation", MISSING_EXECUTOR_IMPLEMENTATION);
- config.allOptions.put("create-dispatcher-json", CREATE_DISPATCHER_JSON);
- config.allOptions.put("use-latest-nms-version", USE_LATEST_NMS_VERSION);
- config.allOptions.put("be-lenient-for-minor-versions", BE_LENIENT_FOR_MINOR_VERSIONS);
- config.allOptions.put("hook-paper-reload", SHOULD_HOOK_PAPER_RELOAD);
- config.allOptions.put("skip-initial-datapack-reload", SKIP_RELOAD_DATAPACKS);
- config.allOptions.put("plugins-to-convert", PLUGINS_TO_CONVERT);
- config.allOptions.put("other-commands-to-convert", OTHER_COMMANDS_TO_CONVERT);
- config.allOptions.put("skip-sender-proxy", SKIP_SENDER_PROXY);
-
- config.allSections.put("messages", SECTION_MESSAGE);
-
- return config;
+ return DefaultedBukkitConfig.create(
+ Map.ofEntries(
+ Map.entry("verbose-outputs", VERBOSE_OUTPUTS),
+ Map.entry("silent-logs", SILENT_LOGS),
+ Map.entry("messages.missing-executor-implementation", MISSING_EXECUTOR_IMPLEMENTATION),
+ Map.entry("create-dispatcher-json", CREATE_DISPATCHER_JSON),
+ Map.entry("use-latest-nms-version", USE_LATEST_NMS_VERSION),
+ Map.entry("be-lenient-for-minor-versions", BE_LENIENT_FOR_MINOR_VERSIONS),
+ Map.entry("hook-paper-reload", SHOULD_HOOK_PAPER_RELOAD),
+ Map.entry("skip-initial-datapack-reload", SKIP_RELOAD_DATAPACKS),
+ Map.entry("plugins-to-convert", PLUGINS_TO_CONVERT),
+ Map.entry("other-commands-to-convert", OTHER_COMMANDS_TO_CONVERT),
+ Map.entry("skip-sender-proxy", SKIP_SENDER_PROXY)
+ ),
+ Map.ofEntries(
+ Map.entry("messages", SECTION_MESSAGE)
+ )
+ );
}
public static DefaultedBukkitConfig create(Map> options, Map sections) {
@@ -114,12 +110,4 @@ public static DefaultedBukkitConfig create(Map>
return config;
}
-
- public Map> getAllOptions() {
- return allOptions;
- }
-
- public Map getAllSections() {
- return allSections;
- }
}
diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/CommandAPIMain.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
index 81d28e47bd..066b49c254 100644
--- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
+++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
@@ -20,15 +20,10 @@
*******************************************************************************/
package dev.jorel.commandapi;
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
+import dev.jorel.commandapi.config.BukkitConfigurationAdapter;
import dev.jorel.commandapi.config.ConfigGenerator;
+import dev.jorel.commandapi.config.ConfigurationAdapter;
+import dev.jorel.commandapi.config.DefaultedBukkitConfig;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -36,6 +31,12 @@
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
/**
* Main CommandAPI plugin entrypoint
*/
@@ -148,12 +149,13 @@ public void onEnable() {
@Override
public void saveDefaultConfig() {
File configFile = new File(getDataFolder(), "config.yml");
- ConfigGenerator configGenerator = ConfigGenerator.createNew();
+ ConfigGenerator configGenerator = ConfigGenerator.createNew(DefaultedBukkitConfig.createDefault());
if (!getDataFolder().exists()) {
getDataFolder().mkdir();
try {
- YamlConfiguration defaultConfig = configGenerator.generateDefaultConfig();
- defaultConfig.save(configFile);
+ ConfigurationAdapter bukkitConfigurationAdapter = new BukkitConfigurationAdapter(new YamlConfiguration());
+ configGenerator.populateDefaultConfig(bukkitConfigurationAdapter);
+ bukkitConfigurationAdapter.config().save(configFile);
} catch (Exception e) {
getLogger().severe("Could not create default config file! This is (probably) a bug.");
getLogger().severe("Error message: " + e.getMessage());
@@ -165,13 +167,14 @@ public void saveDefaultConfig() {
return;
}
// Update the config if necessary
- YamlConfiguration existingConfig = YamlConfiguration.loadConfiguration(configFile);
try {
- YamlConfiguration updatedConfig = configGenerator.generateWithNewValues(existingConfig);
+ YamlConfiguration existingYamlConfig = YamlConfiguration.loadConfiguration(configFile);
+ ConfigurationAdapter existingConfig = new BukkitConfigurationAdapter(existingYamlConfig);
+ ConfigurationAdapter updatedConfig = configGenerator.generateWithNewValues(existingConfig);
if (updatedConfig == null) {
return;
}
- updatedConfig.save(configFile);
+ updatedConfig.config().save(configFile);
} catch (Exception e) {
getLogger().severe("Could not update config! This is (probably) a bug.");
getLogger().severe("Error message: " + e.getMessage());
diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
index 0598289227..14be512bb0 100644
--- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
+++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
@@ -27,7 +27,10 @@
import java.util.Map;
import java.util.Map.Entry;
+import dev.jorel.commandapi.config.BukkitConfigurationAdapter;
import dev.jorel.commandapi.config.ConfigGenerator;
+import dev.jorel.commandapi.config.ConfigurationAdapter;
+import dev.jorel.commandapi.config.DefaultedBukkitConfig;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -147,12 +150,13 @@ public void onEnable() {
@Override
public void saveDefaultConfig() {
File configFile = new File(getDataFolder(), "config.yml");
- ConfigGenerator configGenerator = ConfigGenerator.createNew();
+ ConfigGenerator configGenerator = ConfigGenerator.createNew(DefaultedBukkitConfig.createDefault());
if (!getDataFolder().exists()) {
getDataFolder().mkdir();
try {
- YamlConfiguration defaultConfig = configGenerator.generateDefaultConfig();
- defaultConfig.save(configFile);
+ ConfigurationAdapter bukkitConfigurationAdapter = new BukkitConfigurationAdapter(new YamlConfiguration());
+ configGenerator.populateDefaultConfig(bukkitConfigurationAdapter);
+ bukkitConfigurationAdapter.config().save(configFile);
} catch (Exception e) {
getLogger().severe("Could not create default config file! This is (probably) a bug.");
getLogger().severe("Error message: " + e.getMessage());
@@ -164,13 +168,14 @@ public void saveDefaultConfig() {
return;
}
// Update the config if necessary
- YamlConfiguration existingConfig = YamlConfiguration.loadConfiguration(configFile);
try {
- YamlConfiguration updatedConfig = configGenerator.generateWithNewValues(existingConfig);
+ YamlConfiguration existingYamlConfig = YamlConfiguration.loadConfiguration(configFile);
+ ConfigurationAdapter existingConfig = new BukkitConfigurationAdapter(existingYamlConfig);
+ ConfigurationAdapter updatedConfig = configGenerator.generateWithNewValues(existingConfig);
if (updatedConfig == null) {
return;
}
- updatedConfig.save(configFile);
+ updatedConfig.config().save(configFile);
} catch (Exception e) {
getLogger().severe("Could not update config! This is (probably) a bug.");
getLogger().severe("Error message: " + e.getMessage());
diff --git a/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/pom.xml b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/pom.xml
index 230921a3c3..4a4df888b3 100644
--- a/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/pom.xml
+++ b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/pom.xml
@@ -24,7 +24,7 @@
com.velocitypowered
velocity-api
- 3.1.1
+ 3.3.0-SNAPSHOT
provided
diff --git a/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
index b6458cdb61..8f5c838f2e 100644
--- a/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
+++ b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/CommandAPIMain.java
@@ -8,12 +8,17 @@
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
-import ninja.leaping.configurate.ConfigurationNode;
-import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
+import dev.jorel.commandapi.config.ConfigGenerator;
+import dev.jorel.commandapi.config.ConfigurationAdapter;
+import dev.jorel.commandapi.config.DefaultedVelocityConfig;
+import dev.jorel.commandapi.config.VelocityConfigurationAdapter;
+import org.spongepowered.configurate.CommentedConfigurationNode;
+import org.spongepowered.configurate.ConfigurationNode;
+import org.spongepowered.configurate.yaml.NodeStyle;
+import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Logger;
@@ -34,16 +39,35 @@ public class CommandAPIMain {
public CommandAPIMain(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
// Try to find the config file
Path configFile = dataDirectory.resolve("config.yml");
+ YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
+ .nodeStyle(NodeStyle.BLOCK)
+ .path(configFile)
+ .build();
// If the config doesn't exist, load it from the resources
- if(!Files.exists(configFile)) {
+ ConfigGenerator configGenerator = ConfigGenerator.createNew(DefaultedVelocityConfig.createDefault());
+ if (!Files.exists(configFile)) {
try {
Files.createDirectories(configFile.getParent());
} catch (IOException ignored) {
}
- try (InputStream defaultConfig = getClass().getClassLoader().getResourceAsStream("config.yml")) {
- Files.copy(defaultConfig, configFile);
+ try {
+ ConfigurationAdapter velocityConfigurationAdapter = new VelocityConfigurationAdapter(loader, loader.createNode());
+ configGenerator.populateDefaultConfig(velocityConfigurationAdapter);
+ loader.save(velocityConfigurationAdapter.config());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ try {
+ // If the config does exist, update it if necessary
+ CommentedConfigurationNode existingYamlConfig = loader.load();
+ ConfigurationAdapter existingConfig = new VelocityConfigurationAdapter(loader, existingYamlConfig);
+ ConfigurationAdapter updatedConfig = configGenerator.generateWithNewValues(existingConfig);
+ if (updatedConfig != null) {
+ loader.save(updatedConfig.config());
+ }
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -52,17 +76,17 @@ public CommandAPIMain(ProxyServer server, Logger logger, @DataDirectory Path dat
// Load the file as a yaml node
ConfigurationNode configYAML;
try {
- configYAML = YAMLConfigurationLoader.builder().setPath(configFile).build().load();
+ configYAML = loader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
// Configure the CommandAPI
CommandAPIVelocityConfig config = new CommandAPIVelocityConfig(server, this)
- .verboseOutput(configYAML.getNode("verbose-outputs").getBoolean())
- .silentLogs(configYAML.getNode("silent-logs").getBoolean())
- .missingExecutorImplementationMessage(configYAML.getNode("messages", "missing-executor-implementation").getString())
- .dispatcherFile(configYAML.getNode("create-dispatcher-json").getBoolean() ? new File(dataDirectory.toFile(), "command_registration.json") : null);
+ .verboseOutput(configYAML.node("verbose-outputs").getBoolean())
+ .silentLogs(configYAML.node("silent-logs").getBoolean())
+ .missingExecutorImplementationMessage(configYAML.node("messages", "missing-executor-implementation").getString())
+ .dispatcherFile(configYAML.node("create-dispatcher-json").getBoolean() ? new File(dataDirectory.toFile(), "command_registration.json") : null);
// Load
CommandAPI.setLogger(CommandAPILogger.fromJavaLogger(logger));
@@ -74,13 +98,13 @@ public void onProxyInitialization(ProxyInitializeEvent event) {
// Enable
CommandAPI.onEnable();
}
-
+
@Subscribe
public void onProxyShutdown(ProxyShutdownEvent event) {
// Shut down
CommandAPI.onDisable();
}
-
+
// On /velocity reload
@Subscribe
public void onProxyReload(ProxyReloadEvent event) {
diff --git a/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/config/DefaultedVelocityConfig.java b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/config/DefaultedVelocityConfig.java
new file mode 100644
index 0000000000..5027a5a2a6
--- /dev/null
+++ b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/config/DefaultedVelocityConfig.java
@@ -0,0 +1,36 @@
+package dev.jorel.commandapi.config;
+
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.Map;
+
+@SuppressWarnings("ClassEscapesDefinedScope")
+@ApiStatus.Internal
+public class DefaultedVelocityConfig extends DefaultedConfig {
+
+ private DefaultedVelocityConfig() {}
+
+ public static DefaultedVelocityConfig createDefault() {
+ return DefaultedVelocityConfig.create(
+ Map.ofEntries(
+ Map.entry("verbose-outputs", VERBOSE_OUTPUTS),
+ Map.entry("silent-logs", SILENT_LOGS),
+ Map.entry("messages.missing-executor-implementation", MISSING_EXECUTOR_IMPLEMENTATION),
+ Map.entry("create-dispatcher-json", CREATE_DISPATCHER_JSON)
+ ),
+ Map.ofEntries(
+ Map.entry("messages", SECTION_MESSAGE)
+ )
+ );
+ }
+
+ public static DefaultedVelocityConfig create(Map> options, Map sections) {
+ DefaultedVelocityConfig config = new DefaultedVelocityConfig();
+
+ config.allOptions.putAll(options);
+ config.allSections.putAll(sections);
+
+ return config;
+ }
+
+}
diff --git a/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/config/VelocityConfigurationAdapter.java b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/config/VelocityConfigurationAdapter.java
new file mode 100644
index 0000000000..240c81d50a
--- /dev/null
+++ b/commandapi-platforms/commandapi-velocity/commandapi-velocity-plugin/src/main/java/dev/jorel/commandapi/config/VelocityConfigurationAdapter.java
@@ -0,0 +1,100 @@
+package dev.jorel.commandapi.config;
+
+import org.spongepowered.configurate.CommentedConfigurationNode;
+import org.spongepowered.configurate.ConfigurationNode;
+import org.spongepowered.configurate.serialize.SerializationException;
+import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@SuppressWarnings("ConfusingArgumentToVarargsMethod")
+public record VelocityConfigurationAdapter(YamlConfigurationLoader loader, CommentedConfigurationNode config) implements ConfigurationAdapter {
+
+ @Override
+ public void setValue(String key, Object value) {
+ setValue0(key, value);
+ }
+
+ @Override
+ public void setComment(String key, String[] comment) {
+ config.node(key.split("\\.")).comment(String.join("\n", comment));
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return getValue0(key);
+ }
+
+ @SuppressWarnings("DataFlowIssue")
+ @Override
+ public String[] getComment(String key) {
+ return config.node(key.split("\\.")).comment().split("\n");
+ }
+
+ @Override
+ public Set getKeys() {
+ Set keys = new HashSet<>();
+ for (Object key : config.childrenMap().keySet()) {
+ keys.add((String) key);
+ }
+ return keys;
+ }
+
+ @Override
+ public boolean contains(String key) {
+ return !config.node(key.split("\\.")).virtual();
+ }
+
+ @Override
+ public void tryCreateSection(String key, DefaultedVelocityConfig defaultedVelocityConfig) {
+ if (!key.contains(".")) {
+ return;
+ }
+ String[] path = key.split("\\.");
+ List sectionCandidates = new ArrayList<>(Arrays.asList(path).subList(0, path.length - 1));
+
+ StringBuilder pathSoFar = new StringBuilder();
+ for (String section : sectionCandidates) {
+ if (pathSoFar.isEmpty()) {
+ pathSoFar.append(section);
+ } else {
+ pathSoFar.append(".").append(section);
+ }
+ if (config.node(pathSoFar.toString().split("\\.")).comment() == null) {
+ config.node(pathSoFar.toString().split("\\.")).comment(String.join("\n", defaultedVelocityConfig.getAllSections().get(pathSoFar.toString()).comment()));
+ }
+ }
+ }
+
+ @Override
+ public CommentedConfigurationNode config() {
+ return config;
+ }
+
+ @Override
+ public ConfigurationAdapter createNew() {
+ return new VelocityConfigurationAdapter(loader, loader.createNode());
+ }
+
+ private void setValue0(String key, Object value) {
+ try {
+ config.node(key.split("\\.")).set(value);
+ } catch (SerializationException e) {
+ e.printStackTrace(System.err);
+ }
+ }
+
+ private Object getValue0(String key) {
+ try {
+ return config.node(key.split("\\.")).get(Object.class);
+ } catch (SerializationException e) {
+ e.printStackTrace(System.err);
+ return null;
+ }
+ }
+
+}