mirror of
https://github.com/Multiverse/Multiverse-Core.git
synced 2025-02-13 19:11:38 +01:00
feat: Fully implement working migration and validation
This commit is contained in:
parent
358404b407
commit
cd260b0f5e
@ -5,8 +5,9 @@ import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.EnchancedValueNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.EnhancedValueNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import io.github.townyadvanced.commentedconfiguration.CommentedConfiguration;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
|
||||
@ -78,7 +79,7 @@ public class ConfigHandle {
|
||||
return false;
|
||||
}
|
||||
migrateConfig();
|
||||
addDefaultNodes();
|
||||
parseAllNodes();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -112,22 +113,26 @@ public class ConfigHandle {
|
||||
/**
|
||||
* Adds default node values to the configuration if they are not already present.
|
||||
*/
|
||||
protected void addDefaultNodes() {
|
||||
if (nodes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CommentedConfiguration tempConfig = new CommentedConfiguration(configPath, logger);
|
||||
protected void parseAllNodes() {
|
||||
CommentedConfiguration oldConfig = config;
|
||||
this.config = new CommentedConfiguration(configPath, logger);
|
||||
for (CommentedNode node : nodes) {
|
||||
Logging.config("Parsing node: %s", node.getPath());
|
||||
if (node.getComments().length > 0) {
|
||||
tempConfig.addComment(node.getPath(), node.getComments());
|
||||
config.addComment(node.getPath(), node.getComments());
|
||||
}
|
||||
if (node instanceof ValueNode) {
|
||||
tempConfig.set(node.getPath(), get((ValueNode) node));
|
||||
if (node instanceof TypedValueNode typedNode) {
|
||||
if (!set(typedNode, oldConfig.getObject(node.getPath(), typedNode.getType(), typedNode.getDefaultValue()))) {
|
||||
Logging.warning("Invalid value for node: %s, resetting to default...", node.getPath());
|
||||
setDefault(typedNode);
|
||||
}
|
||||
} else if (node instanceof ValueNode valueNode) {
|
||||
if (!set(valueNode, oldConfig.get(node.getPath(), valueNode.getDefaultValue()))) {
|
||||
Logging.warning("Invalid value for node: %s, resetting to default...", node.getPath());
|
||||
setDefault(valueNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.config = tempConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,8 +215,8 @@ public class ConfigHandle {
|
||||
* @param value The value to set.
|
||||
*/
|
||||
public boolean set(@NotNull ValueNode node, Object value) {
|
||||
if (node instanceof TypedValueNode) {
|
||||
return set(node, value);
|
||||
if (node instanceof TypedValueNode typedValueNode) {
|
||||
return set(typedValueNode, value);
|
||||
}
|
||||
config.set(node.getPath(), value);
|
||||
return true;
|
||||
@ -225,8 +230,8 @@ public class ConfigHandle {
|
||||
* @param <T> The type of the node value.
|
||||
*/
|
||||
public <T> boolean set(@NotNull TypedValueNode<T> node, T value) {
|
||||
if (node instanceof EnchancedValueNode) {
|
||||
return set((EnchancedValueNode<T>) node, value);
|
||||
if (node instanceof EnhancedValueNode<T> enhancedValueNode) {
|
||||
return set(enhancedValueNode, value);
|
||||
}
|
||||
config.set(node.getPath(), value);
|
||||
return true;
|
||||
@ -240,7 +245,10 @@ public class ConfigHandle {
|
||||
* @return True if the value was set, false otherwise.
|
||||
* @param <T> The type of the node value.
|
||||
*/
|
||||
public <T> boolean set(@NotNull EnchancedValueNode<T> node, T value) {
|
||||
public <T> boolean set(@NotNull EnhancedValueNode<T> node, T value) {
|
||||
if (!node.isValid(value)) {
|
||||
return false;
|
||||
}
|
||||
T oldValue = get(node);
|
||||
config.set(node.getPath(), value);
|
||||
node.onSetValue(oldValue, get(node));
|
||||
@ -251,9 +259,8 @@ public class ConfigHandle {
|
||||
* Sets the default value of a node.
|
||||
*
|
||||
* @param node The node to set the default value of.
|
||||
* @param <T> The type of the node value.
|
||||
*/
|
||||
public <T> void setDefault(@NotNull TypedValueNode<T> node) {
|
||||
public void setDefault(@NotNull ValueNode node) {
|
||||
config.set(node.getPath(), node.getDefaultValue());
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,9 @@ import java.nio.file.Path;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVConfig;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.BooleanMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.IntegerMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.InvertBoolMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.MoveMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.VersionMigrator;
|
||||
@ -43,19 +45,29 @@ public class DefaultMVConfig implements MVConfig {
|
||||
.migrator(ConfigMigrator.builder(MVConfigNodes.VERSION)
|
||||
.addVersionMigrator(VersionMigrator.builder(5.0)
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.enforceaccess", "world.enforce-access"))
|
||||
.addAction(BooleanMigratorAction.of("world.enforce-access"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.prefixchat", "messaging.enable-chat-prefix"))
|
||||
.addAction(BooleanMigratorAction.of("messaging.enable-chat-prefix"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.prefixchatformat", "messaging.chat-prefix-format"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.teleportintercept", "world.teleport-intercept"))
|
||||
.addAction(BooleanMigratorAction.of("world.teleport-intercept"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.firstspawnoverride", "spawn.first-spawn-override"))
|
||||
.addAction(BooleanMigratorAction.of("spawn.first-spawn-override"))
|
||||
//.addAction(MoveMigratorAction.of("multiverse-configuration.displaypermerrors", ""))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.globaldebug", "misc.global-debug"))
|
||||
.addAction(IntegerMigratorAction.of("misc.global-debug"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.silentstart", "misc.silent-start"))
|
||||
.addAction(BooleanMigratorAction.of("misc.silent-start"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.firstspawnworld", "spawn.first-spawn-location"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.defaultportalsearch", "portal.use-custom-portal-search"))
|
||||
.addAction(BooleanMigratorAction.of("portal.use-custom-portal-search"))
|
||||
.addAction(InvertBoolMigratorAction.of("portal.use-custom-portal-search"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.portalsearchradius", "portal.custom-portal-search-radius"))
|
||||
.addAction(IntegerMigratorAction.of("portal.custom-portal-search-radius"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.autopurge", "world.auto-purge-entities"))
|
||||
.addAction(BooleanMigratorAction.of("world.auto-purge-entities"))
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.idonotwanttodonate", "misc.show-donation-message"))
|
||||
.addAction(BooleanMigratorAction.of("misc.show-donation-message"))
|
||||
.addAction(InvertBoolMigratorAction.of("misc.show-donation-message"))
|
||||
.build())
|
||||
.build())
|
||||
|
@ -119,6 +119,7 @@ public class MVConfigNodes {
|
||||
.comment("This only applies if use-custom-portal-search is set to true.")
|
||||
.defaultValue(128)
|
||||
.name("custom-portal-search-radius")
|
||||
.validator(value -> value >= 0)
|
||||
.build());
|
||||
|
||||
private static final MVCommentedNode MESSAGING_HEADER = node(MVCommentedNode.builder("messaging")
|
||||
@ -164,6 +165,7 @@ public class MVConfigNodes {
|
||||
.comment(" 3 = finest")
|
||||
.defaultValue(0)
|
||||
.name("global-debug")
|
||||
.validator(value -> value >= 0 && value <= 3)
|
||||
.onSetValue((oldValue, newValue) -> Logging.setDebugLevel(newValue))
|
||||
.build());
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
|
||||
/**
|
||||
* Single migrator action that converts a string value to a boolean.
|
||||
*/
|
||||
public class BooleanMigratorAction implements MigratorAction {
|
||||
|
||||
public static BooleanMigratorAction of(String path) {
|
||||
return new BooleanMigratorAction(path);
|
||||
}
|
||||
|
||||
private final String path;
|
||||
|
||||
protected BooleanMigratorAction(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(ConfigHandle settings) {
|
||||
settings.getConfig().set(path, ACFUtil.isTruthy(settings.getConfig().getString(path, "")));
|
||||
Logging.info("Converted %s to boolean %s", path, settings.getConfig().getBoolean(path));
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class ConfigMigrator {
|
||||
double versionNumber = settings.get(versionNode);
|
||||
for (VersionMigrator versionMigrator : versionMigrators) {
|
||||
if (versionNumber < versionMigrator.getVersion()) {
|
||||
Logging.config("Migrating config from version %s to %s...", versionNumber, versionMigrator.getVersion());
|
||||
Logging.info("Migrating config from version %s to %s...", versionNumber, versionMigrator.getVersion());
|
||||
versionMigrator.migrate(settings);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
/**
|
||||
* Single migrator action that converts a string value to an integer.
|
||||
*/
|
||||
public class IntegerMigratorAction implements MigratorAction {
|
||||
|
||||
public static IntegerMigratorAction of(String path) {
|
||||
return new IntegerMigratorAction(path);
|
||||
}
|
||||
|
||||
private final String path;
|
||||
|
||||
public IntegerMigratorAction(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(ConfigHandle settings) {
|
||||
settings.getConfig().set(path, ACFUtil.parseInt(settings.getConfig().getString(path)));
|
||||
Logging.info("Converted %s to integer %s", path, settings.getConfig().getInt(path));
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
|
||||
/**
|
||||
@ -28,6 +29,8 @@ public class InvertBoolMigratorAction implements MigratorAction {
|
||||
*/
|
||||
@Override
|
||||
public void migrate(ConfigHandle settings) {
|
||||
settings.getConfig().set(path, !settings.getConfig().getBoolean(path));
|
||||
boolean boolValue = !settings.getConfig().getBoolean(path);
|
||||
settings.getConfig().set(path, boolValue);
|
||||
Logging.info("Inverted %s to boolean %s", path, boolValue);
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import java.util.Optional;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode;
|
||||
|
||||
/**
|
||||
* A {@link TypedValueNode} that has a name.
|
||||
* A {@link TypedValueNode} that has a name, validation, and action to be performed when the value is set.
|
||||
*
|
||||
* @param <T> The type of the node's value.
|
||||
*/
|
||||
public interface EnchancedValueNode<T> extends TypedValueNode<T> {
|
||||
public interface EnhancedValueNode<T> extends TypedValueNode<T> {
|
||||
/**
|
||||
* Gets the name of this node. Used for identifying the node from user input.
|
||||
*
|
||||
@ -17,5 +17,13 @@ public interface EnchancedValueNode<T> extends TypedValueNode<T> {
|
||||
*/
|
||||
Optional<String> getName();
|
||||
|
||||
boolean isValid(T value);
|
||||
|
||||
/**
|
||||
* Called when the value of this node is set.
|
||||
*
|
||||
* @param oldValue The old value.
|
||||
* @param newValue The new value.
|
||||
*/
|
||||
void onSetValue(T oldValue, T newValue);
|
||||
}
|
@ -2,15 +2,16 @@ package com.onarandombox.MultiverseCore.configuration.node;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Implementation of {@link EnchancedValueNode}.
|
||||
* Implementation of {@link EnhancedValueNode}.
|
||||
* @param <T> The type of the value.
|
||||
*/
|
||||
public class MVValueNode<T> extends MVCommentedNode implements EnchancedValueNode<T> {
|
||||
public class MVValueNode<T> extends MVCommentedNode implements EnhancedValueNode<T> {
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link MVValueNode}.
|
||||
@ -27,13 +28,15 @@ public class MVValueNode<T> extends MVCommentedNode implements EnchancedValueNod
|
||||
protected final Class<T> type;
|
||||
protected final T defaultValue;
|
||||
protected final String name;
|
||||
protected final Function<T, Boolean> validator;
|
||||
protected final BiConsumer<T, T> onSetValue;
|
||||
|
||||
protected MVValueNode(String path, String[] comments, Class<T> type, T defaultValue, String name, BiConsumer<T, T> onSetValue) {
|
||||
protected MVValueNode(String path, String[] comments, Class<T> type, T defaultValue, String name, Function<T, Boolean> validator, BiConsumer<T, T> onSetValue) {
|
||||
super(path, comments);
|
||||
this.type = type;
|
||||
this.defaultValue = defaultValue;
|
||||
this.name = name;
|
||||
this.validator = validator;
|
||||
this.onSetValue = onSetValue;
|
||||
}
|
||||
|
||||
@ -61,9 +64,25 @@ public class MVValueNode<T> extends MVCommentedNode implements EnchancedValueNod
|
||||
return Optional.ofNullable(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid(T value) {
|
||||
if (validator != null) {
|
||||
return validator.apply(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onSetValue(T oldValue, T newValue) {
|
||||
onSetValue.accept(oldValue, newValue);
|
||||
if (onSetValue != null) {
|
||||
onSetValue.accept(oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,6 +96,7 @@ public class MVValueNode<T> extends MVCommentedNode implements EnchancedValueNod
|
||||
protected final Class<T> type;
|
||||
protected T defaultValue;
|
||||
protected String name;
|
||||
protected Function<T, Boolean> validator;
|
||||
protected BiConsumer<T, T> onSetValue;
|
||||
|
||||
/**
|
||||
@ -113,6 +133,17 @@ public class MVValueNode<T> extends MVCommentedNode implements EnchancedValueNod
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
public B validator(@Nullable Function<T, Boolean> validator) {
|
||||
this.validator = validator;
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action to be performed when the value is set.
|
||||
*
|
||||
* @param onSetValue The action to be performed.
|
||||
* @return This builder.
|
||||
*/
|
||||
public B onSetValue(@Nullable BiConsumer<T, T> onSetValue) {
|
||||
this.onSetValue = onSetValue;
|
||||
return (B) this;
|
||||
@ -123,7 +154,7 @@ public class MVValueNode<T> extends MVCommentedNode implements EnchancedValueNod
|
||||
*/
|
||||
@Override
|
||||
public MVValueNode<T> build() {
|
||||
return new MVValueNode<>(path, comments.toArray(new String[0]), type, defaultValue, name, onSetValue);
|
||||
return new MVValueNode<>(path, comments.toArray(new String[0]), type, defaultValue, name, validator, onSetValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,14 +29,14 @@ public class NodeGroup implements Collection<CommentedNode> {
|
||||
}
|
||||
|
||||
private void addNodeIndex(CommentedNode node) {
|
||||
if (node instanceof EnchancedValueNode) {
|
||||
((EnchancedValueNode<?>) node).getName().ifPresent(name -> nodesMap.put(name, node));
|
||||
if (node instanceof EnhancedValueNode) {
|
||||
((EnhancedValueNode<?>) node).getName().ifPresent(name -> nodesMap.put(name, node));
|
||||
}
|
||||
}
|
||||
|
||||
private void removeNodeIndex(CommentedNode node) {
|
||||
if (node instanceof EnchancedValueNode) {
|
||||
((EnchancedValueNode<?>) node).getName().ifPresent(nodesMap::remove);
|
||||
if (node instanceof EnhancedValueNode) {
|
||||
((EnhancedValueNode<?>) node).getName().ifPresent(nodesMap::remove);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user