From 6427881c98393dc2463e13413fb4637f463cc283 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 7 Sep 2023 12:07:01 +0800 Subject: [PATCH] Finish up clone command --- .../MultiverseCore/commands/CloneCommand.java | 47 +++++++++++++-- .../MultiverseCore/worldnew/WorldManager.java | 53 ++++++++++------- .../worldnew/options/CloneWorldOptions.java | 57 +++++++++++++++++++ .../worldnew/results/CloneWorldResult.java | 45 +++++++++++++++ 4 files changed, 176 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/onarandombox/MultiverseCore/worldnew/options/CloneWorldOptions.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java index 8e3abcaa..33ea9f15 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java @@ -5,18 +5,29 @@ 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.dumptruckman.minecraft.util.Logging; +import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer; import com.onarandombox.MultiverseCore.commandtools.MVCommandManager; import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand; +import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag; +import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup; +import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag; +import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags; import com.onarandombox.MultiverseCore.utils.MVCorei18n; import com.onarandombox.MultiverseCore.worldnew.MVWorld; import com.onarandombox.MultiverseCore.worldnew.WorldManager; +import com.onarandombox.MultiverseCore.worldnew.options.CloneWorldOptions; import jakarta.inject.Inject; import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Service; +import java.util.Collections; +import java.util.Random; + @Service @CommandAlias("mv") public class CloneCommand extends MultiverseCommand { @@ -27,6 +38,18 @@ public class CloneCommand extends MultiverseCommand { public CloneCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) { super(commandManager); this.worldManager = worldManager; + + registerFlagGroup(CommandFlagGroup.builder("mvclone") + .add(CommandFlag.builder("--reset-world-config") + .addAlias("-wc") + .build()) + .add(CommandFlag.builder("--reset-gamerules") + .addAlias("-gm") + .build()) + .add(CommandFlag.builder("--reset-world-border") + .addAlias("-wb") + .build()) + .build()); } @Subcommand("clone") @@ -34,19 +57,35 @@ public class CloneCommand extends MultiverseCommand { @CommandCompletion("@mvworlds:scope=both @empty") @Syntax(" ") @Description("{@@mv-core.clone.description}") - public void onCloneCommand(CommandIssuer issuer, + public void onCloneCommand(MVCommandIssuer issuer, @Syntax("") @Description("{@@mv-core.clone.world.description}") MVWorld world, - @Single @Syntax("") @Description("{@@mv-core.clone.newWorld.description}") - String newWorldName + String newWorldName, + + @Optional + @Syntax("") // TODO + @Description("{@@mv-core.regen.other.description}") + String[] flags ) { + ParsedCommandFlags parsedFlags = parseFlags(flags); + issuer.sendInfo(MVCorei18n.CLONE_CLONING, "{world}", world.getName(), "{newWorld}", newWorldName); - worldManager.cloneWorld(world, newWorldName); + worldManager.cloneWorld(CloneWorldOptions.fromTo(world, newWorldName) + .keepWorldConfig(!parsedFlags.hasFlag("--reset-world-config")) + .keepGameRule(!parsedFlags.hasFlag("--reset-gamerules")) + .keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border")) + ).onSuccess((success) -> { + Logging.fine("World remove success: " + success); + issuer.sendInfo(success.getReasonMessage()); + }).onFailure((failure) -> { + Logging.fine("World remove failure: " + failure); + issuer.sendError(failure.getReasonMessage()); + }); issuer.sendInfo(MVCorei18n.CLONE_SUCCESS, "{world}", newWorldName); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java index 3ef1cc30..2d7a911c 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java @@ -10,13 +10,14 @@ import com.onarandombox.MultiverseCore.utils.result.Result; import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig; import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager; import com.onarandombox.MultiverseCore.worldnew.generators.GeneratorProvider; -import com.onarandombox.MultiverseCore.worldnew.helpers.DataStore; import com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.GameRulesStore; import com.onarandombox.MultiverseCore.worldnew.helpers.DataTransfer; import com.onarandombox.MultiverseCore.worldnew.helpers.FilesManipulator; +import com.onarandombox.MultiverseCore.worldnew.options.CloneWorldOptions; import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions; import com.onarandombox.MultiverseCore.worldnew.options.ImportWorldOptions; import com.onarandombox.MultiverseCore.worldnew.options.RegenWorldOptions; +import com.onarandombox.MultiverseCore.worldnew.results.CloneWorldResult; import com.onarandombox.MultiverseCore.worldnew.results.CreateWorldResult; import com.onarandombox.MultiverseCore.worldnew.results.DeleteWorldResult; import com.onarandombox.MultiverseCore.worldnew.results.ImportWorldResult; @@ -470,47 +471,55 @@ public class WorldManager { /** * Clones an existing multiverse world. * - * @param world The multiverse world to clone. - * @param newWorldName The name of the new world. + * @param options The options for customizing the cloning of a world. */ - public void cloneWorld(@NotNull MVWorld world, @NotNull String newWorldName) { + public Result cloneWorld(@NotNull CloneWorldOptions options) { + MVWorld world = options.world(); + String newWorldName = options.newWorldName(); + if (!worldNameChecker.isValidWorldName(newWorldName)) { Logging.severe("Invalid world name: " + newWorldName); - return; + return Result.failure(CloneWorldResult.Failure.INVALID_WORLDNAME, replace("{world}").with(newWorldName)); } - if (isOfflineWorld(newWorldName)) { - Logging.severe("World already exist offline: " + newWorldName); - return; + if (worldNameChecker.isValidWorldFolder(newWorldName)) { + return Result.failure(CloneWorldResult.Failure.WORLD_EXIST_FOLDER, replace("{world}").with(newWorldName)); } if (isMVWorld(newWorldName)) { Logging.severe("World already loaded: " + newWorldName); - return; + return Result.failure(CloneWorldResult.Failure.WORLD_EXIST_LOADED, replace("{world}").with(newWorldName)); } - if (worldNameChecker.isValidWorldFolder(newWorldName)) { - Logging.severe("World folder already exist: " + newWorldName); - return; + if (isOfflineWorld(newWorldName)) { + Logging.severe("World already exist offline: " + newWorldName); + return Result.failure(CloneWorldResult.Failure.WORLD_EXIST_OFFLINE, replace("{world}").with(newWorldName)); } - // TODO: Configure option on whether to copy these -// GameRulesStore gameRulesStore = GameRulesStore.createAndCopyFrom(world); -// WorldConfigStore worldConfigStore = WorldConfigStore.createAndCopyFrom(world); + DataTransfer dataTransfer = new DataTransfer<>(); + if (options.keepWorldConfig()) { + dataTransfer.addDataStore(new WorldConfigStore(), world); + } + if (options.keepGameRule()) { + dataTransfer.addDataStore(new GameRulesStore(), world); + } + if (options.keepWorldBorder()) { + dataTransfer.addDataStore(new WorldBorderStore(), world); + } File worldFolder = world.getBukkitWorld().map(World::getWorldFolder).getOrNull(); // TODO: Check null? File newWorldFolder = new File(Bukkit.getWorldContainer(), newWorldName); FileUtils.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES); - // TODO: Error handling - importWorld(ImportWorldOptions.worldName(newWorldName) + var importResult = importWorld(ImportWorldOptions.worldName(newWorldName) .environment(world.getEnvironment()) - .generator(world.getGenerator()) - ); + .generator(world.getGenerator())); + if (importResult.isFailure()) { + return Result.failure(CloneWorldResult.Failure.IMPORT_FAILED, importResult.getReasonMessage()); + } - // TODO: Error handling getMVWorld(newWorldName).peek(newWorld -> { -// gameRulesStore.pasteTo(newWorld); -// worldConfigStore.pasteTo(newWorld); + dataTransfer.pasteAllTo(newWorld); saveWorldsConfig(); }); + return Result.success(CloneWorldResult.Success.CLONED, replace("{world}").with(world.getName())); } /** diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/options/CloneWorldOptions.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/options/CloneWorldOptions.java new file mode 100644 index 00000000..47be5d18 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/options/CloneWorldOptions.java @@ -0,0 +1,57 @@ +package com.onarandombox.MultiverseCore.worldnew.options; + +import com.onarandombox.MultiverseCore.worldnew.MVWorld; +import org.jetbrains.annotations.NotNull; + +public class CloneWorldOptions { + public static CloneWorldOptions fromTo(MVWorld world, String newWorldName) { + return new CloneWorldOptions(world, newWorldName); + } + + private final MVWorld world; + private final String newWorldName; + private boolean keepGameRule = true; + private boolean keepWorldConfig = true; + + private boolean keepWorldBorder = true; + + public CloneWorldOptions(MVWorld world, String newWorldName) { + this.world = world; + this.newWorldName = newWorldName; + } + + public MVWorld world() { + return world; + } + + public String newWorldName() { + return newWorldName; + } + + public @NotNull CloneWorldOptions keepGameRule(boolean keepGameRule) { + this.keepGameRule = keepGameRule; + return this; + } + + public boolean keepGameRule() { + return keepGameRule; + } + + public @NotNull CloneWorldOptions keepWorldConfig(boolean keepWorldConfig) { + this.keepWorldConfig = keepWorldConfig; + return this; + } + + public boolean keepWorldConfig() { + return keepWorldConfig; + } + + public @NotNull CloneWorldOptions keepWorldBorder(boolean keepWorldBorder) { + this.keepWorldBorder = keepWorldBorder; + return this; + } + + public boolean keepWorldBorder() { + return keepWorldBorder; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java new file mode 100644 index 00000000..6e7fe97d --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java @@ -0,0 +1,45 @@ +package com.onarandombox.MultiverseCore.worldnew.results; + +import co.aikar.locales.MessageKey; +import co.aikar.locales.MessageKeyProvider; +import com.onarandombox.MultiverseCore.utils.MVCorei18n; +import com.onarandombox.MultiverseCore.utils.result.FailureReason; +import com.onarandombox.MultiverseCore.utils.result.SuccessReason; + +public class CloneWorldResult { + public enum Success implements SuccessReason { + CLONED(MVCorei18n.GENERIC_SUCCESS) + ; + + private final MessageKeyProvider message; + + Success(MessageKeyProvider message) { + this.message = message; + } + + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); + } + } + + public enum Failure implements FailureReason { + INVALID_WORLDNAME(MVCorei18n.CREATEWORLD_INVALIDWORLDNAME), + WORLD_EXIST_FOLDER(MVCorei18n.CREATEWORLD_WORLDEXISTFOLDER), + WORLD_EXIST_OFFLINE(MVCorei18n.CREATEWORLD_WORLDEXISTOFFLINE), + WORLD_EXIST_LOADED(MVCorei18n.CREATEWORLD_WORLDEXISTLOADED), + IMPORT_FAILED(null), + ; + + private final MessageKeyProvider message; + + Failure(MessageKeyProvider message) { + this.message = message; + } + + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); + } + } +}