From 89c6eb41cbef74b9ad3897d117cb1f3c090bf344 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 7 Sep 2023 22:53:53 +0800 Subject: [PATCH] Refactor clone world into multiple smaller methods --- .../MultiverseCore/utils/result/Result.java | 32 +++++++++ .../MultiverseCore/worldnew/WorldManager.java | 67 +++++++++++-------- .../worldnew/results/CloneWorldResult.java | 1 + 3 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java index 3dafc0aa..980e525e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java @@ -7,8 +7,13 @@ import org.jetbrains.annotations.NotNull; import java.util.NoSuchElementException; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Function; public sealed interface Result permits Result.Success, Result.Failure { + static Result success() { + return new Success<>(null, Message.of("Success!")); + } + static Result success(S successReason, MessageReplacement...replacements) { return new Success<>(successReason, replacements); } @@ -17,6 +22,10 @@ public sealed interface Result return new Success<>(successReason, message); } + static Result failure() { + return new Failure<>(null, Message.of("Failed!")); + } + static Result failure(F failureReason, MessageReplacement...replacements) { return new Failure<>(failureReason, replacements); } @@ -62,6 +71,29 @@ public sealed interface Result return this; } + default Result onSuccessThen(Function, Result> function) { + if (this instanceof Success) { + return function.apply((Success) this); + } + return this; + } + + default Result onFailureThen(Function, Result> function) { + if (this instanceof Failure) { + return function.apply((Failure) this); + } + return this; + } + + default R fold(Function, R> failureFunc, Function, R> successFunc) { + if (this instanceof Failure) { + return failureFunc.apply((Failure) this); + } else if (this instanceof Success) { + return successFunc.apply((Success) this); + } + throw new IllegalStateException("Unknown result type: " + this.getClass().getName()); + } + final class Success implements Result { private final S successReason; private final Message message; diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java index f4c92ab2..55830293 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java @@ -5,7 +5,6 @@ import com.google.common.base.Strings; import com.onarandombox.MultiverseCore.api.BlockSafety; import com.onarandombox.MultiverseCore.api.LocationManipulation; import com.onarandombox.MultiverseCore.api.SafeTTeleporter; -import com.onarandombox.MultiverseCore.utils.file.FileUtils; import com.onarandombox.MultiverseCore.utils.result.Result; import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig; import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager; @@ -46,7 +45,8 @@ import java.util.List; import java.util.Map; import static com.onarandombox.MultiverseCore.utils.message.MessageReplacement.replace; -import static com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.*; +import static com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.WorldBorderStore; +import static com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.WorldConfigStore; /** * This manager contains all the world managing functions that your heart desires! @@ -474,9 +474,30 @@ public class WorldManager { * @param options The options for customizing the cloning of a world. */ public Result cloneWorld(@NotNull CloneWorldOptions options) { - MVWorld world = options.world(); - String newWorldName = options.newWorldName(); + return cloneWorldValidateWorld(options) + .onSuccessThen(s -> cloneWorldCopyFolder(options)) + .onSuccessThen(s -> importWorld( + ImportWorldOptions.worldName(options.newWorldName()) + .environment(options.world().getEnvironment()) + .generator(options.world().getGenerator()) + ).fold( + failure -> Result.failure(CloneWorldResult.Failure.IMPORT_FAILED, failure.getReasonMessage()), + success -> Result.success() + )) + .onSuccessThen(s -> getMVWorld(options.newWorldName()).fold( + () -> Result.failure(CloneWorldResult.Failure.MV_WORLD_FAILED, replace("{world}").with(options.newWorldName())), + mvWorld -> { + cloneWorldTransferData(options, mvWorld); + saveWorldsConfig(); + return Result.success(CloneWorldResult.Success.CLONED, + replace("{world}").with(options.world().getName()), + replace("{newworld}").with(mvWorld.getName())); + } + )); + } + private Result cloneWorldValidateWorld(@NotNull CloneWorldOptions options) { + String newWorldName = options.newWorldName(); if (!worldNameChecker.isValidWorldName(newWorldName)) { Logging.severe("Invalid world name: " + newWorldName); return Result.failure(CloneWorldResult.Failure.INVALID_WORLDNAME, replace("{world}").with(newWorldName)); @@ -492,7 +513,21 @@ public class WorldManager { Logging.severe("World already exist offline: " + newWorldName); return Result.failure(CloneWorldResult.Failure.WORLD_EXIST_OFFLINE, replace("{world}").with(newWorldName)); } + return Result.success(); + } + private Result cloneWorldCopyFolder(@NotNull CloneWorldOptions options) { + File worldFolder = options.world().getBukkitWorld().map(World::getWorldFolder).getOrNull(); // TODO: Check null? + File newWorldFolder = new File(Bukkit.getWorldContainer(), options.newWorldName()); + return filesManipulator.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES).fold( + (exception) -> Result.failure(CloneWorldResult.Failure.COPY_FAILED, + replace("{world}").with(options.world().getName()), + replace("{error}").with(exception.getMessage())), + (success) -> Result.success()); + } + + private void cloneWorldTransferData(@NotNull CloneWorldOptions options, @NotNull MVWorld newWorld) { + MVWorld world = options.world(); DataTransfer dataTransfer = new DataTransfer<>(); if (options.keepWorldConfig()) { dataTransfer.addDataStore(new WorldConfigStore(), world); @@ -503,29 +538,7 @@ public class WorldManager { 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); - return filesManipulator.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES).fold( - (exception) -> Result.failure(CloneWorldResult.Failure.COPY_FAILED, - replace("{world}").with(world.getName()), - replace("{error}").with(exception.getMessage())), - (success) -> { - var importResult = importWorld(ImportWorldOptions.worldName(newWorldName) - .environment(world.getEnvironment()) - .generator(world.getGenerator())); - if (importResult.isFailure()) { - return Result.failure(CloneWorldResult.Failure.IMPORT_FAILED, importResult.getReasonMessage()); - } - - getMVWorld(newWorldName).peek(newWorld -> { - dataTransfer.pasteAllTo(newWorld); - saveWorldsConfig(); - }); - return Result.success(CloneWorldResult.Success.CLONED, - replace("{world}").with(world.getName()), - replace("{newworld}").with(newWorldName)); - }); + dataTransfer.pasteAllTo(newWorld); } /** diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java index eed9528f..75a66aee 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java @@ -30,6 +30,7 @@ public class CloneWorldResult { WORLD_EXIST_LOADED(MVCorei18n.CLONEWORLD_WORLDEXISTLOADED), COPY_FAILED(MVCorei18n.CLONEWORLD_COPYFAILED), IMPORT_FAILED(null), + MV_WORLD_FAILED(null), // TODO ; private final MessageKeyProvider message;