feat: Fully implement config command

This commit is contained in:
Ben Woo 2023-03-24 13:00:29 +08:00
parent d321851f0d
commit e3e3c039c3
No known key found for this signature in database
GPG Key ID: FB2A3645536E12C8
8 changed files with 98 additions and 15 deletions

View File

@ -7,7 +7,7 @@ public interface MVConfig {
Object getProperty(String name); Object getProperty(String name);
void setProperty(String name, Object value); boolean setProperty(String name, Object value);
/** /**
* Sets enforceAccess. * Sets enforceAccess.

View File

@ -11,6 +11,7 @@ import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVConfig; import com.onarandombox.MultiverseCore.api.MVConfig;
import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@CommandAlias("mv") @CommandAlias("mv")
@ -24,7 +25,7 @@ public class ConfigCommand extends MultiverseCoreCommand {
@Subcommand("config") @Subcommand("config")
@CommandPermission("multiverse.core.config") @CommandPermission("multiverse.core.config")
@CommandCompletion("@mvconfig") //TODO @CommandCompletion("@mvconfigs")
@Syntax("<name> [new-value]") @Syntax("<name> [new-value]")
@Description("") //TODO @Description("") //TODO
public void onConfigCommand(BukkitCommandIssuer issuer, public void onConfigCommand(BukkitCommandIssuer issuer,
@ -37,14 +38,30 @@ public class ConfigCommand extends MultiverseCoreCommand {
@Single @Single
@Syntax("[new-value]") @Syntax("[new-value]")
@Description("") //TODO @Description("") //TODO
String value MVConfigValue value
) { ) {
if (value == null) { 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; return;
} }
config.setProperty(name, value);
config.save(); config.save();
issuer.sendMessage("Set " + name + " to " + value); issuer.sendMessage("Successfully set " + name + " to " + value);
} }
} }

View File

@ -19,6 +19,7 @@ import com.google.common.collect.Sets;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.configuration.MVConfigNodes;
import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -38,6 +39,7 @@ public class MVCommandCompletions extends PaperCommandCompletions {
registerAsyncCompletion("destinations", this::suggestDestinations); registerAsyncCompletion("destinations", this::suggestDestinations);
registerAsyncCompletion("flags", this::suggestFlags); registerAsyncCompletion("flags", this::suggestFlags);
registerStaticCompletion("gamerules", this::suggestGamerules); registerStaticCompletion("gamerules", this::suggestGamerules);
registerStaticCompletion("mvconfigs", MVConfigNodes.getNodes().getNames());
registerAsyncCompletion("mvworlds", this::suggestMVWorlds); registerAsyncCompletion("mvworlds", this::suggestMVWorlds);
setDefaultCompletion("destinations", ParsedDestination.class); setDefaultCompletion("destinations", ParsedDestination.class);

View File

@ -1,6 +1,7 @@
package com.onarandombox.MultiverseCore.commandtools; package com.onarandombox.MultiverseCore.commandtools;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import co.aikar.commands.BukkitCommandExecutionContext; import co.aikar.commands.BukkitCommandExecutionContext;
@ -12,11 +13,16 @@ import com.google.common.base.Strings;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue; 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.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.display.filters.ContentFilter; import com.onarandombox.MultiverseCore.display.filters.ContentFilter;
import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter; import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter;
import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter; import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter;
import com.onarandombox.MultiverseCore.utils.PlayerFinder; 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.GameRule;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -32,6 +38,7 @@ public class MVCommandContexts extends PaperCommandContexts {
registerContext(ParsedDestination.class, this::parseDestination); registerContext(ParsedDestination.class, this::parseDestination);
registerContext(GameRule.class, this::parseGameRule); registerContext(GameRule.class, this::parseGameRule);
registerContext(GameRuleValue.class, this::parseGameRuleValue); registerContext(GameRuleValue.class, this::parseGameRuleValue);
registerContext(MVConfigValue.class, this::parseMVConfigValue);
registerIssuerAwareContext(MVWorld.class, this::parseMVWorld); registerIssuerAwareContext(MVWorld.class, this::parseMVWorld);
registerIssuerAwareContext(MVWorld[].class, this::parseMVWorldArray); registerIssuerAwareContext(MVWorld[].class, this::parseMVWorldArray);
registerIssuerAwareContext(Player.class, this::parsePlayer); registerIssuerAwareContext(Player.class, this::parsePlayer);
@ -97,6 +104,39 @@ public class MVCommandContexts extends PaperCommandContexts {
return new GameRuleValue(resolvedValue); 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<CommentedNode> 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<?, BukkitCommandExecutionContext> 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) { private MVWorld parseMVWorld(BukkitCommandExecutionContext context) {
String resolve = context.getFlagValue("resolve", ""); String resolve = context.getFlagValue("resolve", "");

View File

@ -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;
}
}

View File

@ -97,8 +97,8 @@ public class DefaultMVConfig implements MVConfig {
} }
@Override @Override
public void setProperty(String name, Object value) { public boolean setProperty(String name, Object value) {
settings.set(name, value); return settings.set(name, value);
} }
@Override @Override

View File

@ -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("If enabled, players will be forced into the gamemode of the world they are entering, unless they have")
.comment("the `mv.bypass.gamemode.<worldname>` permission.") .comment("the `mv.bypass.gamemode.<worldname>` permission.")
.defaultValue(true) .defaultValue(true)
.name("enforce-gamemode")
.build()); .build());
public static final MVValueNode<Boolean> AUTO_PURGE_ENTITIES = node(MVValueNode.builder("world.auto-purge-entities", Boolean.class) public static final MVValueNode<Boolean> AUTO_PURGE_ENTITIES = node(MVValueNode.builder("world.auto-purge-entities", Boolean.class)
.comment("") .comment("")
.comment("Sets whether Multiverse will purge mobs and entities with be automatically.") .comment("Sets whether Multiverse will purge mobs and entities with be automatically.")
.defaultValue(false) .defaultValue(false)
.name("auto-purge-entities")
.build()); .build());
public static final MVValueNode<Boolean> TELEPORT_INTERCEPT = node(MVValueNode.builder("world.teleport-intercept", Boolean.class) public static final MVValueNode<Boolean> 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("If this is set to true, Multiverse will enforce access permissions for all teleportation,")
.comment("including teleportation from other plugins.") .comment("including teleportation from other plugins.")
.defaultValue(true) .defaultValue(true)
.name("teleport-intercept")
.build()); .build());
private static final MVCommentedNode SPAWN_HEADER = node(MVCommentedNode.builder("spawn") 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 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.") .comment("If disabled, it will default to server.properties settings.")
.defaultValue(true) .defaultValue(true)
.name("first-spawn-override")
.build()); .build());
public static final MVValueNode<String> FIRST_SPAWN_LOCATION = node(MVValueNode.builder("spawn.first-spawn-location", String.class) public static final MVValueNode<String> 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("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.") .comment("This only applies if first-spawn-override is set to true.")
.defaultValue("") .defaultValue("")
.name("first-spawn-location")
.build()); .build());
private static final MVCommentedNode PORTAL_HEADER = node(MVCommentedNode.builder("portal") 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("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.") .comment("Setting it to false would mean you want to simply let Bukkit decides the search radius itself.")
.defaultValue(false) .defaultValue(false)
.name("use-custom-portal-search")
.build()); .build());
public static final MVValueNode<Integer> CUSTOM_PORTAL_SEARCH_RADIUS = node(MVValueNode.builder("portal.custom-portal-search-radius", Integer.class) public static final MVValueNode<Integer> 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 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.") .comment("This only applies if use-custom-portal-search is set to true.")
.defaultValue(128) .defaultValue(128)
.name("custom-portal-search-radius")
.build()); .build());
private static final MVCommentedNode MESSAGING_HEADER = node(MVCommentedNode.builder("messaging") 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 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.") .comment("This only applies if use-custom-portal-search is set to true.")
.defaultValue(false) .defaultValue(false)
.name("enable-chat-prefix")
.build()); .build());
public static final MVValueNode<String> CHAT_PREFIX_FORMAT = node(MVValueNode.builder("messaging.chat-prefix-format", String.class) public static final MVValueNode<String> 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 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.") .comment("This only applies if enable-chat-prefix is set to true.")
.defaultValue("[%world%]%chat%") .defaultValue("[%world%]%chat%")
.name("chat-prefix-format")
.build()); .build());
private static final MVCommentedNode MISC_HEADER = node(MVCommentedNode.builder("misc") private static final MVCommentedNode MISC_HEADER = node(MVCommentedNode.builder("misc")
@ -145,18 +154,21 @@ public class MVConfigNodes {
.comment(" 2 = finer") .comment(" 2 = finer")
.comment(" 3 = finest") .comment(" 3 = finest")
.defaultValue(0) .defaultValue(0)
.name("global-debug")
.build()); .build());
public static final MVValueNode<Boolean> SILENT_START = node(MVValueNode.builder("misc.silent-start", Boolean.class) public static final MVValueNode<Boolean> SILENT_START = node(MVValueNode.builder("misc.silent-start", Boolean.class)
.comment("") .comment("")
.comment("If true, the startup console messages will no longer show.") .comment("If true, the startup console messages will no longer show.")
.defaultValue(false) .defaultValue(false)
.name("silent-start")
.build()); .build());
public static final MVValueNode<Boolean> SHOW_DONATION_MESSAGE = node(MVValueNode.builder("misc.show-donation-message", Boolean.class) public static final MVValueNode<Boolean> SHOW_DONATION_MESSAGE = node(MVValueNode.builder("misc.show-donation-message", Boolean.class)
.comment("") .comment("")
.comment("If you don't want to donate, you can set this to false and Multiverse will stop nagging you.") .comment("If you don't want to donate, you can set this to false and Multiverse will stop nagging you.")
.defaultValue(true) .defaultValue(true)
.name("show-donation-message")
.build()); .build());
public static final MVValueNode<Double> VERSION = node(MVValueNode.builder("version", Double.class) public static final MVValueNode<Double> VERSION = node(MVValueNode.builder("version", Double.class)

View File

@ -177,8 +177,9 @@ public class MVSettings {
* @param node The node to set the value of. * @param node The node to set the value of.
* @param value The value to set. * @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); 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 name The name of the node to set the value of.
* @param value The value to set. * @param value The value to set.
*/ */
public void set(@NotNull String name, Object value) { public boolean set(@NotNull String name, Object value) {
nodes.findNode(name).ifPresent(node -> { return nodes.findNode(name)
if (node instanceof ValueNode valueNode) { .map(node -> node instanceof ValueNode valueNode && set(valueNode, value))
set(valueNode, value); .orElse(false);
}
});
} }
/** /**