Skip to content

Commit 0739a4f

Browse files
authored
Merge pull request CommandAPI#596 from JorelAli/dev/config-experiment
Rework plugin config system
2 parents 68ed69e + 392d77f commit 0739a4f

File tree

29 files changed

+874
-763
lines changed

29 files changed

+874
-763
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>dev.jorel</groupId>
9+
<artifactId>commandapi-bukkit</artifactId>
10+
<version>9.6.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>commandapi-bukkit-plugin-common</artifactId>
14+
15+
<build>
16+
<plugins>
17+
<plugin>
18+
<groupId>org.apache.maven.plugins</groupId>
19+
<artifactId>maven-compiler-plugin</artifactId>
20+
<configuration>
21+
<compilerArgs>
22+
<arg>-Xlint</arg>
23+
</compilerArgs>
24+
</configuration>
25+
</plugin>
26+
<plugin>
27+
<groupId>org.jacoco</groupId>
28+
<artifactId>jacoco-maven-plugin</artifactId>
29+
<executions>
30+
<!-- to avoid bugs in some situations -->
31+
<execution>
32+
<id>default-prepare-agent</id>
33+
<goals>
34+
<goal>prepare-agent</goal>
35+
</goals>
36+
</execution>
37+
<!-- create report during maven verify phase -->
38+
<execution>
39+
<id>report</id>
40+
<phase>verify</phase>
41+
<goals>
42+
<goal>report</goal>
43+
</goals>
44+
</execution>
45+
</executions>
46+
</plugin>
47+
</plugins>
48+
</build>
49+
50+
<repositories>
51+
<repository>
52+
<id>papermc-repo</id>
53+
<url>https://repo.papermc.io/repository/maven-public/</url>
54+
</repository>
55+
<repository>
56+
<id>sonatype</id>
57+
<url>https://oss.sonatype.org/content/groups/public/</url>
58+
</repository>
59+
</repositories>
60+
61+
<dependencies>
62+
<dependency>
63+
<groupId>io.papermc.paper</groupId>
64+
<artifactId>paper-api</artifactId>
65+
<version>1.21.1-R0.1-SNAPSHOT</version>
66+
<scope>provided</scope>
67+
</dependency>
68+
<dependency>
69+
<groupId>dev.jorel</groupId>
70+
<artifactId>commandapi-plugin</artifactId>
71+
<version>${project.version}</version>
72+
</dependency>
73+
<dependency>
74+
<groupId>dev.jorel</groupId>
75+
<artifactId>commandapi-bukkit-core</artifactId>
76+
<version>${project.version}</version>
77+
<scope>provided</scope>
78+
</dependency>
79+
</dependencies>
80+
</project>

commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/AdvancedConverter.java renamed to commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-common/src/main/java/dev/jorel/commandapi/AdvancedConverter.java

File renamed without changes.

commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/CommandAPIMain.java renamed to commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-common/src/main/java/dev/jorel/commandapi/CommandAPIMain.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,19 @@
2020
*******************************************************************************/
2121
package dev.jorel.commandapi;
2222

23-
import java.io.File;
24-
import java.util.HashMap;
25-
import java.util.List;
26-
import java.util.Map;
27-
import java.util.Map.Entry;
28-
23+
import dev.jorel.commandapi.config.BukkitConfigurationAdapter;
2924
import org.bukkit.Bukkit;
3025
import org.bukkit.configuration.file.FileConfiguration;
3126
import org.bukkit.plugin.InvalidPluginException;
3227
import org.bukkit.plugin.Plugin;
3328
import org.bukkit.plugin.java.JavaPlugin;
3429

30+
import java.io.File;
31+
import java.util.HashMap;
32+
import java.util.List;
33+
import java.util.Map;
34+
import java.util.Map.Entry;
35+
3536
/**
3637
* Main CommandAPI plugin entrypoint
3738
*/
@@ -133,4 +134,18 @@ private JavaPlugin getAndValidatePlugin(String pluginName) {
133134
public void onEnable() {
134135
CommandAPI.onEnable();
135136
}
137+
138+
/**
139+
* In contrast to the superclass' method {@link org.bukkit.plugin.java.JavaPlugin#saveDefaultConfig()},
140+
* this doesn't fail silently if the config.yml already exists but instead will update the config with
141+
* new values if available.
142+
* <p>
143+
* This should fail silently if all values are set already.
144+
*/
145+
@Override
146+
public void saveDefaultConfig() {
147+
File configFile = new File(getDataFolder(), "config.yml");
148+
BukkitConfigurationAdapter.createDummyInstance().saveDefaultConfig(getDataFolder(), configFile, getLogger());
149+
}
150+
136151
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package dev.jorel.commandapi.config;
2+
3+
import org.bukkit.configuration.ConfigurationSection;
4+
import org.bukkit.configuration.InvalidConfigurationException;
5+
import org.bukkit.configuration.file.YamlConfiguration;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.util.ArrayList;
10+
import java.util.Arrays;
11+
import java.util.HashSet;
12+
import java.util.List;
13+
import java.util.Objects;
14+
import java.util.Set;
15+
import java.util.logging.Logger;
16+
17+
public record BukkitConfigurationAdapter(YamlConfiguration config) implements ConfigurationAdapter<YamlConfiguration> {
18+
19+
public static BukkitConfigurationAdapter createDummyInstance() {
20+
return new BukkitConfigurationAdapter(null);
21+
}
22+
23+
@Override
24+
public void setValue(String key, Object value) {
25+
config.set(key, value);
26+
}
27+
28+
@Override
29+
public void setComment(String key, String[] comment) {
30+
config.setComments(key, Arrays.asList(comment));
31+
}
32+
33+
@Override
34+
public Object getValue(String key) {
35+
return config.get(key);
36+
}
37+
38+
@Override
39+
public String[] getComment(String key) {
40+
List<String> comments = new ArrayList<>(config.getComments(key));
41+
comments.removeIf(Objects::isNull);
42+
return comments.toArray(new String[0]);
43+
}
44+
45+
@Override
46+
public Set<String> getKeys() {
47+
Set<String> keys = new HashSet<>(config.getKeys(true));
48+
keys.removeIf(config::isConfigurationSection);
49+
return keys;
50+
}
51+
52+
@Override
53+
public boolean contains(String key) {
54+
return config.contains(key);
55+
}
56+
57+
@Override
58+
public void tryCreateSection(String key) {
59+
if (!key.contains(".")) {
60+
return;
61+
}
62+
63+
// Collect config keys
64+
Set<String> keys = config.getKeys(true);
65+
keys.removeIf(k -> !config.isConfigurationSection(k));
66+
67+
// Collect sections
68+
String[] sectionCandidates = key.split("\\.");
69+
sectionCandidates = Arrays.copyOf(sectionCandidates, sectionCandidates.length - 1);
70+
71+
// Create new sections
72+
ConfigurationSection section = null;
73+
for (String sectionCandidate : sectionCandidates) {
74+
if (keys.contains(sectionCandidate) && section == null) {
75+
section = config.getConfigurationSection(sectionCandidate);
76+
} else if (section == null) {
77+
section = config.createSection(sectionCandidate);
78+
} else {
79+
ConfigurationSection currentSection = section.getConfigurationSection(sectionCandidate);
80+
if (currentSection == null) {
81+
section = section.createSection(sectionCandidate);
82+
} else {
83+
section = currentSection;
84+
}
85+
}
86+
}
87+
}
88+
89+
@Override
90+
public ConfigurationAdapter<YamlConfiguration> complete() {
91+
String[] configStrings = config.saveToString().split("\n");
92+
StringBuilder configBuilder = new StringBuilder();
93+
for (String configString : configStrings) {
94+
configBuilder.append(configString).append("\n");
95+
if (!configString.contains("#")) {
96+
configBuilder.append("\n");
97+
}
98+
}
99+
try {
100+
config.loadFromString(configBuilder.toString());
101+
} catch (InvalidConfigurationException e) {
102+
e.printStackTrace(System.err);
103+
}
104+
return this;
105+
}
106+
107+
@Override
108+
public ConfigurationAdapter<YamlConfiguration> createNew() {
109+
return new BukkitConfigurationAdapter(new YamlConfiguration());
110+
}
111+
112+
@Override
113+
public void saveDefaultConfig(File directory, File configFile, Logger logger) {
114+
ConfigGenerator configGenerator = ConfigGenerator.createNew(DefaultBukkitConfig.createDefault());
115+
if (!directory.exists()) {
116+
boolean createdDirectory = directory.mkdirs();
117+
if (!createdDirectory) {
118+
logger.severe("Failed to create directory for the CommandAPI's config.yml file!");
119+
}
120+
try {
121+
ConfigurationAdapter<YamlConfiguration> bukkitConfigurationAdapter = new BukkitConfigurationAdapter(new YamlConfiguration());
122+
configGenerator.populateDefaultConfig(bukkitConfigurationAdapter);
123+
bukkitConfigurationAdapter.config().save(configFile);
124+
} catch (IOException e) {
125+
logger.severe("Could not create default config file! This is (probably) a bug.");
126+
logger.severe("Error message: " + e.getMessage());
127+
logger.severe("Stacktrace:");
128+
for (StackTraceElement element : e.getStackTrace()) {
129+
logger.severe(element.toString());
130+
}
131+
}
132+
return;
133+
}
134+
// Update the config if necessary
135+
try {
136+
YamlConfiguration existingYamlConfig = YamlConfiguration.loadConfiguration(configFile);
137+
ConfigurationAdapter<YamlConfiguration> existingConfig = new BukkitConfigurationAdapter(existingYamlConfig);
138+
ConfigurationAdapter<YamlConfiguration> updatedConfig = configGenerator.generateWithNewValues(existingConfig);
139+
if (updatedConfig == null) {
140+
return;
141+
}
142+
updatedConfig.config().save(configFile);
143+
} catch (IOException e) {
144+
logger.severe("Could not update config! This is (probably) a bug.");
145+
logger.severe("Error message: " + e.getMessage());
146+
logger.severe("Stacktrace:");
147+
for (StackTraceElement element : e.getStackTrace()) {
148+
logger.severe(element.toString());
149+
}
150+
}
151+
}
152+
153+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package dev.jorel.commandapi.config;
2+
3+
import java.util.ArrayList;
4+
import java.util.LinkedHashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
public class DefaultBukkitConfig extends DefaultConfig {
9+
10+
public static final CommentedConfigOption<Boolean> USE_LATEST_NMS_VERSION = new CommentedConfigOption<>(
11+
new String[] {
12+
"Use latest version (default: false)",
13+
"If \"true\", the CommandAPI will use the latest available NMS implementation",
14+
"when the CommandAPI is used. This avoids all checks to see if the latest NMS",
15+
"implementation is actually compatible with the current Minecraft version."
16+
}, false
17+
);
18+
19+
public static final CommentedConfigOption<Boolean> BE_LENIENT_FOR_MINOR_VERSIONS = new CommentedConfigOption<>(
20+
new String[] {
21+
"Be lenient with version checks when loading for new minor Minecraft versions (default: false)",
22+
"If \"true\", the CommandAPI loads NMS implementations for potentially unsupported Minecraft versions.",
23+
"For example, this setting may allow updating from 1.21.1 to 1.21.2 as only the minor version is changing",
24+
"but will not allow an update from 1.21.2 to 1.22.",
25+
"Keep in mind that implementations may vary and actually updating the CommandAPI might be necessary."
26+
}, false
27+
);
28+
29+
public static final CommentedConfigOption<Boolean> SHOULD_HOOK_PAPER_RELOAD = new CommentedConfigOption<>(
30+
new String[] {
31+
"Hook into Paper's ServerResourcesReloadedEvent (default: true)",
32+
"If \"true\", and the CommandAPI detects it is running on a Paper server, it will",
33+
"hook into Paper's ServerResourcesReloadedEvent to detect when /minecraft:reload is run.",
34+
"This allows the CommandAPI to automatically call its custom datapack-reloading",
35+
"function which allows CommandAPI commands to be used in datapacks.",
36+
"If you set this to false, CommandAPI commands may not work inside datapacks after",
37+
"reloading datapacks."
38+
}, true
39+
);
40+
41+
public static final CommentedConfigOption<Boolean> SKIP_RELOAD_DATAPACKS = new CommentedConfigOption<>(
42+
new String[] {
43+
"Skips the initial datapack reload when the server loads (default: false)",
44+
"If \"true\", the CommandAPI will not reload datapacks when the server has finished",
45+
"loading. Datapacks will still be reloaded if performed manually when \"hook-paper-reload\"",
46+
"is set to \"true\" and /minecraft:reload is run."
47+
}, false
48+
);
49+
50+
public static final CommentedConfigOption<List<?>> PLUGINS_TO_CONVERT = new CommentedConfigOption<>(
51+
new String[] {
52+
"Plugins to convert (default: [])",
53+
"Controls the list of plugins to process for command conversion."
54+
}, new ArrayList<>()
55+
);
56+
57+
public static final CommentedConfigOption<List<String>> OTHER_COMMANDS_TO_CONVERT = new CommentedConfigOption<>(
58+
new String[] {
59+
"Other commands to convert (default: [])",
60+
"A list of other commands to convert. This should be used for commands which",
61+
"are not declared in a plugin.yml file."
62+
}, new ArrayList<>()
63+
);
64+
65+
public static final CommentedConfigOption<List<String>> SKIP_SENDER_PROXY = new CommentedConfigOption<>(
66+
new String[] {
67+
"Skip sender proxy (default: [])",
68+
"Determines whether the proxy sender should be skipped when converting a",
69+
"command. If you are having issues with plugin command conversion, add the",
70+
"plugin to this list."
71+
}, new ArrayList<>()
72+
);
73+
74+
private DefaultBukkitConfig() {
75+
}
76+
77+
public static DefaultBukkitConfig createDefault() {
78+
Map<String, CommentedConfigOption<?>> options = new LinkedHashMap<>();
79+
options.put("verbose-outputs", VERBOSE_OUTPUTS);
80+
options.put("silent-logs", SILENT_LOGS);
81+
options.put("messages.missing-executor-implementation", MISSING_EXECUTOR_IMPLEMENTATION);
82+
options.put("create-dispatcher-json", CREATE_DISPATCHER_JSON);
83+
options.put("use-latest-nms-version", USE_LATEST_NMS_VERSION);
84+
options.put("be-lenient-for-minor-versions", BE_LENIENT_FOR_MINOR_VERSIONS);
85+
options.put("hook-paper-reload", SHOULD_HOOK_PAPER_RELOAD);
86+
options.put("skip-initial-datapack-reload", SKIP_RELOAD_DATAPACKS);
87+
options.put("plugins-to-convert", PLUGINS_TO_CONVERT);
88+
options.put("other-commands-to-convert", OTHER_COMMANDS_TO_CONVERT);
89+
options.put("skip-sender-proxy", SKIP_SENDER_PROXY);
90+
91+
Map<String, CommentedSection> sections = new LinkedHashMap<>();
92+
sections.put("messages", SECTION_MESSAGE);
93+
94+
return DefaultBukkitConfig.create(options, sections);
95+
}
96+
97+
public static DefaultBukkitConfig create(Map<String, CommentedConfigOption<?>> options, Map<String, CommentedSection> sections) {
98+
DefaultBukkitConfig config = new DefaultBukkitConfig();
99+
100+
config.allOptions.putAll(options);
101+
config.allSections.putAll(sections);
102+
103+
return config;
104+
}
105+
}

commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/exceptions/InvalidNumberException.java renamed to commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-common/src/main/java/dev/jorel/commandapi/exceptions/InvalidNumberException.java

File renamed without changes.

commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/src/main/java/dev/jorel/commandapi/exceptions/UnknownArgumentException.java renamed to commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-common/src/main/java/dev/jorel/commandapi/exceptions/UnknownArgumentException.java

File renamed without changes.

commandapi-platforms/commandapi-bukkit/commandapi-bukkit-plugin-mojang-mapped/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@
8585
<version>${paper.version}</version>
8686
<scope>provided</scope>
8787
</dependency>
88+
<dependency>
89+
<groupId>dev.jorel</groupId>
90+
<artifactId>commandapi-bukkit-plugin-common</artifactId>
91+
<version>${project.version}</version>
92+
</dependency>
8893
</dependencies>
8994

9095
<build>

0 commit comments

Comments
 (0)