From ee1bf8216e5ee363943be6efce64ccd715b04ec2 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 14 Sep 2023 19:07:39 +0800 Subject: [PATCH] Better defaults and completions for ListConfigNode --- .../core/commands/ModifyCommand.java | 2 + .../core/configuration/node/ConfigNode.java | 10 +- .../configuration/node/ListConfigNode.java | 121 ++++++++++++++---- .../core/world/config/WorldConfig.java | 6 +- .../core/world/config/WorldConfigNodes.java | 14 +- .../world/config/WorldsConfigManager.java | 14 +- 6 files changed, 119 insertions(+), 48 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/ModifyCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/ModifyCommand.java index 0f5a6bad..8c36fe79 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commands/ModifyCommand.java +++ b/src/main/java/org/mvplugins/multiverse/core/commands/ModifyCommand.java @@ -5,6 +5,7 @@ import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; import co.aikar.commands.annotation.Description; import co.aikar.commands.annotation.Flags; +import co.aikar.commands.annotation.Single; import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Syntax; import com.dumptruckman.minecraft.util.Logging; @@ -55,6 +56,7 @@ class ModifyCommand extends MultiverseCommand { String propertyName, @Optional + @Single @Syntax("[value]") @Description("") String propertyValue) { diff --git a/src/main/java/org/mvplugins/multiverse/core/configuration/node/ConfigNode.java b/src/main/java/org/mvplugins/multiverse/core/configuration/node/ConfigNode.java index a7687f6c..f97c4fbd 100644 --- a/src/main/java/org/mvplugins/multiverse/core/configuration/node/ConfigNode.java +++ b/src/main/java/org/mvplugins/multiverse/core/configuration/node/ConfigNode.java @@ -42,11 +42,11 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { protected final @Nullable String name; protected final @NotNull Class type; protected final @Nullable Supplier defaultValueSupplier; - protected final @Nullable NodeSuggester suggester; - protected final @Nullable NodeStringParser stringParser; - protected final @Nullable NodeSerializer serializer; - protected final @Nullable Function> validator; - protected final @Nullable BiConsumer onSetValue; + protected @Nullable NodeSuggester suggester; + protected @Nullable NodeStringParser stringParser; + protected @Nullable NodeSerializer serializer; + protected @Nullable Function> validator; + protected @Nullable BiConsumer onSetValue; protected ConfigNode( @NotNull String path, diff --git a/src/main/java/org/mvplugins/multiverse/core/configuration/node/ListConfigNode.java b/src/main/java/org/mvplugins/multiverse/core/configuration/node/ListConfigNode.java index 27b5e11b..34ae9cd7 100644 --- a/src/main/java/org/mvplugins/multiverse/core/configuration/node/ListConfigNode.java +++ b/src/main/java/org/mvplugins/multiverse/core/configuration/node/ListConfigNode.java @@ -1,13 +1,17 @@ package org.mvplugins.multiverse.core.configuration.node; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; +import com.dumptruckman.minecraft.util.Logging; +import io.vavr.Value; import io.vavr.control.Try; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -70,6 +74,91 @@ public class ListConfigNode extends ConfigNode> implements ListValueN this.itemSerializer = itemSerializer; this.itemValidator = itemValidator; this.onSetItemValue = onSetItemValue; + + if (this.itemSuggester != null && this.suggester == null) { + setDefaultSuggester(); + } + if (this.itemStringParser != null && this.stringParser == null) { + Logging.fine("Setting default string parser for list node " + path); + setDefaultStringParser(); + } + if (this.itemValidator != null && this.validator == null) { + setDefaultValidator(); + } + if (this.itemSerializer != null && this.serializer == null) { + setDefaultSerialiser(); + } + if (this.onSetItemValue != null && this.onSetValue == null) { + setDefaultOnSetValue(); + } + } + + private void setDefaultSuggester() { + this.suggester = input -> { + int lastIndexOf = input.lastIndexOf(','); + if (lastIndexOf == -1) { + return itemSuggester.suggest(input); + } + + String lastInput = input.substring(lastIndexOf + 1); + String inputBeforeLast = input.substring(0, lastIndexOf + 1); + Set inputs = Set.of(inputBeforeLast.split(",")); + return itemSuggester.suggest(lastInput).stream() + .filter(item -> !inputs.contains(item)) + .map(item -> inputBeforeLast + item) + .toList(); + }; + } + + private void setDefaultStringParser() { + this.stringParser = (input, type) -> { + if (input == null) { + return Try.failure(new IllegalArgumentException("Input cannot be null")); + } + return Try.sequence(Arrays.stream(input.split(",")) + .map(inputItem -> itemStringParser.parse(inputItem, itemType)) + .toList()).map(Value::toJavaList); + }; + } + + private void setDefaultValidator() { + this.validator = value -> { + if (value != null) { + return Try.sequence(value.stream().map(itemValidator).toList()).map(v -> null); + } + return Try.success(null); + }; + } + + private void setDefaultSerialiser() { + this.serializer = new NodeSerializer<>() { + @Override + public List deserialize(Object object, Class> type) { + if (object instanceof List list) { + return list.stream().map(item -> itemSerializer.deserialize(item, itemType)).toList(); + } + return new ArrayList<>(); + } + + @Override + public Object serialize(List object, Class> type) { + if (object != null) { + return object.stream().map(item -> itemSerializer.serialize(item, itemType)).toList(); + } + return new ArrayList<>(); + } + }; + } + + private void setDefaultOnSetValue() { + this.onSetValue = (oldValue, newValue) -> { + if (oldValue != null) { + oldValue.stream() + .filter(value -> !newValue.contains(value)) + .forEach(item -> onSetItemValue.accept(item, null)); + } + newValue.forEach(item -> onSetItemValue.accept(null, item)); + }; } /** @@ -80,6 +169,9 @@ public class ListConfigNode extends ConfigNode> implements ListValueN return itemType; } + /** + * {@inheritDoc} + */ @Override public @NotNull Collection suggestItem(@Nullable String input) { if (itemSuggester != null) { @@ -88,6 +180,9 @@ public class ListConfigNode extends ConfigNode> implements ListValueN return Collections.emptyList(); } + /** + * {@inheritDoc} + */ @Override public @NotNull Try parseItemFromString(@Nullable String input) { if (itemStringParser != null) { @@ -176,21 +271,9 @@ public class ListConfigNode extends ConfigNode> implements ListValueN */ public @NotNull B itemValidator(@NotNull Function> itemValidator) { this.itemValidator = itemValidator; - if (validator == null) { - setDefaultValidator(); - } return self(); } - private void setDefaultValidator() { - this.validator = value -> { - if (value != null) { - return Try.sequence(value.stream().map(itemValidator).toList()).map(v -> null); - } - return Try.success(null); - }; - } - /** * Sets the onSetValue for the node. * @@ -199,23 +282,9 @@ public class ListConfigNode extends ConfigNode> implements ListValueN */ public @NotNull B onSetItemValue(@Nullable BiConsumer onSetItemValue) { this.onSetItemValue = onSetItemValue; - if (onSetValue == null) { - setDefaultOnSetValue(); - } return self(); } - private void setDefaultOnSetValue() { - this.onSetValue = (oldValue, newValue) -> { - if (oldValue != null) { - oldValue.stream() - .filter(value -> !newValue.contains(value)) - .forEach(item -> onSetItemValue.accept(item, null)); - } - newValue.forEach(item -> onSetItemValue.accept(null, item)); - }; - } - /** * {@inheritDoc} */ diff --git a/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfig.java b/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfig.java index 8a6c0924..534eced1 100644 --- a/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfig.java +++ b/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfig.java @@ -14,6 +14,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.mvplugins.multiverse.core.MultiverseCore; import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType; import org.mvplugins.multiverse.core.configuration.handle.ConfigurationSectionHandle; import org.mvplugins.multiverse.core.configuration.migration.BooleanMigratorAction; @@ -24,7 +25,6 @@ import org.mvplugins.multiverse.core.configuration.migration.MoveMigratorAction; import org.mvplugins.multiverse.core.configuration.migration.NullStringMigratorAction; import org.mvplugins.multiverse.core.configuration.migration.VersionMigrator; import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; -import org.mvplugins.multiverse.core.world.helpers.EnforcementHandler; /** * Represents a world configuration. @@ -38,9 +38,9 @@ public final class WorldConfig { WorldConfig( @NotNull String worldName, @NotNull ConfigurationSection configSection, - @NotNull EnforcementHandler enforcementHandler) { + @NotNull MultiverseCore multiverseCore) { this.worldName = worldName; - this.configNodes = new WorldConfigNodes(enforcementHandler); + this.configNodes = new WorldConfigNodes(multiverseCore); this.configHandle = ConfigurationSectionHandle.builder(configSection) .logger(Logging.getLogger()) .nodes(configNodes.getNodes()) diff --git a/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfigNodes.java b/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfigNodes.java index e0c0c5f2..bc0c6470 100644 --- a/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfigNodes.java +++ b/src/main/java/org/mvplugins/multiverse/core/world/config/WorldConfigNodes.java @@ -1,8 +1,5 @@ package org.mvplugins.multiverse.core.world.config; -import java.util.ArrayList; -import java.util.List; - import org.bukkit.Difficulty; import org.bukkit.GameMode; import org.bukkit.Location; @@ -10,12 +7,14 @@ import org.bukkit.Material; import org.bukkit.World; import org.jetbrains.annotations.NotNull; +import org.mvplugins.multiverse.core.MultiverseCore; import org.mvplugins.multiverse.core.configuration.node.ConfigNode; import org.mvplugins.multiverse.core.configuration.node.ListConfigNode; import org.mvplugins.multiverse.core.configuration.node.Node; import org.mvplugins.multiverse.core.configuration.node.NodeGroup; -import org.mvplugins.multiverse.core.world.config.AllowedPortalType; import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; +import org.mvplugins.multiverse.core.world.MultiverseWorld; +import org.mvplugins.multiverse.core.world.WorldManager; import org.mvplugins.multiverse.core.world.helpers.EnforcementHandler; /** @@ -26,10 +25,12 @@ public class WorldConfigNodes { private final NodeGroup nodes = new NodeGroup(); private EnforcementHandler enforcementHandler; + private WorldManager worldManager; private LoadedMultiverseWorld world = null; - WorldConfigNodes(@NotNull EnforcementHandler enforcementHandler) { - this.enforcementHandler = enforcementHandler; + WorldConfigNodes(@NotNull MultiverseCore multiverseCore) { + this.enforcementHandler = multiverseCore.getService(EnforcementHandler.class); + this.worldManager = multiverseCore.getService(WorldManager.class); } LoadedMultiverseWorld getWorld() { @@ -245,6 +246,7 @@ public class WorldConfigNodes { final ListConfigNode WORLD_BLACKLIST = node(ListConfigNode .listBuilder("world-blacklist", String.class) + .itemSuggester(input -> worldManager.getWorlds().stream().map(MultiverseWorld::getName).toList()) .build()); final ConfigNode VERSION = node(ConfigNode.builder("version", Double.class) diff --git a/src/main/java/org/mvplugins/multiverse/core/world/config/WorldsConfigManager.java b/src/main/java/org/mvplugins/multiverse/core/world/config/WorldsConfigManager.java index c5868c66..6988d261 100644 --- a/src/main/java/org/mvplugins/multiverse/core/world/config/WorldsConfigManager.java +++ b/src/main/java/org/mvplugins/multiverse/core/world/config/WorldsConfigManager.java @@ -33,16 +33,14 @@ public final class WorldsConfigManager { private final Map worldConfigMap; private final File worldConfigFile; + private final MultiverseCore multiverseCore; private YamlConfiguration worldsConfig; - private final EnforcementHandler enforcementHandler; - @Inject - WorldsConfigManager(@NotNull MultiverseCore core, @NotNull EnforcementHandler enforcementHandler) { + WorldsConfigManager(@NotNull MultiverseCore multiverseCore) { worldConfigMap = new HashMap<>(); - worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile(); - - this.enforcementHandler = enforcementHandler; + worldConfigFile = multiverseCore.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile(); + this.multiverseCore = multiverseCore; } /** @@ -128,7 +126,7 @@ public final class WorldsConfigManager { WorldConfig newWorldConfig = new WorldConfig( worldName, getWorldConfigSection(worldName), - enforcementHandler); + multiverseCore); worldConfigMap.put(worldName, newWorldConfig); newWorldsAdded.add(newWorldConfig); }); @@ -183,7 +181,7 @@ public final class WorldsConfigManager { if (worldConfigMap.containsKey(worldName)) { throw new IllegalArgumentException("WorldConfig for world " + worldName + " already exists."); } - WorldConfig worldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName), enforcementHandler); + WorldConfig worldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName), multiverseCore); worldConfigMap.put(worldName, worldConfig); return worldConfig; }