Finish basic CRUD for new world management

This commit is contained in:
Ben Woo 2023-09-03 00:51:07 +08:00
parent 7828c92926
commit b154606922
No known key found for this signature in database
GPG Key ID: FB2A3645536E12C8
16 changed files with 341 additions and 110 deletions

View File

@ -17,7 +17,9 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
@ -26,6 +28,8 @@ import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.World;
@ -38,16 +42,15 @@ import org.jvnet.hk2.annotations.Service;
@CommandAlias("mv")
public class CreateCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
private final WorldManager worldManager;
@Inject
public CreateCommand(
@NotNull MVCommandManager commandManager,
@NotNull MVWorldManager worldManager,
@NotNull WorldManager worldManager,
@NotNull UnsafeCallWrapper unsafeCallWrapper
) {
super(commandManager);
this.worldManager = worldManager;
registerFlagGroup(CommandFlagGroup.builder("mvcreate")
@ -84,7 +87,7 @@ public class CreateCommand extends MultiverseCommand {
@CommandCompletion("@empty @flags:groupName=mvcreate")
@Syntax("<name> <environment> --seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
@Description("{@@mv-core.create.description}")
public void onCreateCommand(BukkitCommandIssuer issuer,
public void onCreateCommand(MVCommandIssuer issuer,
@Conditions("worldname:scope=new")
@Syntax("<name>")
@ -107,23 +110,24 @@ public class CreateCommand extends MultiverseCommand {
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_SEED, "{seed}", parsedFlags.flagValue("--seed", "RANDOM", String.class));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_WORLDTYPE, "{worldType}", parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class).name());
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ADJUSTSPAWN, "{adjustSpawn}", String.valueOf(parsedFlags.hasFlag("--adjust-spawn")));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATOR, "{generator}", parsedFlags.flagValue("--generator", "null", String.class));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATOR, "{generator}", parsedFlags.flagValue("--generator", "", String.class));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_STRUCTURES, "{structures}", String.valueOf(!parsedFlags.hasFlag("--no-structures")));
issuer.sendInfo(MVCorei18n.CREATE_LOADING);
if (!worldManager.addWorld(
worldName,
environment,
parsedFlags.flagValue("--seed", String.class),
parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class),
parsedFlags.hasFlag("--adjust-spawn"),
parsedFlags.flagValue("--generator", String.class),
parsedFlags.hasFlag("--no-structures")
)) {
issuer.sendError(MVCorei18n.CREATE_FAILED, "{worldName}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{worldName}", worldName);
worldManager.createWorld(CreateWorldOptions.worldName(worldName)
.environment(environment)
.seed(parsedFlags.flagValue("--seed", String.class))
.worldType(parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class))
.useSpawnAdjust(parsedFlags.hasFlag("--adjust-spawn"))
.generator(parsedFlags.flagValue("--generator", "", String.class))
.generateStructures(!parsedFlags.hasFlag("--no-structures"))
).onSuccess((success) -> {
Logging.fine("World create success: " + success);
issuer.sendInfo(success.getReasonMessage());
}).onFailure((failure) -> {
Logging.fine("World create failure: " + failure);
issuer.sendError(failure.getReasonMessage());
});
}
}

View File

@ -10,11 +10,14 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@ -23,10 +26,10 @@ import org.jvnet.hk2.annotations.Service;
@CommandAlias("mv")
public class DeleteCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
private final WorldManager worldManager;
@Inject
public DeleteCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
public DeleteCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@ -36,10 +39,10 @@ public class DeleteCommand extends MultiverseCommand {
@CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.delete.description}")
public void onDeleteCommand(BukkitCommandIssuer issuer,
public void onDeleteCommand(MVCommandIssuer issuer,
@Single
@Conditions("worldname:scope=both")
//@Conditions("worldname:scope=both")
@Syntax("<world>")
@Description("The world you want to delete.")
String worldName
@ -47,15 +50,15 @@ public class DeleteCommand extends MultiverseCommand {
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
issuer.getIssuer(),
() -> {
issuer.sendInfo(MVCorei18n.DELETE_DELETING,
"{world}", worldName);
if (!this.worldManager.deleteWorld(worldName)) {
issuer.sendError(MVCorei18n.DELETE_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.DELETE_SUCCESS,
"{world}", worldName);
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());
});
},
this.commandManager.formatMessage(
issuer,

View File

@ -9,10 +9,13 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
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;
import org.jvnet.hk2.annotations.Service;
@ -21,10 +24,10 @@ import org.jvnet.hk2.annotations.Service;
@CommandAlias("mv")
public class LoadCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
private final WorldManager worldManager;
@Inject
public LoadCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
public LoadCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@ -34,23 +37,22 @@ public class LoadCommand extends MultiverseCommand {
@CommandCompletion("@mvworlds:scope=unloaded")
@Syntax("<world>")
@Description("{@@mv-core.load.description}")
public void onLoadCommand(BukkitCommandIssuer issuer,
public void onLoadCommand(MVCommandIssuer issuer,
@Single
@Conditions("worldname:scope=unloaded")
//@Conditions("worldname:scope=unloaded")
@Syntax("<world>")
@Description("{@@mv-core.load.world.description}")
String worldName
) {
issuer.sendInfo(MVCorei18n.LOAD_LOADING,
"{world}", worldName);
if (!this.worldManager.loadWorld(worldName)) {
issuer.sendError(MVCorei18n.LOAD_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.LOAD_SUCCESS,
"{world}", worldName);
issuer.sendInfo(MVCorei18n.LOAD_LOADING, "{world}", worldName);
worldManager.loadWorld(worldName)
.onSuccess((success) -> {
Logging.fine("World load success: " + success);
issuer.sendInfo(success.getReasonMessage());
}).onFailure((failure) -> {
Logging.fine("World load failure: " + failure);
issuer.sendError(failure.getReasonMessage());
});
}
}

View File

@ -1,6 +1,5 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
@ -9,10 +8,11 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
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;
import org.jvnet.hk2.annotations.Service;
@ -21,10 +21,10 @@ import org.jvnet.hk2.annotations.Service;
@CommandAlias("mv")
public class RemoveCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
private final WorldManager worldManager;
@Inject
public RemoveCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
public RemoveCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@ -34,19 +34,21 @@ public class RemoveCommand extends MultiverseCommand {
@CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.remove.description}")
public void onRemoveCommand(BukkitCommandIssuer issuer,
public void onRemoveCommand(MVCommandIssuer issuer,
@Single
@Conditions("mvworlds:scope=both")
//@Conditions("mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.remove.world.description}")
String worldName
) {
if (!this.worldManager.removeWorldFromConfig(worldName)) {
issuer.sendError(MVCorei18n.REMOVE_FAILED);
return;
}
issuer.sendInfo(MVCorei18n.REMOVE_SUCCESS,
"{world}", worldName);
worldManager.removeWorld(worldName)
.onSuccess((success) -> {
Logging.fine("World remove success: " + success);
issuer.sendInfo(success.getReasonMessage());
}).onFailure((failure) -> {
Logging.fine("World remove failure: " + failure);
issuer.sendError(failure.getReasonMessage());
});
}
}

View File

@ -7,11 +7,14 @@ import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
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;
import org.jvnet.hk2.annotations.Service;
@ -20,10 +23,10 @@ import org.jvnet.hk2.annotations.Service;
@CommandAlias("mv")
public class UnloadCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
private final WorldManager worldManager;
@Inject
public UnloadCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
public UnloadCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@ -33,22 +36,20 @@ public class UnloadCommand extends MultiverseCommand {
@CommandCompletion("@mvworlds")
@Syntax("<world>")
@Description("{@@mv-core.unload.description}")
public void onUnloadCommand(BukkitCommandIssuer issuer,
public void onUnloadCommand(MVCommandIssuer issuer,
@Syntax("<world>")
@Description("{@@mv-core.unload.world.description}")
MVWorld world
String worldName // TODO: Use world object
) {
issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING,
"{world}", world.getColoredWorldString());
// TODO: Should be able to use MVWorld object directly for unloadWorld
if (!this.worldManager.unloadWorld(world.getName())) {
issuer.sendError(MVCorei18n.UNLOAD_FAILURE,
"{world}", world.getColoredWorldString());
return;
}
issuer.sendInfo(MVCorei18n.UNLOAD_SUCCESS,
"{world}", world.getColoredWorldString());
issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING, "{world}", worldName);
worldManager.unloadWorld(worldName)
.onSuccess((success) -> {
Logging.fine("World unload success: " + success);
issuer.sendInfo(success.getReasonMessage());
}).onFailure((failure) -> {
Logging.fine("World unload failure: " + failure);
issuer.sendError(failure.getReasonMessage());
});
}
}

View File

@ -199,7 +199,7 @@ public class MVCommandContexts extends PaperCommandContexts {
context.popFirstArg();
return world;
}
if (!context.isOptional()) {
if (context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");

View File

@ -5,6 +5,7 @@ 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;
public sealed interface Result<S extends SuccessReason, F extends FailureReason> permits Result.Success, Result.Failure {
@ -26,16 +27,16 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
@NotNull Message getReasonMessage();
default Result<S, F> onSuccess(Consumer<S> consumer) {
if (this.isSuccess()) {
consumer.accept(this.getSuccessReason());
default Result<S, F> onSuccess(Consumer<Success<F, S>> consumer) {
if (this instanceof Success) {
consumer.accept((Success<F, S>) this);
}
return this;
}
default Result<S, F> onFailure(Consumer<F> consumer) {
if (this.isFailure()) {
consumer.accept(this.getFailureReason());
default Result<S, F> onFailure(Consumer<Failure<S, F>> consumer) {
if (this instanceof Failure) {
consumer.accept((Failure<S, F>) this);
}
return this;
}
@ -117,7 +118,7 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
@Override
public S getSuccessReason() {
throw new NoSuchElementException("No reason for success");
throw new NoSuchElementException("No reason for failure");
}
@Override
@ -127,7 +128,7 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
@Override
public @NotNull Message getReasonMessage() {
return Message.of(failureReason, "Success!", replacements);
return Message.of(failureReason, "Failed!", replacements);
}
@Override

View File

@ -1,16 +1,26 @@
package com.onarandombox.MultiverseCore.worldnew;
import com.dumptruckman.minecraft.util.Logging;
import com.google.common.base.Strings;
import com.onarandombox.MultiverseCore.utils.file.FileUtils;
import com.onarandombox.MultiverseCore.utils.result.Result;
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
import com.onarandombox.MultiverseCore.world.WorldNameChecker;
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig;
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager;
import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions;
import com.onarandombox.MultiverseCore.worldnew.results.CreateWorldResult;
import com.onarandombox.MultiverseCore.worldnew.results.DeleteWorldResult;
import com.onarandombox.MultiverseCore.worldnew.results.LoadWorldResult;
import com.onarandombox.MultiverseCore.worldnew.results.RemoveWorldResult;
import com.onarandombox.MultiverseCore.worldnew.results.UnloadWorldResult;
import io.vavr.control.Option;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
import java.io.File;
@ -35,9 +45,12 @@ public class WorldManager {
public void initAllWorlds() {
populateOfflineWorlds();
getOfflineWorlds().forEach(offlineWorld -> {
if (offlineWorld.getAutoLoad()) {
loadWorld(offlineWorld);
if (!offlineWorld.getAutoLoad()) {
return;
}
loadWorld(offlineWorld).onFailure((failure) -> {
Logging.severe("Failed to load world %s: %s", offlineWorld.getName(), failure);
});
});
saveWorldsConfig();
}
@ -47,6 +60,7 @@ public class WorldManager {
worldsConfigManager.getAllWorldConfigs().forEach(worldConfig -> {
OfflineWorld offlineWorld = new OfflineWorld(worldConfig.getWorldName(), worldConfig);
offlineWorldsMap.put(worldConfig.getWorldName(), offlineWorld);
Logging.fine("Loaded world %s from config", worldConfig.getWorldName());
});
}
@ -55,24 +69,37 @@ public class WorldManager {
*
* @param options The options for customizing the creation of a new world.
*/
public void createWorld(CreateWorldOptions options) {
// TODO: Check valid worldname
public Result<CreateWorldResult.Success, CreateWorldResult.Failure> createWorld(CreateWorldOptions options) {
if (!WorldNameChecker.isValidWorldName(options.worldName())) {
return Result.failure(CreateWorldResult.Failure.INVALID_WORLDNAME);
}
// TODO: Check if world already exists
if (getMVWorld(options.worldName()).isDefined()) {
return Result.failure(CreateWorldResult.Failure.WORLD_EXIST_LOADED);
}
if (getOfflineWorld(options.worldName()).isDefined()) {
return Result.failure(CreateWorldResult.Failure.WORLD_EXIST_OFFLINE);
}
File worldFolder = new File(Bukkit.getWorldContainer(), options.worldName());
if (worldFolder.exists()) {
return Result.failure(CreateWorldResult.Failure.WORLD_EXIST_FOLDER);
}
// Create bukkit world
World world = WorldCreator.name(options.worldName())
.environment(options.environment())
.generateStructures(options.generateStructures())
.generator(options.generator())
.generator(Strings.isNullOrEmpty(options.generator()) ? null : options.generator())
.seed(options.seed())
.type(options.worldType())
.createWorld();
if (world == null) {
// TODO: Better result handling
Logging.severe("Failed to create world: " + options.worldName());
return;
return Result.failure(CreateWorldResult.Failure.BUKKIT_CREATION_FAILED);
}
Logging.fine("Loaded bukkit world: " + world.getName());
// Our multiverse world
WorldConfig worldConfig = worldsConfigManager.addWorldConfig(options.worldName());
@ -87,20 +114,32 @@ public class WorldManager {
worldsMap.put(mvWorld.getName(), mvWorld);
saveWorldsConfig();
return Result.success(CreateWorldResult.Success.CREATED);
}
public void loadWorld(@NotNull OfflineWorld offlineWorld) {
public Result<LoadWorldResult.Success, LoadWorldResult.Failure> loadWorld(@NotNull String worldName) {
return getOfflineWorld(worldName)
.map(this::loadWorld)
.getOrElse(() -> Result.failure(LoadWorldResult.Failure.WORLD_NON_EXISTENT));
}
public Result<LoadWorldResult.Success, LoadWorldResult.Failure> loadWorld(@NotNull OfflineWorld offlineWorld) {
if (isMVWorld(offlineWorld)) {
Logging.severe("World already loaded: " + offlineWorld.getName());
return Result.failure(LoadWorldResult.Failure.WORLD_EXIST_LOADED);
}
// TODO: Reduce copy paste from createWorld method
World world = WorldCreator.name(offlineWorld.getName())
.environment(offlineWorld.getEnvironment())
.generator(offlineWorld.getGenerator())
.generator(Strings.isNullOrEmpty(offlineWorld.getGenerator()) ? null : offlineWorld.getGenerator())
.seed(offlineWorld.getSeed())
.createWorld();
if (world == null) {
// TODO: Better result handling
Logging.severe("Failed to create world: " + offlineWorld.getName());
return;
return Result.failure(LoadWorldResult.Failure.BUKKIT_CREATION_FAILED);
}
Logging.fine("Loaded bukkit world: " + world.getName());
// Our multiverse world
WorldConfig worldConfig = worldsConfigManager.getWorldConfig(offlineWorld.getName());
@ -108,45 +147,74 @@ public class WorldManager {
worldsMap.put(mvWorld.getName(), mvWorld);
saveWorldsConfig();
return Result.success(LoadWorldResult.Success.LOADED);
}
public void unloadWorld(@NotNull MVWorld world) {
public Result<UnloadWorldResult.Success, UnloadWorldResult.Failure> unloadWorld(@NotNull String worldName) {
return getMVWorld(worldName)
.map(this::unloadWorld)
.getOrElse(() -> Result.failure(UnloadWorldResult.Failure.WORLD_NON_EXISTENT));
}
public Result<UnloadWorldResult.Success, UnloadWorldResult.Failure> unloadWorld(@NotNull MVWorld world) {
World bukkitWorld = world.getBukkitWorld();
// TODO: removePlayersFromWorld?
if (!Bukkit.unloadWorld(bukkitWorld, true)) {
Logging.severe("Failed to unload world: " + world.getName());
return;
}
if (Bukkit.getWorld(world.getName()) != null) {
Logging.severe("World still loaded: " + world.getName());
return;
return Result.failure(UnloadWorldResult.Failure.BUKKIT_UNLOAD_FAILED);
}
worldsMap.remove(world.getName());
return Result.success(UnloadWorldResult.Success.UNLOADED);
}
public void removeWorld(@NotNull OfflineWorld world) {
public Result<RemoveWorldResult.Success, UnloadWorldResult.Failure> removeWorld(@NotNull String worldName) {
return getOfflineWorld(worldName)
.map(this::removeWorld)
.getOrElse(() -> Result.failure(RemoveWorldResult.Failure.WORLD_NON_EXISTENT));
}
public Result<RemoveWorldResult.Success, UnloadWorldResult.Failure> removeWorld(@NotNull OfflineWorld world) {
if (world instanceof MVWorld mvWorld) {
unloadWorld(mvWorld);
var result = unloadWorld(mvWorld);
if (result.isFailure()) {
return Result.failure(result.getFailureReason());
}
}
// Remove world from config
offlineWorldsMap.remove(world.getName());
worldsConfigManager.deleteWorldConfig(world.getName());
saveWorldsConfig();
return Result.success(RemoveWorldResult.Success.REMOVED);
}
public void deleteWorld(@NotNull MVWorld world) {
public Result<DeleteWorldResult.Success, UnloadWorldResult.Failure> deleteWorld(@NotNull String worldName) {
return getMVWorld(worldName)
.map(this::deleteWorld)
.getOrElse(() -> Result.failure(DeleteWorldResult.Failure.WORLD_NON_EXISTENT));
}
public Result<DeleteWorldResult.Success, UnloadWorldResult.Failure> deleteWorld(@NotNull MVWorld world) {
// TODO: Attempt to load if unloaded so we can actually delete the world
File worldFolder = world.getBukkitWorld().getWorldFolder();
removeWorld(world);
var result = removeWorld(world);
if (result.isFailure()) {
return Result.failure(result.getFailureReason());
}
// Erase world files from disk
// TODO: Config options to keep certain files
FileUtils.deleteFolder(worldFolder);
if (!FileUtils.deleteFolder(worldFolder)) {
Logging.severe("Failed to delete world folder: " + worldFolder);
return Result.failure(DeleteWorldResult.Failure.FAILED_TO_DELETE_FOLDER);
}
return Result.success(DeleteWorldResult.Success.DELETED);
}
public Option<OfflineWorld> getOfflineWorld(@NotNull String worldName) {
public Option<OfflineWorld> getOfflineWorld(@Nullable String worldName) {
return Option.of(offlineWorldsMap.get(worldName));
}
@ -154,10 +222,22 @@ public class WorldManager {
return offlineWorldsMap.values();
}
public Option<MVWorld> getMVWorld(@NotNull String worldName) {
public Option<MVWorld> getMVWorld(@Nullable String worldName) {
return Option.of(worldsMap.get(worldName));
}
public Collection<MVWorld> getMVWorlds() {
return worldsMap.values();
}
public boolean isMVWorld(@Nullable OfflineWorld world) {
return world != null && isMVWorld(world.getName());
}
public boolean isMVWorld(@Nullable String worldName) {
return worldsMap.containsKey(worldName);
}
public void saveWorldsConfig() {
worldsConfigManager.save();
}

View File

@ -91,7 +91,7 @@ public class WorldConfigNodes {
.build());
public final ConfigNode<String> GENERATOR = node(ConfigNode.builder("generator", String.class)
.defaultValue("")
.defaultValue("@error") // this should be set on world creation
.name("generator")
.build());

View File

@ -113,7 +113,11 @@ public class CreateWorldOptions {
* @param seed The seed of the world to create.
* @return This {@link CreateWorldOptions} instance.
*/
public @NotNull CreateWorldOptions seed(@NotNull String seed) {
public @NotNull CreateWorldOptions seed(@Nullable String seed) {
if (seed == null) {
this.seed = Long.MIN_VALUE;
return this;
}
try {
this.seed = Long.parseLong(seed);
} catch (NumberFormatException numberformatexception) {

View File

@ -0,0 +1,33 @@
package com.onarandombox.MultiverseCore.worldnew.results;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
public class CreateWorldResult {
public enum Success implements SuccessReason {
CREATED
}
public enum Failure implements FailureReason {
INVALID_WORLDNAME(MVCorei18n.GENERIC_FAILURE),
WORLD_EXIST_FOLDER(MVCorei18n.GENERIC_FAILURE),
WORLD_EXIST_OFFLINE(MVCorei18n.GENERIC_FAILURE),
WORLD_EXIST_LOADED(MVCorei18n.GENERIC_FAILURE),
BUKKIT_CREATION_FAILED(MVCorei18n.GENERIC_FAILURE),
;
private final MessageKeyProvider message;
Failure(MessageKeyProvider message) {
this.message = message;
}
@Override
public MessageKey getMessageKey() {
return message.getMessageKey();
}
}
}

View File

@ -0,0 +1,19 @@
package com.onarandombox.MultiverseCore.worldnew.results;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
public class DeleteWorldResult {
public enum Success implements SuccessReason {
DELETED
}
public static class Failure extends RemoveWorldResult.Failure {
public static final Failure FAILED_TO_DELETE_FOLDER = new Failure(MVCorei18n.GENERIC_FAILURE);
Failure(MessageKeyProvider message) {
super(message);
}
}
}

View File

@ -0,0 +1,32 @@
package com.onarandombox.MultiverseCore.worldnew.results;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
public class LoadWorldResult {
public enum Success implements SuccessReason {
LOADED
}
public enum Failure implements FailureReason {
WORLD_NON_EXISTENT(MVCorei18n.GENERIC_FAILURE),
WORLD_EXIST_FOLDER(MVCorei18n.GENERIC_FAILURE),
WORLD_EXIST_LOADED(MVCorei18n.GENERIC_FAILURE),
BUKKIT_CREATION_FAILED(MVCorei18n.GENERIC_FAILURE),
;
private final MessageKeyProvider message;
Failure(MessageKeyProvider message) {
this.message = message;
}
@Override
public MessageKey getMessageKey() {
return message.getMessageKey();
}
}
}

View File

@ -0,0 +1,20 @@
package com.onarandombox.MultiverseCore.worldnew.results;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
public class RemoveWorldResult {
public enum Success implements SuccessReason {
REMOVED
}
public static class Failure extends UnloadWorldResult.Failure {
// TODO
Failure(MessageKeyProvider message) {
super(message);
}
}
}

View File

@ -0,0 +1,30 @@
package com.onarandombox.MultiverseCore.worldnew.results;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
public class UnloadWorldResult {
public enum Success implements SuccessReason {
UNLOADED
}
public static class Failure implements FailureReason {
public static final Failure WORLD_NON_EXISTENT = new Failure(MVCorei18n.GENERIC_FAILURE);
public static final Failure WORLD_OFFLINE = new Failure(MVCorei18n.GENERIC_FAILURE);
public static final Failure BUKKIT_UNLOAD_FAILED = new Failure(MVCorei18n.GENERIC_FAILURE);
private final MessageKeyProvider message;
Failure(MessageKeyProvider message) {
this.message = message;
}
@Override
public MessageKey getMessageKey() {
return message.getMessageKey();
}
}
}

View File

@ -77,7 +77,7 @@ newworld:
currency: AIR
environment: NORMAL
gamemode: SURVIVAL
generator: ''
generator: '@error'
hidden: false
hunger: true
keep-spawn-in-memory: true