From 7759a37b4ec8105e7eded05e9eff13a4ad611bd0 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 23 Mar 2023 23:59:19 +0800 Subject: [PATCH] feat: Implement config names and basic config command --- .../MultiverseCore/MultiverseCore.java | 8 +-- .../MultiverseCore/api/MVConfig.java | 8 +++ .../commands/ConfigCommand.java | 50 +++++++++++++++ .../configuration/DefaultMVConfig.java | 27 +++++++- .../configuration/MVConfigNodes.java | 8 ++- .../utils/settings/MVSettings.java | 63 ++++++++++++++----- .../utils/settings/node/MVValueNode.java | 24 +++++-- .../utils/settings/node/NamedValueNode.java | 7 +++ .../{NodesCollection.java => NodeGroup.java} | 51 +++++++++++++-- 9 files changed, 214 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NamedValueNode.java rename src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/{NodesCollection.java => NodeGroup.java} (52%) diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java index 9590c94f..631c7495 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java @@ -23,6 +23,7 @@ import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.commands.CheckCommand; import com.onarandombox.MultiverseCore.commands.CloneCommand; +import com.onarandombox.MultiverseCore.commands.ConfigCommand; import com.onarandombox.MultiverseCore.commands.ConfirmCommand; import com.onarandombox.MultiverseCore.commands.CreateCommand; import com.onarandombox.MultiverseCore.commands.DebugCommand; @@ -89,7 +90,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore { private final MVWorldManager worldManager = new SimpleMVWorldManager(this); // Configurations - private DefaultMVConfig config; + private MVConfig config; // Listeners private MVChatListener chatListener; @@ -196,6 +197,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore { this.commandManager = new MVCommandManager(this); this.commandManager.registerCommand(new CheckCommand(this)); this.commandManager.registerCommand(new CloneCommand(this)); + this.commandManager.registerCommand(new ConfigCommand(this)); this.commandManager.registerCommand(new ConfirmCommand(this)); this.commandManager.registerCommand(new CreateCommand(this)); this.commandManager.registerCommand(new DebugCommand(this)); @@ -369,9 +371,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore { */ @Override public void loadConfigs() { - config = new DefaultMVConfig(this); - config.load(); - config.save(); + config = DefaultMVConfig.init(this); this.worldManager.loadWorldConfig(new File(getDataFolder(), "worlds.yml")); diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java index 46029486..1180de5c 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java @@ -1,6 +1,14 @@ package com.onarandombox.MultiverseCore.api; public interface MVConfig { + boolean load(); + + void save(); + + Object getProperty(String name); + + void setProperty(String name, Object value); + /** * Sets enforceAccess. * @param enforceAccess The new value. diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java new file mode 100644 index 00000000..2888e6c4 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java @@ -0,0 +1,50 @@ +package com.onarandombox.MultiverseCore.commands; + +import co.aikar.commands.BukkitCommandIssuer; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandCompletion; +import co.aikar.commands.annotation.CommandPermission; +import co.aikar.commands.annotation.Description; +import co.aikar.commands.annotation.Optional; +import co.aikar.commands.annotation.Single; +import co.aikar.commands.annotation.Subcommand; +import co.aikar.commands.annotation.Syntax; +import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.MVConfig; +import org.jetbrains.annotations.NotNull; + +@CommandAlias("mv") +public class ConfigCommand extends MultiverseCoreCommand { + private final MVConfig config; + + public ConfigCommand(@NotNull MultiverseCore plugin) { + super(plugin); + this.config = plugin.getMVConfig(); + } + + @Subcommand("config") + @CommandPermission("multiverse.core.config") + @CommandCompletion("@mvconfig") //TODO + @Syntax(" [new-value]") + @Description("") //TODO + public void onConfigCommand(BukkitCommandIssuer issuer, + + @Syntax("") + @Description("") //TODO + String name, + + @Optional + @Single + @Syntax("[new-value]") + @Description("") //TODO + String value + ) { + if (value == null) { + issuer.sendMessage(name + "is currently set to " + config.getProperty(name)); + return; + } + config.setProperty(name, value); + config.save(); + issuer.sendMessage("Set " + name + " to " + value); + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java b/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java index 16e6c2b4..a8988b27 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java +++ b/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java @@ -17,6 +17,19 @@ public class DefaultMVConfig implements MVConfig { public static final String CONFIG_FILENAME = "config.yml"; public static final double CONFIG_VERSION = 5.0; + /** + * Creates a new DefaultMVConfig instance and loads the configuration automatically. + * + * @param core The MultiverseCore instance. + * @return The new DefaultMVConfig instance. + */ + public static DefaultMVConfig init(MultiverseCore core) { + var config = new DefaultMVConfig(core); + config.load(); + config.save(); + return config; + } + private final Path configPath; private final MVSettings settings; @@ -27,7 +40,7 @@ public class DefaultMVConfig implements MVConfig { settings = MVSettings.builder(configPath) .logger(Logging.getLogger()) - .defaultNodes(MVConfigNodes.getNodes()) + .nodes(MVConfigNodes.getNodes()) .migrator(ConfigMigrator.builder(MVConfigNodes.VERSION) .addVersionMigrator(VersionMigrator.builder(5.0) .addAction(MoveMigratorAction.of("multiverse-configuration.enforceaccess", "world.enforce-access")) @@ -67,14 +80,26 @@ public class DefaultMVConfig implements MVConfig { } } + @Override public boolean load() { return settings.load(); } + @Override public void save() { settings.save(); } + @Override + public Object getProperty(String name) { + return settings.get(name); + } + + @Override + public void setProperty(String name, Object value) { + settings.set(name, value); + } + @Override public void setEnforceAccess(boolean enforceAccess) { settings.set(MVConfigNodes.ENFORCE_ACCESS, enforceAccess); diff --git a/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java b/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java index d6d7f91e..3ce3ebfc 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java +++ b/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java @@ -1,16 +1,18 @@ package com.onarandombox.MultiverseCore.configuration; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import com.onarandombox.MultiverseCore.utils.settings.node.MVCommentedNode; import com.onarandombox.MultiverseCore.utils.settings.node.MVValueNode; +import com.onarandombox.MultiverseCore.utils.settings.node.NodeGroup; import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode; public class MVConfigNodes { - private static final List nodes = new ArrayList<>(); + private static final NodeGroup nodes = new NodeGroup(); - public static List getNodes() { + public static NodeGroup getNodes() { return nodes; } @@ -54,6 +56,7 @@ public class MVConfigNodes { .comment("If this is set to true, players will only be able to enter worlds they have") .comment("the `mv.access.` permission.") .defaultValue(false) + .name("enforce-access") .build()); public static final MVValueNode ENFORCE_GAMEMODE = node(MVValueNode.builder("world.enforce-gamemode", Boolean.class) @@ -166,5 +169,6 @@ public class MVConfigNodes { .comment("This just signifies the version number so we can see what version of config you have.") .comment("NEVER TOUCH THIS VALUE") .defaultValue(DefaultMVConfig.CONFIG_VERSION) + .name(null) .build()); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/MVSettings.java b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/MVSettings.java index f983bca1..fe9898df 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/MVSettings.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/MVSettings.java @@ -3,10 +3,11 @@ package com.onarandombox.MultiverseCore.utils.settings; import java.io.File; import java.io.IOException; import java.nio.file.Path; -import java.util.List; +import java.util.Collection; import java.util.logging.Logger; import com.onarandombox.MultiverseCore.utils.settings.migration.ConfigMigrator; +import com.onarandombox.MultiverseCore.utils.settings.node.NodeGroup; import io.github.townyadvanced.commentedconfiguration.CommentedConfiguration; import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode; import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode; @@ -27,7 +28,7 @@ public class MVSettings { protected final Path configPath; protected final Logger logger; - protected final List defaultNodes; + protected final NodeGroup nodes; protected final ConfigMigrator migrator; @@ -38,12 +39,12 @@ public class MVSettings { * * @param configPath The path to the configuration file. * @param logger The Logger to use for error messages. - * @param defaultNodes The default node values to add to the configuration. + * @param nodes All the node path and values for the configuration. * @param migrator The migrator to use for migrating the configuration. */ - protected MVSettings(@NotNull Path configPath, @Nullable Logger logger, @Nullable List defaultNodes, ConfigMigrator migrator) { + protected MVSettings(@NotNull Path configPath, @Nullable Logger logger, @NotNull NodeGroup nodes, ConfigMigrator migrator) { this.configPath = configPath; - this.defaultNodes = defaultNodes; + this.nodes = nodes; this.logger = logger; this.migrator = migrator; } @@ -86,6 +87,9 @@ public class MVSettings { return true; } + /** + * Migration of the configuration based on {@link ConfigMigrator}. + */ protected void migrateConfig() { migrator.migrate(this); } @@ -94,17 +98,16 @@ public class MVSettings { * Adds default node values to the configuration if they are not already present. */ protected void addDefaultNodes() { - if (defaultNodes == null || defaultNodes.isEmpty()) { + if (nodes.isEmpty()) { return; } CommentedConfiguration tempConfig = new CommentedConfiguration(configPath, logger); - for (CommentedNode node : defaultNodes) { + for (CommentedNode node : nodes) { if (node.getComments().length > 0) { tempConfig.addComment(node.getPath(), node.getComments()); } - if (node instanceof ValueNode) { - ValueNode valueNode = (ValueNode) node; + if (node instanceof ValueNode valueNode) { tempConfig.set(node.getPath(), get(valueNode)); } } @@ -133,6 +136,18 @@ public class MVSettings { return config.get(node.getPath(), node.getDefaultValue()); } + /** + * Get the value of the node by name. + * + * @param name The name of the node to get the value of. + * @return The value of the node. + */ + public Object get(@NotNull String name) { + return nodes.findNode(name) + .map(node -> (node instanceof ValueNode valueNode) ? get(valueNode) : null) + .orElse(null); + } + /** * Gets the value of a node, if the node has a default value, it will be returned if the node is not found. * @@ -166,6 +181,20 @@ public class MVSettings { config.set(node.getPath(), value); } + /** + * Set the value of the node by name. + * + * @param name The name of the node to set the value of. + * @param value The value to set. + */ + public void set(@NotNull String name, Object value) { + nodes.findNode(name).ifPresent(node -> { + if (node instanceof ValueNode valueNode) { + set(valueNode, value); + } + }); + } + /** * Sets the value of a node, if the validator is not null, it will be tested first. * @@ -177,12 +206,18 @@ public class MVSettings { config.set(node.getPath(), value); } + /** + * Sets the default value of a node. + * + * @param node The node to set the default value of. + * @param The type of the node value. + */ public void setDefault(@NotNull TypedValueNode node) { config.set(node.getPath(), node.getDefaultValue()); } /** - * Gets the configuration object. + * Gets the inner configuration object. * * @return The configuration object. */ @@ -194,7 +229,7 @@ public class MVSettings { private final Path configPath; private Logger logger; - private List defaultNodes; + private NodeGroup nodes; private ConfigMigrator migrator; @@ -215,8 +250,8 @@ public class MVSettings { return this; } - public Builder defaultNodes(@Nullable List defaultNodes) { - this.defaultNodes = defaultNodes; + public Builder nodes(@Nullable NodeGroup nodes) { + this.nodes = nodes; return this; } @@ -226,7 +261,7 @@ public class MVSettings { } public MVSettings build() { - return new MVSettings(configPath, logger, defaultNodes, migrator); + return new MVSettings(configPath, logger, nodes, migrator); } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/MVValueNode.java b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/MVValueNode.java index c96b6fe6..b97e0c84 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/MVValueNode.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/MVValueNode.java @@ -1,23 +1,23 @@ package com.onarandombox.MultiverseCore.utils.settings.node; -import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class MVValueNode extends MVCommentedNode implements TypedValueNode { +public class MVValueNode extends MVCommentedNode implements NamedValueNode { public static Builder builder(String path, Class type) { return new Builder<>(path, type); } protected final Class type; + protected final T defaultValue; + protected final String name; - private final T defaultValue; - - protected MVValueNode(String path, String[] comments, Class type, T defaultValue) { + protected MVValueNode(String path, String[] comments, Class type, T defaultValue, String name) { super(path, comments); this.type = type; this.defaultValue = defaultValue; + this.name = name; } @Override @@ -30,14 +30,21 @@ public class MVValueNode extends MVCommentedNode implements TypedValueNode return defaultValue; } + @Override + public String getName() { + return name; + } + public static class Builder> extends MVCommentedNode.Builder { protected final Class type; protected T defaultValue; + private String name; public Builder(String path, Class type) { super(path); this.type = type; + this.name = path; } public B defaultValue(T defaultValue) { @@ -45,9 +52,14 @@ public class MVValueNode extends MVCommentedNode implements TypedValueNode return (B) this; } + public B name(String name) { + this.name = name; + return (B) this; + } + @Override public MVValueNode build() { - return new MVValueNode<>(path, comments.toArray(new String[0]), type, defaultValue); + return new MVValueNode<>(path, comments.toArray(new String[0]), type, defaultValue, name); } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NamedValueNode.java b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NamedValueNode.java new file mode 100644 index 00000000..712f3418 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NamedValueNode.java @@ -0,0 +1,7 @@ +package com.onarandombox.MultiverseCore.utils.settings.node; + +import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode; + +public interface NamedValueNode extends TypedValueNode { + String getName(); +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NodesCollection.java b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NodeGroup.java similarity index 52% rename from src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NodesCollection.java rename to src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NodeGroup.java index d06493a6..187f5d71 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NodesCollection.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/node/NodeGroup.java @@ -1,18 +1,51 @@ package com.onarandombox.MultiverseCore.utils.settings.node; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import com.dumptruckman.minecraft.util.Logging; import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode; import org.jetbrains.annotations.NotNull; -public class NodesCollection implements Collection { +public class NodeGroup implements Collection { private final Collection nodes; + private final Map nodesMap; - public NodesCollection(Collection nodes) { - this.nodes = nodes; + public NodeGroup() { + this.nodes = new ArrayList<>(); + this.nodesMap = new HashMap<>(); } + public NodeGroup(Collection nodes) { + this.nodes = nodes; + this.nodesMap = new HashMap<>(nodes.size()); + nodes.forEach(this::addNodeIndex); + } + + private void addNodeIndex(CommentedNode node) { + if (node instanceof NamedValueNode namedValueNode && namedValueNode.getName() != null) { + nodesMap.put(namedValueNode.getName(), node); + } + } + + private void removeNodeIndex(CommentedNode node) { + if (node instanceof NamedValueNode namedValueNode) { + nodesMap.remove(namedValueNode.getName()); + } + } + + public Collection getNames() { + return nodesMap.keySet(); + } + + public Optional findNode(String name) { + return Optional.ofNullable(nodesMap.get(name)); + } @Override public int size() { @@ -49,12 +82,20 @@ public class NodesCollection implements Collection { @Override public boolean add(CommentedNode commentedNode) { - return nodes.add(commentedNode); + if (nodes.add(commentedNode)) { + addNodeIndex(commentedNode); + return true; + } + return false; } @Override public boolean remove(Object o) { - return nodes.remove(o); + if (nodes.remove(o) && o instanceof CommentedNode) { + removeNodeIndex((CommentedNode) o); + return true; + } + return false; } @Override