diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java index 1180de5c..c3692d2c 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVConfig.java @@ -7,7 +7,7 @@ public interface MVConfig { Object getProperty(String name); - void setProperty(String name, Object value); + boolean setProperty(String name, Object value); /** * Sets enforceAccess. diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java index 2888e6c4..1d9246a7 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java @@ -11,6 +11,7 @@ import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Syntax; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVConfig; +import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue; import org.jetbrains.annotations.NotNull; @CommandAlias("mv") @@ -24,7 +25,7 @@ public class ConfigCommand extends MultiverseCoreCommand { @Subcommand("config") @CommandPermission("multiverse.core.config") - @CommandCompletion("@mvconfig") //TODO + @CommandCompletion("@mvconfigs") @Syntax(" [new-value]") @Description("") //TODO public void onConfigCommand(BukkitCommandIssuer issuer, @@ -37,14 +38,30 @@ public class ConfigCommand extends MultiverseCoreCommand { @Single @Syntax("[new-value]") @Description("") //TODO - String value + MVConfigValue value ) { if (value == null) { - issuer.sendMessage(name + "is currently set to " + config.getProperty(name)); + showConfigValue(issuer, name); + return; + } + updateConfigValue(issuer, name, value.getValue()); + } + + private void showConfigValue(BukkitCommandIssuer issuer, String name) { + Object currentValue = config.getProperty(name); + if (currentValue == null) { + issuer.sendMessage("No such config option: " + name); + return; + } + issuer.sendMessage(name + "is currently set to " + config.getProperty(name)); + } + + private void updateConfigValue(BukkitCommandIssuer issuer, String name, Object value) { + if (!config.setProperty(name, value)) { + issuer.sendMessage("Unable to set " + name + " to " + value); return; } - config.setProperty(name, value); config.save(); - issuer.sendMessage("Set " + name + " to " + value); + issuer.sendMessage("Successfully set " + name + " to " + value); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java index ff5671d8..70973d87 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java @@ -19,6 +19,7 @@ import com.google.common.collect.Sets; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorldManager; +import com.onarandombox.MultiverseCore.configuration.MVConfigNodes; import com.onarandombox.MultiverseCore.destination.ParsedDestination; import org.bukkit.GameRule; import org.jetbrains.annotations.NotNull; @@ -38,6 +39,7 @@ public class MVCommandCompletions extends PaperCommandCompletions { registerAsyncCompletion("destinations", this::suggestDestinations); registerAsyncCompletion("flags", this::suggestFlags); registerStaticCompletion("gamerules", this::suggestGamerules); + registerStaticCompletion("mvconfigs", MVConfigNodes.getNodes().getNames()); registerAsyncCompletion("mvworlds", this::suggestMVWorlds); setDefaultCompletion("destinations", ParsedDestination.class); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandContexts.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandContexts.java index dc3d1a07..5a7eba2e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandContexts.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandContexts.java @@ -1,6 +1,7 @@ package com.onarandombox.MultiverseCore.commandtools; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import co.aikar.commands.BukkitCommandExecutionContext; @@ -12,11 +13,16 @@ import com.google.common.base.Strings; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue; +import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue; +import com.onarandombox.MultiverseCore.configuration.MVConfigNodes; import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.display.filters.ContentFilter; import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter; import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter; import com.onarandombox.MultiverseCore.utils.PlayerFinder; +import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode; +import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode; +import io.github.townyadvanced.commentedconfiguration.setting.ValueNode; import org.bukkit.GameRule; import org.bukkit.entity.Player; @@ -32,6 +38,7 @@ public class MVCommandContexts extends PaperCommandContexts { registerContext(ParsedDestination.class, this::parseDestination); registerContext(GameRule.class, this::parseGameRule); registerContext(GameRuleValue.class, this::parseGameRuleValue); + registerContext(MVConfigValue.class, this::parseMVConfigValue); registerIssuerAwareContext(MVWorld.class, this::parseMVWorld); registerIssuerAwareContext(MVWorld[].class, this::parseMVWorldArray); registerIssuerAwareContext(Player.class, this::parsePlayer); @@ -97,6 +104,39 @@ public class MVCommandContexts extends PaperCommandContexts { return new GameRuleValue(resolvedValue); } + private MVConfigValue parseMVConfigValue(BukkitCommandExecutionContext context) { + String configName = (String) context.getResolvedArg(String.class); + if (Strings.isNullOrEmpty(configName)) { + throw new InvalidCommandArgument("No config name specified."); + } + Optional node = MVConfigNodes.getNodes().findNode(configName); + if (node.isEmpty()) { + throw new InvalidCommandArgument("The config " + configName + " is not valid."); + } + + String valueString = context.getFirstArg(); + if (Strings.isNullOrEmpty(valueString)) { + throw new InvalidCommandArgument("No config value specified."); + } + + if (!(node.get() instanceof TypedValueNode)) { + context.popFirstArg(); + return new MVConfigValue(valueString); + } + + ContextResolver resolver = getResolver(((TypedValueNode) node.get()).getType()); + if (resolver == null) { + context.popFirstArg(); + return new MVConfigValue(valueString); + } + + Object resolvedValue = resolver.getContext(context); + if (resolvedValue == null) { + throw new InvalidCommandArgument("The config value " + valueString + " is not valid for config " + configName + "."); + } + return new MVConfigValue(resolvedValue); + } + private MVWorld parseMVWorld(BukkitCommandExecutionContext context) { String resolve = context.getFlagValue("resolve", ""); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/context/MVConfigValue.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/context/MVConfigValue.java new file mode 100644 index 00000000..03d2c0aa --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/context/MVConfigValue.java @@ -0,0 +1,13 @@ +package com.onarandombox.MultiverseCore.commandtools.context; + +public class MVConfigValue { + private final Object value; + + public MVConfigValue(Object value) { + this.value = value; + } + + public Object getValue() { + return value; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java b/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java index 5dba9bea..79933337 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java +++ b/src/main/java/com/onarandombox/MultiverseCore/configuration/DefaultMVConfig.java @@ -97,8 +97,8 @@ public class DefaultMVConfig implements MVConfig { } @Override - public void setProperty(String name, Object value) { - settings.set(name, value); + public boolean setProperty(String name, Object value) { + return settings.set(name, value); } @Override diff --git a/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java b/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java index c1c6d762..5e3b97c9 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java +++ b/src/main/java/com/onarandombox/MultiverseCore/configuration/MVConfigNodes.java @@ -61,12 +61,14 @@ public class MVConfigNodes { .comment("If enabled, players will be forced into the gamemode of the world they are entering, unless they have") .comment("the `mv.bypass.gamemode.` permission.") .defaultValue(true) + .name("enforce-gamemode") .build()); public static final MVValueNode AUTO_PURGE_ENTITIES = node(MVValueNode.builder("world.auto-purge-entities", Boolean.class) .comment("") .comment("Sets whether Multiverse will purge mobs and entities with be automatically.") .defaultValue(false) + .name("auto-purge-entities") .build()); public static final MVValueNode TELEPORT_INTERCEPT = node(MVValueNode.builder("world.teleport-intercept", Boolean.class) @@ -74,6 +76,7 @@ public class MVConfigNodes { .comment("If this is set to true, Multiverse will enforce access permissions for all teleportation,") .comment("including teleportation from other plugins.") .defaultValue(true) + .name("teleport-intercept") .build()); private static final MVCommentedNode SPAWN_HEADER = node(MVCommentedNode.builder("spawn") @@ -86,6 +89,7 @@ public class MVConfigNodes { .comment("If enabled, Multiverse will set the first spawn location of a world to the spawn location of the world.") .comment("If disabled, it will default to server.properties settings.") .defaultValue(true) + .name("first-spawn-override") .build()); public static final MVValueNode FIRST_SPAWN_LOCATION = node(MVValueNode.builder("spawn.first-spawn-location", String.class) @@ -93,6 +97,7 @@ public class MVConfigNodes { .comment("Sets the world that Multiverse will use as the location for players that first join the server.") .comment("This only applies if first-spawn-override is set to true.") .defaultValue("") + .name("first-spawn-location") .build()); private static final MVCommentedNode PORTAL_HEADER = node(MVCommentedNode.builder("portal") @@ -104,6 +109,7 @@ public class MVConfigNodes { .comment("This config option defines whether or not Multiverse should interfere with's Bukkit's default portal search radius.") .comment("Setting it to false would mean you want to simply let Bukkit decides the search radius itself.") .defaultValue(false) + .name("use-custom-portal-search") .build()); public static final MVValueNode CUSTOM_PORTAL_SEARCH_RADIUS = node(MVValueNode.builder("portal.custom-portal-search-radius", Integer.class) @@ -111,6 +117,7 @@ public class MVConfigNodes { .comment("This config option defines the search radius Multiverse should use when searching for a portal.") .comment("This only applies if use-custom-portal-search is set to true.") .defaultValue(128) + .name("custom-portal-search-radius") .build()); private static final MVCommentedNode MESSAGING_HEADER = node(MVCommentedNode.builder("messaging") @@ -122,6 +129,7 @@ public class MVConfigNodes { .comment("This config option defines whether or not Multiverse should prefix the chat with the world name.") .comment("This only applies if use-custom-portal-search is set to true.") .defaultValue(false) + .name("enable-chat-prefix") .build()); public static final MVValueNode CHAT_PREFIX_FORMAT = node(MVValueNode.builder("messaging.chat-prefix-format", String.class) @@ -129,6 +137,7 @@ public class MVConfigNodes { .comment("This config option defines the format Multiverse should use when prefixing the chat with the world name.") .comment("This only applies if enable-chat-prefix is set to true.") .defaultValue("[%world%]%chat%") + .name("chat-prefix-format") .build()); private static final MVCommentedNode MISC_HEADER = node(MVCommentedNode.builder("misc") @@ -145,18 +154,21 @@ public class MVConfigNodes { .comment(" 2 = finer") .comment(" 3 = finest") .defaultValue(0) + .name("global-debug") .build()); public static final MVValueNode SILENT_START = node(MVValueNode.builder("misc.silent-start", Boolean.class) .comment("") .comment("If true, the startup console messages will no longer show.") .defaultValue(false) + .name("silent-start") .build()); public static final MVValueNode SHOW_DONATION_MESSAGE = node(MVValueNode.builder("misc.show-donation-message", Boolean.class) .comment("") .comment("If you don't want to donate, you can set this to false and Multiverse will stop nagging you.") .defaultValue(true) + .name("show-donation-message") .build()); public static final MVValueNode VERSION = node(MVValueNode.builder("version", Double.class) 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 fe9898df..10cef4d4 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/settings/MVSettings.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/settings/MVSettings.java @@ -177,8 +177,9 @@ public class MVSettings { * @param node The node to set the value of. * @param value The value to set. */ - public void set(@NotNull ValueNode node, Object value) { + public boolean set(@NotNull ValueNode node, Object value) { config.set(node.getPath(), value); + return true; } /** @@ -187,12 +188,10 @@ public class MVSettings { * @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); - } - }); + public boolean set(@NotNull String name, Object value) { + return nodes.findNode(name) + .map(node -> node instanceof ValueNode valueNode && set(valueNode, value)) + .orElse(false); } /**