Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework plugin config system #596

Merged
merged 26 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d4bdade
Rework plugin config system
DerEchtePilz Aug 20, 2024
2c698f8
Use a loop instead of a Stream
DerEchtePilz Aug 21, 2024
9ca2efe
We want stacktraces
DerEchtePilz Aug 21, 2024
77029d2
Include generated config.yml in the documentation
DerEchtePilz Aug 23, 2024
6bdc2fd
Address code review
DerEchtePilz Sep 5, 2024
86b3f27
Use a LinkedHashMap for config options
DerEchtePilz Sep 5, 2024
3140b23
First iteration of an extendable and testable config system
DerEchtePilz Sep 7, 2024
78b1f7c
Update config system to be platform agnostic
DerEchtePilz Sep 15, 2024
a21e635
Clean up dependencies
DerEchtePilz Sep 15, 2024
a0bd0ef
Fix stuff
DerEchtePilz Sep 22, 2024
90fac61
Annotations
DerEchtePilz Sep 22, 2024
5b8886a
Fix Annotations
DerEchtePilz Sep 22, 2024
460a466
Fix more stuff
DerEchtePilz Sep 23, 2024
25b040e
Fix defaults in config.md
DerEchtePilz Sep 23, 2024
7d2ef1e
Simplify a thing
DerEchtePilz Sep 23, 2024
beeca43
Fix VelocityConfigurationAdapter#getKeys()
DerEchtePilz Sep 23, 2024
32b7eed
Don't update the Velocity config if not necessary
DerEchtePilz Sep 23, 2024
e1c35d7
Clean up Velocity plugin class
DerEchtePilz Sep 24, 2024
be6dfa3
Create static method to create a dummy instance
DerEchtePilz Sep 25, 2024
0e0d2d5
Remove Velocity config file
DerEchtePilz Sep 25, 2024
2698520
Introduce common modules to not include config classes in API modules
DerEchtePilz Sep 26, 2024
aa0d977
Remove unnecessary dependency
DerEchtePilz Sep 28, 2024
bff49cd
Move more common classes into the common module
DerEchtePilz Sep 28, 2024
677d545
Inline some stuff
DerEchtePilz Sep 28, 2024
f66e16c
Address code review
DerEchtePilz Oct 7, 2024
392d77f
More code review
DerEchtePilz Oct 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>dev.jorel</groupId>
<artifactId>commandapi-bukkit</artifactId>
<version>9.6.0-SNAPSHOT</version>
</parent>

<artifactId>commandapi-bukkit-plugin-common</artifactId>
DerEchtePilz marked this conversation as resolved.
Show resolved Hide resolved

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-Xlint</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<!-- to avoid bugs in some situations -->
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<!-- create report during maven verify phase -->
<execution>
<id>report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>papermc-repo</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>dev.jorel</groupId>
<artifactId>commandapi-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.jorel</groupId>
<artifactId>commandapi-bukkit-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package dev.jorel.commandapi.config;

import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Logger;

public record BukkitConfigurationAdapter(YamlConfiguration config) implements ConfigurationAdapter<YamlConfiguration> {

public static BukkitConfigurationAdapter createDummyInstance() {
return new BukkitConfigurationAdapter(null);
}

@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<String> comments = new ArrayList<>(config.getComments(key));
comments.removeIf(Objects::isNull);
return comments.toArray(new String[0]);
}

@Override
public Set<String> getKeys() {
Set<String> keys = new HashSet<>(config.getKeys(true));
keys.removeIf(config::isConfigurationSection);
return keys;
}

@Override
public boolean contains(String key) {
return config.contains(key);
}

@Override
public void tryCreateSection(String key, DefaultConfig defaultedBukkitConfig) {
if (!key.contains(".")) {
return;
}

// Collect config keys
Set<String> keys = getKeys();
keys.removeIf(k -> !config.isConfigurationSection(k));
DerEchtePilz marked this conversation as resolved.
Show resolved Hide resolved

// Collect sections
String[] paths = key.split("\\.");
List<String> sectionCandidates = new ArrayList<>(Arrays.asList(paths).subList(0, paths.length - 1));
DerEchtePilz marked this conversation as resolved.
Show resolved Hide resolved

// Create new sections
ConfigurationSection section = null;
StringBuilder pathSoFar = new StringBuilder();
for (String sectionCandidate : sectionCandidates) {
DerEchtePilz marked this conversation as resolved.
Show resolved Hide resolved
if (pathSoFar.isEmpty()) {
pathSoFar.append(sectionCandidate);
} else {
pathSoFar.append(".").append(sectionCandidate);
}

if (keys.contains(sectionCandidate) && section == null) {
section = config.getConfigurationSection(sectionCandidate);
} else if (section == null) {
section = config.createSection(sectionCandidate);
config.setComments(pathSoFar.toString(), Arrays.asList(defaultedBukkitConfig.getAllSections().get(pathSoFar.toString()).comment()));
} else {
ConfigurationSection currentSection = section.getConfigurationSection(sectionCandidate);
if (currentSection == null) {
section = section.createSection(sectionCandidate);
config.setComments(pathSoFar.toString(), Arrays.asList(defaultedBukkitConfig.getAllSections().get(pathSoFar.toString()).comment()));
} else {
section = currentSection;
}
}
}
}

@Override
public ConfigurationAdapter<YamlConfiguration> complete() {
String[] configStrings = config.saveToString().split("\n");
StringBuilder configBuilder = new StringBuilder();
for (String configString : configStrings) {
configBuilder.append(configString).append("\n");
if (!configString.contains("#")) {
configBuilder.append("\n");
}
}
try {
config.loadFromString(configBuilder.toString());
} catch (InvalidConfigurationException e) {
e.printStackTrace(System.err);
}
return this;
}

@Override
public ConfigurationAdapter<YamlConfiguration> createNew() {
return new BukkitConfigurationAdapter(new YamlConfiguration());
}

@Override
public void saveDefaultConfig(File directory, File configFile, Logger logger) {
DerEchtePilz marked this conversation as resolved.
Show resolved Hide resolved
ConfigGenerator configGenerator = ConfigGenerator.createNew(DefaultBukkitConfig.createDefault());
if (!directory.exists()) {
directory.mkdir();
try {
ConfigurationAdapter<YamlConfiguration> bukkitConfigurationAdapter = new BukkitConfigurationAdapter(new YamlConfiguration());
configGenerator.populateDefaultConfig(bukkitConfigurationAdapter);
bukkitConfigurationAdapter.config().save(configFile);
} catch (Exception e) {
logger.severe("Could not create default config file! This is (probably) a bug.");
logger.severe("Error message: " + e.getMessage());
logger.severe("Stacktrace:");
for (StackTraceElement element : e.getStackTrace()) {
logger.severe(element.toString());
}
}
return;
}
// Update the config if necessary
try {
YamlConfiguration existingYamlConfig = YamlConfiguration.loadConfiguration(configFile);
ConfigurationAdapter<YamlConfiguration> existingConfig = new BukkitConfigurationAdapter(existingYamlConfig);
ConfigurationAdapter<YamlConfiguration> updatedConfig = configGenerator.generateWithNewValues(existingConfig);
if (updatedConfig == null) {
return;
}
updatedConfig.config().save(configFile);
} catch (Exception e) {
logger.severe("Could not update config! This is (probably) a bug.");
logger.severe("Error message: " + e.getMessage());
logger.severe("Stacktrace:");
for (StackTraceElement element : e.getStackTrace()) {
logger.severe(element.toString());
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package dev.jorel.commandapi.config;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class DefaultBukkitConfig extends DefaultConfig {

public static final CommentedConfigOption<Boolean> USE_LATEST_NMS_VERSION = new CommentedConfigOption<>(
new String[] {
"Use latest version (default: false)",
"If \"true\", the CommandAPI will use the latest available NMS implementation",
"when the CommandAPI is used. This avoids all checks to see if the latest NMS",
"implementation is actually compatible with the current Minecraft version."
}, false
);

public static final CommentedConfigOption<Boolean> BE_LENIENT_FOR_MINOR_VERSIONS = new CommentedConfigOption<>(
new String[] {
"Be lenient with version checks when loading for new minor Minecraft versions (default: false)",
"If \"true\", the CommandAPI loads NMS implementations for potentially unsupported Minecraft versions.",
"For example, this setting may allow updating from 1.21.1 to 1.21.2 as only the minor version is changing",
"but will not allow an update from 1.21.2 to 1.22.",
"Keep in mind that implementations may vary and actually updating the CommandAPI might be necessary."
}, false
);

public static final CommentedConfigOption<Boolean> SHOULD_HOOK_PAPER_RELOAD = new CommentedConfigOption<>(
new String[] {
"Hook into Paper's ServerResourcesReloadedEvent (default: true)",
"If \"true\", and the CommandAPI detects it is running on a Paper server, it will",
"hook into Paper's ServerResourcesReloadedEvent to detect when /minecraft:reload is run.",
"This allows the CommandAPI to automatically call its custom datapack-reloading",
"function which allows CommandAPI commands to be used in datapacks.",
"If you set this to false, CommandAPI commands may not work inside datapacks after",
"reloading datapacks."
}, true
);

public static final CommentedConfigOption<Boolean> SKIP_RELOAD_DATAPACKS = new CommentedConfigOption<>(
new String[] {
"Skips the initial datapack reload when the server loads (default: false)",
"If \"true\", the CommandAPI will not reload datapacks when the server has finished",
"loading. Datapacks will still be reloaded if performed manually when \"hook-paper-reload\"",
"is set to \"true\" and /minecraft:reload is run."
}, false
);

public static final CommentedConfigOption<List<?>> PLUGINS_TO_CONVERT = new CommentedConfigOption<>(
new String[] {
"Plugins to convert (default: [])",
"Controls the list of plugins to process for command conversion."
}, new ArrayList<>()
);

public static final CommentedConfigOption<List<String>> OTHER_COMMANDS_TO_CONVERT = new CommentedConfigOption<>(
new String[] {
"Other commands to convert (default: [])",
"A list of other commands to convert. This should be used for commands which",
"are not declared in a plugin.yml file."
}, new ArrayList<>()
);

public static final CommentedConfigOption<List<String>> SKIP_SENDER_PROXY = new CommentedConfigOption<>(
new String[] {
"Skip sender proxy (default: [])",
"Determines whether the proxy sender should be skipped when converting a",
"command. If you are having issues with plugin command conversion, add the",
"plugin to this list."
}, new ArrayList<>()
);

private DefaultBukkitConfig() {
}

public static DefaultBukkitConfig createDefault() {
Map<String, CommentedConfigOption<?>> options = new LinkedHashMap<>();
options.put("verbose-outputs", VERBOSE_OUTPUTS);
options.put("silent-logs", SILENT_LOGS);
options.put("messages.missing-executor-implementation", MISSING_EXECUTOR_IMPLEMENTATION);
options.put("create-dispatcher-json", CREATE_DISPATCHER_JSON);
options.put("use-latest-nms-version", USE_LATEST_NMS_VERSION);
options.put("be-lenient-for-minor-versions", BE_LENIENT_FOR_MINOR_VERSIONS);
options.put("hook-paper-reload", SHOULD_HOOK_PAPER_RELOAD);
options.put("skip-initial-datapack-reload", SKIP_RELOAD_DATAPACKS);
options.put("plugins-to-convert", PLUGINS_TO_CONVERT);
options.put("other-commands-to-convert", OTHER_COMMANDS_TO_CONVERT);
options.put("skip-sender-proxy", SKIP_SENDER_PROXY);

Map<String, CommentedSection> sections = new LinkedHashMap<>();
sections.put("messages", SECTION_MESSAGE);

return DefaultBukkitConfig.create(options, sections);
}

public static DefaultBukkitConfig create(Map<String, CommentedConfigOption<?>> options, Map<String, CommentedSection> sections) {
DefaultBukkitConfig config = new DefaultBukkitConfig();

config.allOptions.putAll(options);
config.allSections.putAll(sections);

return config;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@
<version>${paper.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>dev.jorel</groupId>
<artifactId>commandapi-bukkit-plugin-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
Loading
Loading