From f9877201f5653063695d9e09a5ec88384a30f03e Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 19:43:56 +0800 Subject: [PATCH 1/8] Revamp results to support value returns --- .../MultiverseCore/commands/CloneCommand.java | 8 +- .../commands/CreateCommand.java | 8 +- .../commands/DeleteCommand.java | 20 +- .../commands/ImportCommand.java | 8 +- .../MultiverseCore/commands/LoadCommand.java | 8 +- .../MultiverseCore/commands/RegenCommand.java | 8 +- .../commands/RemoveCommand.java | 8 +- .../commands/UnloadCommand.java | 8 +- .../MultiverseCore/utils/result/Result.java | 238 +++++++++------ .../utils/result/ResultChain.java | 12 +- .../MultiverseCore/worldnew/WorldManager.java | 282 +++++++++--------- .../entrycheck/WorldEntryChecker.java | 8 +- .../resources/multiverse-core_en.properties | 4 +- 13 files changed, 342 insertions(+), 278 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java index d50ed9cb..ca7ef1e8 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java @@ -73,12 +73,12 @@ public class CloneCommand extends MultiverseCommand { .keepWorldConfig(!parsedFlags.hasFlag("--reset-world-config")) .keepGameRule(!parsedFlags.hasFlag("--reset-gamerules")) .keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border")) - ).onSuccess((success) -> { + ).onSuccess(success -> { Logging.fine("World remove success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { Logging.fine("World remove failure: " + failure); - issuer.sendError(failure.getReasonMessage()); + issuer.sendError(failure.getMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java index c06a1890..cd03ee4e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java @@ -104,12 +104,12 @@ public class CreateCommand extends MultiverseCommand { .useSpawnAdjust(!parsedFlags.hasFlag("--no-adjust-spawn")) .generator(parsedFlags.flagValue("--generator", "", String.class)) .generateStructures(!parsedFlags.hasFlag("--no-structures")) - ).onSuccess((success) -> { + ).onSuccess(success -> { Logging.fine("World create success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { Logging.fine("World create failure: " + failure); - issuer.sendError(failure.getReasonMessage()); + issuer.sendError(failure.getMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java index b30d0c23..b418ee0f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java @@ -49,14 +49,18 @@ public class DeleteCommand extends MultiverseCommand { issuer.getIssuer(), () -> { issuer.sendInfo(MVCorei18n.DELETE_DELETING, "{world}", worldName); - worldManager.deleteWorld(worldName) - .onSuccess((success) -> { - Logging.fine("World delete success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { - Logging.fine("World delete failure: " + failure); - issuer.sendError(failure.getReasonMessage()); - }); + try { + worldManager.deleteWorld(worldName) + .onSuccess(success -> { + Logging.fine("World delete success: " + success); + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { + Logging.fine("World delete failure: " + failure); + issuer.sendError(failure.getMessage()); + }); + } catch (Exception e) { + e.printStackTrace(); + } }, this.commandManager.formatMessage( issuer, diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java index e3886b25..69edac0f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java @@ -79,12 +79,12 @@ public class ImportCommand extends MultiverseCommand { .environment(environment) .generator(parsedFlags.flagValue("--generator", String.class)) .useSpawnAdjust(parsedFlags.hasFlag("--adjust-spawn")) - ).onSuccess((success) -> { + ).onSuccess(success -> { Logging.fine("World create success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { Logging.fine("World create failure: " + failure); - issuer.sendError(failure.getReasonMessage()); + issuer.sendError(failure.getMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java index 95a7a00e..451a32d5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java @@ -45,12 +45,12 @@ public class LoadCommand extends MultiverseCommand { ) { issuer.sendInfo(MVCorei18n.LOAD_LOADING, "{world}", worldName); worldManager.loadWorld(worldName) - .onSuccess((success) -> { + .onSuccess(success -> { Logging.fine("World load success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { Logging.fine("World load failure: " + failure); - issuer.sendError(failure.getReasonMessage()); + issuer.sendError(failure.getMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java index 5c8cb2d5..d691d3cf 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java @@ -85,12 +85,12 @@ public class RegenCommand extends MultiverseCommand { .keepWorldConfig(!parsedFlags.hasFlag("--reset-world-config")) .keepGameRule(!parsedFlags.hasFlag("--reset-gamerules")) .keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border")) - ).onSuccess((success) -> { + ).onSuccess(success -> { Logging.fine("World create success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { Logging.fine("World create failure: " + failure); - issuer.sendError(failure.getReasonMessage()); + issuer.sendError(failure.getMessage()); }); }, this.commandManager.formatMessage( diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java index dd1c77f6..a9e62b66 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java @@ -43,12 +43,12 @@ public class RemoveCommand extends MultiverseCommand { String worldName ) { worldManager.removeWorld(worldName) - .onSuccess((success) -> { + .onSuccess(success -> { Logging.fine("World remove success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { Logging.fine("World remove failure: " + failure); - issuer.sendError(failure.getReasonMessage()); + issuer.sendError(failure.getMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java index 81b1aeda..e949aa69 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java @@ -42,12 +42,12 @@ public class UnloadCommand extends MultiverseCommand { ) { issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING, "{world}", world.getAlias()); worldManager.unloadWorld(world) - .onSuccess((success) -> { + .onSuccess(success -> { Logging.fine("World unload success: " + success); - issuer.sendInfo(success.getReasonMessage()); - }).onFailure((failure) -> { + issuer.sendInfo(success.getMessage()); + }).onFailure(failure -> { Logging.fine("World unload failure: " + failure); - issuer.sendError(failure.getReasonMessage()); + issuer.sendError(failure.getMessage()); }); } } 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 980e525e..12f76b3d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java @@ -2,120 +2,189 @@ package com.onarandombox.MultiverseCore.utils.result; import com.onarandombox.MultiverseCore.utils.message.Message; import com.onarandombox.MultiverseCore.utils.message.MessageReplacement; -import org.jetbrains.annotations.NotNull; -import java.util.NoSuchElementException; -import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; -public sealed interface Result permits Result.Success, Result.Failure { - static Result success() { - return new Success<>(null, Message.of("Success!")); +public interface Result { + + static Result success() { + return new Success<>(null, null, Message.of("Success!")); } - static Result success(S successReason, MessageReplacement...replacements) { - return new Success<>(successReason, replacements); + static Result success( + S successReason, MessageReplacement... messageReplacements) { + return new Success<>(null, successReason, Message.of(successReason, "Success!", messageReplacements)); } - static Result success(S successReason, Message message) { - return new Success<>(successReason, message); + static Result success( + S successReason, Message message) { + return new Success<>(null, successReason, message); } - static Result failure() { + static Result successValue(T value) { + return new Success<>(value, null, Message.of("Success!")); + } + + static Result successValue( + T value, S successReason, MessageReplacement... messageReplacements) { + return new Success<>(value, successReason, Message.of(successReason, "Success!", messageReplacements)); + } + + static Result successValue( + T value, S successReason, Message message) { + return new Success<>(value, successReason, message); + } + + static Result failure() { return new Failure<>(null, Message.of("Failed!")); } - static Result failure(F failureReason, MessageReplacement...replacements) { - return new Failure<>(failureReason, replacements); + static Result failure( + F failureReason, MessageReplacement... messageReplacements) { + return new Failure<>(failureReason, Message.of(failureReason, "Failed!", messageReplacements)); } - static Result failure(F failureReason, Message message) { + static Result failure( + F failureReason, Message message) { return new Failure<>(failureReason, message); } - boolean isSuccess(); - boolean isFailure(); + T getValue(); S getSuccessReason(); F getFailureReason(); - @NotNull Message getReasonMessage(); + Message getMessage(); - default Result onSuccess(Consumer> consumer) { + default boolean isSuccess() { + return this instanceof Success; + } + + default boolean isFailure() { + return this instanceof Failure; + } + + default Result peek(Consumer consumer) { if (this instanceof Success) { - consumer.accept((Success) this); + consumer.accept(getValue()); } return this; } - default Result onFailure(Consumer> consumer) { - if (this instanceof Failure) { - consumer.accept((Failure) this); - } - return this; - } - - default Result onSuccessReason(S successReason, Consumer consumer) { - if (this.isSuccess() && this.getSuccessReason() == successReason) { - consumer.accept(this.getSuccessReason()); - } - return this; - } - - default Result onFailureReason(F failureReason, Consumer consumer) { - if (this.isFailure() && this.getFailureReason() == failureReason) { - consumer.accept(this.getFailureReason()); - } - return this; - } - - default Result onSuccessThen(Function, Result> function) { + default Result map(Function, Result> mapper) { if (this instanceof Success) { - return function.apply((Success) this); + return mapper.apply((Success) this); + } else { + return new Failure<>(getFailureReason(), getMessage()); + } + } + + default Result map(Supplier> mapper) { + if (this instanceof Success) { + return mapper.get(); + } else { + return new Failure<>(getFailureReason(), getMessage()); + } + } + + default Result mapValue(Function> mapper) { + if (this instanceof Success) { + return mapper.apply(this.getValue()); + } else { + return new Failure<>(getFailureReason(), getMessage()); + } + } + + default Result convertReason( + NS success, NF failure) { + if (this instanceof Success) { + return new Success<>(getValue(), success, getMessage()); + } else { + return new Failure<>(failure, getMessage()); + } + } + + default N fold(Function, N> failureMapper, Function, N> successMapper) { + if (this instanceof Success) { + return successMapper.apply((Success) this); + } else { + return failureMapper.apply((Failure) this); + } + } + + default Result onSuccess(Runnable runnable) { + if (this instanceof Success) { + runnable.run(); } return this; } - default Result onFailureThen(Function, Result> function) { - if (this instanceof Failure) { - return function.apply((Failure) this); + default Result onSuccess(Consumer> consumer) { + if (this instanceof Success) { + consumer.accept((Success) 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); + default Result onSuccessReason(S successReason, Runnable runnable) { + if (this instanceof Success && this.getSuccessReason() == successReason) { + runnable.run(); } - throw new IllegalStateException("Unknown result type: " + this.getClass().getName()); + return this; } - final class Success implements Result { + default Result onSuccessValue(Consumer consumer) { + if (this instanceof Success) { + consumer.accept(getValue()); + } + return this; + } + + default Result onSuccessReason(Consumer consumer) { + if (this instanceof Success) { + consumer.accept(getSuccessReason()); + } + return this; + } + + default Result onFailure(Runnable runnable) { + if (this instanceof Failure) { + runnable.run(); + } + return this; + } + + default Result onFailure(Consumer> consumer) { + if (this instanceof Failure) { + consumer.accept((Failure) this); + } + return this; + } + + default Result onFailureReason(Consumer consumer) { + if (this instanceof Failure) { + consumer.accept(getFailureReason()); + } + return this; + } + + class Success implements Result { + private final T value; private final S successReason; private final Message message; - public Success(S successReason, Message message) { + Success(T value, S successReason, Message message) { + this.value = value; this.successReason = successReason; this.message = message; } - public Success(S successReason, MessageReplacement[] replacements) { - this.successReason = successReason; - this.message = Message.of(successReason, "Success!", replacements); - } - @Override - public boolean isSuccess() { - return true; - } - - @Override - public boolean isFailure() { - return false; + public T getValue() { + return value; } @Override @@ -125,49 +194,40 @@ public sealed interface Result @Override public F getFailureReason() { - throw new NoSuchElementException("No reason for failure"); + return null; } @Override - public @NotNull Message getReasonMessage() { + public Message getMessage() { return message; } @Override public String toString() { - return "Success{" + - "reason=" + successReason + - '}'; + return "Success{" + + "reason=" + successReason + ", " + + "value=" + value + + '}'; } } - final class Failure implements Result { + class Failure implements Result { private final F failureReason; private final Message message; - public Failure(F failureReason, Message message) { + Failure(F failureReason, Message message) { this.failureReason = failureReason; this.message = message; } - public Failure(F failureReason, MessageReplacement[] replacements) { - this.failureReason = failureReason; - this.message = Message.of(failureReason, "Success!", replacements); - } - @Override - public boolean isSuccess() { - return false; - } - - @Override - public boolean isFailure() { - return true; + public T getValue() { + return null; } @Override public S getSuccessReason() { - throw new NoSuchElementException("No reason for failure"); + return null; } @Override @@ -176,15 +236,15 @@ public sealed interface Result } @Override - public @NotNull Message getReasonMessage() { + public Message getMessage() { return message; } @Override public String toString() { - return "Failure{" + - "reason=" + failureReason + - '}'; + return "Failure{" + + "reason=" + failureReason + + '}'; } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java b/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java index 752317dc..405f7ef6 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java @@ -21,9 +21,9 @@ public class ResultChain { } private final boolean isSuccess; - private final List> results; + private final List> results; - ResultChain(boolean isSuccess, List> results) { + ResultChain(boolean isSuccess, List> results) { this.isSuccess = isSuccess; this.results = results; } @@ -102,7 +102,7 @@ public class ResultChain { } public Message getLastResultMessage() { - return Iterables.getLast(results).getReasonMessage(); + return Iterables.getLast(results).getMessage(); } @Override @@ -115,7 +115,7 @@ public class ResultChain { public static class Builder { private final boolean stopOnFailure; - private final List> results; + private final List> results; private boolean isSuccess = true; @@ -124,11 +124,11 @@ public class ResultChain { this.results = new ArrayList<>(); } - public Builder then(Supplier> resultSupplier) { + public Builder then(Supplier> resultSupplier) { if (!isSuccess && stopOnFailure) { return this; } - Result result = resultSupplier.get(); + Result result = resultSupplier.get(); if (result.isFailure()) { isSuccess = false; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java index 54159120..65903dbe 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java @@ -47,6 +47,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import static com.onarandombox.MultiverseCore.utils.message.MessageReplacement.replace; import static com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.WorldBorderStore; @@ -169,25 +170,22 @@ public class WorldManager { * @param options The options for customizing the creation of a new world. * @return The result of the creation. */ - public Result createWorld(CreateWorldOptions options) { - return invalidateCreateWorldOptions(options).getOrElse(() -> createValidatedWorld(options)); + public Result createWorld(CreateWorldOptions options) { + return validateCreateWorldOptions(options).mapValue(this::createValidatedWorld); } - private Option> invalidateCreateWorldOptions( + private Result validateCreateWorldOptions( CreateWorldOptions options) { - Result result = null; - if (!worldNameChecker.isValidWorldName(options.worldName())) { - result = worldActionResult(CreateWorldResult.Failure.INVALID_WORLDNAME, options.worldName()); + return worldActionResult(CreateWorldResult.Failure.INVALID_WORLDNAME, options.worldName()); } else if (getLoadedWorld(options.worldName()).isDefined()) { - result = worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_LOADED, options.worldName()); + return worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_LOADED, options.worldName()); } else if (getWorld(options.worldName()).isDefined()) { - result = worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_UNLOADED, options.worldName()); + return worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_UNLOADED, options.worldName()); } else if (hasWorldFolder(options.worldName())) { - result = worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_FOLDER, options.worldName()); + return worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_FOLDER, options.worldName()); } - - return Option.of(result); + return Result.successValue(options); } private boolean hasWorldFolder(String worldName) { @@ -195,21 +193,25 @@ public class WorldManager { return worldFolder.exists(); } - private Result createValidatedWorld( + private Result createValidatedWorld( CreateWorldOptions options) { String parsedGenerator = parseGenerator(options.worldName(), options.generator()); - return createBukkitWorld(WorldCreator.name(options.worldName()) + WorldCreator worldCreator = WorldCreator.name(options.worldName()) .environment(options.environment()) .generateStructures(options.generateStructures()) .generator(parsedGenerator) .seed(options.seed()) - .type(options.worldType())).fold( - exception -> worldActionResult(CreateWorldResult.Failure.BUKKIT_CREATION_FAILED, - options.worldName(), exception.getMessage()), - world -> { - newLoadedMultiverseWorld(world, parsedGenerator, options.useSpawnAdjust()); - return worldActionResult(CreateWorldResult.Success.CREATED, world.getName()); - }); + .type(options.worldType()); + return createBukkitWorld(worldCreator).fold( + exception -> worldActionResult(CreateWorldResult.Failure.BUKKIT_CREATION_FAILED, + options.worldName(), exception), + world -> { + LoadedMultiverseWorld loadedWorld = newLoadedMultiverseWorld( + world, + parsedGenerator, + options.useSpawnAdjust()); + return worldActionResult(loadedWorld, CreateWorldResult.Success.CREATED, world.getName()); + }); } /** @@ -218,39 +220,41 @@ public class WorldManager { * @param options The options for customizing the import of an existing world folder. * @return The result of the import. */ - public Result importWorld(ImportWorldOptions options) { - return invalidateImportWorldOptions(options).getOrElse(() -> importValidatedWorld(options)); - } - - private Option> invalidateImportWorldOptions( + public Result importWorld( ImportWorldOptions options) { - Result result = null; - - if (!worldNameChecker.isValidWorldName(options.worldName())) { - result = worldActionResult(ImportWorldResult.Failure.INVALID_WORLDNAME, options.worldName()); - } else if (!worldNameChecker.isValidWorldFolder(options.worldName())) { - result = worldActionResult(ImportWorldResult.Failure.WORLD_FOLDER_INVALID, options.worldName()); - } else if (isLoadedWorld(options.worldName())) { - result = worldActionResult(ImportWorldResult.Failure.WORLD_EXIST_LOADED, options.worldName()); - } else if (isWorld(options.worldName())) { - result = worldActionResult(ImportWorldResult.Failure.WORLD_EXIST_UNLOADED, options.worldName()); - } - - return Option.of(result); + return validateImportWorldOptions(options).mapValue(this::doImportWorld); } - private Result importValidatedWorld( + private Result validateImportWorldOptions( + ImportWorldOptions options) { + String worldName = options.worldName(); + if (!worldNameChecker.isValidWorldName(worldName)) { + return worldActionResult(ImportWorldResult.Failure.INVALID_WORLDNAME, worldName); + } else if (!worldNameChecker.isValidWorldFolder(worldName)) { + return worldActionResult(ImportWorldResult.Failure.WORLD_FOLDER_INVALID, worldName); + } else if (isLoadedWorld(worldName)) { + return worldActionResult(ImportWorldResult.Failure.WORLD_EXIST_LOADED, worldName); + } else if (isWorld(worldName)) { + return worldActionResult(ImportWorldResult.Failure.WORLD_EXIST_UNLOADED, worldName); + } + return Result.successValue(options); + } + + private Result doImportWorld( ImportWorldOptions options) { String parsedGenerator = parseGenerator(options.worldName(), options.generator()); - return createBukkitWorld(WorldCreator.name(options.worldName()) + WorldCreator worldCreator = WorldCreator.name(options.worldName()) .environment(options.environment()) - .generator(parsedGenerator)).fold( - exception -> worldActionResult(ImportWorldResult.Failure.BUKKIT_CREATION_FAILED, - options.worldName(), exception.getMessage()), - world -> { - newLoadedMultiverseWorld(world, parsedGenerator, options.useSpawnAdjust()); - return worldActionResult(ImportWorldResult.Success.IMPORTED, options.worldName()); - }); + .generator(parsedGenerator); + return createBukkitWorld(worldCreator).fold( + exception -> worldActionResult(ImportWorldResult.Failure.BUKKIT_CREATION_FAILED, + options.worldName(), exception), + world -> { + LoadedMultiverseWorld loadedWorld = newLoadedMultiverseWorld(world, + parsedGenerator, + options.useSpawnAdjust()); + return worldActionResult(loadedWorld, ImportWorldResult.Success.IMPORTED, options.worldName()); + }); } /** @@ -273,7 +277,8 @@ public class WorldManager { * @param generator The generator string. * @param adjustSpawn Whether to adjust spawn. */ - private void newLoadedMultiverseWorld(@NotNull World world, @Nullable String generator, boolean adjustSpawn) { + private LoadedMultiverseWorld newLoadedMultiverseWorld( + @NotNull World world, @Nullable String generator, boolean adjustSpawn) { WorldConfig worldConfig = worldsConfigManager.addWorldConfig(world.getName()); worldConfig.setAdjustSpawn(adjustSpawn); worldConfig.setGenerator(generator == null ? "" : generator); @@ -289,6 +294,7 @@ public class WorldManager { locationManipulation); loadedWorldsMap.put(loadedWorld.getName(), loadedWorld); saveWorldsConfig(); + return loadedWorld; } /** @@ -297,7 +303,7 @@ public class WorldManager { * @param worldName The name of the world to load. * @return The result of the load. */ - public Result loadWorld(@NotNull String worldName) { + public Result loadWorld(@NotNull String worldName) { return getWorld(worldName) .map(this::loadWorld) .getOrElse(() -> worldNameChecker.isValidWorldFolder(worldName) @@ -311,34 +317,32 @@ public class WorldManager { * @param mvWorld The world to load. * @return The result of the load. */ - public Result loadWorld(@NotNull MultiverseWorld mvWorld) { - return invalidateWorldToLoad(mvWorld).getOrElse(() -> loadValidatedWorld(mvWorld)); + public Result loadWorld(@NotNull MultiverseWorld mvWorld) { + return validateWorldToLoad(mvWorld).map(() -> doLoadWorld(mvWorld)); } - private Option> invalidateWorldToLoad( + private Result validateWorldToLoad( @NotNull MultiverseWorld mvWorld) { - Result result = null; - if (loadTracker.contains(mvWorld.getName())) { // This is to prevent recursive calls by WorldLoadEvent Logging.fine("World already loading: " + mvWorld.getName()); - result = worldActionResult(LoadWorldResult.Failure.WORLD_ALREADY_LOADING, mvWorld.getName()); + return worldActionResult(LoadWorldResult.Failure.WORLD_ALREADY_LOADING, mvWorld.getName()); } else if (isLoadedWorld(mvWorld)) { Logging.severe("World already loaded: " + mvWorld.getName()); - result = worldActionResult(LoadWorldResult.Failure.WORLD_EXIST_LOADED, mvWorld.getName()); + return worldActionResult(LoadWorldResult.Failure.WORLD_EXIST_LOADED, mvWorld.getName()); } - return Option.of(result); + return Result.success(); } - private Result loadValidatedWorld( + private Result doLoadWorld( @NotNull MultiverseWorld mvWorld) { return createBukkitWorld(WorldCreator.name(mvWorld.getName()) .environment(mvWorld.getEnvironment()) .generator(Strings.isNullOrEmpty(mvWorld.getGenerator()) ? null : mvWorld.getGenerator()) .seed(mvWorld.getSeed())).fold( exception -> worldActionResult(LoadWorldResult.Failure.BUKKIT_CREATION_FAILED, - mvWorld.getName(), exception.getMessage()), + mvWorld.getName(), exception), world -> { // TODO: Check worldConfig null WorldConfig worldConfig = worldsConfigManager.getWorldConfig(mvWorld.getName()); @@ -350,7 +354,7 @@ public class WorldManager { locationManipulation); loadedWorldsMap.put(loadedWorld.getName(), loadedWorld); saveWorldsConfig(); - return worldActionResult(LoadWorldResult.Success.LOADED, loadedWorld.getName()); + return worldActionResult(loadedWorld, LoadWorldResult.Success.LOADED, loadedWorld.getName()); }); } @@ -360,7 +364,7 @@ public class WorldManager { * @param world The bukkit world to unload. * @return The result of the unload action. */ - public Result unloadWorld(@NotNull World world) { + public Result unloadWorld(@NotNull World world) { return unloadWorld(world.getName()); } @@ -370,7 +374,7 @@ public class WorldManager { * @param worldName The name of the world to unload. * @return The result of the unload action. */ - public Result unloadWorld(@NotNull String worldName) { + public Result unloadWorld(@NotNull String worldName) { return getLoadedWorld(worldName) .map(this::unloadWorld) .getOrElse(() -> isUnloadedWorld(worldName) @@ -384,7 +388,7 @@ public class WorldManager { * @param world The multiverse world to unload. * @return The result of the unload action. */ - public Result unloadWorld( + public Result unloadWorld( @NotNull LoadedMultiverseWorld world) { if (unloadTracker.contains(world.getName())) { // This is to prevent recursive calls by WorldUnloadEvent @@ -396,7 +400,7 @@ public class WorldManager { return unloadBukkitWorld(world.getBukkitWorld().getOrNull()).fold( exception -> worldActionResult(UnloadWorldResult.Failure.BUKKIT_UNLOAD_FAILED, - world.getName(), exception.getMessage()), + world.getName(), exception), success -> Option.of(loadedWorldsMap.remove(world.getName())).fold( () -> { Logging.severe("Failed to remove world from map: " + world.getName()); @@ -405,7 +409,8 @@ public class WorldManager { mvWorld -> { Logging.fine("Removed MultiverseWorld from map: " + world.getName()); mvWorld.getWorldConfig().deferenceMVWorld(); - return worldActionResult(UnloadWorldResult.Success.UNLOADED, world.getName()); + return worldActionResult(getWorld(mvWorld.getName()).getOrNull(), + UnloadWorldResult.Success.UNLOADED, world.getName()); })); } @@ -416,7 +421,7 @@ public class WorldManager { * @param worldName The name of the world to remove. * @return The result of the remove. */ - public Result removeWorld( + public Result removeWorld( @NotNull String worldName) { return getWorld(worldName) .map(this::removeWorld) @@ -430,7 +435,7 @@ public class WorldManager { * @param world The multiverse world to remove. * @return The result of the remove. */ - public Result removeWorld(@NotNull MultiverseWorld world) { + public Result removeWorld(@NotNull MultiverseWorld world) { return getLoadedWorld(world).fold( () -> removeWorldFromConfig(world), this::removeWorld); @@ -443,11 +448,11 @@ public class WorldManager { * @param loadedWorld The multiverse world to remove. * @return The result of the remove. */ - public Result removeWorld( + public Result removeWorld( @NotNull LoadedMultiverseWorld loadedWorld) { var result = unloadWorld(loadedWorld); if (result.isFailure()) { - return Result.failure(RemoveWorldResult.Failure.UNLOAD_FAILED, result.getReasonMessage()); + return Result.failure(RemoveWorldResult.Failure.UNLOAD_FAILED, result.getMessage()); } return removeWorldFromConfig(loadedWorld); } @@ -458,14 +463,14 @@ public class WorldManager { * @param world The multiverse world to remove. * @return The result of the remove. */ - private Result + private Result removeWorldFromConfig(@NotNull MultiverseWorld world) { // Remove world from config worldsMap.remove(world.getName()); worldsConfigManager.deleteWorldConfig(world.getName()); saveWorldsConfig(); - return Result.success(RemoveWorldResult.Success.REMOVED); + return worldActionResult(RemoveWorldResult.Success.REMOVED, world.getName()); } /** @@ -475,7 +480,7 @@ public class WorldManager { * @param worldName The name of the world to delete. * @return The result of the delete action. */ - public Result deleteWorld(@NotNull String worldName) { + public Result deleteWorld(@NotNull String worldName) { return getWorld(worldName) .map(this::deleteWorld) .getOrElse(() -> worldActionResult(DeleteWorldResult.Failure.WORLD_NON_EXISTENT, worldName)); @@ -488,15 +493,11 @@ public class WorldManager { * @param world The world to delete. * @return The result of the delete action. */ - public Result deleteWorld(@NotNull MultiverseWorld world) { + public Result deleteWorld(@NotNull MultiverseWorld world) { return getLoadedWorld(world).fold( - () -> { - var result = loadWorld(world); - if (result.isFailure()) { - return worldActionResult(DeleteWorldResult.Failure.LOAD_FAILED, world.getName()); - } - return deleteWorld(world); - }, + () -> loadWorld(world) + .convertReason((DeleteWorldResult.Success) null, DeleteWorldResult.Failure.LOAD_FAILED) + .mapValue(this::deleteWorld), this::deleteWorld); } @@ -506,25 +507,27 @@ public class WorldManager { * @param world The multiverse world to delete. * @return The result of the delete action. */ - public Result + public Result deleteWorld(@NotNull LoadedMultiverseWorld world) { + // TODO: Possible config options to keep certain files + AtomicReference worldFolder = new AtomicReference<>(); + return validateWorldToDelete(world) + .peek(worldFolder::set) + .map(() -> removeWorld(world).convertReason(null, DeleteWorldResult.Failure.REMOVE_FAILED)) + .map(() -> filesManipulator.deleteFolder(worldFolder.get()).fold( + exception -> worldActionResult(DeleteWorldResult.Failure.FAILED_TO_DELETE_FOLDER, + world.getName(), exception), + success -> worldActionResult(DeleteWorldResult.Success.DELETED, world.getName()))); + } + + private Result validateWorldToDelete( + @NotNull LoadedMultiverseWorld world) { File worldFolder = world.getBukkitWorld().map(World::getWorldFolder).getOrNull(); if (worldFolder == null || !worldNameChecker.isValidWorldFolder(worldFolder)) { Logging.severe("Failed to get world folder for world: " + world.getName()); return worldActionResult(DeleteWorldResult.Failure.WORLD_FOLDER_NOT_FOUND, world.getName()); } - - var result = removeWorld(world); - if (result.isFailure()) { - return Result.failure(DeleteWorldResult.Failure.REMOVE_FAILED, result.getReasonMessage()); - } - - // Erase world files from disk - // TODO: Possible config options to keep certain files - return filesManipulator.deleteFolder(worldFolder).fold( - exception -> worldActionResult(DeleteWorldResult.Failure.FAILED_TO_DELETE_FOLDER, - world.getName(), exception.getMessage()), - success -> worldActionResult(DeleteWorldResult.Success.DELETED, world.getName())); + return Result.successValue(worldFolder); } /** @@ -533,29 +536,23 @@ public class WorldManager { * @param options The options for customizing the cloning of a world. * @return The result of the clone. */ - public Result cloneWorld(@NotNull CloneWorldOptions options) { + public Result cloneWorld(@NotNull CloneWorldOptions options) { 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 -> getLoadedWorld(options.newWorldName()).fold( - () -> worldActionResult(CloneWorldResult.Failure.MV_WORLD_FAILED, options.newWorldName()), - mvWorld -> { - cloneWorldTransferData(options, mvWorld); - saveWorldsConfig(); - return Result.success(CloneWorldResult.Success.CLONED, - replaceWorldName(options.world().getName()), - replace("{newworld}").with(mvWorld.getName())); - })); + .mapValue(this::cloneWorldCopyFolder) + .mapValue(validatedOptions -> { + ImportWorldOptions importWorldOptions = ImportWorldOptions.worldName(validatedOptions.newWorldName()) + .environment(validatedOptions.world().getEnvironment()) + .generator(validatedOptions.world().getGenerator()); + return importWorld(importWorldOptions).convertReason(null, CloneWorldResult.Failure.IMPORT_FAILED); + }) + .mapValue(newWorld -> { + cloneWorldTransferData(options, newWorld); + saveWorldsConfig(); + return worldActionResult(CloneWorldResult.Success.CLONED, newWorld.getName()); + }); } - private Result cloneWorldValidateWorld( + private Result cloneWorldValidateWorld( @NotNull CloneWorldOptions options) { String newWorldName = options.newWorldName(); if (!worldNameChecker.isValidWorldName(newWorldName)) { @@ -573,18 +570,18 @@ public class WorldManager { Logging.severe("World already exist unloaded: " + newWorldName); return worldActionResult(CloneWorldResult.Failure.WORLD_EXIST_UNLOADED, newWorldName); } - return Result.success(); + return Result.successValue(options); } - private Result cloneWorldCopyFolder( + private Result cloneWorldCopyFolder( @NotNull CloneWorldOptions options) { // TODO: Check null? File worldFolder = options.world().getBukkitWorld().map(World::getWorldFolder).getOrNull(); File newWorldFolder = new File(Bukkit.getWorldContainer(), options.newWorldName()); return filesManipulator.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES).fold( - exception -> worldActionResult(CloneWorldResult.Failure.COPY_FAILED, options.world().getName(), - exception.getMessage()), - success -> Result.success()); + exception -> worldActionResult(CloneWorldResult.Failure.COPY_FAILED, + options.world().getName(), exception), + success -> Result.successValue(options)); } private void cloneWorldTransferData(@NotNull CloneWorldOptions options, @NotNull LoadedMultiverseWorld newWorld) { @@ -615,12 +612,11 @@ public class WorldManager { * @param options The options for customizing the regeneration of a world. * @return The result of the regeneration. */ - public Result regenWorld(@NotNull RegenWorldOptions options) { + public Result regenWorld(@NotNull RegenWorldOptions options) { // TODO: Teleport players out of world, and back in after regen + LoadedMultiverseWorld world = options.world(); - DataTransfer dataTransfer = transferData(options, world); - CreateWorldOptions createWorldOptions = CreateWorldOptions.worldName(world.getName()) .environment(world.getEnvironment()) .generateStructures(world.canGenerateStructures().getOrElse(true)) @@ -628,36 +624,40 @@ public class WorldManager { .seed(options.seed()) .worldType(world.getWorldType().getOrElse(WorldType.NORMAL)); - var deleteResult = deleteWorld(world); - if (deleteResult.isFailure()) { - return Result.failure(RegenWorldResult.Failure.DELETE_FAILED, deleteResult.getReasonMessage()); - } - - var createResult = createWorld(createWorldOptions); - if (createResult.isFailure()) { - return Result.failure(RegenWorldResult.Failure.CREATE_FAILED, createResult.getReasonMessage()); - } - - getLoadedWorld(createWorldOptions.worldName()).peek(newWorld -> { - dataTransfer.pasteAllTo(newWorld); - saveWorldsConfig(); - }); - return worldActionResult(RegenWorldResult.Success.REGENERATED, world.getName()); + return deleteWorld(world) + .convertReason((RegenWorldResult.Success) null, RegenWorldResult.Failure.DELETE_FAILED) + .map(() -> createWorld(createWorldOptions).convertReason(null, RegenWorldResult.Failure.CREATE_FAILED)) + .mapValue(newWorld -> { + dataTransfer.pasteAllTo(newWorld); + saveWorldsConfig(); + return worldActionResult(newWorld, RegenWorldResult.Success.REGENERATED, newWorld.getName()); + }); } - private Result worldActionResult( + private Result worldActionResult( @NotNull S messageKeyProvider, @NotNull String worldName) { return Result.success(messageKeyProvider, replaceWorldName(worldName)); } - private Result worldActionResult( + private Result worldActionResult( + @NotNull T value, @NotNull S successReason, @NotNull String worldName) { + return Result.successValue(value, successReason, replaceWorldName(worldName)); + } + + private Result worldActionResult( + @NotNull F failureReason, @NotNull Result result) { + return Result.failure(failureReason, result.getMessage()); + } + + private Result worldActionResult( @NotNull F messageKeyProvider, @NotNull String worldName) { return Result.failure(messageKeyProvider, replaceWorldName(worldName)); } - private Result worldActionResult( - @NotNull F messageKeyProvider, @NotNull String worldName, @NotNull String errorMessage) { - return Result.failure(messageKeyProvider, replaceWorldName(worldName), replaceError(errorMessage)); + private Result worldActionResult( + @NotNull F messageKeyProvider, @NotNull String worldName, @NotNull Throwable error) { + // TODO: Localize error message if its a MultiverseException + return Result.failure(messageKeyProvider, replaceWorldName(worldName), replaceError(error.getMessage())); } private MessageReplacement replaceWorldName(@NotNull String worldName) { diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java index 47b7faae..13285950 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java @@ -50,7 +50,7 @@ public class WorldEntryChecker { .build(); } - public Result canAccessWorld(@NotNull MultiverseWorld world) { + public Result canAccessWorld(@NotNull MultiverseWorld world) { if (!config.getEnforceAccess()) { return Result.success(WorldAccessResult.Success.NO_ENFORCE_WORLD_ACCESS); } @@ -59,7 +59,7 @@ public class WorldEntryChecker { : Result.failure(WorldAccessResult.Failure.NO_WORLD_ACCESS); } - public Result isWithinPlayerLimit(@NotNull LoadedMultiverseWorld world) { + public Result isWithinPlayerLimit(@NotNull LoadedMultiverseWorld world) { final int playerLimit = world.getPlayerLimit(); if (playerLimit <= -1) { return Result.success(PlayerLimitResult.Success.NO_PLAYERLIMIT); @@ -72,7 +72,7 @@ public class WorldEntryChecker { : Result.failure(PlayerLimitResult.Failure.EXCEED_PLAYERLIMIT); } - public Result isNotBlacklisted(@Nullable LoadedMultiverseWorld fromWorld, @NotNull LoadedMultiverseWorld toWorld) { + public Result isNotBlacklisted(@Nullable LoadedMultiverseWorld fromWorld, @NotNull LoadedMultiverseWorld toWorld) { if (fromWorld == null) { return Result.success(BlacklistResult.Success.UNKNOWN_FROM_WORLD); } @@ -81,7 +81,7 @@ public class WorldEntryChecker { : Result.success(BlacklistResult.Success.NOT_BLACKLISTED); } - public Result canPayEntryFee(LoadedMultiverseWorld world) { + public Result canPayEntryFee(LoadedMultiverseWorld world) { double price = world.getPrice(); Material currency = world.getCurrency(); if (price == 0D && (currency == null || currency == EntryFee.DISABLED_MATERIAL)) { diff --git a/src/main/resources/multiverse-core_en.properties b/src/main/resources/multiverse-core_en.properties index 0143c2fe..16f760fb 100644 --- a/src/main/resources/multiverse-core_en.properties +++ b/src/main/resources/multiverse-core_en.properties @@ -130,12 +130,12 @@ mv-core.entrycheck.exceedplayerlimit=the world has reached its player limit. mv-core.entrycheck.noworldaccess=you do not have permissions to access the world. # world manager result -mv-core.cloneworld.cloned=&aWorld '{world}' cloned to '{newworld}'! +mv-core.cloneworld.cloned=&aWorld cloned to '{world}'! mv-core.cloneworld.invalidworldname=World '{world}' contains invalid characters! mv-core.cloneworld.worldexistfolder=World '{world}' exists in server folders! You need to delete it first before cloning. mv-core.cloneworld.worldexistunloaded=World '{world}' already exists and it's unloaded! You need to delete it first before cloning. mv-core.cloneworld.worldexistloaded=World '{world}' already exists! You need to delete it first before cloning. -mv-core.cloneworld.copyfailed=Failed to copy world '{world}' to '{newworld}': {error}\n&fSee console for more details. +mv-core.cloneworld.copyfailed=Failed to copy world to '{world}': {error}\n&fSee console for more details. mv-core.createworld.created=&aWorld '{world}' created! mv-core.createworld.invalidworldname=World '{world}' contains invalid characters! From c8fed721374914f3f890d99c8f55bb0e90a1f54d Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 21:37:36 +0800 Subject: [PATCH 2/8] Refactor to `Result` and `Attempt` --- .../MultiverseCore/commands/CloneCommand.java | 10 +- .../commands/CreateCommand.java | 9 +- .../commands/DeleteCommand.java | 8 +- .../commands/ImportCommand.java | 10 +- .../MultiverseCore/commands/LoadCommand.java | 8 +- .../MultiverseCore/commands/RegenCommand.java | 10 +- .../commands/RemoveCommand.java | 9 +- .../commands/UnloadCommand.java | 8 +- .../MultiverseCore/utils/result/Attempt.java | 174 ++++++++++++++ .../MultiverseCore/utils/result/Result.java | 214 +++++------------- .../utils/result/ResultChain.java | 12 +- .../MultiverseCore/worldnew/WorldManager.java | 138 +++++------ .../entrycheck/WorldEntryChecker.java | 8 +- 13 files changed, 334 insertions(+), 284 deletions(-) create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java index ca7ef1e8..de3e6dde 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java @@ -73,12 +73,12 @@ public class CloneCommand extends MultiverseCommand { .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.getMessage()); + ).onSuccess(newWorld -> { + Logging.fine("World clone success: " + newWorld); + issuer.sendInfo(MVCorei18n.CLONEWORLD_CLONED, "{world}", newWorld.getName()); }).onFailure(failure -> { - Logging.fine("World remove failure: " + failure); - issuer.sendError(failure.getMessage()); + Logging.fine("World clone failure: " + failure); + issuer.sendError(failure.getFailureMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java index cd03ee4e..d368b948 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java @@ -3,7 +3,6 @@ package com.onarandombox.MultiverseCore.commands; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; -import co.aikar.commands.annotation.Conditions; import co.aikar.commands.annotation.Description; import co.aikar.commands.annotation.Optional; import co.aikar.commands.annotation.Subcommand; @@ -104,12 +103,12 @@ public class CreateCommand extends MultiverseCommand { .useSpawnAdjust(!parsedFlags.hasFlag("--no-adjust-spawn")) .generator(parsedFlags.flagValue("--generator", "", String.class)) .generateStructures(!parsedFlags.hasFlag("--no-structures")) - ).onSuccess(success -> { - Logging.fine("World create success: " + success); - issuer.sendInfo(success.getMessage()); + ).onSuccess(newWorld -> { + Logging.fine("World create success: " + newWorld); + issuer.sendInfo(MVCorei18n.CREATEWORLD_CREATED, "{world}", newWorld.getName()); }).onFailure(failure -> { Logging.fine("World create failure: " + failure); - issuer.sendError(failure.getMessage()); + issuer.sendError(failure.getFailureMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java index b418ee0f..434a9c40 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java @@ -51,12 +51,12 @@ public class DeleteCommand extends MultiverseCommand { issuer.sendInfo(MVCorei18n.DELETE_DELETING, "{world}", worldName); try { worldManager.deleteWorld(worldName) - .onSuccess(success -> { - Logging.fine("World delete success: " + success); - issuer.sendInfo(success.getMessage()); + .onSuccess(deletedWorldName -> { + Logging.fine("World delete success: " + deletedWorldName); + issuer.sendInfo(MVCorei18n.DELETEWORLD_DELETED, "{world}", deletedWorldName); }).onFailure(failure -> { Logging.fine("World delete failure: " + failure); - issuer.sendError(failure.getMessage()); + issuer.sendError(failure.getFailureMessage()); }); } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java index 69edac0f..c7c60d9e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java @@ -79,12 +79,12 @@ public class ImportCommand extends MultiverseCommand { .environment(environment) .generator(parsedFlags.flagValue("--generator", String.class)) .useSpawnAdjust(parsedFlags.hasFlag("--adjust-spawn")) - ).onSuccess(success -> { - Logging.fine("World create success: " + success); - issuer.sendInfo(success.getMessage()); + ).onSuccess(newWorld -> { + Logging.fine("World import success: " + newWorld); + issuer.sendInfo(MVCorei18n.IMPORTWORLD_IMPORTED, "{world}", newWorld.getName()); }).onFailure(failure -> { - Logging.fine("World create failure: " + failure); - issuer.sendError(failure.getMessage()); + Logging.fine("World import failure: " + failure); + issuer.sendError(failure.getFailureMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java index 451a32d5..33fcbca8 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java @@ -45,12 +45,12 @@ public class LoadCommand extends MultiverseCommand { ) { issuer.sendInfo(MVCorei18n.LOAD_LOADING, "{world}", worldName); worldManager.loadWorld(worldName) - .onSuccess(success -> { - Logging.fine("World load success: " + success); - issuer.sendInfo(success.getMessage()); + .onSuccess(newWorld -> { + Logging.fine("World load success: " + newWorld); + issuer.sendInfo(MVCorei18n.LOADWORLD_LOADED, "{world}", newWorld.getName()); }).onFailure(failure -> { Logging.fine("World load failure: " + failure); - issuer.sendError(failure.getMessage()); + issuer.sendError(failure.getFailureMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java index d691d3cf..9533f4f4 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java @@ -85,12 +85,12 @@ public class RegenCommand extends MultiverseCommand { .keepWorldConfig(!parsedFlags.hasFlag("--reset-world-config")) .keepGameRule(!parsedFlags.hasFlag("--reset-gamerules")) .keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border")) - ).onSuccess(success -> { - Logging.fine("World create success: " + success); - issuer.sendInfo(success.getMessage()); + ).onSuccess(newWorld -> { + Logging.fine("World regen success: " + newWorld); + issuer.sendInfo(MVCorei18n.REGENWORLD_REGENERATED, "{world}", newWorld.getName()); }).onFailure(failure -> { - Logging.fine("World create failure: " + failure); - issuer.sendError(failure.getMessage()); + Logging.fine("World regen failure: " + failure); + issuer.sendError(failure.getFailureMessage()); }); }, this.commandManager.formatMessage( diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java index a9e62b66..0d600b2d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/RemoveCommand.java @@ -12,6 +12,7 @@ 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.utils.MVCorei18n; import com.onarandombox.MultiverseCore.worldnew.WorldManager; import jakarta.inject.Inject; import org.jetbrains.annotations.NotNull; @@ -43,12 +44,12 @@ public class RemoveCommand extends MultiverseCommand { String worldName ) { worldManager.removeWorld(worldName) - .onSuccess(success -> { - Logging.fine("World remove success: " + success); - issuer.sendInfo(success.getMessage()); + .onSuccess(removedWorldName -> { + Logging.fine("World remove success: " + removedWorldName); + issuer.sendInfo(MVCorei18n.REMOVEWORLD_REMOVED, "{world}", removedWorldName); }).onFailure(failure -> { Logging.fine("World remove failure: " + failure); - issuer.sendError(failure.getMessage()); + issuer.sendError(failure.getFailureMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java index e949aa69..e7049871 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java @@ -42,12 +42,12 @@ public class UnloadCommand extends MultiverseCommand { ) { issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING, "{world}", world.getAlias()); worldManager.unloadWorld(world) - .onSuccess(success -> { - Logging.fine("World unload success: " + success); - issuer.sendInfo(success.getMessage()); + .onSuccess(loadedWorld -> { + Logging.fine("World unload success: " + loadedWorld); + issuer.sendInfo(MVCorei18n.UNLOADWORLD_UNLOADED, "{world}", loadedWorld.getName()); }).onFailure(failure -> { Logging.fine("World unload failure: " + failure); - issuer.sendError(failure.getMessage()); + issuer.sendError(failure.getFailureMessage()); }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java new file mode 100644 index 00000000..fe375bee --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java @@ -0,0 +1,174 @@ +package com.onarandombox.MultiverseCore.utils.result; + +import com.onarandombox.MultiverseCore.utils.message.Message; +import com.onarandombox.MultiverseCore.utils.message.MessageReplacement; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public interface Attempt { + + static Attempt success(T value) { + return new Success<>(value); + } + + static Attempt failure( + F failureReason, MessageReplacement... messageReplacements) { + return new Failure<>(failureReason, Message.of(failureReason, "Failed!", messageReplacements)); + } + + static Attempt failure(F failureReason, Message message) { + return new Failure<>(failureReason, message); + } + + T get(); + + F getFailureReason(); + + Message getFailureMessage(); + + default boolean isSuccess() { + return this instanceof Success; + } + + default boolean isFailure() { + return this instanceof Failure; + } + + default Attempt peek(Consumer consumer) { + if (this instanceof Success) { + consumer.accept(get()); + } + return this; + } + + default Attempt map(Function> mapper) { + if (this instanceof Success) { + return mapper.apply(this.get()); + } else { + return new Failure<>(getFailureReason(), getFailureMessage()); + } + } + + default Attempt map(Supplier> mapper) { + if (this instanceof Success) { + return mapper.get(); + } else { + return new Failure<>(getFailureReason(), getFailureMessage()); + } + } + + default Attempt convertReason(NF failure) { + if (this instanceof Success) { + return new Success<>(get()); + } else { + return new Failure<>(failure, getFailureMessage()); + } + } + + default N fold(Function, N> failureMapper, Function successMapper) { + if (this instanceof Success) { + return successMapper.apply(get()); + } else { + return failureMapper.apply((Failure) this); + } + } + + default Attempt onSuccess(Runnable runnable) { + if (this instanceof Success) { + runnable.run(); + } + return this; + } + + default Attempt onSuccess(Consumer consumer) { + if (this instanceof Success) { + consumer.accept(get()); + } + return this; + } + + default Attempt onFailure(Runnable runnable) { + if (this instanceof Failure) { + runnable.run(); + } + return this; + } + + default Attempt onFailure(Consumer> consumer) { + if (this instanceof Failure) { + consumer.accept((Failure) this); + } + return this; + } + + default Attempt onFailureReason(Consumer consumer) { + if (this instanceof Failure) { + consumer.accept(getFailureReason()); + } + return this; + } + + class Success implements Attempt { + private final T value; + + Success(T value) { + this.value = value; + } + + @Override + public T get() { + return value; + } + + @Override + public F getFailureReason() { + throw new IllegalStateException("Attempt is a success!"); + } + + @Override + public Message getFailureMessage() { + throw new IllegalStateException("Attempt is a success!"); + } + + @Override + public String toString() { + return "Success{" + + "value=" + value + + '}'; + } + } + + class Failure implements Attempt { + private final F failureReason; + private final Message message; + + Failure(F failureReason, Message message) { + this.failureReason = failureReason; + this.message = message; + } + + @Override + public T get() { + throw new IllegalStateException("Attempt is a failure!"); + } + + @Override + public F getFailureReason() { + return failureReason; + } + + @Override + public Message getFailureMessage() { + return message; + } + + @Override + public String toString() { + return "Failure{" + + "reason=" + failureReason + + '}'; + } + } +} 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 12f76b3d..03bcf789 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java @@ -2,189 +2,77 @@ package com.onarandombox.MultiverseCore.utils.result; import com.onarandombox.MultiverseCore.utils.message.Message; import com.onarandombox.MultiverseCore.utils.message.MessageReplacement; +import org.jetbrains.annotations.NotNull; +import java.util.NoSuchElementException; import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -public interface Result { - - static Result success() { - return new Success<>(null, null, Message.of("Success!")); +public sealed interface Result permits Result.Success, Result.Failure { + static Result success( + S successReason, MessageReplacement... replacements) { + return new Success<>(successReason, replacements); } - static Result success( - S successReason, MessageReplacement... messageReplacements) { - return new Success<>(null, successReason, Message.of(successReason, "Success!", messageReplacements)); + static Result failure( + F failureReason, MessageReplacement... replacements) { + return new Failure<>(failureReason, replacements); } - static Result success( - S successReason, Message message) { - return new Success<>(null, successReason, message); - } + boolean isSuccess(); - static Result successValue(T value) { - return new Success<>(value, null, Message.of("Success!")); - } - - static Result successValue( - T value, S successReason, MessageReplacement... messageReplacements) { - return new Success<>(value, successReason, Message.of(successReason, "Success!", messageReplacements)); - } - - static Result successValue( - T value, S successReason, Message message) { - return new Success<>(value, successReason, message); - } - - static Result failure() { - return new Failure<>(null, Message.of("Failed!")); - } - - static Result failure( - F failureReason, MessageReplacement... messageReplacements) { - return new Failure<>(failureReason, Message.of(failureReason, "Failed!", messageReplacements)); - } - - static Result failure( - F failureReason, Message message) { - return new Failure<>(failureReason, message); - } - - T getValue(); + boolean isFailure(); S getSuccessReason(); F getFailureReason(); - Message getMessage(); + @NotNull Message getReasonMessage(); - default boolean isSuccess() { - return this instanceof Success; - } - - default boolean isFailure() { - return this instanceof Failure; - } - - default Result peek(Consumer consumer) { - if (this instanceof Success) { - consumer.accept(getValue()); + default Result onSuccess(Consumer consumer) { + if (this.isSuccess()) { + consumer.accept(this.getSuccessReason()); } return this; } - default Result map(Function, Result> mapper) { - if (this instanceof Success) { - return mapper.apply((Success) this); - } else { - return new Failure<>(getFailureReason(), getMessage()); - } - } - - default Result map(Supplier> mapper) { - if (this instanceof Success) { - return mapper.get(); - } else { - return new Failure<>(getFailureReason(), getMessage()); - } - } - - default Result mapValue(Function> mapper) { - if (this instanceof Success) { - return mapper.apply(this.getValue()); - } else { - return new Failure<>(getFailureReason(), getMessage()); - } - } - - default Result convertReason( - NS success, NF failure) { - if (this instanceof Success) { - return new Success<>(getValue(), success, getMessage()); - } else { - return new Failure<>(failure, getMessage()); - } - } - - default N fold(Function, N> failureMapper, Function, N> successMapper) { - if (this instanceof Success) { - return successMapper.apply((Success) this); - } else { - return failureMapper.apply((Failure) this); - } - } - - default Result onSuccess(Runnable runnable) { - if (this instanceof Success) { - runnable.run(); + default Result onFailure(Consumer consumer) { + if (this.isFailure()) { + consumer.accept(this.getFailureReason()); } return this; } - default Result onSuccess(Consumer> consumer) { - if (this instanceof Success) { - consumer.accept((Success) this); + default Result onSuccessReason(S successReason, Consumer consumer) { + if (this.isSuccess() && this.getSuccessReason() == successReason) { + consumer.accept(this.getSuccessReason()); } return this; } - default Result onSuccessReason(S successReason, Runnable runnable) { - if (this instanceof Success && this.getSuccessReason() == successReason) { - runnable.run(); + default Result onFailureReason(F failureReason, Consumer consumer) { + if (this.isFailure() && this.getFailureReason() == failureReason) { + consumer.accept(this.getFailureReason()); } return this; } - default Result onSuccessValue(Consumer consumer) { - if (this instanceof Success) { - consumer.accept(getValue()); - } - return this; - } - - default Result onSuccessReason(Consumer consumer) { - if (this instanceof Success) { - consumer.accept(getSuccessReason()); - } - return this; - } - - default Result onFailure(Runnable runnable) { - if (this instanceof Failure) { - runnable.run(); - } - return this; - } - - default Result onFailure(Consumer> consumer) { - if (this instanceof Failure) { - consumer.accept((Failure) this); - } - return this; - } - - default Result onFailureReason(Consumer consumer) { - if (this instanceof Failure) { - consumer.accept(getFailureReason()); - } - return this; - } - - class Success implements Result { - private final T value; + final class Success implements Result { private final S successReason; - private final Message message; + private final MessageReplacement[] replacements; - Success(T value, S successReason, Message message) { - this.value = value; + public Success(S successReason, MessageReplacement[] replacements) { this.successReason = successReason; - this.message = message; + this.replacements = replacements; } @Override - public T getValue() { - return value; + public boolean isSuccess() { + return true; + } + + @Override + public boolean isFailure() { + return false; } @Override @@ -194,40 +82,44 @@ public interface Result { @Override public F getFailureReason() { - return null; + throw new NoSuchElementException("No reason for failure"); } @Override - public Message getMessage() { - return message; + public @NotNull Message getReasonMessage() { + return Message.of(successReason, "Success!", replacements); } @Override public String toString() { return "Success{" - + "reason=" + successReason + ", " - + "value=" + value + + "reason=" + successReason + '}'; } } - class Failure implements Result { + final class Failure implements Result { private final F failureReason; - private final Message message; + private final MessageReplacement[] replacements; - Failure(F failureReason, Message message) { + public Failure(F failureReason, MessageReplacement[] replacements) { this.failureReason = failureReason; - this.message = message; + this.replacements = replacements; } @Override - public T getValue() { - return null; + public boolean isSuccess() { + return false; + } + + @Override + public boolean isFailure() { + return true; } @Override public S getSuccessReason() { - return null; + throw new NoSuchElementException("No reason for success"); } @Override @@ -236,8 +128,8 @@ public interface Result { } @Override - public Message getMessage() { - return message; + public @NotNull Message getReasonMessage() { + return Message.of(failureReason, "Success!", replacements); } @Override diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java b/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java index 405f7ef6..752317dc 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/ResultChain.java @@ -21,9 +21,9 @@ public class ResultChain { } private final boolean isSuccess; - private final List> results; + private final List> results; - ResultChain(boolean isSuccess, List> results) { + ResultChain(boolean isSuccess, List> results) { this.isSuccess = isSuccess; this.results = results; } @@ -102,7 +102,7 @@ public class ResultChain { } public Message getLastResultMessage() { - return Iterables.getLast(results).getMessage(); + return Iterables.getLast(results).getReasonMessage(); } @Override @@ -115,7 +115,7 @@ public class ResultChain { public static class Builder { private final boolean stopOnFailure; - private final List> results; + private final List> results; private boolean isSuccess = true; @@ -124,11 +124,11 @@ public class ResultChain { this.results = new ArrayList<>(); } - public Builder then(Supplier> resultSupplier) { + public Builder then(Supplier> resultSupplier) { if (!isSuccess && stopOnFailure) { return this; } - Result result = resultSupplier.get(); + Result result = resultSupplier.get(); if (result.isFailure()) { isSuccess = false; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java index 65903dbe..a5302c35 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java @@ -7,8 +7,7 @@ import com.onarandombox.MultiverseCore.api.LocationManipulation; import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.utils.message.MessageReplacement; import com.onarandombox.MultiverseCore.utils.result.FailureReason; -import com.onarandombox.MultiverseCore.utils.result.Result; -import com.onarandombox.MultiverseCore.utils.result.SuccessReason; +import com.onarandombox.MultiverseCore.utils.result.Attempt; import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig; import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager; import com.onarandombox.MultiverseCore.worldnew.generators.GeneratorProvider; @@ -170,11 +169,11 @@ public class WorldManager { * @param options The options for customizing the creation of a new world. * @return The result of the creation. */ - public Result createWorld(CreateWorldOptions options) { - return validateCreateWorldOptions(options).mapValue(this::createValidatedWorld); + public Attempt createWorld(CreateWorldOptions options) { + return validateCreateWorldOptions(options).map(this::createValidatedWorld); } - private Result validateCreateWorldOptions( + private Attempt validateCreateWorldOptions( CreateWorldOptions options) { if (!worldNameChecker.isValidWorldName(options.worldName())) { return worldActionResult(CreateWorldResult.Failure.INVALID_WORLDNAME, options.worldName()); @@ -185,7 +184,7 @@ public class WorldManager { } else if (hasWorldFolder(options.worldName())) { return worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_FOLDER, options.worldName()); } - return Result.successValue(options); + return worldActionResult(options); } private boolean hasWorldFolder(String worldName) { @@ -193,7 +192,7 @@ public class WorldManager { return worldFolder.exists(); } - private Result createValidatedWorld( + private Attempt createValidatedWorld( CreateWorldOptions options) { String parsedGenerator = parseGenerator(options.worldName(), options.generator()); WorldCreator worldCreator = WorldCreator.name(options.worldName()) @@ -210,7 +209,7 @@ public class WorldManager { world, parsedGenerator, options.useSpawnAdjust()); - return worldActionResult(loadedWorld, CreateWorldResult.Success.CREATED, world.getName()); + return worldActionResult(loadedWorld); }); } @@ -220,12 +219,12 @@ public class WorldManager { * @param options The options for customizing the import of an existing world folder. * @return The result of the import. */ - public Result importWorld( + public Attempt importWorld( ImportWorldOptions options) { - return validateImportWorldOptions(options).mapValue(this::doImportWorld); + return validateImportWorldOptions(options).map(this::doImportWorld); } - private Result validateImportWorldOptions( + private Attempt validateImportWorldOptions( ImportWorldOptions options) { String worldName = options.worldName(); if (!worldNameChecker.isValidWorldName(worldName)) { @@ -237,10 +236,10 @@ public class WorldManager { } else if (isWorld(worldName)) { return worldActionResult(ImportWorldResult.Failure.WORLD_EXIST_UNLOADED, worldName); } - return Result.successValue(options); + return worldActionResult(options); } - private Result doImportWorld( + private Attempt doImportWorld( ImportWorldOptions options) { String parsedGenerator = parseGenerator(options.worldName(), options.generator()); WorldCreator worldCreator = WorldCreator.name(options.worldName()) @@ -253,7 +252,7 @@ public class WorldManager { LoadedMultiverseWorld loadedWorld = newLoadedMultiverseWorld(world, parsedGenerator, options.useSpawnAdjust()); - return worldActionResult(loadedWorld, ImportWorldResult.Success.IMPORTED, options.worldName()); + return worldActionResult(loadedWorld); }); } @@ -303,7 +302,7 @@ public class WorldManager { * @param worldName The name of the world to load. * @return The result of the load. */ - public Result loadWorld(@NotNull String worldName) { + public Attempt loadWorld(@NotNull String worldName) { return getWorld(worldName) .map(this::loadWorld) .getOrElse(() -> worldNameChecker.isValidWorldFolder(worldName) @@ -314,14 +313,14 @@ public class WorldManager { /** * Loads an existing world in config. * - * @param mvWorld The world to load. + * @param world The world to load. * @return The result of the load. */ - public Result loadWorld(@NotNull MultiverseWorld mvWorld) { - return validateWorldToLoad(mvWorld).map(() -> doLoadWorld(mvWorld)); + public Attempt loadWorld(@NotNull MultiverseWorld world) { + return validateWorldToLoad(world).map(this::doLoadWorld); } - private Result validateWorldToLoad( + private Attempt validateWorldToLoad( @NotNull MultiverseWorld mvWorld) { if (loadTracker.contains(mvWorld.getName())) { // This is to prevent recursive calls by WorldLoadEvent @@ -331,12 +330,10 @@ public class WorldManager { Logging.severe("World already loaded: " + mvWorld.getName()); return worldActionResult(LoadWorldResult.Failure.WORLD_EXIST_LOADED, mvWorld.getName()); } - - return Result.success(); + return worldActionResult(mvWorld); } - private Result doLoadWorld( - @NotNull MultiverseWorld mvWorld) { + private Attempt doLoadWorld(@NotNull MultiverseWorld mvWorld) { return createBukkitWorld(WorldCreator.name(mvWorld.getName()) .environment(mvWorld.getEnvironment()) .generator(Strings.isNullOrEmpty(mvWorld.getGenerator()) ? null : mvWorld.getGenerator()) @@ -354,7 +351,7 @@ public class WorldManager { locationManipulation); loadedWorldsMap.put(loadedWorld.getName(), loadedWorld); saveWorldsConfig(); - return worldActionResult(loadedWorld, LoadWorldResult.Success.LOADED, loadedWorld.getName()); + return worldActionResult(loadedWorld); }); } @@ -364,7 +361,7 @@ public class WorldManager { * @param world The bukkit world to unload. * @return The result of the unload action. */ - public Result unloadWorld(@NotNull World world) { + public Attempt unloadWorld(@NotNull World world) { return unloadWorld(world.getName()); } @@ -374,7 +371,7 @@ public class WorldManager { * @param worldName The name of the world to unload. * @return The result of the unload action. */ - public Result unloadWorld(@NotNull String worldName) { + public Attempt unloadWorld(@NotNull String worldName) { return getLoadedWorld(worldName) .map(this::unloadWorld) .getOrElse(() -> isUnloadedWorld(worldName) @@ -388,7 +385,7 @@ public class WorldManager { * @param world The multiverse world to unload. * @return The result of the unload action. */ - public Result unloadWorld( + public Attempt unloadWorld( @NotNull LoadedMultiverseWorld world) { if (unloadTracker.contains(world.getName())) { // This is to prevent recursive calls by WorldUnloadEvent @@ -409,8 +406,7 @@ public class WorldManager { mvWorld -> { Logging.fine("Removed MultiverseWorld from map: " + world.getName()); mvWorld.getWorldConfig().deferenceMVWorld(); - return worldActionResult(getWorld(mvWorld.getName()).getOrNull(), - UnloadWorldResult.Success.UNLOADED, world.getName()); + return worldActionResult(getWorld(mvWorld.getName()).get()); })); } @@ -421,7 +417,7 @@ public class WorldManager { * @param worldName The name of the world to remove. * @return The result of the remove. */ - public Result removeWorld( + public Attempt removeWorld( @NotNull String worldName) { return getWorld(worldName) .map(this::removeWorld) @@ -435,7 +431,7 @@ public class WorldManager { * @param world The multiverse world to remove. * @return The result of the remove. */ - public Result removeWorld(@NotNull MultiverseWorld world) { + public Attempt removeWorld(@NotNull MultiverseWorld world) { return getLoadedWorld(world).fold( () -> removeWorldFromConfig(world), this::removeWorld); @@ -448,11 +444,11 @@ public class WorldManager { * @param loadedWorld The multiverse world to remove. * @return The result of the remove. */ - public Result removeWorld( + public Attempt removeWorld( @NotNull LoadedMultiverseWorld loadedWorld) { var result = unloadWorld(loadedWorld); if (result.isFailure()) { - return Result.failure(RemoveWorldResult.Failure.UNLOAD_FAILED, result.getMessage()); + return Attempt.failure(RemoveWorldResult.Failure.UNLOAD_FAILED, result.getFailureMessage()); } return removeWorldFromConfig(loadedWorld); } @@ -463,14 +459,14 @@ public class WorldManager { * @param world The multiverse world to remove. * @return The result of the remove. */ - private Result + private Attempt removeWorldFromConfig(@NotNull MultiverseWorld world) { // Remove world from config worldsMap.remove(world.getName()); worldsConfigManager.deleteWorldConfig(world.getName()); saveWorldsConfig(); - return worldActionResult(RemoveWorldResult.Success.REMOVED, world.getName()); + return worldActionResult(world.getName()); } /** @@ -480,7 +476,7 @@ public class WorldManager { * @param worldName The name of the world to delete. * @return The result of the delete action. */ - public Result deleteWorld(@NotNull String worldName) { + public Attempt deleteWorld(@NotNull String worldName) { return getWorld(worldName) .map(this::deleteWorld) .getOrElse(() -> worldActionResult(DeleteWorldResult.Failure.WORLD_NON_EXISTENT, worldName)); @@ -493,11 +489,11 @@ public class WorldManager { * @param world The world to delete. * @return The result of the delete action. */ - public Result deleteWorld(@NotNull MultiverseWorld world) { + public Attempt deleteWorld(@NotNull MultiverseWorld world) { return getLoadedWorld(world).fold( () -> loadWorld(world) - .convertReason((DeleteWorldResult.Success) null, DeleteWorldResult.Failure.LOAD_FAILED) - .mapValue(this::deleteWorld), + .convertReason(DeleteWorldResult.Failure.LOAD_FAILED) + .map(this::deleteWorld), this::deleteWorld); } @@ -507,27 +503,26 @@ public class WorldManager { * @param world The multiverse world to delete. * @return The result of the delete action. */ - public Result - deleteWorld(@NotNull LoadedMultiverseWorld world) { + public Attempt deleteWorld(@NotNull LoadedMultiverseWorld world) { // TODO: Possible config options to keep certain files AtomicReference worldFolder = new AtomicReference<>(); return validateWorldToDelete(world) .peek(worldFolder::set) - .map(() -> removeWorld(world).convertReason(null, DeleteWorldResult.Failure.REMOVE_FAILED)) + .map(() -> removeWorld(world).convertReason(DeleteWorldResult.Failure.REMOVE_FAILED)) .map(() -> filesManipulator.deleteFolder(worldFolder.get()).fold( exception -> worldActionResult(DeleteWorldResult.Failure.FAILED_TO_DELETE_FOLDER, world.getName(), exception), - success -> worldActionResult(DeleteWorldResult.Success.DELETED, world.getName()))); + success -> worldActionResult(world.getName()))); } - private Result validateWorldToDelete( + private Attempt validateWorldToDelete( @NotNull LoadedMultiverseWorld world) { File worldFolder = world.getBukkitWorld().map(World::getWorldFolder).getOrNull(); if (worldFolder == null || !worldNameChecker.isValidWorldFolder(worldFolder)) { Logging.severe("Failed to get world folder for world: " + world.getName()); return worldActionResult(DeleteWorldResult.Failure.WORLD_FOLDER_NOT_FOUND, world.getName()); } - return Result.successValue(worldFolder); + return worldActionResult(worldFolder); } /** @@ -536,23 +531,23 @@ public class WorldManager { * @param options The options for customizing the cloning of a world. * @return The result of the clone. */ - public Result cloneWorld(@NotNull CloneWorldOptions options) { + public Attempt cloneWorld(@NotNull CloneWorldOptions options) { return cloneWorldValidateWorld(options) - .mapValue(this::cloneWorldCopyFolder) - .mapValue(validatedOptions -> { + .map(this::cloneWorldCopyFolder) + .map(validatedOptions -> { ImportWorldOptions importWorldOptions = ImportWorldOptions.worldName(validatedOptions.newWorldName()) .environment(validatedOptions.world().getEnvironment()) .generator(validatedOptions.world().getGenerator()); - return importWorld(importWorldOptions).convertReason(null, CloneWorldResult.Failure.IMPORT_FAILED); + return importWorld(importWorldOptions).convertReason(CloneWorldResult.Failure.IMPORT_FAILED); }) - .mapValue(newWorld -> { + .map(newWorld -> { cloneWorldTransferData(options, newWorld); saveWorldsConfig(); - return worldActionResult(CloneWorldResult.Success.CLONED, newWorld.getName()); + return worldActionResult(newWorld); }); } - private Result cloneWorldValidateWorld( + private Attempt cloneWorldValidateWorld( @NotNull CloneWorldOptions options) { String newWorldName = options.newWorldName(); if (!worldNameChecker.isValidWorldName(newWorldName)) { @@ -570,10 +565,10 @@ public class WorldManager { Logging.severe("World already exist unloaded: " + newWorldName); return worldActionResult(CloneWorldResult.Failure.WORLD_EXIST_UNLOADED, newWorldName); } - return Result.successValue(options); + return worldActionResult(options); } - private Result cloneWorldCopyFolder( + private Attempt cloneWorldCopyFolder( @NotNull CloneWorldOptions options) { // TODO: Check null? File worldFolder = options.world().getBukkitWorld().map(World::getWorldFolder).getOrNull(); @@ -581,7 +576,7 @@ public class WorldManager { return filesManipulator.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES).fold( exception -> worldActionResult(CloneWorldResult.Failure.COPY_FAILED, options.world().getName(), exception), - success -> Result.successValue(options)); + success -> worldActionResult(options)); } private void cloneWorldTransferData(@NotNull CloneWorldOptions options, @NotNull LoadedMultiverseWorld newWorld) { @@ -612,7 +607,7 @@ public class WorldManager { * @param options The options for customizing the regeneration of a world. * @return The result of the regeneration. */ - public Result regenWorld(@NotNull RegenWorldOptions options) { + public Attempt regenWorld(@NotNull RegenWorldOptions options) { // TODO: Teleport players out of world, and back in after regen LoadedMultiverseWorld world = options.world(); @@ -625,39 +620,28 @@ public class WorldManager { .worldType(world.getWorldType().getOrElse(WorldType.NORMAL)); return deleteWorld(world) - .convertReason((RegenWorldResult.Success) null, RegenWorldResult.Failure.DELETE_FAILED) - .map(() -> createWorld(createWorldOptions).convertReason(null, RegenWorldResult.Failure.CREATE_FAILED)) - .mapValue(newWorld -> { + .convertReason(RegenWorldResult.Failure.DELETE_FAILED) + .map(() -> createWorld(createWorldOptions).convertReason(RegenWorldResult.Failure.CREATE_FAILED)) + .map(newWorld -> { dataTransfer.pasteAllTo(newWorld); saveWorldsConfig(); - return worldActionResult(newWorld, RegenWorldResult.Success.REGENERATED, newWorld.getName()); + return worldActionResult(newWorld); }); } - private Result worldActionResult( - @NotNull S messageKeyProvider, @NotNull String worldName) { - return Result.success(messageKeyProvider, replaceWorldName(worldName)); + private Attempt worldActionResult(@NotNull T value) { + return Attempt.success(value); } - private Result worldActionResult( - @NotNull T value, @NotNull S successReason, @NotNull String worldName) { - return Result.successValue(value, successReason, replaceWorldName(worldName)); - } - - private Result worldActionResult( - @NotNull F failureReason, @NotNull Result result) { - return Result.failure(failureReason, result.getMessage()); - } - - private Result worldActionResult( + private Attempt worldActionResult( @NotNull F messageKeyProvider, @NotNull String worldName) { - return Result.failure(messageKeyProvider, replaceWorldName(worldName)); + return Attempt.failure(messageKeyProvider, replaceWorldName(worldName)); } - private Result worldActionResult( + private Attempt worldActionResult( @NotNull F messageKeyProvider, @NotNull String worldName, @NotNull Throwable error) { // TODO: Localize error message if its a MultiverseException - return Result.failure(messageKeyProvider, replaceWorldName(worldName), replaceError(error.getMessage())); + return Attempt.failure(messageKeyProvider, replaceWorldName(worldName), replaceError(error.getMessage())); } private MessageReplacement replaceWorldName(@NotNull String worldName) { diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java index 13285950..47b7faae 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/entrycheck/WorldEntryChecker.java @@ -50,7 +50,7 @@ public class WorldEntryChecker { .build(); } - public Result canAccessWorld(@NotNull MultiverseWorld world) { + public Result canAccessWorld(@NotNull MultiverseWorld world) { if (!config.getEnforceAccess()) { return Result.success(WorldAccessResult.Success.NO_ENFORCE_WORLD_ACCESS); } @@ -59,7 +59,7 @@ public class WorldEntryChecker { : Result.failure(WorldAccessResult.Failure.NO_WORLD_ACCESS); } - public Result isWithinPlayerLimit(@NotNull LoadedMultiverseWorld world) { + public Result isWithinPlayerLimit(@NotNull LoadedMultiverseWorld world) { final int playerLimit = world.getPlayerLimit(); if (playerLimit <= -1) { return Result.success(PlayerLimitResult.Success.NO_PLAYERLIMIT); @@ -72,7 +72,7 @@ public class WorldEntryChecker { : Result.failure(PlayerLimitResult.Failure.EXCEED_PLAYERLIMIT); } - public Result isNotBlacklisted(@Nullable LoadedMultiverseWorld fromWorld, @NotNull LoadedMultiverseWorld toWorld) { + public Result isNotBlacklisted(@Nullable LoadedMultiverseWorld fromWorld, @NotNull LoadedMultiverseWorld toWorld) { if (fromWorld == null) { return Result.success(BlacklistResult.Success.UNKNOWN_FROM_WORLD); } @@ -81,7 +81,7 @@ public class WorldEntryChecker { : Result.success(BlacklistResult.Success.NOT_BLACKLISTED); } - public Result canPayEntryFee(LoadedMultiverseWorld world) { + public Result canPayEntryFee(LoadedMultiverseWorld world) { double price = world.getPrice(); Material currency = world.getCurrency(); if (price == 0D && (currency == null || currency == EntryFee.DISABLED_MATERIAL)) { From 2fe6297b1da108c2c3735586e38833753c32c447 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 21:45:30 +0800 Subject: [PATCH 3/8] Fix unintended changes to result --- .../MultiverseCore/utils/result/Result.java | 72 +++++++++++++++---- 1 file changed, 57 insertions(+), 15 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 03bcf789..6e029943 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java @@ -6,18 +6,27 @@ import org.jetbrains.annotations.NotNull; import java.util.NoSuchElementException; import java.util.function.Consumer; +import java.util.function.Function; public sealed interface Result permits Result.Success, Result.Failure { + static Result success( - S successReason, MessageReplacement... replacements) { + S successReason, MessageReplacement...replacements) { return new Success<>(successReason, replacements); } + static Result success(S successReason, Message message) { + return new Success<>(successReason, message); + } + static Result failure( - F failureReason, MessageReplacement... replacements) { + F failureReason, MessageReplacement...replacements) { return new Failure<>(failureReason, replacements); } + static Result failure(F failureReason, Message message) { + return new Failure<>(failureReason, message); + } boolean isSuccess(); boolean isFailure(); @@ -28,16 +37,16 @@ public sealed interface Result @NotNull Message getReasonMessage(); - default Result onSuccess(Consumer consumer) { - if (this.isSuccess()) { - consumer.accept(this.getSuccessReason()); + default Result onSuccess(Consumer> consumer) { + if (this instanceof Success) { + consumer.accept((Success) this); } return this; } - default Result onFailure(Consumer consumer) { - if (this.isFailure()) { - consumer.accept(this.getFailureReason()); + default Result onFailure(Consumer> consumer) { + if (this instanceof Failure) { + consumer.accept((Failure) this); } return this; } @@ -56,13 +65,41 @@ 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 MessageReplacement[] replacements; + private final Message message; + + public Success(S successReason, Message message) { + this.successReason = successReason; + this.message = message; + } public Success(S successReason, MessageReplacement[] replacements) { this.successReason = successReason; - this.replacements = replacements; + this.message = Message.of(successReason, "Success!", replacements); } @Override @@ -87,7 +124,7 @@ public sealed interface Result @Override public @NotNull Message getReasonMessage() { - return Message.of(successReason, "Success!", replacements); + return message; } @Override @@ -100,11 +137,16 @@ public sealed interface Result final class Failure implements Result { private final F failureReason; - private final MessageReplacement[] replacements; + private final Message message; + + public Failure(F failureReason, Message message) { + this.failureReason = failureReason; + this.message = message; + } public Failure(F failureReason, MessageReplacement[] replacements) { this.failureReason = failureReason; - this.replacements = replacements; + this.message = Message.of(failureReason, "Success!", replacements); } @Override @@ -119,7 +161,7 @@ public sealed interface Result @Override public S getSuccessReason() { - throw new NoSuchElementException("No reason for success"); + throw new NoSuchElementException("No reason for failure"); } @Override @@ -129,7 +171,7 @@ public sealed interface Result @Override public @NotNull Message getReasonMessage() { - return Message.of(failureReason, "Success!", replacements); + return message; } @Override From 656d9ac2088c38921054de0a2c0baaa54258c63f Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 22:17:10 +0800 Subject: [PATCH 4/8] Refactor map Attempt methods --- .../MultiverseCore/utils/result/Attempt.java | 30 +++++++++++++++++-- .../MultiverseCore/worldnew/WorldManager.java | 24 +++++++-------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java index fe375bee..d7c2ff98 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java @@ -43,15 +43,31 @@ public interface Attempt { return this; } - default Attempt map(Function> mapper) { + default Attempt map(Function mapper) { if (this instanceof Success) { - return mapper.apply(this.get()); + return new Success<>(mapper.apply(get())); } else { return new Failure<>(getFailureReason(), getFailureMessage()); } } - default Attempt map(Supplier> mapper) { + default Attempt map(Supplier mapper) { + if (this instanceof Success) { + return new Success<>(mapper.get()); + } else { + return new Failure<>(getFailureReason(), getFailureMessage()); + } + } + + default Attempt mapAttempt(Function> mapper) { + if (this instanceof Success) { + return mapper.apply(get()); + } else { + return new Failure<>(getFailureReason(), getFailureMessage()); + } + } + + default Attempt mapAttempt(Supplier> mapper) { if (this instanceof Success) { return mapper.get(); } else { @@ -59,6 +75,14 @@ public interface Attempt { } } + default Attempt transform(UF failureReason) { + if (this instanceof Success) { + return new Success<>(get()); + } else { + return new Failure<>(failureReason, getFailureMessage()); + } + } + default Attempt convertReason(NF failure) { if (this instanceof Success) { return new Success<>(get()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java index a5302c35..cb1c4cc5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java @@ -170,7 +170,7 @@ public class WorldManager { * @return The result of the creation. */ public Attempt createWorld(CreateWorldOptions options) { - return validateCreateWorldOptions(options).map(this::createValidatedWorld); + return validateCreateWorldOptions(options).mapAttempt(this::createValidatedWorld); } private Attempt validateCreateWorldOptions( @@ -221,7 +221,7 @@ public class WorldManager { */ public Attempt importWorld( ImportWorldOptions options) { - return validateImportWorldOptions(options).map(this::doImportWorld); + return validateImportWorldOptions(options).mapAttempt(this::doImportWorld); } private Attempt validateImportWorldOptions( @@ -317,7 +317,7 @@ public class WorldManager { * @return The result of the load. */ public Attempt loadWorld(@NotNull MultiverseWorld world) { - return validateWorldToLoad(world).map(this::doLoadWorld); + return validateWorldToLoad(world).mapAttempt(this::doLoadWorld); } private Attempt validateWorldToLoad( @@ -493,7 +493,7 @@ public class WorldManager { return getLoadedWorld(world).fold( () -> loadWorld(world) .convertReason(DeleteWorldResult.Failure.LOAD_FAILED) - .map(this::deleteWorld), + .mapAttempt(this::deleteWorld), this::deleteWorld); } @@ -508,8 +508,8 @@ public class WorldManager { AtomicReference worldFolder = new AtomicReference<>(); return validateWorldToDelete(world) .peek(worldFolder::set) - .map(() -> removeWorld(world).convertReason(DeleteWorldResult.Failure.REMOVE_FAILED)) - .map(() -> filesManipulator.deleteFolder(worldFolder.get()).fold( + .mapAttempt(() -> removeWorld(world).transform(DeleteWorldResult.Failure.REMOVE_FAILED)) + .mapAttempt(() -> filesManipulator.deleteFolder(worldFolder.get()).fold( exception -> worldActionResult(DeleteWorldResult.Failure.FAILED_TO_DELETE_FOLDER, world.getName(), exception), success -> worldActionResult(world.getName()))); @@ -533,17 +533,16 @@ public class WorldManager { */ public Attempt cloneWorld(@NotNull CloneWorldOptions options) { return cloneWorldValidateWorld(options) - .map(this::cloneWorldCopyFolder) - .map(validatedOptions -> { + .mapAttempt(this::cloneWorldCopyFolder) + .mapAttempt(validatedOptions -> { ImportWorldOptions importWorldOptions = ImportWorldOptions.worldName(validatedOptions.newWorldName()) .environment(validatedOptions.world().getEnvironment()) .generator(validatedOptions.world().getGenerator()); return importWorld(importWorldOptions).convertReason(CloneWorldResult.Failure.IMPORT_FAILED); }) - .map(newWorld -> { + .onSuccess(newWorld -> { cloneWorldTransferData(options, newWorld); saveWorldsConfig(); - return worldActionResult(newWorld); }); } @@ -621,11 +620,10 @@ public class WorldManager { return deleteWorld(world) .convertReason(RegenWorldResult.Failure.DELETE_FAILED) - .map(() -> createWorld(createWorldOptions).convertReason(RegenWorldResult.Failure.CREATE_FAILED)) - .map(newWorld -> { + .mapAttempt(() -> createWorld(createWorldOptions).convertReason(RegenWorldResult.Failure.CREATE_FAILED)) + .onSuccess(newWorld -> { dataTransfer.pasteAllTo(newWorld); saveWorldsConfig(); - return worldActionResult(newWorld); }); } From 6f9f9085fd245957f3514b1940532846aad9152d Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 22:29:42 +0800 Subject: [PATCH 5/8] Refactor world results to remove success reason --- .../MultiverseCore/commands/CloneCommand.java | 43 +++--- .../commands/CreateCommand.java | 2 +- .../commands/DeleteCommand.java | 2 +- .../commands/ImportCommand.java | 2 +- .../MultiverseCore/commands/LoadCommand.java | 2 +- .../MultiverseCore/commands/RegenCommand.java | 2 +- .../commands/UnloadCommand.java | 2 +- .../MultiverseCore/utils/MVCorei18n.java | 15 +- .../MultiverseCore/worldnew/WorldManager.java | 141 +++++++++--------- .../worldnew/results/CloneWorldResult.java | 47 ++---- .../worldnew/results/CreateWorldResult.java | 41 ++--- .../worldnew/results/DeleteWorldResult.java | 41 ++--- .../worldnew/results/ImportWorldResult.java | 42 ++---- .../worldnew/results/LoadWorldResult.java | 42 ++---- .../worldnew/results/RegenWorldResult.java | 37 ++--- .../worldnew/results/RemoveWorldResult.java | 36 ++--- .../worldnew/results/UnloadWorldResult.java | 40 ++--- .../resources/multiverse-core_en.properties | 17 +-- .../core/commandtools/LocalizationTest.kt | 2 +- 19 files changed, 205 insertions(+), 351 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java index de3e6dde..9138a178 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java @@ -51,34 +51,35 @@ public class CloneCommand extends MultiverseCommand { @CommandCompletion("@mvworlds:scope=both @empty") @Syntax(" ") @Description("{@@mv-core.clone.description}") - public void onCloneCommand(MVCommandIssuer issuer, + void onCloneCommand( + MVCommandIssuer issuer, - @Syntax("") - @Description("{@@mv-core.clone.world.description}") - LoadedMultiverseWorld world, + @Syntax("") + @Description("{@@mv-core.clone.world.description}") + LoadedMultiverseWorld world, - @Syntax("") - @Description("{@@mv-core.clone.newWorld.description}") - String newWorldName, + @Syntax("") + @Description("{@@mv-core.clone.newWorld.description}") + String newWorldName, - @Optional - @Syntax("") // TODO - @Description("{@@mv-core.regen.other.description}") - String[] flags - ) { + @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(CloneWorldOptions.fromTo(world, newWorldName) + CloneWorldOptions cloneWorldOptions = CloneWorldOptions.fromTo(world, newWorldName) .keepWorldConfig(!parsedFlags.hasFlag("--reset-world-config")) .keepGameRule(!parsedFlags.hasFlag("--reset-gamerules")) - .keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border")) - ).onSuccess(newWorld -> { - Logging.fine("World clone success: " + newWorld); - issuer.sendInfo(MVCorei18n.CLONEWORLD_CLONED, "{world}", newWorld.getName()); - }).onFailure(failure -> { - Logging.fine("World clone failure: " + failure); - issuer.sendError(failure.getFailureMessage()); - }); + .keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border")); + worldManager.cloneWorld(cloneWorldOptions) + .onSuccess(newWorld -> { + Logging.fine("World clone success: " + newWorld); + issuer.sendInfo(MVCorei18n.CLONE_SUCCESS, "{world}", newWorld.getName()); + }).onFailure(failure -> { + Logging.fine("World clone failure: " + failure); + issuer.sendError(failure.getFailureMessage()); + }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java index d368b948..e5021218 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java @@ -105,7 +105,7 @@ public class CreateCommand extends MultiverseCommand { .generateStructures(!parsedFlags.hasFlag("--no-structures")) ).onSuccess(newWorld -> { Logging.fine("World create success: " + newWorld); - issuer.sendInfo(MVCorei18n.CREATEWORLD_CREATED, "{world}", newWorld.getName()); + issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{world}", newWorld.getName()); }).onFailure(failure -> { Logging.fine("World create failure: " + failure); issuer.sendError(failure.getFailureMessage()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java index 434a9c40..f8b34799 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java @@ -53,7 +53,7 @@ public class DeleteCommand extends MultiverseCommand { worldManager.deleteWorld(worldName) .onSuccess(deletedWorldName -> { Logging.fine("World delete success: " + deletedWorldName); - issuer.sendInfo(MVCorei18n.DELETEWORLD_DELETED, "{world}", deletedWorldName); + issuer.sendInfo(MVCorei18n.DELETE_SUCCESS, "{world}", deletedWorldName); }).onFailure(failure -> { Logging.fine("World delete failure: " + failure); issuer.sendError(failure.getFailureMessage()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java index c7c60d9e..11c5d012 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java @@ -81,7 +81,7 @@ public class ImportCommand extends MultiverseCommand { .useSpawnAdjust(parsedFlags.hasFlag("--adjust-spawn")) ).onSuccess(newWorld -> { Logging.fine("World import success: " + newWorld); - issuer.sendInfo(MVCorei18n.IMPORTWORLD_IMPORTED, "{world}", newWorld.getName()); + issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS, "{world}", newWorld.getName()); }).onFailure(failure -> { Logging.fine("World import failure: " + failure); issuer.sendError(failure.getFailureMessage()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java index 33fcbca8..1c421e9d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/LoadCommand.java @@ -47,7 +47,7 @@ public class LoadCommand extends MultiverseCommand { worldManager.loadWorld(worldName) .onSuccess(newWorld -> { Logging.fine("World load success: " + newWorld); - issuer.sendInfo(MVCorei18n.LOADWORLD_LOADED, "{world}", newWorld.getName()); + issuer.sendInfo(MVCorei18n.LOAD_SUCCESS, "{world}", newWorld.getName()); }).onFailure(failure -> { Logging.fine("World load failure: " + failure); issuer.sendError(failure.getFailureMessage()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java index 9533f4f4..7360fec5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java @@ -87,7 +87,7 @@ public class RegenCommand extends MultiverseCommand { .keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border")) ).onSuccess(newWorld -> { Logging.fine("World regen success: " + newWorld); - issuer.sendInfo(MVCorei18n.REGENWORLD_REGENERATED, "{world}", newWorld.getName()); + issuer.sendInfo(MVCorei18n.REGEN_SUCCESS, "{world}", newWorld.getName()); }).onFailure(failure -> { Logging.fine("World regen failure: " + failure); issuer.sendError(failure.getFailureMessage()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java index e7049871..72fd6902 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/UnloadCommand.java @@ -44,7 +44,7 @@ public class UnloadCommand extends MultiverseCommand { worldManager.unloadWorld(world) .onSuccess(loadedWorld -> { Logging.fine("World unload success: " + loadedWorld); - issuer.sendInfo(MVCorei18n.UNLOADWORLD_UNLOADED, "{world}", loadedWorld.getName()); + issuer.sendInfo(MVCorei18n.UNLOAD_SUCCESS, "{world}", loadedWorld.getName()); }).onFailure(failure -> { Logging.fine("World unload failure: " + failure); issuer.sendError(failure.getFailureMessage()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java index f1fba352..dd4faa47 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java @@ -16,6 +16,7 @@ public enum MVCorei18n implements MessageKeyProvider { // clone command CLONE_CLONING, + CLONE_SUCCESS, // Coordinates command COORDINATES_INFO_TITLE, @@ -34,6 +35,7 @@ public enum MVCorei18n implements MessageKeyProvider { CREATE_PROPERTIES_GENERATOR, CREATE_PROPERTIES_STRUCTURES, CREATE_LOADING, + CREATE_SUCCESS, // delete command DELETE_DELETING, @@ -56,13 +58,16 @@ public enum MVCorei18n implements MessageKeyProvider { // import command IMPORT_IMPORTING, + IMPORT_SUCCESS, // load command LOAD_LOADING, + LOAD_SUCCESS, // regen command REGEN_REGENERATING, REGEN_PROMPT, + REGEN_SUCCESS, // reload command RELOAD_RELOADING, @@ -77,6 +82,7 @@ public enum MVCorei18n implements MessageKeyProvider { // unload command UNLOAD_UNLOADING, + UNLOAD_SUCCESS, // debug command DEBUG_INFO_OFF, @@ -94,46 +100,39 @@ public enum MVCorei18n implements MessageKeyProvider { ENTRYCHECK_NOWORLDACCESS, // world manager result - CLONEWORLD_CLONED, CLONEWORLD_INVALIDWORLDNAME, CLONEWORLD_WORLDEXISTFOLDER, CLONEWORLD_WORLDEXISTUNLOADED, CLONEWORLD_WORLDEXISTLOADED, CLONEWORLD_COPYFAILED, - CREATEWORLD_CREATED, CREATEWORLD_INVALIDWORLDNAME, CREATEWORLD_WORLDEXISTFOLDER, CREATEWORLD_WORLDEXISTUNLOADED, CREATEWORLD_WORLDEXISTLOADED, CREATEWORLD_BUKKITCREATIONFAILED, - DELETEWORLD_DELETED, + DELETE_SUCCESS, DELETEWORLD_WORLDNONEXISTENT, DELETEWORLD_LOADFAILED, DELETEWORLD_WORLDFOLDERNOTFOUND, DELETEWORLD_FAILEDTODELETEFOLDER, - IMPORTWORLD_IMPORTED, IMPORTWORLD_INVALIDWORLDNAME, IMPORTWORLD_WORLDFOLDERINVALID, IMPORTWORLD_WORLDEXISTUNLOADED, IMPORTWORLD_WORLDEXISTLOADED, IMPORTWORLD_BUKKITCREATIONFAILED, - LOADWORLD_LOADED, LOADWORLD_WORLDALREADYLOADING, LOADWORLD_WORLDNONEXISTENT, LOADWORLD_WORLDEXISTFOLDER, LOADWORLD_WORLDEXISTLOADED, LOADWORLD_BUKKITCREATIONFAILED, - REGENWORLD_REGENERATED, - REMOVEWORLD_REMOVED, REMOVEWORLD_WORLDNONEXISTENT, - UNLOADWORLD_UNLOADED, UNLOADWORLD_WORLDALREADYUNLOADING, UNLOADWORLD_WORLDNONEXISTENT, UNLOADWORLD_WORLDUNLOADED, diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java index cb1c4cc5..64001b9d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java @@ -6,8 +6,8 @@ import com.onarandombox.MultiverseCore.api.BlockSafety; import com.onarandombox.MultiverseCore.api.LocationManipulation; import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.utils.message.MessageReplacement; -import com.onarandombox.MultiverseCore.utils.result.FailureReason; import com.onarandombox.MultiverseCore.utils.result.Attempt; +import com.onarandombox.MultiverseCore.utils.result.FailureReason; import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig; import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager; import com.onarandombox.MultiverseCore.worldnew.generators.GeneratorProvider; @@ -169,20 +169,20 @@ public class WorldManager { * @param options The options for customizing the creation of a new world. * @return The result of the creation. */ - public Attempt createWorld(CreateWorldOptions options) { + public Attempt createWorld(CreateWorldOptions options) { return validateCreateWorldOptions(options).mapAttempt(this::createValidatedWorld); } - private Attempt validateCreateWorldOptions( + private Attempt validateCreateWorldOptions( CreateWorldOptions options) { if (!worldNameChecker.isValidWorldName(options.worldName())) { - return worldActionResult(CreateWorldResult.Failure.INVALID_WORLDNAME, options.worldName()); + return worldActionResult(CreateWorldResult.INVALID_WORLDNAME, options.worldName()); } else if (getLoadedWorld(options.worldName()).isDefined()) { - return worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_LOADED, options.worldName()); + return worldActionResult(CreateWorldResult.WORLD_EXIST_LOADED, options.worldName()); } else if (getWorld(options.worldName()).isDefined()) { - return worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_UNLOADED, options.worldName()); + return worldActionResult(CreateWorldResult.WORLD_EXIST_UNLOADED, options.worldName()); } else if (hasWorldFolder(options.worldName())) { - return worldActionResult(CreateWorldResult.Failure.WORLD_EXIST_FOLDER, options.worldName()); + return worldActionResult(CreateWorldResult.WORLD_EXIST_FOLDER, options.worldName()); } return worldActionResult(options); } @@ -192,7 +192,7 @@ public class WorldManager { return worldFolder.exists(); } - private Attempt createValidatedWorld( + private Attempt createValidatedWorld( CreateWorldOptions options) { String parsedGenerator = parseGenerator(options.worldName(), options.generator()); WorldCreator worldCreator = WorldCreator.name(options.worldName()) @@ -202,7 +202,7 @@ public class WorldManager { .seed(options.seed()) .type(options.worldType()); return createBukkitWorld(worldCreator).fold( - exception -> worldActionResult(CreateWorldResult.Failure.BUKKIT_CREATION_FAILED, + exception -> worldActionResult(CreateWorldResult.BUKKIT_CREATION_FAILED, options.worldName(), exception), world -> { LoadedMultiverseWorld loadedWorld = newLoadedMultiverseWorld( @@ -219,34 +219,34 @@ public class WorldManager { * @param options The options for customizing the import of an existing world folder. * @return The result of the import. */ - public Attempt importWorld( + public Attempt importWorld( ImportWorldOptions options) { return validateImportWorldOptions(options).mapAttempt(this::doImportWorld); } - private Attempt validateImportWorldOptions( + private Attempt validateImportWorldOptions( ImportWorldOptions options) { String worldName = options.worldName(); if (!worldNameChecker.isValidWorldName(worldName)) { - return worldActionResult(ImportWorldResult.Failure.INVALID_WORLDNAME, worldName); + return worldActionResult(ImportWorldResult.INVALID_WORLDNAME, worldName); } else if (!worldNameChecker.isValidWorldFolder(worldName)) { - return worldActionResult(ImportWorldResult.Failure.WORLD_FOLDER_INVALID, worldName); + return worldActionResult(ImportWorldResult.WORLD_FOLDER_INVALID, worldName); } else if (isLoadedWorld(worldName)) { - return worldActionResult(ImportWorldResult.Failure.WORLD_EXIST_LOADED, worldName); + return worldActionResult(ImportWorldResult.WORLD_EXIST_LOADED, worldName); } else if (isWorld(worldName)) { - return worldActionResult(ImportWorldResult.Failure.WORLD_EXIST_UNLOADED, worldName); + return worldActionResult(ImportWorldResult.WORLD_EXIST_UNLOADED, worldName); } return worldActionResult(options); } - private Attempt doImportWorld( + private Attempt doImportWorld( ImportWorldOptions options) { String parsedGenerator = parseGenerator(options.worldName(), options.generator()); WorldCreator worldCreator = WorldCreator.name(options.worldName()) .environment(options.environment()) .generator(parsedGenerator); return createBukkitWorld(worldCreator).fold( - exception -> worldActionResult(ImportWorldResult.Failure.BUKKIT_CREATION_FAILED, + exception -> worldActionResult(ImportWorldResult.BUKKIT_CREATION_FAILED, options.worldName(), exception), world -> { LoadedMultiverseWorld loadedWorld = newLoadedMultiverseWorld(world, @@ -302,12 +302,12 @@ public class WorldManager { * @param worldName The name of the world to load. * @return The result of the load. */ - public Attempt loadWorld(@NotNull String worldName) { + public Attempt loadWorld(@NotNull String worldName) { return getWorld(worldName) .map(this::loadWorld) .getOrElse(() -> worldNameChecker.isValidWorldFolder(worldName) - ? worldActionResult(LoadWorldResult.Failure.WORLD_EXIST_FOLDER, worldName) - : worldActionResult(LoadWorldResult.Failure.WORLD_NON_EXISTENT, worldName)); + ? worldActionResult(LoadWorldResult.WORLD_EXIST_FOLDER, worldName) + : worldActionResult(LoadWorldResult.WORLD_NON_EXISTENT, worldName)); } /** @@ -316,29 +316,29 @@ public class WorldManager { * @param world The world to load. * @return The result of the load. */ - public Attempt loadWorld(@NotNull MultiverseWorld world) { + public Attempt loadWorld(@NotNull MultiverseWorld world) { return validateWorldToLoad(world).mapAttempt(this::doLoadWorld); } - private Attempt validateWorldToLoad( + private Attempt validateWorldToLoad( @NotNull MultiverseWorld mvWorld) { if (loadTracker.contains(mvWorld.getName())) { // This is to prevent recursive calls by WorldLoadEvent Logging.fine("World already loading: " + mvWorld.getName()); - return worldActionResult(LoadWorldResult.Failure.WORLD_ALREADY_LOADING, mvWorld.getName()); + return worldActionResult(LoadWorldResult.WORLD_ALREADY_LOADING, mvWorld.getName()); } else if (isLoadedWorld(mvWorld)) { Logging.severe("World already loaded: " + mvWorld.getName()); - return worldActionResult(LoadWorldResult.Failure.WORLD_EXIST_LOADED, mvWorld.getName()); + return worldActionResult(LoadWorldResult.WORLD_EXIST_LOADED, mvWorld.getName()); } return worldActionResult(mvWorld); } - private Attempt doLoadWorld(@NotNull MultiverseWorld mvWorld) { + private Attempt doLoadWorld(@NotNull MultiverseWorld mvWorld) { return createBukkitWorld(WorldCreator.name(mvWorld.getName()) .environment(mvWorld.getEnvironment()) .generator(Strings.isNullOrEmpty(mvWorld.getGenerator()) ? null : mvWorld.getGenerator()) .seed(mvWorld.getSeed())).fold( - exception -> worldActionResult(LoadWorldResult.Failure.BUKKIT_CREATION_FAILED, + exception -> worldActionResult(LoadWorldResult.BUKKIT_CREATION_FAILED, mvWorld.getName(), exception), world -> { // TODO: Check worldConfig null @@ -361,7 +361,7 @@ public class WorldManager { * @param world The bukkit world to unload. * @return The result of the unload action. */ - public Attempt unloadWorld(@NotNull World world) { + public Attempt unloadWorld(@NotNull World world) { return unloadWorld(world.getName()); } @@ -371,12 +371,12 @@ public class WorldManager { * @param worldName The name of the world to unload. * @return The result of the unload action. */ - public Attempt unloadWorld(@NotNull String worldName) { + public Attempt unloadWorld(@NotNull String worldName) { return getLoadedWorld(worldName) .map(this::unloadWorld) .getOrElse(() -> isUnloadedWorld(worldName) - ? worldActionResult(UnloadWorldResult.Failure.WORLD_UNLOADED, worldName) - : worldActionResult(UnloadWorldResult.Failure.WORLD_NON_EXISTENT, worldName)); + ? worldActionResult(UnloadWorldResult.WORLD_UNLOADED, worldName) + : worldActionResult(UnloadWorldResult.WORLD_NON_EXISTENT, worldName)); } /** @@ -385,23 +385,23 @@ public class WorldManager { * @param world The multiverse world to unload. * @return The result of the unload action. */ - public Attempt unloadWorld( + public Attempt unloadWorld( @NotNull LoadedMultiverseWorld world) { if (unloadTracker.contains(world.getName())) { // This is to prevent recursive calls by WorldUnloadEvent Logging.fine("World already unloading: " + world.getName()); - return worldActionResult(UnloadWorldResult.Failure.WORLD_ALREADY_UNLOADING, world.getName()); + return worldActionResult(UnloadWorldResult.WORLD_ALREADY_UNLOADING, world.getName()); } // TODO: removePlayersFromWorld? return unloadBukkitWorld(world.getBukkitWorld().getOrNull()).fold( - exception -> worldActionResult(UnloadWorldResult.Failure.BUKKIT_UNLOAD_FAILED, + exception -> worldActionResult(UnloadWorldResult.BUKKIT_UNLOAD_FAILED, world.getName(), exception), success -> Option.of(loadedWorldsMap.remove(world.getName())).fold( () -> { Logging.severe("Failed to remove world from map: " + world.getName()); - return worldActionResult(UnloadWorldResult.Failure.WORLD_NON_EXISTENT, world.getName()); + return worldActionResult(UnloadWorldResult.WORLD_NON_EXISTENT, world.getName()); }, mvWorld -> { Logging.fine("Removed MultiverseWorld from map: " + world.getName()); @@ -417,11 +417,11 @@ public class WorldManager { * @param worldName The name of the world to remove. * @return The result of the remove. */ - public Attempt removeWorld( + public Attempt removeWorld( @NotNull String worldName) { return getWorld(worldName) .map(this::removeWorld) - .getOrElse(() -> worldActionResult(RemoveWorldResult.Failure.WORLD_NON_EXISTENT, worldName)); + .getOrElse(() -> worldActionResult(RemoveWorldResult.WORLD_NON_EXISTENT, worldName)); } /** @@ -431,7 +431,7 @@ public class WorldManager { * @param world The multiverse world to remove. * @return The result of the remove. */ - public Attempt removeWorld(@NotNull MultiverseWorld world) { + public Attempt removeWorld(@NotNull MultiverseWorld world) { return getLoadedWorld(world).fold( () -> removeWorldFromConfig(world), this::removeWorld); @@ -444,13 +444,10 @@ public class WorldManager { * @param loadedWorld The multiverse world to remove. * @return The result of the remove. */ - public Attempt removeWorld( - @NotNull LoadedMultiverseWorld loadedWorld) { - var result = unloadWorld(loadedWorld); - if (result.isFailure()) { - return Attempt.failure(RemoveWorldResult.Failure.UNLOAD_FAILED, result.getFailureMessage()); - } - return removeWorldFromConfig(loadedWorld); + public Attempt removeWorld(@NotNull LoadedMultiverseWorld loadedWorld) { + return unloadWorld(loadedWorld) + .transform(RemoveWorldResult.UNLOAD_FAILED) + .mapAttempt(this::removeWorldFromConfig); } /** @@ -459,8 +456,7 @@ public class WorldManager { * @param world The multiverse world to remove. * @return The result of the remove. */ - private Attempt - removeWorldFromConfig(@NotNull MultiverseWorld world) { + private Attempt removeWorldFromConfig(@NotNull MultiverseWorld world) { // Remove world from config worldsMap.remove(world.getName()); worldsConfigManager.deleteWorldConfig(world.getName()); @@ -476,10 +472,10 @@ public class WorldManager { * @param worldName The name of the world to delete. * @return The result of the delete action. */ - public Attempt deleteWorld(@NotNull String worldName) { + public Attempt deleteWorld(@NotNull String worldName) { return getWorld(worldName) .map(this::deleteWorld) - .getOrElse(() -> worldActionResult(DeleteWorldResult.Failure.WORLD_NON_EXISTENT, worldName)); + .getOrElse(() -> worldActionResult(DeleteWorldResult.WORLD_NON_EXISTENT, worldName)); } /** @@ -489,10 +485,10 @@ public class WorldManager { * @param world The world to delete. * @return The result of the delete action. */ - public Attempt deleteWorld(@NotNull MultiverseWorld world) { + public Attempt deleteWorld(@NotNull MultiverseWorld world) { return getLoadedWorld(world).fold( () -> loadWorld(world) - .convertReason(DeleteWorldResult.Failure.LOAD_FAILED) + .convertReason(DeleteWorldResult.LOAD_FAILED) .mapAttempt(this::deleteWorld), this::deleteWorld); } @@ -503,24 +499,24 @@ public class WorldManager { * @param world The multiverse world to delete. * @return The result of the delete action. */ - public Attempt deleteWorld(@NotNull LoadedMultiverseWorld world) { + public Attempt deleteWorld(@NotNull LoadedMultiverseWorld world) { // TODO: Possible config options to keep certain files AtomicReference worldFolder = new AtomicReference<>(); return validateWorldToDelete(world) .peek(worldFolder::set) - .mapAttempt(() -> removeWorld(world).transform(DeleteWorldResult.Failure.REMOVE_FAILED)) + .mapAttempt(() -> removeWorld(world).transform(DeleteWorldResult.REMOVE_FAILED)) .mapAttempt(() -> filesManipulator.deleteFolder(worldFolder.get()).fold( - exception -> worldActionResult(DeleteWorldResult.Failure.FAILED_TO_DELETE_FOLDER, + exception -> worldActionResult(DeleteWorldResult.FAILED_TO_DELETE_FOLDER, world.getName(), exception), success -> worldActionResult(world.getName()))); } - private Attempt validateWorldToDelete( + private Attempt validateWorldToDelete( @NotNull LoadedMultiverseWorld world) { File worldFolder = world.getBukkitWorld().map(World::getWorldFolder).getOrNull(); if (worldFolder == null || !worldNameChecker.isValidWorldFolder(worldFolder)) { Logging.severe("Failed to get world folder for world: " + world.getName()); - return worldActionResult(DeleteWorldResult.Failure.WORLD_FOLDER_NOT_FOUND, world.getName()); + return worldActionResult(DeleteWorldResult.WORLD_FOLDER_NOT_FOUND, world.getName()); } return worldActionResult(worldFolder); } @@ -531,14 +527,15 @@ public class WorldManager { * @param options The options for customizing the cloning of a world. * @return The result of the clone. */ - public Attempt cloneWorld(@NotNull CloneWorldOptions options) { + public Attempt cloneWorld(@NotNull CloneWorldOptions options) { return cloneWorldValidateWorld(options) .mapAttempt(this::cloneWorldCopyFolder) .mapAttempt(validatedOptions -> { - ImportWorldOptions importWorldOptions = ImportWorldOptions.worldName(validatedOptions.newWorldName()) + ImportWorldOptions importWorldOptions = ImportWorldOptions + .worldName(validatedOptions.newWorldName()) .environment(validatedOptions.world().getEnvironment()) .generator(validatedOptions.world().getGenerator()); - return importWorld(importWorldOptions).convertReason(CloneWorldResult.Failure.IMPORT_FAILED); + return importWorld(importWorldOptions).convertReason(CloneWorldResult.IMPORT_FAILED); }) .onSuccess(newWorld -> { cloneWorldTransferData(options, newWorld); @@ -546,34 +543,34 @@ public class WorldManager { }); } - private Attempt cloneWorldValidateWorld( + private Attempt cloneWorldValidateWorld( @NotNull CloneWorldOptions options) { String newWorldName = options.newWorldName(); if (!worldNameChecker.isValidWorldName(newWorldName)) { Logging.severe("Invalid world name: " + newWorldName); - return worldActionResult(CloneWorldResult.Failure.INVALID_WORLDNAME, newWorldName); + return worldActionResult(CloneWorldResult.INVALID_WORLDNAME, newWorldName); } if (worldNameChecker.isValidWorldFolder(newWorldName)) { - return worldActionResult(CloneWorldResult.Failure.WORLD_EXIST_FOLDER, newWorldName); + return worldActionResult(CloneWorldResult.WORLD_EXIST_FOLDER, newWorldName); } if (isLoadedWorld(newWorldName)) { Logging.severe("World already loaded when attempting to clone: " + newWorldName); - return worldActionResult(CloneWorldResult.Failure.WORLD_EXIST_LOADED, newWorldName); + return worldActionResult(CloneWorldResult.WORLD_EXIST_LOADED, newWorldName); } if (isWorld(newWorldName)) { Logging.severe("World already exist unloaded: " + newWorldName); - return worldActionResult(CloneWorldResult.Failure.WORLD_EXIST_UNLOADED, newWorldName); + return worldActionResult(CloneWorldResult.WORLD_EXIST_UNLOADED, newWorldName); } return worldActionResult(options); } - private Attempt cloneWorldCopyFolder( + private Attempt cloneWorldCopyFolder( @NotNull CloneWorldOptions options) { // TODO: Check null? File worldFolder = options.world().getBukkitWorld().map(World::getWorldFolder).getOrNull(); File newWorldFolder = new File(Bukkit.getWorldContainer(), options.newWorldName()); return filesManipulator.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES).fold( - exception -> worldActionResult(CloneWorldResult.Failure.COPY_FAILED, + exception -> worldActionResult(CloneWorldResult.COPY_FAILED, options.world().getName(), exception), success -> worldActionResult(options)); } @@ -606,7 +603,7 @@ public class WorldManager { * @param options The options for customizing the regeneration of a world. * @return The result of the regeneration. */ - public Attempt regenWorld(@NotNull RegenWorldOptions options) { + public Attempt regenWorld(@NotNull RegenWorldOptions options) { // TODO: Teleport players out of world, and back in after regen LoadedMultiverseWorld world = options.world(); @@ -619,8 +616,8 @@ public class WorldManager { .worldType(world.getWorldType().getOrElse(WorldType.NORMAL)); return deleteWorld(world) - .convertReason(RegenWorldResult.Failure.DELETE_FAILED) - .mapAttempt(() -> createWorld(createWorldOptions).convertReason(RegenWorldResult.Failure.CREATE_FAILED)) + .convertReason(RegenWorldResult.DELETE_FAILED) + .mapAttempt(() -> createWorld(createWorldOptions).convertReason(RegenWorldResult.CREATE_FAILED)) .onSuccess(newWorld -> { dataTransfer.pasteAllTo(newWorld); saveWorldsConfig(); @@ -632,14 +629,14 @@ public class WorldManager { } private Attempt worldActionResult( - @NotNull F messageKeyProvider, @NotNull String worldName) { - return Attempt.failure(messageKeyProvider, replaceWorldName(worldName)); + @NotNull F failureReason, @NotNull String worldName) { + return Attempt.failure(failureReason, replaceWorldName(worldName)); } private Attempt worldActionResult( - @NotNull F messageKeyProvider, @NotNull String worldName, @NotNull Throwable error) { + @NotNull F failureReason, @NotNull String worldName, @NotNull Throwable error) { // TODO: Localize error message if its a MultiverseException - return Attempt.failure(messageKeyProvider, replaceWorldName(worldName), replaceError(error.getMessage())); + return Attempt.failure(failureReason, replaceWorldName(worldName), replaceError(error.getMessage())); } private MessageReplacement replaceWorldName(@NotNull String worldName) { 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 c368ac9c..e2d5e8d0 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CloneWorldResult.java @@ -9,41 +9,24 @@ import com.onarandombox.MultiverseCore.utils.result.SuccessReason; /** * Result of a world clone operation. */ -public class CloneWorldResult { - public enum Success implements SuccessReason { - CLONED(MVCorei18n.CLONEWORLD_CLONED); +public enum CloneWorldResult implements FailureReason { + INVALID_WORLDNAME(MVCorei18n.CLONEWORLD_INVALIDWORLDNAME), + WORLD_EXIST_FOLDER(MVCorei18n.CLONEWORLD_WORLDEXISTFOLDER), + WORLD_EXIST_UNLOADED(MVCorei18n.CLONEWORLD_WORLDEXISTUNLOADED), + WORLD_EXIST_LOADED(MVCorei18n.CLONEWORLD_WORLDEXISTLOADED), + COPY_FAILED(MVCorei18n.CLONEWORLD_COPYFAILED), + IMPORT_FAILED(null), + MV_WORLD_FAILED(null), // TODO + ; - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + CloneWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - INVALID_WORLDNAME(MVCorei18n.CLONEWORLD_INVALIDWORLDNAME), - WORLD_EXIST_FOLDER(MVCorei18n.CLONEWORLD_WORLDEXISTFOLDER), - WORLD_EXIST_UNLOADED(MVCorei18n.CLONEWORLD_WORLDEXISTUNLOADED), - WORLD_EXIST_LOADED(MVCorei18n.CLONEWORLD_WORLDEXISTLOADED), - COPY_FAILED(MVCorei18n.CLONEWORLD_COPYFAILED), - IMPORT_FAILED(null), - MV_WORLD_FAILED(null), // TODO - ; - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CreateWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CreateWorldResult.java index 21a1ef87..3003e2e0 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CreateWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/CreateWorldResult.java @@ -9,38 +9,21 @@ import com.onarandombox.MultiverseCore.utils.result.SuccessReason; /** * Result of a world creation operation. */ -public class CreateWorldResult { - public enum Success implements SuccessReason { - CREATED(MVCorei18n.CREATEWORLD_CREATED); +public enum CreateWorldResult implements FailureReason { + INVALID_WORLDNAME(MVCorei18n.CREATEWORLD_INVALIDWORLDNAME), + WORLD_EXIST_FOLDER(MVCorei18n.CREATEWORLD_WORLDEXISTFOLDER), + WORLD_EXIST_UNLOADED(MVCorei18n.CREATEWORLD_WORLDEXISTUNLOADED), + WORLD_EXIST_LOADED(MVCorei18n.CREATEWORLD_WORLDEXISTLOADED), + BUKKIT_CREATION_FAILED(MVCorei18n.CREATEWORLD_BUKKITCREATIONFAILED); - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + CreateWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - INVALID_WORLDNAME(MVCorei18n.CREATEWORLD_INVALIDWORLDNAME), - WORLD_EXIST_FOLDER(MVCorei18n.CREATEWORLD_WORLDEXISTFOLDER), - WORLD_EXIST_UNLOADED(MVCorei18n.CREATEWORLD_WORLDEXISTUNLOADED), - WORLD_EXIST_LOADED(MVCorei18n.CREATEWORLD_WORLDEXISTLOADED), - BUKKIT_CREATION_FAILED(MVCorei18n.CREATEWORLD_BUKKITCREATIONFAILED); - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/DeleteWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/DeleteWorldResult.java index 604c0ad6..d90901df 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/DeleteWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/DeleteWorldResult.java @@ -9,38 +9,21 @@ import com.onarandombox.MultiverseCore.utils.result.SuccessReason; /** * Result of a world deletion operation. */ -public class DeleteWorldResult { - public enum Success implements SuccessReason { - DELETED(MVCorei18n.DELETEWORLD_DELETED); +public enum DeleteWorldResult implements FailureReason { + WORLD_NON_EXISTENT(MVCorei18n.DELETEWORLD_WORLDNONEXISTENT), + LOAD_FAILED(MVCorei18n.DELETEWORLD_LOADFAILED), + WORLD_FOLDER_NOT_FOUND(MVCorei18n.DELETEWORLD_WORLDFOLDERNOTFOUND), + REMOVE_FAILED(null), + FAILED_TO_DELETE_FOLDER(MVCorei18n.DELETEWORLD_FAILEDTODELETEFOLDER); - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + DeleteWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - WORLD_NON_EXISTENT(MVCorei18n.DELETEWORLD_WORLDNONEXISTENT), - LOAD_FAILED(MVCorei18n.DELETEWORLD_LOADFAILED), - WORLD_FOLDER_NOT_FOUND(MVCorei18n.DELETEWORLD_WORLDFOLDERNOTFOUND), - REMOVE_FAILED(null), - FAILED_TO_DELETE_FOLDER(MVCorei18n.DELETEWORLD_FAILEDTODELETEFOLDER); - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/ImportWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/ImportWorldResult.java index 80da357f..7fd29ab1 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/ImportWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/ImportWorldResult.java @@ -4,43 +4,25 @@ 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; /** * Result of a world import operation. */ -public class ImportWorldResult { - public enum Success implements SuccessReason { - IMPORTED(MVCorei18n.IMPORTWORLD_IMPORTED); +public enum ImportWorldResult implements FailureReason { + INVALID_WORLDNAME(MVCorei18n.IMPORTWORLD_INVALIDWORLDNAME), + WORLD_FOLDER_INVALID(MVCorei18n.IMPORTWORLD_WORLDFOLDERINVALID), + WORLD_EXIST_UNLOADED(MVCorei18n.IMPORTWORLD_WORLDEXISTUNLOADED), + WORLD_EXIST_LOADED(MVCorei18n.IMPORTWORLD_WORLDEXISTLOADED), + BUKKIT_CREATION_FAILED(MVCorei18n.IMPORTWORLD_BUKKITCREATIONFAILED); - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + ImportWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - INVALID_WORLDNAME(MVCorei18n.IMPORTWORLD_INVALIDWORLDNAME), - WORLD_FOLDER_INVALID(MVCorei18n.IMPORTWORLD_WORLDFOLDERINVALID), - WORLD_EXIST_UNLOADED(MVCorei18n.IMPORTWORLD_WORLDEXISTUNLOADED), - WORLD_EXIST_LOADED(MVCorei18n.IMPORTWORLD_WORLDEXISTLOADED), - BUKKIT_CREATION_FAILED(MVCorei18n.IMPORTWORLD_BUKKITCREATIONFAILED); - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/LoadWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/LoadWorldResult.java index 32483c3e..6db886e6 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/LoadWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/LoadWorldResult.java @@ -4,43 +4,25 @@ 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; /** * Result of a world loading operation. */ -public class LoadWorldResult { - public enum Success implements SuccessReason { - LOADED(MVCorei18n.LOADWORLD_LOADED); +public enum LoadWorldResult implements FailureReason { + WORLD_ALREADY_LOADING(MVCorei18n.LOADWORLD_WORLDALREADYLOADING), + WORLD_NON_EXISTENT(MVCorei18n.LOADWORLD_WORLDNONEXISTENT), + WORLD_EXIST_FOLDER(MVCorei18n.LOADWORLD_WORLDEXISTFOLDER), + WORLD_EXIST_LOADED(MVCorei18n.LOADWORLD_WORLDEXISTLOADED), + BUKKIT_CREATION_FAILED(MVCorei18n.LOADWORLD_BUKKITCREATIONFAILED); - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + LoadWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - WORLD_ALREADY_LOADING(MVCorei18n.LOADWORLD_WORLDALREADYLOADING), - WORLD_NON_EXISTENT(MVCorei18n.LOADWORLD_WORLDNONEXISTENT), - WORLD_EXIST_FOLDER(MVCorei18n.LOADWORLD_WORLDEXISTFOLDER), - WORLD_EXIST_LOADED(MVCorei18n.LOADWORLD_WORLDEXISTLOADED), - BUKKIT_CREATION_FAILED(MVCorei18n.LOADWORLD_BUKKITCREATIONFAILED); - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RegenWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RegenWorldResult.java index 4b8ef070..125a3ca2 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RegenWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RegenWorldResult.java @@ -2,42 +2,23 @@ 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; /** * Result of a world regeneration operation. */ -public class RegenWorldResult { - public enum Success implements SuccessReason { - REGENERATED(MVCorei18n.REGENWORLD_REGENERATED); +public enum RegenWorldResult implements FailureReason { + DELETE_FAILED(null), + CREATE_FAILED(null); - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + RegenWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - DELETE_FAILED(null), - CREATE_FAILED(null); - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RemoveWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RemoveWorldResult.java index e5b79386..1ddfdf44 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RemoveWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/RemoveWorldResult.java @@ -4,40 +4,22 @@ 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; /** * Result of a world removal operation. */ -public class RemoveWorldResult { - public enum Success implements SuccessReason { - REMOVED(MVCorei18n.REMOVEWORLD_REMOVED); +public enum RemoveWorldResult implements FailureReason { + WORLD_NON_EXISTENT(MVCorei18n.REMOVEWORLD_WORLDNONEXISTENT), + UNLOAD_FAILED(null); - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + RemoveWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - WORLD_NON_EXISTENT(MVCorei18n.REMOVEWORLD_WORLDNONEXISTENT), - UNLOAD_FAILED(null); - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/UnloadWorldResult.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/UnloadWorldResult.java index 6038a050..3884944b 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/UnloadWorldResult.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/results/UnloadWorldResult.java @@ -4,42 +4,24 @@ 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; /** * Result of a world unloading operation. */ -public class UnloadWorldResult { - public enum Success implements SuccessReason { - UNLOADED(MVCorei18n.UNLOADWORLD_UNLOADED); +public enum UnloadWorldResult implements FailureReason { + WORLD_ALREADY_UNLOADING(MVCorei18n.UNLOADWORLD_WORLDALREADYUNLOADING), + WORLD_NON_EXISTENT(MVCorei18n.UNLOADWORLD_WORLDNONEXISTENT), + WORLD_UNLOADED(MVCorei18n.UNLOADWORLD_WORLDUNLOADED), + BUKKIT_UNLOAD_FAILED(MVCorei18n.UNLOADWORLD_BUKKITUNLOADFAILED); - private final MessageKeyProvider message; + private final MessageKeyProvider message; - Success(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + UnloadWorldResult(MessageKeyProvider message) { + this.message = message; } - public enum Failure implements FailureReason { - WORLD_ALREADY_UNLOADING(MVCorei18n.UNLOADWORLD_WORLDALREADYUNLOADING), - WORLD_NON_EXISTENT(MVCorei18n.UNLOADWORLD_WORLDNONEXISTENT), - WORLD_UNLOADED(MVCorei18n.UNLOADWORLD_WORLDUNLOADED), - BUKKIT_UNLOAD_FAILED(MVCorei18n.UNLOADWORLD_BUKKITUNLOADFAILED); - - private final MessageKeyProvider message; - - Failure(MessageKeyProvider message) { - this.message = message; - } - - @Override - public MessageKey getMessageKey() { - return message.getMessageKey(); - } + @Override + public MessageKey getMessageKey() { + return message.getMessageKey(); } } diff --git a/src/main/resources/multiverse-core_en.properties b/src/main/resources/multiverse-core_en.properties index 16f760fb..178a6efd 100644 --- a/src/main/resources/multiverse-core_en.properties +++ b/src/main/resources/multiverse-core_en.properties @@ -13,6 +13,7 @@ mv-core.clone.description=Clones a world. mv-core.clone.world.description=The target world to clone. mv-core.clone.newWorld.description=The new cloned world name. mv-core.clone.cloning=Cloning world '{world}' to '{newworld}'... +mv-core.clone.success=&aWorld cloned to '{world}'! # /mv confirm mv-core.confirm.description=Confirms dangerous commands before executing them. @@ -39,6 +40,7 @@ mv-core.create.properties.adjustspawn=- Adjust Spawn: &f{adjustSpawn} mv-core.create.properties.generator=- Generator: &f{generator} mv-core.create.properties.structures=- Structures: &f{structures} mv-core.create.loading=Creating world... +mv-core.create.success=&aWorld '{world}' created! # /mv debug mv-core.debug.info.description=Show the current debug level. @@ -52,6 +54,7 @@ mv-core.debug.change.level.description=Debug level to set to. mv-core.delete.description=Deletes a world on your server PERMANENTLY. mv-core.delete.deleting=Deleting world '{world}'... mv-core.delete.prompt=Are you sure you want to delete world '{world}'? +mv-core.delete.success=&aWorld '{world}' deleted! # /mv dumps mv-core.dumps.description=Dumps version info to the console or paste services @@ -78,11 +81,13 @@ mv-core.import.name.description=Name of the world folder. mv-core.import.env.description=The world's environment. See: /mv env mv-core.import.other.description=Other world settings. See: https://gg.gg/nn8c2 mv-core.import.importing=Starting import of world '{world}'... +mv-core.import.success=&aWorld '{world}' imported! # /mv load mv-core.load.description=Loads a world. World must be already in worlds.yml, else please use /mv import. mv-core.load.world.description=Name of world you want to load. mv-core.load.loading=Loading world '{world}'... +mv-core.load.success=&aWorld '{world}' loaded! # /mv regen mv-core.regen.description=Regenerates a world on your server. The previous state will be lost PERMANENTLY. @@ -90,6 +95,7 @@ mv-core.regen.world.description=World that you want to regen. mv-core.regen.other.description=Other world settings. See: http://gg.gg/nn8lk mv-core.regen.regenerating=Regenerating world '{world}'... mv-core.regen.prompt=Are you sure you want to regenerate world '{world}'? +mv-core.regen.success=&aWorld '{world}' regenerated! # /mv reload mv-core.reload.description=Reloads config files for all Multiverse modules. @@ -99,6 +105,7 @@ mv-core.reload.success=&aReload complete! # /mv remove mv-core.remove.description=Unloads a world from Multiverse and removes it from worlds.yml. This does NOT delete the world folder. mv-core.remove.world.description=World you want to remove from MV's knowledge. +mv-core.remove.success=&aWorld '{world}' removed! # /mv mv-core.root.title=&a{name} version {version} @@ -114,6 +121,7 @@ mv-core.teleport.success=Teleporting {player} to {destination}... mv-core.unload.description=Unloads a world from Multiverse. This does NOT remove the world folder. This does NOT remove it from the config file. mv-core.unload.world.description=Name of the world you want to unload. mv-core.unload.unloading=Unloading world '{world}'... +mv-core.unload.success=&aWorld '{world}' unloaded! # /mv usage mv-core.usage.description=Show Multiverse-Core command usage. @@ -130,46 +138,37 @@ mv-core.entrycheck.exceedplayerlimit=the world has reached its player limit. mv-core.entrycheck.noworldaccess=you do not have permissions to access the world. # world manager result -mv-core.cloneworld.cloned=&aWorld cloned to '{world}'! mv-core.cloneworld.invalidworldname=World '{world}' contains invalid characters! mv-core.cloneworld.worldexistfolder=World '{world}' exists in server folders! You need to delete it first before cloning. mv-core.cloneworld.worldexistunloaded=World '{world}' already exists and it's unloaded! You need to delete it first before cloning. mv-core.cloneworld.worldexistloaded=World '{world}' already exists! You need to delete it first before cloning. mv-core.cloneworld.copyfailed=Failed to copy world to '{world}': {error}\n&fSee console for more details. -mv-core.createworld.created=&aWorld '{world}' created! mv-core.createworld.invalidworldname=World '{world}' contains invalid characters! mv-core.createworld.worldexistfolder=World '{world}' already exists in server folders!&f Type '&a/mv import {world} &f' if you wish to import it. mv-core.createworld.worldexistunloaded=World '{world}' already exists, but it's not loaded!&f Type '&a/mv load {world}&f' if you wish to load it. mv-core.createworld.worldexistloaded=World '{world}' already exists! mv-core.createworld.bukkitcreationfailed=Bukkit failed to create world '{world}': {error}\n&fSee console for more details. -mv-core.deleteworld.deleted=&aWorld '{world}' deleted! mv-core.deleteworld.worldnonexistent=World '{world}' not found! mv-core.deleteworld.loadfailed=Unable to load world '{world}', does the world folder exist?&f You can run '&a/mv remove {world}&f' to remove it from Multiverse, or attempt to load again with '&a/mv load {world}&f'. mv-core.deleteworld.worldfoldernotfound=World '{world}' folder not found! mv-core.deleteworld.failedtodeletefolder=Failed to delete world folder '{world}': {error}\n&fSee console for more details. -mv-core.importworld.imported=&aWorld '{world}' imported! mv-core.importworld.invalidworldname=World '{world}' contains invalid characters! mv-core.importworld.worldexistunloaded=World '{world}' already exists, but it's not loaded!&f Type '&a/mv load {world}&f' if you wish to load it. mv-core.importworld.worldexistloaded=World '{world}' already exists! mv-core.importworld.worldfolderinvalid=World '{world}' folder contents does not seem to be a valid world! mv-core.importworld.bukkitcreationfailed=Bukkit failed to import world '{world}': {error}\n&fSee console for more details. -mv-core.loadworld.loaded=&aWorld '{world}' loaded! mv-core.loadworld.worldalreadyloading=World '{world}' is already loading! Please wait... mv-core.loadworld.worldnonexistent=World '{world}' not found! Use '&a/mv create {world} &f' to create it. mv-core.loadworld.worldexistfolder=World '{world}' exists in server folders, but it's not known to Multiverse!&f Type '&a/mv import {world} &f' if you wish to import it. mv-core.loadworld.worldexistloaded=World '{world}' is already loaded! mv-core.loadworld.bukkitcreationfailed=Bukkit failed to load world '{world}': {error}\n&fSee console for more details. -mv-core.regenworld.regenerated=&aWorld '{world}' regenerated! - -mv-core.removeworld.removed=&aWorld '{world}' removed! mv-core.removeworld.worldnonexistent=World '{world}' not found! -mv-core.unloadworld.unloaded=&aWorld '{world}' unloaded! mv-core.unloadworld.worldalreadyunloading=World '{world}' is already unloading! Please wait... mv-core.unloadworld.worldnonexistent=World '{world}' does not exist! mv-core.unloadworld.worldunloaded=World '{world}' is already unloaded! diff --git a/src/test/java/org/mvplugins/multiverse/core/commandtools/LocalizationTest.kt b/src/test/java/org/mvplugins/multiverse/core/commandtools/LocalizationTest.kt index 167d5017..bfd223eb 100644 --- a/src/test/java/org/mvplugins/multiverse/core/commandtools/LocalizationTest.kt +++ b/src/test/java/org/mvplugins/multiverse/core/commandtools/LocalizationTest.kt @@ -202,7 +202,7 @@ class LocalizationTest : TestWithMockBukkit() { private val messageString = "Hello $replacementKey!" private val replacedMessageString = messageString.replace(replacementKey, replacementValue) - private val message = MVCorei18n.CLONEWORLD_CLONED + private val message = MVCorei18n.CLONE_SUCCESS .bundle(messageString, replace(replacementKey).with(replacementValue)) @Test From 99846b5567b980a1b88ee95ddc0d74f82636c0f8 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 23:00:15 +0800 Subject: [PATCH 6/8] Add javadocs and fix some checkstyles --- .../listeners/MVWorldListener.java | 4 +- .../MultiverseCore/utils/result/Attempt.java | 168 ++++++++++++++++-- .../MultiverseCore/utils/result/Result.java | 161 +++++++++++++++-- .../MultiverseCore/worldnew/WorldManager.java | 8 +- 4 files changed, 304 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVWorldListener.java b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVWorldListener.java index d0daf64b..2e85b043 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVWorldListener.java +++ b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVWorldListener.java @@ -43,7 +43,7 @@ public class MVWorldListener implements InjectableListener { return; } worldManager.unloadWorld(event.getWorld()).onFailure(failure -> { - if (failure.getFailureReason() != UnloadWorldResult.Failure.WORLD_ALREADY_UNLOADING) { + if (failure.getFailureReason() != UnloadWorldResult.WORLD_ALREADY_UNLOADING) { Logging.severe("Failed to unload world: " + failure); } }); @@ -60,7 +60,7 @@ public class MVWorldListener implements InjectableListener { .peek(world -> { Logging.fine("Loading world: " + world.getName()); worldManager.loadWorld(world).onFailure(failure -> { - if (failure.getFailureReason() != LoadWorldResult.Failure.WORLD_ALREADY_LOADING) { + if (failure.getFailureReason() != LoadWorldResult.WORLD_ALREADY_LOADING) { Logging.severe("Failed to load world: " + failure); } }); diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java index d7c2ff98..177a57cc 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Attempt.java @@ -7,35 +7,98 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -public interface Attempt { +/** + * Represents an attempt to process a value that can fail with a reason that has a localized message. + * + * @param The type of the value. + * @param The type of failure reason. + */ +public sealed interface Attempt permits Attempt.Success, Attempt.Failure { + /** + * Creates a new success attempt. + * + * @param value The value. + * @param The type of the value. + * @param The type of failure reason. + * @return The new success attempt. + */ static Attempt success(T value) { return new Success<>(value); } + /** + * Creates a new failure attempt. + * + * @param failureReason The reason for failure. + * @param messageReplacements The replacements for the failure message. + * @param The type of the value. + * @param The type of failure reason. + * @return The new failure attempt. + */ static Attempt failure( F failureReason, MessageReplacement... messageReplacements) { return new Failure<>(failureReason, Message.of(failureReason, "Failed!", messageReplacements)); } + /** + * Creates a new failure attempt with a custom message. + * + * @param failureReason The reason for failure. + * @param message The custom message for failure. This will override the default message. + * @param The type of the value. + * @param The type of failure reason. + * @return The new failure attempt. + */ static Attempt failure(F failureReason, Message message) { return new Failure<>(failureReason, message); } + /** + * Gets the value of this attempt. Exceptions will be thrown if this is a failure attempt. + * + * @return The value. + */ T get(); + /** + * Gets the reason for failure. Exceptions will be thrown if this is a success attempt. + * + * @return The reason for failure. + */ F getFailureReason(); + /** + * Gets the message for failure. Exceptions will be thrown if this is a success attempt. + * + * @return The message for failure. + */ Message getFailureMessage(); + /** + * Returns whether this attempt is a success. + * + * @return Whether this attempt is a success. + */ default boolean isSuccess() { return this instanceof Success; } + /** + * Returns whether this attempt is a failure. + * + * @return Whether this attempt is a failure. + */ default boolean isFailure() { return this instanceof Failure; } + /** + * Peeks at the value if this is a success attempt. + * + * @param consumer The consumer with the value. + * @return This attempt. + */ default Attempt peek(Consumer consumer) { if (this instanceof Success) { consumer.accept(get()); @@ -43,6 +106,13 @@ public interface Attempt { return this; } + /** + * Maps the value to another value if this is a success attempt. + * + * @param mapper The mapper. + * @param The type of the new value. + * @return The new attempt. + */ default Attempt map(Function mapper) { if (this instanceof Success) { return new Success<>(mapper.apply(get())); @@ -51,6 +121,13 @@ public interface Attempt { } } + /** + * Maps the value to another attempt if this is a success attempt. + * + * @param mapper The mapper. + * @param The type of the new value. + * @return The new attempt. + */ default Attempt map(Supplier mapper) { if (this instanceof Success) { return new Success<>(mapper.get()); @@ -59,6 +136,13 @@ public interface Attempt { } } + /** + * Maps the value to another attempt with the same fail reason if this is a success attempt. + * + * @param mapper The mapper. + * @param The type of the new value. + * @return The new attempt. + */ default Attempt mapAttempt(Function> mapper) { if (this instanceof Success) { return mapper.apply(get()); @@ -67,6 +151,13 @@ public interface Attempt { } } + /** + * Maps the value to another attempt with the same fail reason if this is a success attempt. + * + * @param mapper The mapper. + * @param The type of the new value. + * @return The new attempt. + */ default Attempt mapAttempt(Supplier> mapper) { if (this instanceof Success) { return mapper.get(); @@ -75,6 +166,13 @@ public interface Attempt { } } + /** + * Maps to another attempt with a different fail reason. + * + * @param failureReason The new fail reason. + * @param The type of the new fail reason. + * @return The new attempt. + */ default Attempt transform(UF failureReason) { if (this instanceof Success) { return new Success<>(get()); @@ -83,14 +181,14 @@ public interface Attempt { } } - default Attempt convertReason(NF failure) { - if (this instanceof Success) { - return new Success<>(get()); - } else { - return new Failure<>(failure, getFailureMessage()); - } - } - + /** + * Calls either the failure or success function depending on the result type. + * + * @param failureMapper The failure function. + * @param successMapper The success function. + * @param The type of the new value. + * @return The result of the function. + */ default N fold(Function, N> failureMapper, Function successMapper) { if (this instanceof Success) { return successMapper.apply(get()); @@ -99,6 +197,12 @@ public interface Attempt { } } + /** + * Calls the given runnable if this is a success attempt. + * + * @param runnable The runnable. + * @return This attempt. + */ default Attempt onSuccess(Runnable runnable) { if (this instanceof Success) { runnable.run(); @@ -106,6 +210,12 @@ public interface Attempt { return this; } + /** + * Calls the given consumer if this is a success attempt. + * + * @param consumer The consumer with the value. + * @return This attempt. + */ default Attempt onSuccess(Consumer consumer) { if (this instanceof Success) { consumer.accept(get()); @@ -113,6 +223,12 @@ public interface Attempt { return this; } + /** + * Calls the given consumer if this is a failure attempt. + * + * @param runnable The runnable. + * @return This attempt. + */ default Attempt onFailure(Runnable runnable) { if (this instanceof Failure) { runnable.run(); @@ -120,6 +236,12 @@ public interface Attempt { return this; } + /** + * Calls the given consumer if this is a failure attempt. + * + * @param consumer The consumer with the failure instance. + * @return This attempt. + */ default Attempt onFailure(Consumer> consumer) { if (this instanceof Failure) { consumer.accept((Failure) this); @@ -127,6 +249,12 @@ public interface Attempt { return this; } + /** + * Calls the given runnable if this is a failure attempt. + * + * @param consumer The consumer with the failure reason. + * @return This attempt. + */ default Attempt onFailureReason(Consumer consumer) { if (this instanceof Failure) { consumer.accept(getFailureReason()); @@ -134,7 +262,13 @@ public interface Attempt { return this; } - class Success implements Attempt { + /** + * Represents a successful attempt with a value. + * + * @param The type of the value. + * @param The type of failure reason. + */ + final class Success implements Attempt { private final T value; Success(T value) { @@ -148,12 +282,12 @@ public interface Attempt { @Override public F getFailureReason() { - throw new IllegalStateException("Attempt is a success!"); + throw new UnsupportedOperationException("No failure reason as attempt is a success"); } @Override public Message getFailureMessage() { - throw new IllegalStateException("Attempt is a success!"); + throw new UnsupportedOperationException("No failure message as attempt is a success"); } @Override @@ -164,7 +298,13 @@ public interface Attempt { } } - class Failure implements Attempt { + /** + * Represents a failed attempt with a reason. + * + * @param The type of the value. + * @param The type of failure reason. + */ + final class Failure implements Attempt { private final F failureReason; private final Message message; @@ -175,7 +315,7 @@ public interface Attempt { @Override public T get() { - throw new IllegalStateException("Attempt is a failure!"); + throw new UnsupportedOperationException("No value as attempt is a failure"); } @Override 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 6e029943..479f0854 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/Result.java @@ -8,42 +8,123 @@ import java.util.NoSuchElementException; import java.util.function.Consumer; import java.util.function.Function; -public sealed interface Result permits Result.Success, Result.Failure { +/** + * Represents result of an operation with a reason for success or failure that has localized messages. + * + * @param The type of success reason. + * @param The type of failure reason. + */ +public sealed interface Result + permits Result.Success, Result.Failure { + /** + * Creates a new success result. + * + * @param successReason The reason for success. + * @param replacements The replacements for the success message. + * @param The type of failure reason. + * @param The type of success reason. + * @return The new success result. + */ static Result success( - S successReason, MessageReplacement...replacements) { + S successReason, MessageReplacement... replacements) { return new Success<>(successReason, replacements); } + /** + * Creates a new success result. + * + * @param successReason The reason for success. + * @param message The custom message for success. This will override the default message. + * @param The type of failure reason. + * @param The type of success reason. + * @return The new success result. + */ static Result success(S successReason, Message message) { return new Success<>(successReason, message); } + /** + * Creates a new failure result. + * + * @param failureReason The reason for failure. + * @param replacements The replacements for the failure message. + * @param The type of failure reason. + * @param The type of success reason. + * @return The new failure result. + */ static Result failure( - F failureReason, MessageReplacement...replacements) { + F failureReason, MessageReplacement... replacements) { return new Failure<>(failureReason, replacements); } + /** + * Creates a new failure result. + * + * @param failureReason The reason for failure. + * @param message The custom message for failure. This will override the default message. + * @param The type of failure reason. + * @param The type of success reason. + * @return The new failure result. + */ static Result failure(F failureReason, Message message) { return new Failure<>(failureReason, message); } + + /** + * Returns whether this result is a success. + * + * @return Whether this result is a success. + */ boolean isSuccess(); + /** + * Returns whether this result is a failure. + * + * @return Whether this result is a failure. + */ boolean isFailure(); + /** + * Returns the reason for success. + * + * @return The reason for success. + */ S getSuccessReason(); + /** + * Returns the reason for failure. + * + * @return The reason for failure. + */ F getFailureReason(); + /** + * Returns the message for the reason of this result. + * + * @return The message for the reason. + */ @NotNull Message getReasonMessage(); - default Result onSuccess(Consumer> consumer) { + /** + * Executes the given consumer if this result is a success. + * + * @param consumer The consumer with success object. + * @return This result. + */ + default Result onSuccess(Consumer> consumer) { if (this instanceof Success) { - consumer.accept((Success) this); + consumer.accept((Success) this); } return this; } + /** + * Executes the given consumer if this result is a failure. + * + * @param consumer The consumer with failure object. + * @return This result. + */ default Result onFailure(Consumer> consumer) { if (this instanceof Failure) { consumer.accept((Failure) this); @@ -51,6 +132,13 @@ public sealed interface Result return this; } + /** + * Executes the given consumer if this result is a success and the success reason matches the given reason. + * + * @param successReason The success reason to match. + * @param consumer The consumer with success reason. + * @return This result. + */ default Result onSuccessReason(S successReason, Consumer consumer) { if (this.isSuccess() && this.getSuccessReason() == successReason) { consumer.accept(this.getSuccessReason()); @@ -58,6 +146,13 @@ public sealed interface Result return this; } + /** + * Executes the given consumer if this result is a failure and the failure reason matches the given reason. + * + * @param failureReason The failure reason to match. + * @param consumer The consumer with failure reason. + * @return This result. + */ default Result onFailureReason(F failureReason, Consumer consumer) { if (this.isFailure() && this.getFailureReason() == failureReason) { consumer.accept(this.getFailureReason()); @@ -65,13 +160,25 @@ public sealed interface Result return this; } - default Result onSuccessThen(Function, Result> function) { + /** + * Executes the given function if this result is a success and returns the result of the function. + * + * @param function The function with success object. + * @return The result of the function. + */ + default Result onSuccessThen(Function, Result> function) { if (this instanceof Success) { - return function.apply((Success) this); + return function.apply((Success) this); } return this; } + /** + * Executes the given function if this result is a failure and returns the result of the function. + * + * @param function The function with failure object. + * @return The result of the function. + */ default Result onFailureThen(Function, Result> function) { if (this instanceof Failure) { return function.apply((Failure) this); @@ -79,25 +186,39 @@ public sealed interface Result return this; } - default R fold(Function, R> failureFunc, Function, R> successFunc) { + /** + * Executes either the failure or success function depending on the result type. + * + * @param failureFunc The function with success reason. + * @param successFunc The function with success reason. + * @param The type of the result. + * @return The result of the function. + */ + 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); + return successFunc.apply((Success) this); } throw new IllegalStateException("Unknown result type: " + this.getClass().getName()); } - final class Success implements Result { + /** + * The class for a successful result. + * + * @param The type of failure reason. + * @param The type of success reason. + */ + final class Success implements Result { private final S successReason; private final Message message; - public Success(S successReason, Message message) { + Success(S successReason, Message message) { this.successReason = successReason; this.message = message; } - public Success(S successReason, MessageReplacement[] replacements) { + Success(S successReason, MessageReplacement[] replacements) { this.successReason = successReason; this.message = Message.of(successReason, "Success!", replacements); } @@ -119,7 +240,7 @@ public sealed interface Result @Override public F getFailureReason() { - throw new NoSuchElementException("No reason for failure"); + throw new UnsupportedOperationException("No reason for success"); } @Override @@ -135,18 +256,24 @@ public sealed interface Result } } + /** + * The class for a failed result. + * + * @param The type of success reason. + * @param The type of failure reason. + */ final class Failure implements Result { private final F failureReason; private final Message message; - public Failure(F failureReason, Message message) { + Failure(F failureReason, Message message) { this.failureReason = failureReason; this.message = message; } - public Failure(F failureReason, MessageReplacement[] replacements) { + Failure(F failureReason, MessageReplacement[] replacements) { this.failureReason = failureReason; - this.message = Message.of(failureReason, "Success!", replacements); + this.message = Message.of(failureReason, "Failed!", replacements); } @Override @@ -161,7 +288,7 @@ public sealed interface Result @Override public S getSuccessReason() { - throw new NoSuchElementException("No reason for failure"); + throw new UnsupportedOperationException("No reason for failure"); } @Override diff --git a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java index 64001b9d..8a16d24e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java @@ -488,7 +488,7 @@ public class WorldManager { public Attempt deleteWorld(@NotNull MultiverseWorld world) { return getLoadedWorld(world).fold( () -> loadWorld(world) - .convertReason(DeleteWorldResult.LOAD_FAILED) + .transform(DeleteWorldResult.LOAD_FAILED) .mapAttempt(this::deleteWorld), this::deleteWorld); } @@ -535,7 +535,7 @@ public class WorldManager { .worldName(validatedOptions.newWorldName()) .environment(validatedOptions.world().getEnvironment()) .generator(validatedOptions.world().getGenerator()); - return importWorld(importWorldOptions).convertReason(CloneWorldResult.IMPORT_FAILED); + return importWorld(importWorldOptions).transform(CloneWorldResult.IMPORT_FAILED); }) .onSuccess(newWorld -> { cloneWorldTransferData(options, newWorld); @@ -616,8 +616,8 @@ public class WorldManager { .worldType(world.getWorldType().getOrElse(WorldType.NORMAL)); return deleteWorld(world) - .convertReason(RegenWorldResult.DELETE_FAILED) - .mapAttempt(() -> createWorld(createWorldOptions).convertReason(RegenWorldResult.CREATE_FAILED)) + .transform(RegenWorldResult.DELETE_FAILED) + .mapAttempt(() -> createWorld(createWorldOptions).transform(RegenWorldResult.CREATE_FAILED)) .onSuccess(newWorld -> { dataTransfer.pasteAllTo(newWorld); saveWorldsConfig(); From 8ffd716190b1a3babebf27006fae7b390ce27728 Mon Sep 17 00:00:00 2001 From: Jeremy Wood Date: Sun, 10 Sep 2023 13:34:36 -0400 Subject: [PATCH 7/8] Fix some checkstyle issues. --- .../MultiverseCore/commands/CloneCommand.java | 2 +- .../commands/CreateCommand.java | 3 +-- .../commands/DeleteCommand.java | 20 ++++++++----------- .../commands/ImportCommand.java | 17 ++++++++-------- .../MultiverseCore/utils/MVCorei18n.java | 6 ++++-- .../utils/result/package-info.java | 1 + 6 files changed, 24 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/result/package-info.java diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java index 9138a178..17bb67b7 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CloneCommand.java @@ -63,7 +63,7 @@ public class CloneCommand extends MultiverseCommand { String newWorldName, @Optional - @Syntax("") // TODO + @Syntax(/* TODO */ "") @Description("{@@mv-core.regen.other.description}") String[] flags) { ParsedCommandFlags parsedFlags = parseFlags(flags); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java index e5021218..bcb4f87b 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java @@ -82,8 +82,7 @@ public class CreateCommand extends MultiverseCommand { @Optional @Syntax("--seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures") @Description("{@@mv-core.create.flags.description}") - String[] flags - ) { + String[] flags) { ParsedCommandFlags parsedFlags = parseFlags(flags); issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES, "{worldName}", worldName); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java index f8b34799..e23c4a02 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/DeleteCommand.java @@ -49,18 +49,14 @@ public class DeleteCommand extends MultiverseCommand { issuer.getIssuer(), () -> { issuer.sendInfo(MVCorei18n.DELETE_DELETING, "{world}", worldName); - try { - worldManager.deleteWorld(worldName) - .onSuccess(deletedWorldName -> { - Logging.fine("World delete success: " + deletedWorldName); - issuer.sendInfo(MVCorei18n.DELETE_SUCCESS, "{world}", deletedWorldName); - }).onFailure(failure -> { - Logging.fine("World delete failure: " + failure); - issuer.sendError(failure.getFailureMessage()); - }); - } catch (Exception e) { - e.printStackTrace(); - } + worldManager.deleteWorld(worldName) + .onSuccess(deletedWorldName -> { + Logging.fine("World delete success: " + deletedWorldName); + issuer.sendInfo(MVCorei18n.DELETE_SUCCESS, "{world}", deletedWorldName); + }).onFailure(failure -> { + Logging.fine("World delete failure: " + failure); + issuer.sendError(failure.getFailureMessage()); + }); }, this.commandManager.formatMessage( issuer, diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java index 11c5d012..7031f8f7 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java @@ -78,13 +78,14 @@ public class ImportCommand extends MultiverseCommand { worldManager.importWorld(ImportWorldOptions.worldName(worldName) .environment(environment) .generator(parsedFlags.flagValue("--generator", String.class)) - .useSpawnAdjust(parsedFlags.hasFlag("--adjust-spawn")) - ).onSuccess(newWorld -> { - Logging.fine("World import success: " + newWorld); - issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS, "{world}", newWorld.getName()); - }).onFailure(failure -> { - Logging.fine("World import failure: " + failure); - issuer.sendError(failure.getFailureMessage()); - }); + .useSpawnAdjust(parsedFlags.hasFlag("--adjust-spawn"))) + .onSuccess(newWorld -> { + Logging.fine("World import success: " + newWorld); + issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS, "{world}", newWorld.getName()); + }) + .onFailure(failure -> { + Logging.fine("World import failure: " + failure); + issuer.sendError(failure.getFailureMessage()); + }); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java index dd4faa47..fcfe1bea 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java @@ -7,6 +7,8 @@ import com.onarandombox.MultiverseCore.utils.message.MessageReplacement; import org.jetbrains.annotations.NotNull; public enum MVCorei18n implements MessageKeyProvider { + // BEGIN CHECKSTYLE-SUPPRESSION: Javadoc + // config status CONFIG_SAVE_FAILED, CONFIG_NODE_NOTFOUND, @@ -140,9 +142,9 @@ public enum MVCorei18n implements MessageKeyProvider { // generic GENERIC_SUCCESS, - GENERIC_FAILURE + GENERIC_FAILURE; - ; + // END CHECKSTYLE-SUPPRESSION: Javadoc private final MessageKey key = MessageKey.of("mv-core." + this.name().replace('_', '.').toLowerCase()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/result/package-info.java b/src/main/java/com/onarandombox/MultiverseCore/utils/result/package-info.java new file mode 100644 index 00000000..b4b03292 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/result/package-info.java @@ -0,0 +1 @@ +package com.onarandombox.MultiverseCore.utils.result; From 089655fadadc7e0c5bcd0f34e552dd31795758c1 Mon Sep 17 00:00:00 2001 From: Jeremy Wood Date: Sun, 10 Sep 2023 13:35:25 -0400 Subject: [PATCH 8/8] Fix some more checkstyle issues. --- .../MultiverseCore/commands/CreateCommand.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java index bcb4f87b..cbc3b502 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java @@ -101,13 +101,13 @@ public class CreateCommand extends MultiverseCommand { .worldType(parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class)) .useSpawnAdjust(!parsedFlags.hasFlag("--no-adjust-spawn")) .generator(parsedFlags.flagValue("--generator", "", String.class)) - .generateStructures(!parsedFlags.hasFlag("--no-structures")) - ).onSuccess(newWorld -> { - Logging.fine("World create success: " + newWorld); - issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{world}", newWorld.getName()); - }).onFailure(failure -> { - Logging.fine("World create failure: " + failure); - issuer.sendError(failure.getFailureMessage()); - }); + .generateStructures(!parsedFlags.hasFlag("--no-structures"))) + .onSuccess(newWorld -> { + Logging.fine("World create success: " + newWorld); + issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{world}", newWorld.getName()); + }).onFailure(failure -> { + Logging.fine("World create failure: " + failure); + issuer.sendError(failure.getFailureMessage()); + }); } }