Skip to content

Commit

Permalink
Update config system to be platform agnostic
Browse files Browse the repository at this point in the history
  • Loading branch information
DerEchtePilz committed Sep 15, 2024
1 parent 311f4ba commit 667a533
Show file tree
Hide file tree
Showing 13 changed files with 457 additions and 206 deletions.
8 changes: 8 additions & 0 deletions commandapi-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,20 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>

<!-- Other dependencies -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>provided</scope>
</dependency>
</dependencies>


Expand Down
Original file line number Diff line number Diff line change
@@ -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 <T, C extends DefaultedConfig> void populateDefaultConfig(ConfigurationAdapter<T, C> adapter) {
for (Map.Entry<String, CommentedConfigOption<?>> 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 <T, C extends DefaultedConfig> ConfigurationAdapter<T, C> generateWithNewValues(ConfigurationAdapter<T, C> existingConfig) {
ConfigurationAdapter<T, C> updatedConfig = existingConfig.createNew();

boolean shouldRemoveValues = shouldRemoveOptions(existingConfig);

boolean wasConfigUpdated = false;
for (Map.Entry<String, CommentedConfigOption<?>> 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 <T, C extends DefaultedConfig> boolean shouldRemoveOptions(ConfigurationAdapter<T, C> config) {
Set<String> configOptions = config.getKeys();
Set<String> defaultConfigOptions = defaultedConfig.getAllOptions().keySet();

boolean shouldRemoveOptions = false;
for (String option : configOptions) {
if (!defaultConfigOptions.contains(option)) {
shouldRemoveOptions = true;
break;
}
}
return shouldRemoveOptions;
}

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

import org.jetbrains.annotations.ApiStatus;

import java.util.Set;

@ApiStatus.Internal
public interface ConfigurationAdapter<Configuration, DefaultConfiguration extends DefaultedConfig> {

void setValue(String key, Object value);

void setComment(String key, String[] comment);

Object getValue(String key);

String[] getComment(String key);

Set<String> getKeys();

boolean contains(String key);

void tryCreateSection(String key, DefaultConfiguration defaultConfiguration);

Configuration config();

ConfigurationAdapter<Configuration, DefaultConfiguration> createNew();

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
@ApiStatus.Internal
public abstract class DefaultedConfig {

final Map<String, CommentedConfigOption<?>> allOptions = new LinkedHashMap<>();
final Map<String, CommentedSection> allSections = new LinkedHashMap<>();
protected final Map<String, CommentedConfigOption<?>> allOptions = new LinkedHashMap<>();
protected final Map<String, CommentedSection> allSections = new LinkedHashMap<>();

public static final CommentedConfigOption<Boolean> VERBOSE_OUTPUTS = new CommentedConfigOption<>(
List.of(
Expand Down Expand Up @@ -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<String, CommentedConfigOption<?>> getAllOptions() {
return allOptions;
}

public final Map<String, CommentedSection> getAllSections() {
return allSections;
}

}
Original file line number Diff line number Diff line change
@@ -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<YamlConfiguration, DefaultedBukkitConfig> {

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

@Override
public Set<String> 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<String> keys = getKeys();
keys.removeIf(k -> !config.isConfigurationSection(k));

// Collect sections
String[] paths = key.split("\\.");
List<String> 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<YamlConfiguration, DefaultedBukkitConfig> 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);
}

}
Loading

0 comments on commit 667a533

Please sign in to comment.