From 180680f2972496241db7f443e06fefeaea0ff0dc Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:01:26 +0800 Subject: [PATCH 1/9] Add method to get MultiverseWorld from a bukkit world. --- .../mvplugins/multiverse/core/world/WorldManager.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/org/mvplugins/multiverse/core/world/WorldManager.java b/src/main/java/org/mvplugins/multiverse/core/world/WorldManager.java index c4064263..1d5d1777 100644 --- a/src/main/java/org/mvplugins/multiverse/core/world/WorldManager.java +++ b/src/main/java/org/mvplugins/multiverse/core/world/WorldManager.java @@ -737,6 +737,17 @@ public class WorldManager { return !isLoadedWorld(worldName) && isWorld(worldName); } + /** + * Get a world that may or may not be loaded. It will an {@link LoadedMultiverseWorld} if the world is loaded, + * otherwise returns an {@link MultiverseWorld} instance. + * + * @param world The bukkit world to get. + * @return The world if it exists. + */ + public Option getWorld(@Nullable World world) { + return Option.of(world).flatMap(this::getWorld); + } + /** * Get a world that may or may not be loaded. It will an {@link LoadedMultiverseWorld} if the world is loaded, * otherwise returns an {@link MultiverseWorld} instance. From fb240a19fa8404595d2c1508fec44c5d8e57c35b Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:02:29 +0800 Subject: [PATCH 2/9] Add context resolving for MultiverseWorld class --- .../core/commandtools/MVCommandContexts.java | 126 ++++++++++++------ 1 file changed, 85 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java index 79a8de64..d5f38894 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java +++ b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java @@ -27,10 +27,11 @@ import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter; import org.mvplugins.multiverse.core.display.filters.RegexContentFilter; import org.mvplugins.multiverse.core.utils.PlayerFinder; import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; +import org.mvplugins.multiverse.core.world.MultiverseWorld; import org.mvplugins.multiverse.core.world.WorldManager; @Service -public class MVCommandContexts extends PaperCommandContexts { +class MVCommandContexts extends PaperCommandContexts { private final MVCommandManager mvCommandManager; private final DestinationsProvider destinationsProvider; @@ -38,12 +39,11 @@ public class MVCommandContexts extends PaperCommandContexts { private final MVCoreConfig config; @Inject - public MVCommandContexts( + MVCommandContexts( MVCommandManager mvCommandManager, DestinationsProvider destinationsProvider, WorldManager worldManager, - MVCoreConfig config - ) { + MVCoreConfig config) { super(mvCommandManager); this.mvCommandManager = mvCommandManager; this.destinationsProvider = destinationsProvider; @@ -56,9 +56,10 @@ public class MVCommandContexts extends PaperCommandContexts { registerContext(ParsedDestination.class, this::parseDestination); registerContext(GameRule.class, this::parseGameRule); registerContext(GameRuleValue.class, this::parseGameRuleValue); + registerIssuerAwareContext(LoadedMultiverseWorld.class, this::parseLoadedMultiverseWorld); + registerIssuerAwareContext(LoadedMultiverseWorld[].class, this::parseLoadedMultiverseWorldArray); + registerIssuerAwareContext(MultiverseWorld.class, this::parseMultiverseWorld); registerContext(MVConfigValue.class, this::parseMVConfigValue); - registerIssuerAwareContext(LoadedMultiverseWorld.class, this::parseMVWorld); - registerIssuerAwareContext(LoadedMultiverseWorld[].class, this::parseMVWorldArray); registerIssuerAwareContext(Player.class, this::parsePlayer); registerIssuerAwareContext(Player[].class, this::parsePlayerArray); } @@ -129,40 +130,7 @@ 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."); - } - Option node = config.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 ValueNode)) { - context.popFirstArg(); - return new MVConfigValue(valueString); - } - - ContextResolver resolver = getResolver(((ValueNode) 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 LoadedMultiverseWorld parseMVWorld(BukkitCommandExecutionContext context) { + private LoadedMultiverseWorld parseLoadedMultiverseWorld(BukkitCommandExecutionContext context) { String resolve = context.getFlagValue("resolve", ""); // Get world based on sender only @@ -205,7 +173,7 @@ public class MVCommandContexts extends PaperCommandContexts { throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world."); } - private LoadedMultiverseWorld[] parseMVWorldArray(BukkitCommandExecutionContext context) { + private LoadedMultiverseWorld[] parseLoadedMultiverseWorldArray(BukkitCommandExecutionContext context) { String resolve = context.getFlagValue("resolve", ""); LoadedMultiverseWorld playerWorld = null; @@ -265,6 +233,82 @@ public class MVCommandContexts extends PaperCommandContexts { throw new InvalidCommandArgument("World " + worldStrings + " is not a loaded multiverse world."); } + private MultiverseWorld parseMultiverseWorld(BukkitCommandExecutionContext context) { + String resolve = context.getFlagValue("resolve", ""); + + // Get world based on sender only + if (resolve.equals("issuerOnly")) { + if (context.getIssuer().isPlayer()) { + return worldManager.getWorld(context.getIssuer().getPlayer().getWorld()).getOrNull(); + } + if (context.isOptional()) { + return null; + } + throw new InvalidCommandArgument("This command can only be used by a player in a Multiverse World."); + } + + String worldName = context.getFirstArg(); + MultiverseWorld world = worldManager.getWorld(worldName).getOrNull(); + + // Get world based on input, fallback to sender if input is not a world + if (resolve.equals("issuerAware")) { + if (world != null) { + context.popFirstArg(); + return world; + } + if (context.getIssuer().isPlayer()) { + return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull(); + } + if (context.isOptional()) { + return null; + } + throw new InvalidCommandArgument("Player is not in a Multiverse World."); + } + + // Get world based on input only + if (world != null) { + context.popFirstArg(); + return world; + } + if (context.isOptional()) { + return null; + } + throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world."); + } + + private MVConfigValue parseMVConfigValue(BukkitCommandExecutionContext context) { + String configName = (String) context.getResolvedArg(String.class); + if (Strings.isNullOrEmpty(configName)) { + throw new InvalidCommandArgument("No config name specified."); + } + Option node = config.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 ValueNode)) { + context.popFirstArg(); + return new MVConfigValue(valueString); + } + + ContextResolver resolver = getResolver(((ValueNode) 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 Player parsePlayer(BukkitCommandExecutionContext context) { String resolve = context.getFlagValue("resolve", ""); From b99de26deb1bcb6f3296db6a07da71f2b16b1fe0 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:06:08 +0800 Subject: [PATCH 3/9] Use MultiverseWorld instead of worldname string for RemoveCommand --- .../mvplugins/multiverse/core/commands/RemoveCommand.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java index 677f55dc..9879dd62 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java +++ b/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java @@ -17,6 +17,7 @@ import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer; import org.mvplugins.multiverse.core.commandtools.MVCommandManager; import org.mvplugins.multiverse.core.commandtools.MultiverseCommand; import org.mvplugins.multiverse.core.utils.MVCorei18n; +import org.mvplugins.multiverse.core.world.MultiverseWorld; import org.mvplugins.multiverse.core.world.WorldManager; @Service @@ -43,8 +44,8 @@ class RemoveCommand extends MultiverseCommand { @Conditions("mvworlds:scope=both") @Syntax("") @Description("{@@mv-core.remove.world.description}") - String worldName) { - worldManager.removeWorld(worldName) + MultiverseWorld world) { + worldManager.removeWorld(world) .onSuccess(removedWorldName -> { Logging.fine("World remove success: " + removedWorldName); issuer.sendInfo(MVCorei18n.REMOVEWORLD_REMOVED, "{world}", removedWorldName); From 80fcf8fe1950f8ab0118035af9ed3529a0132f98 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:10:02 +0800 Subject: [PATCH 4/9] Fix remove success message key --- .../mvplugins/multiverse/core/commands/RemoveCommand.java | 2 +- .../org/mvplugins/multiverse/core/utils/MVCorei18n.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java index 677f55dc..67d21c2b 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java +++ b/src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java @@ -47,7 +47,7 @@ class RemoveCommand extends MultiverseCommand { worldManager.removeWorld(worldName) .onSuccess(removedWorldName -> { Logging.fine("World remove success: " + removedWorldName); - issuer.sendInfo(MVCorei18n.REMOVEWORLD_REMOVED, "{world}", removedWorldName); + issuer.sendInfo(MVCorei18n.REMOVE_SUCCESS, "{world}", removedWorldName); }).onFailure(failure -> { Logging.fine("World remove failure: " + failure); issuer.sendError(failure.getFailureMessage()); diff --git a/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java b/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java index c1eed20d..c8a4af49 100644 --- a/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java +++ b/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java @@ -43,6 +43,7 @@ public enum MVCorei18n implements MessageKeyProvider { // delete command DELETE_DELETING, DELETE_PROMPT, + DELETE_SUCCESS, // Dumps command DUMPS_DESCRIPTION, @@ -76,6 +77,9 @@ public enum MVCorei18n implements MessageKeyProvider { RELOAD_RELOADING, RELOAD_SUCCESS, + // remove command + REMOVE_SUCCESS, + // root MV command ROOT_TITLE, ROOT_HELP, @@ -115,7 +119,6 @@ public enum MVCorei18n implements MessageKeyProvider { CREATEWORLD_WORLDEXISTLOADED, CREATEWORLD_BUKKITCREATIONFAILED, - DELETE_SUCCESS, DELETEWORLD_WORLDNONEXISTENT, DELETEWORLD_LOADFAILED, DELETEWORLD_WORLDFOLDERNOTFOUND, @@ -133,7 +136,6 @@ public enum MVCorei18n implements MessageKeyProvider { LOADWORLD_WORLDEXISTLOADED, LOADWORLD_BUKKITCREATIONFAILED, - REMOVEWORLD_REMOVED, REMOVEWORLD_WORLDNONEXISTENT, UNLOADWORLD_WORLDALREADYUNLOADING, From bbfc1a05e8c5ff5a6a1bd3fd39336d7176299947 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:18:04 +0800 Subject: [PATCH 5/9] Cleanup MultiverseCommand and add docs --- .../core/commandtools/MultiverseCommand.java | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/commandtools/MultiverseCommand.java b/src/main/java/org/mvplugins/multiverse/core/commandtools/MultiverseCommand.java index dfd06383..c2252565 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commandtools/MultiverseCommand.java +++ b/src/main/java/org/mvplugins/multiverse/core/commandtools/MultiverseCommand.java @@ -11,15 +11,26 @@ import org.mvplugins.multiverse.core.commandtools.flags.CommandFlagGroup; import org.mvplugins.multiverse.core.commandtools.flags.CommandFlagsManager; import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags; +/** + * Base class for all Multiverse commands. + */ @Contract -public abstract class MultiverseCommand extends BaseCommand { +public abstract class MultiverseCommand extends BaseCommand { + /** + * The command manager with multiverse specific methods. + */ protected final MVCommandManager commandManager; + /** + * The flags manager for the above command manager. + */ + protected final CommandFlagsManager flagsManager; private String flagGroupName; private CommandFlagGroup.Builder flagGroupBuilder; protected MultiverseCommand(@NotNull MVCommandManager commandManager) { this.commandManager = commandManager; + this.flagsManager = commandManager.getFlagsManager(); } @PostConstruct @@ -30,10 +41,22 @@ public abstract class MultiverseCommand extends BaseCommand { } } - protected CommandFlagsManager getFlagsManager() { - return commandManager.getFlagsManager(); + private void registerFlagGroup(@NotNull CommandFlagGroup flagGroup) { + if (flagGroupName != null) { + throw new IllegalStateException("Flag group already registered! (name: " + flagGroupName + ")"); + } + flagsManager.registerFlagGroup(flagGroup); + flagGroupName = flagGroup.getName(); + Logging.finest("Registered flag group: " + flagGroupName); } + /** + * Add a new flag to the flag builder. + * + * @param flag The flag to add. + * @param The type of the flag. + * @return The flag. + */ protected T flag(T flag) { if (flagGroupBuilder == null) { flagGroupBuilder = CommandFlagGroup.builder("mv" + getClass().getSimpleName().toLowerCase()); @@ -43,16 +66,13 @@ public abstract class MultiverseCommand extends BaseCommand { return flag; } - protected void registerFlagGroup(@NotNull CommandFlagGroup flagGroup) { - if (flagGroupName != null) { - throw new IllegalStateException("Flag group already registered! (name: " + flagGroupName + ")"); - } - getFlagsManager().registerFlagGroup(flagGroup); - flagGroupName = flagGroup.getName(); - Logging.fine("Registered flag group: " + flagGroupName); - } - + /** + * Parses flags. + * + * @param flags The raw string array to parse into flags. + * @return The parsed flags. + */ protected @NotNull ParsedCommandFlags parseFlags(@NotNull String[] flags) { - return getFlagsManager().parse(flagGroupName, flags); + return flagsManager.parse(flagGroupName, flags); } } From 6ba51fa573275ba820f109512ea136a5db4352fc Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:25:03 +0800 Subject: [PATCH 6/9] Implement lowercased enum completion and fix some checkstyles --- .../core/commands/CreateCommand.java | 2 +- .../core/commands/ImportCommand.java | 2 +- .../commandtools/MVCommandCompletions.java | 28 +++++++++++++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/CreateCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/CreateCommand.java index 435aa9c6..e05f6125 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commands/CreateCommand.java +++ b/src/main/java/org/mvplugins/multiverse/core/commands/CreateCommand.java @@ -71,7 +71,7 @@ class CreateCommand extends MultiverseCommand { @Subcommand("create") @CommandPermission("multiverse.core.create") - @CommandCompletion("@empty @flags:groupName=mvcreatecommand") + @CommandCompletion("@empty @environments @flags:groupName=mvcreatecommand") @Syntax(" --seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures") @Description("{@@mv-core.create.description}") void onCreateCommand( diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/ImportCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/ImportCommand.java index 63c91751..859de2dd 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commands/ImportCommand.java +++ b/src/main/java/org/mvplugins/multiverse/core/commands/ImportCommand.java @@ -54,7 +54,7 @@ class ImportCommand extends MultiverseCommand { @Subcommand("import") @CommandPermission("multiverse.core.import") - @CommandCompletion("@mvworlds:scope=potential @flags:groupName=mvimportcommand") + @CommandCompletion("@mvworlds:scope=potential @environments @flags:groupName=mvimportcommand") @Syntax(" --generator [generator[:id]] --adjust-spawn") @Description("{@@mv-core.import.description") void onImportCommand( diff --git a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java index 2e605c3f..b1f126f9 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java +++ b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java @@ -3,6 +3,7 @@ package org.mvplugins.multiverse.core.commandtools; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -18,7 +19,10 @@ import com.dumptruckman.minecraft.util.Logging; import com.google.common.collect.Sets; import io.vavr.control.Try; import jakarta.inject.Inject; +import org.bukkit.Difficulty; +import org.bukkit.GameMode; import org.bukkit.GameRule; +import org.bukkit.World; import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Service; @@ -30,19 +34,18 @@ import org.mvplugins.multiverse.core.world.MultiverseWorld; import org.mvplugins.multiverse.core.world.WorldManager; @Service -public class MVCommandCompletions extends PaperCommandCompletions { +class MVCommandCompletions extends PaperCommandCompletions { - protected final MVCommandManager commandManager; + private final MVCommandManager commandManager; private final WorldManager worldManager; private final DestinationsProvider destinationsProvider; @Inject - public MVCommandCompletions( + MVCommandCompletions( @NotNull MVCommandManager mvCommandManager, @NotNull WorldManager worldManager, @NotNull DestinationsProvider destinationsProvider, - @NotNull MVCoreConfig config - ) { + @NotNull MVCoreConfig config) { super(mvCommandManager); this.commandManager = mvCommandManager; this.worldManager = worldManager; @@ -50,13 +53,19 @@ public class MVCommandCompletions extends PaperCommandCompletions { registerAsyncCompletion("commands", this::suggestCommands); registerAsyncCompletion("destinations", this::suggestDestinations); + registerStaticCompletion("difficulties", suggestEnums(Difficulty.class)); + registerStaticCompletion("environments", suggestEnums(World.Environment.class)); registerAsyncCompletion("flags", this::suggestFlags); + registerStaticCompletion("gamemodes", suggestEnums(GameMode.class)); registerStaticCompletion("gamerules", this::suggestGamerules); registerStaticCompletion("mvconfigs", config.getNodes().getNames()); registerAsyncCompletion("mvworlds", this::suggestMVWorlds); setDefaultCompletion("destinations", ParsedDestination.class); + setDefaultCompletion("difficulties", Difficulty.class); + setDefaultCompletion("environments", World.Environment.class); setDefaultCompletion("flags", String[].class); + setDefaultCompletion("gamemodes", GameMode.class); setDefaultCompletion("gamerules", GameRule.class); setDefaultCompletion("mvworlds", LoadedMultiverseWorld.class); } @@ -94,7 +103,7 @@ public class MVCommandCompletions extends PaperCommandCompletions { } return this.destinationsProvider - .suggestDestinations((BukkitCommandIssuer)context.getIssuer(), context.getInput()); + .suggestDestinations((BukkitCommandIssuer) context.getIssuer(), context.getInput()); } private Collection suggestFlags(@NotNull BukkitCommandCompletionContext context) { @@ -152,4 +161,11 @@ public class MVCommandCompletions extends PaperCommandCompletions { Logging.severe("Invalid MVWorld scope: " + scope); return Collections.emptyList(); } + + private > Collection suggestEnums(Class enumClass) { + return EnumSet.allOf(enumClass).stream() + .map(Enum::name) + .map(String::toLowerCase) + .toList(); + } } From cce041877f862842271a7951f4e4457f20574634 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:31:34 +0800 Subject: [PATCH 7/9] Cleanup NodeGroup with docs and annotation --- .../core/configuration/node/NodeGroup.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/configuration/node/NodeGroup.java b/src/main/java/org/mvplugins/multiverse/core/configuration/node/NodeGroup.java index 82e44363..a95e5789 100644 --- a/src/main/java/org/mvplugins/multiverse/core/configuration/node/NodeGroup.java +++ b/src/main/java/org/mvplugins/multiverse/core/configuration/node/NodeGroup.java @@ -9,6 +9,7 @@ import java.util.Map; import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode; import io.vavr.control.Option; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * A collection of {@link CommentedNode}s, with mappings to nodes by name. @@ -17,24 +18,32 @@ public class NodeGroup implements Collection { private final Collection nodes; private final Map nodesMap; + /** + * Creates a new empty node group. + */ public NodeGroup() { this.nodes = new ArrayList<>(); this.nodesMap = new HashMap<>(); } - public NodeGroup(Collection nodes) { + /** + * Creates a new node group with the given nodes. + * + * @param nodes The nodes to make up the group. + */ + public NodeGroup(@NotNull Collection nodes) { this.nodes = nodes; this.nodesMap = new HashMap<>(nodes.size()); nodes.forEach(this::addNodeIndex); } - private void addNodeIndex(Node node) { + private void addNodeIndex(@NotNull Node node) { if (node instanceof ValueNode) { ((ValueNode) node).getName().peek(name -> nodesMap.put(name, node)); } } - private void removeNodeIndex(Node node) { + private void removeNodeIndex(@NotNull Node node) { if (node instanceof ValueNode) { ((ValueNode) node).getName().peek(nodesMap::remove); } @@ -45,32 +54,29 @@ public class NodeGroup implements Collection { * * @return The names of all nodes in this group. */ - public Collection getNames() { + public @NotNull Collection getNames() { return nodesMap.keySet(); } - public Map getNodesMap() { - return nodesMap; - } - /** * Gets the node with the given name. * * @param name The name of the node to get. * @return The node with the given name, or {@link Option.None} if no node with the given name exists. */ - public Option findNode(String name) { + public @NotNull Option findNode(@Nullable String name) { return Option.of(nodesMap.get(name)); } /** * Gets the node with the given name. * - * @param name The name of the node to get. - * @param type The type of the node to get. + * @param name The name of node to get. + * @param type The type of node to get. + * @param The type of node. * @return The node with the given name, or {@link Option.None} if no node with the given name exists. */ - public Option findNode(String name, Class type) { + public @NotNull Option findNode(@Nullable String name, @NotNull Class type) { return Option.of(nodesMap.get(name)).map(node -> type.isAssignableFrom(node.getClass()) ? (T) node : null); } From e4bff6937207756350b4a7d7ee6ae188a9e5ef28 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:39:59 +0800 Subject: [PATCH 8/9] Pass multiverse core instance directly into WorldConfigNodes --- .../multiverse/core/world/config/WorldConfig.java | 6 +++--- .../core/world/config/WorldConfigNodes.java | 6 +++--- .../core/world/config/WorldsConfigManager.java | 11 +++++------ 3 files changed, 11 insertions(+), 12 deletions(-) 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 c49b5319..b92e4561 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.ConfigurationSectionHandle; import org.mvplugins.multiverse.core.configuration.migration.BooleanMigratorAction; import org.mvplugins.multiverse.core.configuration.migration.ConfigMigrator; @@ -23,7 +24,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. @@ -37,9 +37,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 8c6d6f3b..008d7e86 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 @@ -10,10 +10,10 @@ 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.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.helpers.EnforcementHandler; @@ -27,8 +27,8 @@ public class WorldConfigNodes { private EnforcementHandler enforcementHandler; private LoadedMultiverseWorld world = null; - WorldConfigNodes(@NotNull EnforcementHandler enforcementHandler) { - this.enforcementHandler = enforcementHandler; + WorldConfigNodes(@NotNull MultiverseCore multiverseCore) { + this.enforcementHandler = multiverseCore.getService(EnforcementHandler.class); } LoadedMultiverseWorld getWorld() { 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..2bd1263f 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 @@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Service; import org.mvplugins.multiverse.core.MultiverseCore; -import org.mvplugins.multiverse.core.world.helpers.EnforcementHandler; /** * Manages the worlds.yml file. @@ -35,14 +34,14 @@ public final class WorldsConfigManager { private final File worldConfigFile; private YamlConfiguration worldsConfig; - private final EnforcementHandler enforcementHandler; + private final MultiverseCore multiverseCore; @Inject - WorldsConfigManager(@NotNull MultiverseCore core, @NotNull EnforcementHandler enforcementHandler) { + WorldsConfigManager(@NotNull MultiverseCore core, @NotNull MultiverseCore multiverseCore) { worldConfigMap = new HashMap<>(); worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile(); - this.enforcementHandler = enforcementHandler; + this.multiverseCore = multiverseCore; } /** @@ -128,7 +127,7 @@ public final class WorldsConfigManager { WorldConfig newWorldConfig = new WorldConfig( worldName, getWorldConfigSection(worldName), - enforcementHandler); + multiverseCore); worldConfigMap.put(worldName, newWorldConfig); newWorldsAdded.add(newWorldConfig); }); @@ -183,7 +182,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; } From 6611ec4457becb529e42dd8be067a94214dc8555 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 20 Sep 2023 13:45:14 +0800 Subject: [PATCH 9/9] Make defaultValue a supplier and fix some checkstyle in ConfigNode --- .../core/configuration/node/ConfigNode.java | 62 ++++++++++++++----- 1 file changed, 47 insertions(+), 15 deletions(-) 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 b20b377f..26d0001d 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 @@ -2,6 +2,7 @@ package org.mvplugins.multiverse.core.configuration.node; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.function.Supplier; import io.vavr.control.Option; import io.vavr.control.Try; @@ -10,6 +11,7 @@ import org.jetbrains.annotations.Nullable; /** * A node that contains a value. + * * @param The type of the value. */ public class ConfigNode extends ConfigHeaderNode implements ValueNode { @@ -19,19 +21,18 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { * * @param path The path of the node. * @param type The type of the value. - * @return The new builder. * @param The type of the value. + * @return The new builder. */ public static @NotNull ConfigNode.Builder> builder( @NotNull String path, - @NotNull Class type - ) { + @NotNull Class type) { return new ConfigNode.Builder<>(path, type); } protected final @Nullable String name; protected final @NotNull Class type; - protected final @Nullable T defaultValue; + protected final @Nullable Supplier defaultValue; protected final @Nullable NodeSerializer serializer; protected final @Nullable Function> validator; protected final @Nullable BiConsumer onSetValue; @@ -41,11 +42,10 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { @NotNull String[] comments, @Nullable String name, @NotNull Class type, - @Nullable T defaultValue, + @Nullable Supplier defaultValue, @Nullable NodeSerializer serializer, @Nullable Function> validator, - @Nullable BiConsumer onSetValue - ) { + @Nullable BiConsumer onSetValue) { super(path, comments); this.name = name; this.type = type; @@ -76,7 +76,10 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { */ @Override public @Nullable T getDefaultValue() { - return defaultValue; + if (defaultValue != null) { + return defaultValue.get(); + } + return null; } public @Nullable NodeSerializer getSerializer() { @@ -115,7 +118,7 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { protected @Nullable String name; protected @NotNull final Class type; - protected @Nullable T defaultValue; + protected @Nullable Supplier defaultValue; protected @Nullable NodeSerializer serializer; protected @Nullable Function> validator; protected @Nullable BiConsumer onSetValue; @@ -142,8 +145,19 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { * @return This builder. */ public @NotNull B defaultValue(@NotNull T defaultValue) { + this.defaultValue = () -> defaultValue; + return self(); + } + + /** + * Sets the default value for this node. + * + * @param defaultValue The default value supplier. + * @return This builder. + */ + public @NotNull B defaultValue(@NotNull Supplier defaultValue) { this.defaultValue = defaultValue; - return (B) this; + return self(); } /** @@ -154,17 +168,29 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { */ public @NotNull B name(@Nullable String name) { this.name = name; - return (B) this; + return self(); } + /** + * Sets the serializer for this node. + * + * @param serializer The serializer for this node. + * @return This builder. + */ public @NotNull B serializer(@NotNull NodeSerializer serializer) { this.serializer = serializer; - return (B) this; + return self(); } + /** + * Sets the validator for this node. + * + * @param validator The validator for this node. + * @return This builder. + */ public @NotNull B validator(@NotNull Function> validator) { this.validator = validator; - return (B) this; + return self(); } /** @@ -175,7 +201,7 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { */ public @NotNull B onSetValue(@NotNull BiConsumer onSetValue) { this.onSetValue = onSetValue; - return (B) this; + return self(); } /** @@ -183,7 +209,13 @@ public class ConfigNode extends ConfigHeaderNode implements ValueNode { */ @Override public @NotNull ConfigNode build() { - return new ConfigNode<>(path, comments.toArray(new String[0]), name, type, defaultValue, serializer, validator, onSetValue); + return new ConfigNode<>(path, comments.toArray(new String[0]), + name, type, defaultValue,serializer, validator, onSetValue); + } + + protected @NotNull B self() { + //noinspection unchecked + return (B) this; } } }