Merge pull request #3013 from Multiverse/world-revamp-continue
Continue revamping World/WorldManager.
This commit is contained in:
commit
d3fa42a035
|
@ -8,11 +8,15 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: dbelyaev/action-checkstyle@v0.8.4
|
||||
continue-on-error: true
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
checkstyle_version: 10.12.2
|
||||
checkstyle_config: ./config/mv_checks.xml
|
||||
level: warning
|
||||
|
|
|
@ -442,7 +442,7 @@
|
|||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MemberName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$|^[A-Z][A-Z0-9_]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
|
|
|
@ -11,8 +11,6 @@ import com.dumptruckman.minecraft.util.Logging;
|
|||
import com.onarandombox.MultiverseCore.anchor.AnchorManager;
|
||||
import com.onarandombox.MultiverseCore.api.Destination;
|
||||
import com.onarandombox.MultiverseCore.api.MVCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
import com.onarandombox.MultiverseCore.commandtools.PluginLocales;
|
||||
|
@ -26,10 +24,14 @@ import com.onarandombox.MultiverseCore.utils.TestingMode;
|
|||
import com.onarandombox.MultiverseCore.utils.metrics.MetricsConfigurator;
|
||||
import com.onarandombox.MultiverseCore.world.WorldProperties;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.NullLocation;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.SpawnLocation;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import me.main__.util.SerializationConfig.SerializationConfig;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||
|
@ -57,9 +59,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
|
|||
@Inject
|
||||
private Provider<MVCoreConfig> configProvider;
|
||||
@Inject
|
||||
private Provider<MVWorldManager> worldManagerProvider;
|
||||
@Inject
|
||||
private Provider<WorldManager> newWorldManagerProvider;
|
||||
private Provider<WorldManager> worldManagerProvider;
|
||||
@Inject
|
||||
private Provider<AnchorManager> anchorManagerProvider;
|
||||
@Inject
|
||||
|
@ -102,6 +102,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
|
|||
@Override
|
||||
public void onEnable() {
|
||||
initializeDependencyInjection();
|
||||
ConfigurationSerialization.registerClass(NullLocation.class);
|
||||
ConfigurationSerialization.registerClass(SpawnLocation.class);
|
||||
|
||||
// Load our configs first as we need them for everything else.
|
||||
var config = configProvider.get();
|
||||
|
@ -111,39 +113,28 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
|
|||
this.getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.setShowingConfig(shouldShowConfig());
|
||||
|
||||
var worldManager = worldManagerProvider.get();
|
||||
// Initialize the worlds
|
||||
worldManagerProvider.get().initAllWorlds().andThenTry(() -> {
|
||||
// Setup economy here so vault is loaded
|
||||
loadEconomist();
|
||||
|
||||
worldManager.loadWorldsConfig();
|
||||
worldManager.getDefaultWorldGenerators();
|
||||
worldManager.loadDefaultWorlds();
|
||||
worldManager.loadWorlds(true);
|
||||
|
||||
// Now set the firstspawnworld (after the worlds are loaded):
|
||||
worldManager.setFirstSpawnWorld(config.getFirstSpawnLocation());
|
||||
MVWorld firstSpawnWorld = worldManager.getFirstSpawnWorld();
|
||||
if (firstSpawnWorld != null) {
|
||||
config.setFirstSpawnLocation(firstSpawnWorld.getName());
|
||||
}
|
||||
|
||||
var newWorldManager = newWorldManagerProvider.get();
|
||||
newWorldManager.loadAllWorlds(); // TODO: Possibly move this to constructor of WorldManager
|
||||
|
||||
//Setup economy here so vault is loaded
|
||||
this.loadEconomist();
|
||||
|
||||
// Init all the other stuff
|
||||
this.loadAnchors();
|
||||
this.registerEvents();
|
||||
this.setUpLocales();
|
||||
this.registerCommands();
|
||||
this.registerDestinations();
|
||||
this.setupMetrics();
|
||||
this.loadPlaceholderAPIIntegration();
|
||||
this.saveAllConfigs();
|
||||
this.logEnableMessage();
|
||||
// Init all the other stuff
|
||||
loadAnchors();
|
||||
registerEvents();
|
||||
setUpLocales();
|
||||
registerCommands();
|
||||
registerDestinations();
|
||||
setupMetrics();
|
||||
loadPlaceholderAPIIntegration();
|
||||
saveAllConfigs();
|
||||
logEnableMessage();
|
||||
}).onFailure(e -> {
|
||||
Logging.severe("Failed to multiverse core! Disabling...");
|
||||
e.printStackTrace();
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,7 +142,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
|
|||
*/
|
||||
@Override
|
||||
public void onDisable() {
|
||||
this.saveAllConfigs();
|
||||
saveAllConfigs();
|
||||
shutdownDependencyInjection();
|
||||
Logging.shutdown();
|
||||
}
|
||||
|
@ -372,12 +363,12 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
|
|||
*/
|
||||
@Override
|
||||
public boolean saveAllConfigs() {
|
||||
return configProvider.get().save()
|
||||
// TODO: Make this all Try<Void>
|
||||
return configProvider.get().save().isSuccess()
|
||||
&& worldManagerProvider.get().saveWorldsConfig()
|
||||
&& anchorManagerProvider.get().saveAnchors();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the best service from this plugin that implements the given contract or has the given implementation.
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@ public interface MVConfig {
|
|||
* Loads the config from disk.
|
||||
* @return True if the config was loaded successfully.
|
||||
*/
|
||||
boolean load();
|
||||
Try<Void> load();
|
||||
|
||||
/**
|
||||
* Whether the config has been loaded.
|
||||
|
@ -23,7 +23,7 @@ public interface MVConfig {
|
|||
/**
|
||||
* Saves the config to disk.
|
||||
*/
|
||||
boolean save();
|
||||
Try<Void> save();
|
||||
|
||||
/**
|
||||
* Gets the nodes for the config.
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
package com.onarandombox.MultiverseCore.commands;
|
||||
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
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.Single;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
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.commandtools.flags.CommandFlag;
|
||||
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
|
||||
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.CloneWorldOptions;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
@ -21,12 +26,24 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@CommandAlias("mv")
|
||||
public class CloneCommand extends MultiverseCommand {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public CloneCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
|
||||
public CloneCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
|
||||
registerFlagGroup(CommandFlagGroup.builder("mvclone")
|
||||
.add(CommandFlag.builder("--reset-world-config")
|
||||
.addAlias("-wc")
|
||||
.build())
|
||||
.add(CommandFlag.builder("--reset-gamerules")
|
||||
.addAlias("-gm")
|
||||
.build())
|
||||
.add(CommandFlag.builder("--reset-world-border")
|
||||
.addAlias("-wb")
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
|
||||
@Subcommand("clone")
|
||||
|
@ -34,28 +51,35 @@ public class CloneCommand extends MultiverseCommand {
|
|||
@CommandCompletion("@mvworlds:scope=both @empty")
|
||||
@Syntax("<world> <new world name>")
|
||||
@Description("{@@mv-core.clone.description}")
|
||||
public void onCloneCommand(CommandIssuer issuer,
|
||||
void onCloneCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Conditions("worldname:scope=both")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.clone.world.description}")
|
||||
String worldName,
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.clone.world.description}")
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Single
|
||||
@Conditions("worldname:scope=new")
|
||||
@Syntax("<new world name>")
|
||||
@Description("{@@mv-core.clone.newWorld.description}")
|
||||
String newWorldName
|
||||
) {
|
||||
issuer.sendInfo(MVCorei18n.CLONE_CLONING,
|
||||
"{world}", worldName,
|
||||
"{newWorld}", newWorldName);
|
||||
@Syntax("<new world name>")
|
||||
@Description("{@@mv-core.clone.newWorld.description}")
|
||||
String newWorldName,
|
||||
|
||||
if (!this.worldManager.cloneWorld(worldName, newWorldName)) {
|
||||
issuer.sendError(MVCorei18n.CLONE_FAILED);
|
||||
return;
|
||||
}
|
||||
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS,
|
||||
"{world}", newWorldName);
|
||||
@Optional
|
||||
@Syntax(/* TODO */ "")
|
||||
@Description("{@@mv-core.regen.other.description}")
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
issuer.sendInfo(MVCorei18n.CLONE_CLONING, "{world}", world.getName(), "{newworld}", newWorldName);
|
||||
CloneWorldOptions cloneWorldOptions = CloneWorldOptions.fromTo(world, newWorldName)
|
||||
.keepWorldConfig(!parsedFlags.hasFlag("--reset-world-config"))
|
||||
.keepGameRule(!parsedFlags.hasFlag("--reset-gamerules"))
|
||||
.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());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ import co.aikar.commands.annotation.Description;
|
|||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import com.onarandombox.MultiverseCore.api.LocationManipulation;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -40,12 +40,12 @@ public class CoordinatesCommand extends MultiverseCommand {
|
|||
Player player,
|
||||
|
||||
@Flags("resolve=issuerOnly")
|
||||
MVWorld world
|
||||
LoadedMultiverseWorld world
|
||||
) {
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_TITLE);
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLD, "{world}", world.getName());
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_ALIAS, "{alias}", world.getColoredWorldString());
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLDSCALE, "{scale}", String.valueOf(world.getScaling()));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_ALIAS, "{alias}", world.getAlias());
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLDSCALE, "{scale}", String.valueOf(world.getScale()));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_COORDINATES, "{coordinates}", locationManipulation.strCoords(player.getLocation()));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_DIRECTION, "{direction}", locationManipulation.getDirection(player.getLocation()));
|
||||
}
|
||||
|
|
|
@ -1,23 +1,14 @@
|
|||
package com.onarandombox.MultiverseCore.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
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;
|
||||
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.commandtools.flags.CommandFlag;
|
||||
|
@ -25,52 +16,46 @@ import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
|
|||
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
|
||||
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.generators.GeneratorProvider;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
@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 UnsafeCallWrapper unsafeCallWrapper
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull GeneratorProvider generatorProvider
|
||||
) {
|
||||
super(commandManager);
|
||||
|
||||
this.worldManager = worldManager;
|
||||
|
||||
registerFlagGroup(CommandFlagGroup.builder("mvcreate")
|
||||
.add(CommandValueFlag.builder("--seed", String.class)
|
||||
.addAlias("-s")
|
||||
.completion(() -> Collections.singleton(String.valueOf(new Random().nextLong())))
|
||||
.completion((input) -> Collections.singleton(String.valueOf(new Random().nextLong())))
|
||||
.build())
|
||||
.add(CommandValueFlag.builder("--generator", String.class)
|
||||
.addAlias("-g")
|
||||
.completion(() -> Arrays.stream(Bukkit.getServer().getPluginManager().getPlugins())
|
||||
.filter(Plugin::isEnabled)
|
||||
.filter(genplugin -> unsafeCallWrapper.wrap(
|
||||
() -> genplugin.getDefaultWorldGenerator("world", ""),
|
||||
genplugin.getName(),
|
||||
"Get generator"
|
||||
) != null)
|
||||
.map(genplugin -> genplugin.getDescription().getName())
|
||||
.collect(Collectors.toList()))
|
||||
.completion(generatorProvider::suggestGeneratorString)
|
||||
.build())
|
||||
.add(CommandValueFlag.enumBuilder("--world-type", WorldType.class)
|
||||
.addAlias("-t")
|
||||
.build())
|
||||
.add(CommandFlag.builder("--adjust-spawn")
|
||||
.add(CommandFlag.builder("--no-adjust-spawn")
|
||||
.addAlias("-n")
|
||||
.build())
|
||||
.add(CommandFlag.builder("--no-structures")
|
||||
|
@ -84,9 +69,8 @@ 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>")
|
||||
@Description("{@@mv-core.create.name.description}")
|
||||
String worldName,
|
||||
|
@ -98,32 +82,32 @@ 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);
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ENVIRONMENT, "{environment}", environment.name());
|
||||
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_ADJUSTSPAWN, "{adjustSpawn}", String.valueOf(!parsedFlags.hasFlag("--no-adjust-spawn")));
|
||||
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("--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());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.onarandombox.MultiverseCore.commands;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.MessageType;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
|
@ -10,11 +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.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.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 +24,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,7 +37,7 @@ 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")
|
||||
|
@ -47,15 +48,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(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,
|
||||
|
|
|
@ -10,7 +10,6 @@ import co.aikar.commands.annotation.Subcommand;
|
|||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
|
||||
|
@ -23,6 +22,7 @@ import com.onarandombox.MultiverseCore.utils.webpaste.PasteFailedException;
|
|||
import com.onarandombox.MultiverseCore.utils.webpaste.PasteService;
|
||||
import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceFactory;
|
||||
import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceType;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
@ -45,12 +45,12 @@ import static com.onarandombox.MultiverseCore.utils.file.FileUtils.getServerProp
|
|||
public class DumpsCommand extends MultiverseCommand {
|
||||
|
||||
private final MultiverseCore plugin;
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public DumpsCommand(@NotNull MVCommandManager commandManager,
|
||||
@NotNull MultiverseCore plugin,
|
||||
@NotNull MVWorldManager worldManager) {
|
||||
@NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.plugin = plugin;
|
||||
this.worldManager = worldManager;
|
||||
|
@ -184,7 +184,7 @@ public class DumpsCommand extends MultiverseCommand {
|
|||
return "# Multiverse-Core Version info" + "\n\n"
|
||||
+ " - Multiverse-Core Version: " + this.plugin.getDescription().getVersion() + '\n'
|
||||
+ " - Bukkit Version: " + this.plugin.getServer().getVersion() + '\n'
|
||||
+ " - Loaded Worlds: " + worldManager.getMVWorlds() + '\n'
|
||||
+ " - Loaded Worlds: " + worldManager.getLoadedWorlds() + '\n'
|
||||
+ " - Multiverse Plugins Loaded: " + this.plugin.getPluginCount() + '\n';
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@ import co.aikar.commands.annotation.Description;
|
|||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
|
@ -45,13 +46,14 @@ public class GameruleCommand extends MultiverseCommand {
|
|||
@Flags("resolve=issuerAware")
|
||||
@Syntax("[World or *]")
|
||||
@Description("{@@mv-core.gamerule.world.description}")
|
||||
MVWorld[] worlds
|
||||
LoadedMultiverseWorld[] worlds
|
||||
) {
|
||||
Object value = gameRuleValue.getValue();
|
||||
boolean success = true;
|
||||
for(MVWorld world : worlds) {
|
||||
for(LoadedMultiverseWorld world : worlds) {
|
||||
// Set gamerules and add false to list if it fails
|
||||
if (!world.getCBWorld().setGameRule(gamerule, value)) {
|
||||
World bukkitWorld = world.getBukkitWorld().getOrNull();
|
||||
if (bukkitWorld == null || !bukkitWorld.setGameRule(gamerule, value)) {
|
||||
issuer.sendError(MVCorei18n.GAMERULE_FAILED,
|
||||
"{gamerule}", gamerule.getName(),
|
||||
"{value}", value.toString(),
|
||||
|
|
|
@ -11,7 +11,6 @@ import co.aikar.commands.annotation.Flags;
|
|||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
|
@ -24,6 +23,7 @@ import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter;
|
|||
import com.onarandombox.MultiverseCore.display.handlers.PagedSendHandler;
|
||||
import com.onarandombox.MultiverseCore.display.parsers.MapContentProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameRule;
|
||||
|
@ -81,7 +81,7 @@ public class GamerulesCommand extends MultiverseCommand {
|
|||
@Flags("resolve=issuerAware")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.gamerules.description.world}")
|
||||
MVWorld world,
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
|
@ -91,11 +91,11 @@ public class GamerulesCommand extends MultiverseCommand {
|
|||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
ContentDisplay.create()
|
||||
.addContent(new MapContentProvider<>(getGameRuleMap(world.getCBWorld()))
|
||||
.addContent(new MapContentProvider<>(getGameRuleMap(world.getBukkitWorld().getOrNull())) // TODO: Handle null
|
||||
.withKeyColor(ChatColor.AQUA)
|
||||
.withValueColor(ChatColor.WHITE))
|
||||
.withSendHandler(new PagedSendHandler()
|
||||
.withHeader(this.getTitle(issuer, world.getCBWorld()))
|
||||
.withHeader(this.getTitle(issuer, world.getBukkitWorld().getOrNull()))
|
||||
.doPagination(true)
|
||||
.withTargetPage(parsedFlags.flagValue(PAGE_FLAG, 1))
|
||||
.withFilter(parsedFlags.flagValue(FILTER_FLAG, DefaultContentFilter.get())))
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package com.onarandombox.MultiverseCore.commands;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
|
@ -12,7 +8,8 @@ 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.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.commandtools.flags.CommandFlag;
|
||||
|
@ -20,11 +17,11 @@ import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
|
|||
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
|
||||
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.generators.GeneratorProvider;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.ImportWorldOptions;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
|
@ -32,29 +29,21 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@CommandAlias("mv")
|
||||
public class ImportCommand extends MultiverseCommand {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public ImportCommand(
|
||||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull MVWorldManager worldManager,
|
||||
@NotNull UnsafeCallWrapper unsafeCallWrapper
|
||||
) {
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull GeneratorProvider generatorProvider
|
||||
) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
|
||||
registerFlagGroup(CommandFlagGroup.builder("mvimport")
|
||||
.add(CommandValueFlag.builder("--generator", String.class)
|
||||
.addAlias("-g")
|
||||
.completion(() -> Arrays.stream(Bukkit.getServer().getPluginManager().getPlugins())
|
||||
.filter(Plugin::isEnabled)
|
||||
.filter(genplugin -> unsafeCallWrapper.wrap(
|
||||
() -> genplugin.getDefaultWorldGenerator("world", ""),
|
||||
genplugin.getName(),
|
||||
"Get generator"
|
||||
) != null)
|
||||
.map(genplugin -> genplugin.getDescription().getName())
|
||||
.collect(Collectors.toList()))
|
||||
.completion(generatorProvider::suggestGeneratorString)
|
||||
.build())
|
||||
.add(CommandFlag.builder("--adjust-spawn")
|
||||
.addAlias("-a")
|
||||
|
@ -67,7 +56,7 @@ public class ImportCommand extends MultiverseCommand {
|
|||
@CommandCompletion("@mvworlds:scope=potential @flags:groupName=mvimport")
|
||||
@Syntax("<name> <env> --generator [generator[:id]] --adjust-spawn")
|
||||
@Description("{@@mv-core.import.description")
|
||||
public void onImportCommand(BukkitCommandIssuer issuer,
|
||||
public void onImportCommand(MVCommandIssuer issuer,
|
||||
|
||||
@Conditions("worldname:scope=new")
|
||||
@Syntax("<name>")
|
||||
|
@ -85,20 +74,18 @@ public class ImportCommand extends MultiverseCommand {
|
|||
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
issuer.sendInfo(MVCorei18n.IMPORT_IMPORTING,
|
||||
"{world}", worldName);
|
||||
|
||||
if (!this.worldManager.addWorld(
|
||||
worldName, environment,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
parsedFlags.flagValue("--generator", String.class),
|
||||
parsedFlags.hasFlag("--adjust-spawn"))
|
||||
) {
|
||||
issuer.sendError(MVCorei18n.IMPORT_FAILED);
|
||||
return;
|
||||
}
|
||||
issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS);
|
||||
issuer.sendInfo(MVCorei18n.IMPORT_IMPORTING, "{world}", worldName);
|
||||
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());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package com.onarandombox.MultiverseCore.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
|
@ -11,9 +7,7 @@ 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.onarandombox.MultiverseCore.MultiverseCore;
|
||||
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.commandtools.flags.CommandFlagGroup;
|
||||
|
@ -25,26 +19,30 @@ import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter;
|
|||
import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter;
|
||||
import com.onarandombox.MultiverseCore.display.handlers.PagedSendHandler;
|
||||
import com.onarandombox.MultiverseCore.display.parsers.ListContentProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
|
||||
import com.onarandombox.MultiverseCore.world.entrycheck.WorldEntryCheckerProvider;
|
||||
import com.onarandombox.MultiverseCore.worldnew.entrycheck.WorldEntryChecker;
|
||||
import com.onarandombox.MultiverseCore.worldnew.entrycheck.WorldEntryCheckerProvider;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@CommandAlias("mv")
|
||||
public class ListCommand extends MultiverseCommand {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final WorldEntryCheckerProvider worldEntryCheckerProvider;
|
||||
|
||||
@Inject
|
||||
public ListCommand(
|
||||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull MVWorldManager worldManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull WorldEntryCheckerProvider worldEntryCheckerProvider
|
||||
) {
|
||||
super(commandManager);
|
||||
|
@ -80,7 +78,7 @@ public class ListCommand extends MultiverseCommand {
|
|||
@CommandCompletion("@flags:groupName=mvlist")
|
||||
@Syntax("--filter [filter] --page [page]")
|
||||
@Description("Displays a listing of all worlds that you can enter.")
|
||||
public void onListCommand(BukkitCommandIssuer issuer,
|
||||
public void onListCommand(MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("--filter [filter] --page [page]")
|
||||
@Description("Filters the list of worlds by the given regex and displays the given page.")
|
||||
|
@ -96,49 +94,42 @@ public class ListCommand extends MultiverseCommand {
|
|||
.send(issuer);
|
||||
}
|
||||
|
||||
private List<String> getListContents(BukkitCommandIssuer issuer) {
|
||||
Player player = issuer.isPlayer() ? issuer.getPlayer() : null;
|
||||
private List<String> getListContents(MVCommandIssuer issuer) {
|
||||
List<String> worldList = new ArrayList<>();
|
||||
WorldEntryChecker worldEntryChecker = worldEntryCheckerProvider.forSender(issuer.getIssuer());
|
||||
|
||||
worldManager.getMVWorlds().stream()
|
||||
.filter(world -> player == null || worldEntryCheckerProvider.forSender(player).canAccessWorld(world).isSuccess())
|
||||
.filter(world -> canSeeWorld(player, world))
|
||||
.map(world -> hiddenText(world) + world.getColoredWorldString() + " - " + parseColouredEnvironment(world.getEnvironment()))
|
||||
worldManager.getLoadedWorlds().stream()
|
||||
.filter(world -> worldEntryChecker.canAccessWorld(world).isSuccess())
|
||||
.filter(world -> canSeeWorld(issuer, world))
|
||||
.map(world -> hiddenText(world) + world.getAlias() + " - " + parseColouredEnvironment(world.getEnvironment()))
|
||||
.sorted()
|
||||
.forEach(worldList::add);
|
||||
|
||||
worldManager.getUnloadedWorlds().stream()
|
||||
.filter(world -> issuer.hasPermission("multiverse.access." + world)) // TODO: Refactor stray permission check
|
||||
.map(world -> ChatColor.GRAY + world + " - UNLOADED")
|
||||
.filter(world -> worldEntryChecker.canAccessWorld(world).isSuccess())
|
||||
.map(world -> ChatColor.GRAY + world.getAlias() + " - UNLOADED")
|
||||
.sorted()
|
||||
.forEach(worldList::add);
|
||||
|
||||
return worldList;
|
||||
}
|
||||
|
||||
private boolean canSeeWorld(Player player, MVWorld world) {
|
||||
private boolean canSeeWorld(MVCommandIssuer issuer, LoadedMultiverseWorld world) {
|
||||
return !world.isHidden()
|
||||
|| player == null
|
||||
|| player.hasPermission("multiverse.core.modify"); // TODO: Refactor stray permission check
|
||||
|| issuer.hasPermission("multiverse.core.modify"); // TODO: Refactor stray permission check
|
||||
}
|
||||
|
||||
private String hiddenText(MVWorld world) {
|
||||
private String hiddenText(LoadedMultiverseWorld world) {
|
||||
return (world.isHidden()) ? String.format("%s[H] ", ChatColor.GRAY) : "";
|
||||
}
|
||||
|
||||
private String parseColouredEnvironment(World.Environment env) {
|
||||
ChatColor color = ChatColor.GOLD;
|
||||
switch (env) {
|
||||
case NETHER:
|
||||
color = ChatColor.RED;
|
||||
break;
|
||||
case NORMAL:
|
||||
color = ChatColor.GREEN;
|
||||
break;
|
||||
case THE_END:
|
||||
color = ChatColor.AQUA;
|
||||
break;
|
||||
}
|
||||
ChatColor color = switch (env) {
|
||||
case NETHER -> ChatColor.RED;
|
||||
case NORMAL -> ChatColor.GREEN;
|
||||
case THE_END -> ChatColor.AQUA;
|
||||
default -> ChatColor.GOLD;
|
||||
};
|
||||
return color + env.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,12 @@ 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 +22,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,7 +35,7 @@ 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")
|
||||
|
@ -42,15 +43,14 @@ public class LoadCommand extends MultiverseCommand {
|
|||
@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(newWorld -> {
|
||||
Logging.fine("World load success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.LOAD_SUCCESS, "{world}", newWorld.getName());
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World load failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
package com.onarandombox.MultiverseCore.commands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.MessageType;
|
||||
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;
|
||||
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.commandtools.flags.CommandFlag;
|
||||
|
@ -22,47 +18,58 @@ import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
|
|||
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
|
||||
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.RegenWorldOptions;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
@Service
|
||||
@CommandAlias("mv")
|
||||
public class RegenCommand extends MultiverseCommand {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public RegenCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
|
||||
public RegenCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
|
||||
registerFlagGroup(CommandFlagGroup.builder("mvregen")
|
||||
.add(CommandValueFlag.builder("--seed", String.class)
|
||||
.addAlias("-s")
|
||||
.completion(() -> Collections.singleton(String.valueOf(new Random().nextLong())))
|
||||
.completion((input) -> Collections.singleton(String.valueOf(new Random().nextLong())))
|
||||
.optional()
|
||||
.build())
|
||||
.add(CommandFlag.builder("--keep-gamerules")
|
||||
.addAlias("-k")
|
||||
.add(CommandFlag.builder("--reset-world-config")
|
||||
.addAlias("-wc")
|
||||
.build())
|
||||
.add(CommandFlag.builder("--reset-gamerules")
|
||||
.addAlias("-gm")
|
||||
.build())
|
||||
.add(CommandFlag.builder("--reset-world-border")
|
||||
.addAlias("-wb")
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
|
||||
@Subcommand("regen")
|
||||
@CommandPermission("multiverse.core.regen")
|
||||
@CommandCompletion("@mvworlds:scope=both @flags:groupName=mvregen")
|
||||
@CommandCompletion("@mvworlds:scope=loaded @flags:groupName=mvregen")
|
||||
@Syntax("<world> --seed [seed] --keep-gamerules")
|
||||
@Description("{@@mv-core.regen.description}")
|
||||
public void onRegenCommand(BukkitCommandIssuer issuer,
|
||||
public void onRegenCommand(MVCommandIssuer issuer,
|
||||
|
||||
@Conditions("worldname:scope=both")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.regen.world.description}")
|
||||
String worldName,
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("--seed [seed] --keep-gamerules")
|
||||
@Syntax("--seed [seed] --reset-gamerules")
|
||||
@Description("{@@mv-core.regen.other.description}")
|
||||
String[] flags
|
||||
) {
|
||||
|
@ -71,27 +78,26 @@ public class RegenCommand extends MultiverseCommand {
|
|||
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
|
||||
issuer.getIssuer(),
|
||||
() -> {
|
||||
issuer.sendInfo(MVCorei18n.REGEN_REGENERATING,
|
||||
"{world}", worldName);
|
||||
if (!this.worldManager.regenWorld(
|
||||
worldName,
|
||||
parsedFlags.hasFlag("--seed"),
|
||||
!parsedFlags.hasFlagValue("--seed"),
|
||||
parsedFlags.flagValue("--seed", String.class),
|
||||
parsedFlags.hasFlag("--keep-gamerules")
|
||||
)) {
|
||||
issuer.sendError(MVCorei18n.REGEN_FAILED,
|
||||
"{world}", worldName);
|
||||
return;
|
||||
}
|
||||
issuer.sendInfo(MVCorei18n.REGEN_SUCCESS,
|
||||
"{world}", worldName);
|
||||
issuer.sendInfo(MVCorei18n.REGEN_REGENERATING, "{world}", world.getName());
|
||||
worldManager.regenWorld(RegenWorldOptions.world(world)
|
||||
.randomSeed(parsedFlags.hasFlag("--seed"))
|
||||
.seed(parsedFlags.flagValue("--seed", String.class))
|
||||
.keepWorldConfig(!parsedFlags.hasFlag("--reset-world-config"))
|
||||
.keepGameRule(!parsedFlags.hasFlag("--reset-gamerules"))
|
||||
.keepWorldBorder(!parsedFlags.hasFlag("--reset-world-border"))
|
||||
).onSuccess(newWorld -> {
|
||||
Logging.fine("World regen success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.REGEN_SUCCESS, "{world}", newWorld.getName());
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World regen failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
},
|
||||
this.commandManager.formatMessage(
|
||||
issuer,
|
||||
MessageType.INFO,
|
||||
MVCorei18n.REGEN_PROMPT,
|
||||
"{world}", worldName)
|
||||
"{world}", world.getName())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,32 @@
|
|||
package com.onarandombox.MultiverseCore.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.anchor.AnchorManager;
|
||||
import com.onarandombox.MultiverseCore.api.MVCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.event.MVConfigReloadEvent;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@CommandAlias("mv")
|
||||
public class ReloadCommand extends MultiverseCommand {
|
||||
|
||||
private final MVCoreConfig config;
|
||||
private final AnchorManager anchorManager;
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final PluginManager pluginManager;
|
||||
|
||||
@Inject
|
||||
|
@ -36,7 +34,7 @@ public class ReloadCommand extends MultiverseCommand {
|
|||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull MVCoreConfig config,
|
||||
@NotNull AnchorManager anchorManager,
|
||||
@NotNull MVWorldManager worldManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PluginManager pluginManager
|
||||
) {
|
||||
super(commandManager);
|
||||
|
@ -51,14 +49,18 @@ public class ReloadCommand extends MultiverseCommand {
|
|||
@Description("{@@mv-core.reload.description}")
|
||||
public void onReloadCommand(@NotNull BukkitCommandIssuer issuer) {
|
||||
issuer.sendInfo(MVCorei18n.RELOAD_RELOADING);
|
||||
this.config.load();
|
||||
this.worldManager.loadWorldsConfig();
|
||||
this.worldManager.loadWorlds(true);
|
||||
this.anchorManager.loadAnchors();
|
||||
try {
|
||||
// TODO: Make this all Try<Void>
|
||||
this.config.load().getOrElseThrow(e -> new RuntimeException("Failed to load config", e));
|
||||
this.worldManager.initAllWorlds().getOrElseThrow(e -> new RuntimeException("Failed to init worlds", e));
|
||||
this.anchorManager.loadAnchors();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
List<String> configsLoaded = new ArrayList<>();
|
||||
configsLoaded.add("Multiverse-Core - config.yml");
|
||||
configsLoaded.add("Multiverse-Core - worlds.yml");
|
||||
configsLoaded.add("Multiverse-Core - worlds2.yml");
|
||||
configsLoaded.add("Multiverse-Core - anchors.yml");
|
||||
|
||||
MVConfigReloadEvent configReload = new MVConfigReloadEvent(configsLoaded);
|
||||
|
|
|
@ -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,12 @@ 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 +22,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,7 +35,7 @@ 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")
|
||||
|
@ -42,11 +43,13 @@ public class RemoveCommand extends MultiverseCommand {
|
|||
@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(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.getFailureMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
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;
|
||||
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.onarandombox.MultiverseCore.api.MVWorld;
|
||||
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.commandtools.flags.CommandFlag;
|
||||
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.UnloadWorldOptions;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
@ -20,35 +25,51 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@CommandAlias("mv")
|
||||
public class UnloadCommand extends MultiverseCommand {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
private final CommandFlag REMOVE_PLAYERS_FLAG = flag(CommandFlag.builder("--remove-players")
|
||||
.addAlias("-r")
|
||||
.build());
|
||||
|
||||
private final CommandFlag NO_SAVE_FLAG = flag(CommandFlag.builder("--no-save")
|
||||
.addAlias("-n")
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
public UnloadCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
|
||||
public UnloadCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
@Subcommand("unload")
|
||||
@CommandPermission("multiverse.core.unload")
|
||||
@CommandCompletion("@mvworlds")
|
||||
@CommandCompletion("@mvworlds @flags:groupName=mvunloadcommand")
|
||||
@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
|
||||
) {
|
||||
issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING,
|
||||
"{world}", world.getColoredWorldString());
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.unload.world.description}")
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
// 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());
|
||||
@Optional
|
||||
@Syntax("[--remove-players] [--no-save]")
|
||||
@Description("{@@mv-core.gamerules.description.page}")
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING, "{world}", world.getAlias());
|
||||
UnloadWorldOptions unloadWorldOptions = UnloadWorldOptions.world(world)
|
||||
.removePlayers(parsedFlags.hasFlag(REMOVE_PLAYERS_FLAG))
|
||||
.saveBukkitWorld(!parsedFlags.hasFlag(NO_SAVE_FLAG));
|
||||
worldManager.unloadWorld(unloadWorldOptions)
|
||||
.onSuccess(loadedWorld -> {
|
||||
Logging.fine("World unload success: " + loadedWorld);
|
||||
issuer.sendInfo(MVCorei18n.UNLOAD_SUCCESS, "{world}", loadedWorld.getName());
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World unload failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,25 @@
|
|||
package com.onarandombox.MultiverseCore.commandtools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import co.aikar.commands.BukkitCommandCompletionContext;
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.PaperCommandCompletions;
|
||||
import co.aikar.commands.RegisteredCommand;
|
||||
import co.aikar.commands.RootCommand;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
|
||||
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.MultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.GameRule;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -9,35 +28,17 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import co.aikar.commands.BukkitCommandCompletionContext;
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.PaperCommandCompletions;
|
||||
import co.aikar.commands.RegisteredCommand;
|
||||
import co.aikar.commands.RootCommand;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
|
||||
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.GameRule;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
@Service
|
||||
public class MVCommandCompletions extends PaperCommandCompletions {
|
||||
|
||||
protected final MVCommandManager commandManager;
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
|
||||
@Inject
|
||||
public MVCommandCompletions(
|
||||
@NotNull MVCommandManager mvCommandManager,
|
||||
@NotNull MVWorldManager worldManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull DestinationsProvider destinationsProvider,
|
||||
@NotNull MVCoreConfig config
|
||||
) {
|
||||
|
@ -56,7 +57,7 @@ public class MVCommandCompletions extends PaperCommandCompletions {
|
|||
setDefaultCompletion("destinations", ParsedDestination.class);
|
||||
setDefaultCompletion("flags", String[].class);
|
||||
setDefaultCompletion("gamerules", GameRule.class);
|
||||
setDefaultCompletion("mvworlds", MVWorld.class);
|
||||
setDefaultCompletion("mvworlds", LoadedMultiverseWorld.class);
|
||||
}
|
||||
|
||||
private Collection<String> suggestCommands(BukkitCommandCompletionContext context) {
|
||||
|
@ -128,23 +129,26 @@ public class MVCommandCompletions extends PaperCommandCompletions {
|
|||
|
||||
private List<String> getMVWorldNames(BukkitCommandCompletionContext context) {
|
||||
String scope = context.getConfig("scope", "loaded");
|
||||
List<String> worlds = new ArrayList<>();
|
||||
switch (scope) {
|
||||
case "both":
|
||||
worlds.addAll(worldManager.getUnloadedWorlds());
|
||||
case "loaded":
|
||||
worldManager.getMVWorlds()
|
||||
case "both" -> {
|
||||
return worldManager.getWorlds().stream().map(MultiverseWorld::getName).toList();
|
||||
}
|
||||
case "loaded" -> {
|
||||
return worldManager.getLoadedWorlds()
|
||||
.stream()
|
||||
.map(MVWorld::getName)
|
||||
.forEach(worlds::add);
|
||||
break;
|
||||
case "unloaded":
|
||||
worlds.addAll(worldManager.getUnloadedWorlds());
|
||||
break;
|
||||
case "potential":
|
||||
worlds.addAll(worldManager.getPotentialWorlds());
|
||||
break;
|
||||
.map(LoadedMultiverseWorld::getName)
|
||||
.toList();
|
||||
}
|
||||
case "unloaded" -> {
|
||||
return worldManager.getUnloadedWorlds().stream()
|
||||
.map(MultiverseWorld::getName)
|
||||
.toList();
|
||||
}
|
||||
case "potential" -> {
|
||||
return worldManager.getPotentialWorlds();
|
||||
}
|
||||
}
|
||||
return worlds;
|
||||
Logging.severe("Invalid MVWorld scope: " + scope);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,19 +6,19 @@ import co.aikar.commands.BukkitConditionContext;
|
|||
import co.aikar.commands.CommandConditions;
|
||||
import co.aikar.commands.ConditionContext;
|
||||
import co.aikar.commands.ConditionFailedException;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.world.WorldNameChecker;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MVCommandConditions {
|
||||
static void load(MVCommandManager commandManager, MVWorldManager worldManager) {
|
||||
static void load(MVCommandManager commandManager, WorldManager worldManager) {
|
||||
new MVCommandConditions(commandManager, worldManager);
|
||||
}
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final MVCommandManager commandManager;
|
||||
|
||||
private MVCommandConditions(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
|
||||
private MVCommandConditions(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
this.commandManager = commandManager;
|
||||
registerConditions();
|
||||
|
@ -40,14 +40,14 @@ public class MVCommandConditions {
|
|||
switch (scope) {
|
||||
// Worlds that are loaded
|
||||
case "loaded":
|
||||
if (!this.worldManager.isMVWorld(worldName)) {
|
||||
if (!this.worldManager.isLoadedWorld(worldName)) {
|
||||
throw new ConditionFailedException("World with name '" + worldName + "' does not exist or is not loaded!");
|
||||
}
|
||||
break;
|
||||
// Worlds that are unloaded
|
||||
case "unloaded":
|
||||
if (!this.worldManager.hasUnloadedWorld(worldName, false)) {
|
||||
if (this.worldManager.isMVWorld(worldName)) {
|
||||
if (!this.worldManager.isUnloadedWorld(worldName)) {
|
||||
if (this.worldManager.isLoadedWorld(worldName)) {
|
||||
throw new ConditionFailedException("World with name '" + worldName + "' is loaded already!");
|
||||
}
|
||||
throw new ConditionFailedException("World with name '" + worldName + "' does not exist!");
|
||||
|
@ -55,20 +55,20 @@ public class MVCommandConditions {
|
|||
break;
|
||||
// World that are loaded or unloaded
|
||||
case "both":
|
||||
if (!this.worldManager.hasUnloadedWorld(worldName, true)) {
|
||||
if (!this.worldManager.isWorld(worldName)) {
|
||||
throw new ConditionFailedException("World with name '" + worldName + "' does not exist!");
|
||||
}
|
||||
break;
|
||||
// World that are does not exist
|
||||
case "new":
|
||||
if (this.worldManager.hasUnloadedWorld(worldName, true)) {
|
||||
if (this.worldManager.isWorld(worldName)) {
|
||||
throw new ConditionFailedException("World with name '" + worldName + "' already exists!");
|
||||
}
|
||||
switch (WorldNameChecker.checkName(worldName)) {
|
||||
case INVALID_CHARS:
|
||||
throw new ConditionFailedException("World name '" + worldName + "' contains invalid characters!");
|
||||
case BLACKLISTED:
|
||||
throw new ConditionFailedException("World name '" + worldName + "' is used for critical server operations and is blacklisted!");
|
||||
case INVALID_CHARS ->
|
||||
throw new ConditionFailedException("World name '" + worldName + "' contains invalid characters!");
|
||||
case BLACKLISTED ->
|
||||
throw new ConditionFailedException("World name '" + worldName + "' is used for critical server operations and is blacklisted!");
|
||||
}
|
||||
break;
|
||||
// Probably a typo happened here
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.onarandombox.MultiverseCore.commandtools;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import co.aikar.commands.BukkitCommandExecutionContext;
|
||||
|
@ -10,8 +9,6 @@ import co.aikar.commands.InvalidCommandArgument;
|
|||
import co.aikar.commands.PaperCommandContexts;
|
||||
import co.aikar.commands.contexts.ContextResolver;
|
||||
import com.google.common.base.Strings;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue;
|
||||
import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
|
@ -23,6 +20,8 @@ import com.onarandombox.MultiverseCore.display.filters.ContentFilter;
|
|||
import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter;
|
||||
import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter;
|
||||
import com.onarandombox.MultiverseCore.utils.PlayerFinder;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import io.vavr.control.Option;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.GameRule;
|
||||
|
@ -34,14 +33,14 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
|
||||
private final MVCommandManager mvCommandManager;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final MVCoreConfig config;
|
||||
|
||||
@Inject
|
||||
public MVCommandContexts(
|
||||
MVCommandManager mvCommandManager,
|
||||
DestinationsProvider destinationsProvider,
|
||||
MVWorldManager worldManager,
|
||||
WorldManager worldManager,
|
||||
MVCoreConfig config
|
||||
) {
|
||||
super(mvCommandManager);
|
||||
|
@ -57,8 +56,8 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
registerContext(GameRule.class, this::parseGameRule);
|
||||
registerContext(GameRuleValue.class, this::parseGameRuleValue);
|
||||
registerContext(MVConfigValue.class, this::parseMVConfigValue);
|
||||
registerIssuerAwareContext(MVWorld.class, this::parseMVWorld);
|
||||
registerIssuerAwareContext(MVWorld[].class, this::parseMVWorldArray);
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld.class, this::parseMVWorld);
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld[].class, this::parseMVWorldArray);
|
||||
registerIssuerAwareContext(Player.class, this::parsePlayer);
|
||||
registerIssuerAwareContext(Player[].class, this::parsePlayerArray);
|
||||
}
|
||||
|
@ -162,13 +161,13 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
return new MVConfigValue(resolvedValue);
|
||||
}
|
||||
|
||||
private MVWorld parseMVWorld(BukkitCommandExecutionContext context) {
|
||||
private LoadedMultiverseWorld parseMVWorld(BukkitCommandExecutionContext context) {
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
// Get world based on sender only
|
||||
if (resolve.equals("issuerOnly")) {
|
||||
if (context.getIssuer().isPlayer()) {
|
||||
return worldManager.getMVWorld(context.getIssuer().getPlayer().getWorld());
|
||||
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
|
@ -177,7 +176,7 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
}
|
||||
|
||||
String worldName = context.getFirstArg();
|
||||
MVWorld world = worldManager.getMVWorld(worldName);
|
||||
LoadedMultiverseWorld world = worldManager.getLoadedWorld(worldName).getOrNull();
|
||||
|
||||
// Get world based on input, fallback to sender if input is not a world
|
||||
if (resolve.equals("issuerAware")) {
|
||||
|
@ -186,7 +185,7 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
return world;
|
||||
}
|
||||
if (context.getIssuer().isPlayer()) {
|
||||
return worldManager.getMVWorld(context.getIssuer().getPlayer().getWorld());
|
||||
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
|
@ -205,18 +204,18 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
|
||||
}
|
||||
|
||||
private MVWorld[] parseMVWorldArray(BukkitCommandExecutionContext context) {
|
||||
private LoadedMultiverseWorld[] parseMVWorldArray(BukkitCommandExecutionContext context) {
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
MVWorld playerWorld = null;
|
||||
LoadedMultiverseWorld playerWorld = null;
|
||||
if (context.getIssuer().isPlayer()) {
|
||||
playerWorld = worldManager.getMVWorld(context.getIssuer().getPlayer().getWorld());
|
||||
playerWorld = worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
|
||||
}
|
||||
|
||||
// Get world based on sender only
|
||||
if (resolve.equals("issuerOnly")) {
|
||||
if (playerWorld != null) {
|
||||
return new MVWorld[]{playerWorld};
|
||||
return new LoadedMultiverseWorld[]{playerWorld};
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
|
@ -226,13 +225,13 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
|
||||
String worldStrings = context.getFirstArg();
|
||||
String[] worldNames = worldStrings == null ? new String[0] : worldStrings.split(",");
|
||||
Set<MVWorld> worlds = new HashSet<>(worldNames.length);
|
||||
Set<LoadedMultiverseWorld> worlds = new HashSet<>(worldNames.length);
|
||||
for (String worldName : worldNames) {
|
||||
if ("*".equals(worldName)) {
|
||||
worlds.addAll(worldManager.getMVWorlds());
|
||||
worlds.addAll(worldManager.getLoadedWorlds());
|
||||
break;
|
||||
}
|
||||
MVWorld world = worldManager.getMVWorld(worldName);
|
||||
LoadedMultiverseWorld world = worldManager.getLoadedWorld(worldName).getOrNull();
|
||||
if (world == null) {
|
||||
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
|
||||
}
|
||||
|
@ -243,10 +242,10 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
if (resolve.equals("issuerAware")) {
|
||||
if (!worlds.isEmpty()) {
|
||||
context.popFirstArg();
|
||||
return worlds.toArray(new MVWorld[0]);
|
||||
return worlds.toArray(new LoadedMultiverseWorld[0]);
|
||||
}
|
||||
if (playerWorld != null) {
|
||||
return new MVWorld[]{playerWorld};
|
||||
return new LoadedMultiverseWorld[]{playerWorld};
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
|
@ -257,7 +256,7 @@ public class MVCommandContexts extends PaperCommandContexts {
|
|||
// Get world based on input only
|
||||
if (!worlds.isEmpty()) {
|
||||
context.popFirstArg();
|
||||
return worlds.toArray(new MVWorld[0]);
|
||||
return worlds.toArray(new LoadedMultiverseWorld[0]);
|
||||
}
|
||||
if (context.isOptional()) {
|
||||
return null;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.onarandombox.MultiverseCore.commandtools;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import co.aikar.commands.BukkitCommandCompletionContext;
|
||||
import co.aikar.commands.BukkitCommandExecutionContext;
|
||||
import co.aikar.commands.BukkitLocales;
|
||||
|
@ -11,9 +9,9 @@ import co.aikar.commands.CommandHelp;
|
|||
import co.aikar.commands.HelpEntry;
|
||||
import co.aikar.commands.PaperCommandManager;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.queue.CommandQueueManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -21,6 +19,8 @@ import org.bukkit.command.CommandSender;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Main class to manage permissions.
|
||||
*/
|
||||
|
@ -39,7 +39,7 @@ public class MVCommandManager extends PaperCommandManager {
|
|||
@NotNull CommandQueueManager commandQueueManager,
|
||||
@NotNull Provider<MVCommandContexts> commandContextsProvider,
|
||||
@NotNull Provider<MVCommandCompletions> commandCompletionsProvider,
|
||||
@NotNull MVWorldManager worldManager
|
||||
@NotNull WorldManager worldManager
|
||||
) {
|
||||
super(plugin);
|
||||
this.flagsManager = flagsManager;
|
||||
|
|
|
@ -60,10 +60,9 @@ public class CommandFlagsManager {
|
|||
Collection<String> suggestions = new ArrayList<>();
|
||||
CommandFlag currentFlag = (flags.length <= 1) ? null : flagGroup.getFlagByKey(flags[flags.length - 2]);
|
||||
|
||||
if (currentFlag instanceof CommandValueFlag) {
|
||||
CommandValueFlag<?> valueFlag = (CommandValueFlag<?>) currentFlag;
|
||||
if (currentFlag instanceof CommandValueFlag<?> valueFlag) {
|
||||
if (valueFlag.getCompletion() != null) {
|
||||
suggestions.addAll(valueFlag.getCompletion().get());
|
||||
suggestions.addAll(valueFlag.getCompletion().apply(flags[flags.length - 1]));
|
||||
}
|
||||
if (valueFlag.isOptional()) {
|
||||
suggestions.addAll(flagGroup.getRemainingKeys(flags));
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -43,7 +42,7 @@ public class CommandValueFlag<T> extends CommandFlag {
|
|||
private final boolean optional;
|
||||
private final T defaultValue;
|
||||
private final Function<String, T> context;
|
||||
private final Supplier<Collection<String>> completion;
|
||||
private final Function<String, Collection<String>> completion;
|
||||
|
||||
/**
|
||||
* Creates a new flag.
|
||||
|
@ -63,7 +62,7 @@ public class CommandValueFlag<T> extends CommandFlag {
|
|||
boolean optional,
|
||||
@Nullable T defaultValue,
|
||||
@Nullable Function<String, T> context,
|
||||
@Nullable Supplier<Collection<String>> completion
|
||||
@Nullable Function<String, Collection<String>> completion
|
||||
) {
|
||||
super(key, aliases);
|
||||
this.type = type;
|
||||
|
@ -114,7 +113,7 @@ public class CommandValueFlag<T> extends CommandFlag {
|
|||
*
|
||||
* @return The completion.
|
||||
*/
|
||||
public @Nullable Supplier<Collection<String>> getCompletion() {
|
||||
public @Nullable Function<String, Collection<String>> getCompletion() {
|
||||
return completion;
|
||||
}
|
||||
|
||||
|
@ -129,7 +128,7 @@ public class CommandValueFlag<T> extends CommandFlag {
|
|||
protected boolean optional = false;
|
||||
protected T defaultValue = null;
|
||||
protected Function<String, T> context = null;
|
||||
protected Supplier<Collection<String>> completion = null;
|
||||
protected Function<String, Collection<String>> completion = null;
|
||||
|
||||
/**
|
||||
* Create a new builder.
|
||||
|
@ -177,10 +176,10 @@ public class CommandValueFlag<T> extends CommandFlag {
|
|||
/**
|
||||
* Set the completion callback for autocomplete.
|
||||
*
|
||||
* @param completion The completion.
|
||||
* @param completion The completion. Input is the current input string, and output is the list of suggestions.
|
||||
* @return The builder.
|
||||
*/
|
||||
public @NotNull S completion(@NotNull Supplier<Collection<String>> completion) {
|
||||
public @NotNull S completion(@NotNull Function<String, Collection<String>> completion) {
|
||||
this.completion = completion;
|
||||
return (S) this;
|
||||
}
|
||||
|
@ -210,7 +209,7 @@ public class CommandValueFlag<T> extends CommandFlag {
|
|||
protected boolean optional = false;
|
||||
protected T defaultValue = null;
|
||||
protected Function<String, T> context = null;
|
||||
protected Supplier<Collection<String>> completion = null;
|
||||
protected Function<String, Collection<String>> completion = null;
|
||||
|
||||
public EnumBuilder(@NotNull String key, @NotNull Class<T> type) {
|
||||
super(key);
|
||||
|
@ -234,7 +233,7 @@ public class CommandValueFlag<T> extends CommandFlag {
|
|||
.map(type -> type.name().toLowerCase())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
this.completion = () -> types;
|
||||
this.completion = (input) -> types;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -89,7 +89,7 @@ public class MVCoreConfig implements MVConfig {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean load() {
|
||||
public Try<Void> load() {
|
||||
migrateFromOldConfigFile();
|
||||
return configHandle.load();
|
||||
}
|
||||
|
@ -100,9 +100,8 @@ public class MVCoreConfig implements MVConfig {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean save() {
|
||||
configHandle.save();
|
||||
return true;
|
||||
public Try<Void> save() {
|
||||
return configHandle.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.onarandombox.MultiverseCore.configuration.handle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -9,6 +10,7 @@ import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
|||
import com.onarandombox.MultiverseCore.configuration.node.CommentedNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import io.github.townyadvanced.commentedconfiguration.CommentedConfiguration;
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -35,9 +37,12 @@ public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfigu
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected boolean loadConfigObject() {
|
||||
protected void loadConfigObject() throws IOException {
|
||||
config = new CommentedConfiguration(configPath, logger);
|
||||
return config.load();
|
||||
if (!config.load()) {
|
||||
throw new IOException("Failed to load commented config file " + configPath
|
||||
+ ". See console for details.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,9 +76,9 @@ public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfigu
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean save() {
|
||||
config.save();
|
||||
return true;
|
||||
public Try<Void> save() {
|
||||
// TODO: There is no way to check if the save was successful.
|
||||
return Try.run(() -> config.save());
|
||||
}
|
||||
|
||||
public static class Builder extends FileConfigHandle.Builder<CommentedConfiguration, Builder> {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.onarandombox.MultiverseCore.configuration.handle;
|
|||
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -16,7 +17,7 @@ public class ConfigurationSectionHandle extends GenericConfigHandle<Configuratio
|
|||
return new Builder<>(configurationSection);
|
||||
}
|
||||
|
||||
public ConfigurationSectionHandle(@NotNull ConfigurationSection configurationSection,
|
||||
protected ConfigurationSectionHandle(@NotNull ConfigurationSection configurationSection,
|
||||
@Nullable Logger logger,
|
||||
@Nullable NodeGroup nodes,
|
||||
@Nullable ConfigMigrator migrator) {
|
||||
|
@ -24,6 +25,17 @@ public class ConfigurationSectionHandle extends GenericConfigHandle<Configuratio
|
|||
this.config = configurationSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configuration with a new configuration section.
|
||||
*
|
||||
* @param section The configuration section.
|
||||
* @return Whether the configuration was loaded or its given error.
|
||||
*/
|
||||
public Try<Void> load(@NotNull ConfigurationSection section) {
|
||||
this.config = section;
|
||||
return load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link ConfigurationSectionHandle}.
|
||||
*
|
||||
|
|
|
@ -5,12 +5,11 @@ import java.io.IOException;
|
|||
import java.nio.file.Path;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -33,49 +32,43 @@ abstract class FileConfigHandle<C extends FileConfiguration> extends GenericConf
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean load() {
|
||||
boolean newFileCreated;
|
||||
try {
|
||||
newFileCreated = createConfigFile();
|
||||
} catch (IOException e) {
|
||||
Logging.severe("Failed to create config file: %s", configFile.getName());
|
||||
Logging.severe(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (!loadConfigObject()) {
|
||||
Logging.severe("Failed to load config file: %s", configFile.getName());
|
||||
return false;
|
||||
}
|
||||
if (!newFileCreated) {
|
||||
migrateConfig();
|
||||
}
|
||||
setUpNodes();
|
||||
return true;
|
||||
public Try<Void> load() {
|
||||
boolean isNewFile = !configFile.exists();
|
||||
return createConfigFile()
|
||||
.andThenTry(this::loadConfigObject)
|
||||
.andThenTry(() -> {
|
||||
if (!isNewFile) {
|
||||
migrateConfig();
|
||||
}
|
||||
setUpNodes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new config file if file does not exist
|
||||
* Create a new config file if file does not exist.
|
||||
*
|
||||
* @return True if file exist or created successfully, otherwise false.
|
||||
* @return Whether the file was created or its given error.
|
||||
*/
|
||||
protected boolean createConfigFile() throws IOException {
|
||||
if (configFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
return configFile.createNewFile();
|
||||
protected Try<Void> createConfigFile() {
|
||||
return Try.run(() -> {
|
||||
if (configFile.exists()) {
|
||||
return;
|
||||
}
|
||||
if (!configFile.createNewFile()) {
|
||||
throw new IOException("Failed to create config file: " + configFile.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configuration object.
|
||||
*
|
||||
* @return True if the configuration was loaded successfully, false otherwise.
|
||||
*/
|
||||
protected abstract boolean loadConfigObject();
|
||||
protected abstract void loadConfigObject() throws IOException, InvalidConfigurationException;
|
||||
|
||||
/**
|
||||
* Saves the configuration.
|
||||
*/
|
||||
public abstract boolean save();
|
||||
public abstract Try<Void> save();
|
||||
|
||||
/**
|
||||
* Checks if the configuration is loaded.
|
||||
|
|
|
@ -3,9 +3,7 @@ package com.onarandombox.MultiverseCore.configuration.handle;
|
|||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ConfigNodeNotFoundException;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeSerializer;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
@ -24,7 +22,7 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
|||
|
||||
protected C config;
|
||||
|
||||
public GenericConfigHandle(@Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
|
||||
protected GenericConfigHandle(@Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
|
||||
this.logger = logger;
|
||||
this.nodes = nodes;
|
||||
this.migrator = migrator;
|
||||
|
@ -33,12 +31,15 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
|
|||
/**
|
||||
* Loads the configuration.
|
||||
*
|
||||
* @return True if the configuration was loaded successfully, false otherwise.
|
||||
* @return Whether the configuration was loaded or its given error.
|
||||
*/
|
||||
public boolean load() {
|
||||
migrateConfig();
|
||||
setUpNodes();
|
||||
return true;
|
||||
public Try<Void> load() {
|
||||
return Try.run(() -> {
|
||||
if (!config.getKeys(false).isEmpty()) {
|
||||
migrateConfig();
|
||||
}
|
||||
setUpNodes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.logging.Logger;
|
|||
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -35,27 +35,17 @@ public class YamlConfigHandle extends FileConfigHandle<YamlConfiguration> {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected boolean loadConfigObject() {
|
||||
protected void loadConfigObject() throws IOException, InvalidConfigurationException {
|
||||
config = new YamlConfiguration();
|
||||
try {
|
||||
config.load(configFile);
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
config.load(configFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean save() {
|
||||
try {
|
||||
config.save(configFile);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
public Try<Void> save() {
|
||||
return Try.run(() -> config.save(configFile));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
/**
|
||||
* Single migrator action that converts a string value to a long.
|
||||
*/
|
||||
public class LongMigratorAction implements MigratorAction {
|
||||
|
||||
public static LongMigratorAction of(String path) {
|
||||
return new LongMigratorAction(path);
|
||||
}
|
||||
|
||||
private final String path;
|
||||
|
||||
LongMigratorAction(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void migrate(ConfigurationSection config) {
|
||||
config.set(path, ACFUtil.parseLong(config.getString(path)));
|
||||
Logging.info("Converted %s to long %s", path, config.getLong(path));
|
||||
}
|
||||
}
|
|
@ -37,8 +37,8 @@ public class MoveMigratorAction implements MigratorAction {
|
|||
public void migrate(ConfigurationSection config) {
|
||||
Optional.ofNullable(config.get(fromPath))
|
||||
.ifPresent(value -> {
|
||||
config.set(toPath, value);
|
||||
config.set(fromPath, null);
|
||||
config.set(toPath, value);
|
||||
Logging.config("Moved path %s to %s", fromPath, toPath);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
/**
|
||||
* Single migrator action changes a string value of "null" to an empty string.
|
||||
*/
|
||||
public class NullStringMigratorAction implements MigratorAction {
|
||||
|
||||
public static NullStringMigratorAction of(String path) {
|
||||
return new NullStringMigratorAction(path);
|
||||
}
|
||||
|
||||
private final String path;
|
||||
|
||||
protected NullStringMigratorAction(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void migrate(ConfigurationSection config) {
|
||||
config.set(path, "null".equals(config.getString(path)) ? "" : config.getString(path));
|
||||
Logging.info("Converted %s to %s", path, config.getString(path));
|
||||
}
|
||||
}
|
|
@ -5,11 +5,12 @@ import java.util.Collections;
|
|||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import com.onarandombox.MultiverseCore.api.Destination;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.api.Teleporter;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
@ -17,10 +18,10 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@Service
|
||||
public class CannonDestination implements Destination<CannonDestinationInstance> {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public CannonDestination(MVWorldManager worldManager) {
|
||||
public CannonDestination(WorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
|
@ -53,7 +54,7 @@ public class CannonDestination implements Destination<CannonDestinationInstance>
|
|||
return null;
|
||||
}
|
||||
|
||||
MVWorld world = this.worldManager.getMVWorld(worldName);
|
||||
World world = this.worldManager.getLoadedWorld(worldName).map(LoadedMultiverseWorld::getBukkitWorld).getOrNull().getOrNull();
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -62,7 +63,7 @@ public class CannonDestination implements Destination<CannonDestinationInstance>
|
|||
double dSpeed;
|
||||
try {
|
||||
location = new Location(
|
||||
world.getCBWorld(),
|
||||
world,
|
||||
Double.parseDouble(coordinatesParams[0]),
|
||||
Double.parseDouble(coordinatesParams[1]),
|
||||
Double.parseDouble(coordinatesParams[2]),
|
||||
|
|
|
@ -5,11 +5,12 @@ import java.util.Collections;
|
|||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import com.onarandombox.MultiverseCore.api.Destination;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.api.Teleporter;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
@ -17,10 +18,10 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@Service
|
||||
public class ExactDestination implements Destination<ExactDestinationInstance> {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public ExactDestination(MVWorldManager worldManager) {
|
||||
public ExactDestination(WorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
|
@ -49,7 +50,7 @@ public class ExactDestination implements Destination<ExactDestinationInstance> {
|
|||
return null;
|
||||
}
|
||||
|
||||
MVWorld world = this.worldManager.getMVWorld(worldName);
|
||||
World world = this.worldManager.getLoadedWorld(worldName).map(LoadedMultiverseWorld::getBukkitWorld).getOrNull().getOrNull();
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -57,7 +58,7 @@ public class ExactDestination implements Destination<ExactDestinationInstance> {
|
|||
Location location;
|
||||
try {
|
||||
location = new Location(
|
||||
world.getCBWorld(),
|
||||
world,
|
||||
Double.parseDouble(coordinatesParams[0]),
|
||||
Double.parseDouble(coordinatesParams[1]),
|
||||
Double.parseDouble(coordinatesParams[2])
|
||||
|
|
|
@ -6,9 +6,9 @@ import java.util.Collections;
|
|||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import com.onarandombox.MultiverseCore.api.Destination;
|
||||
import com.onarandombox.MultiverseCore.api.LocationManipulation;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.api.Teleporter;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -17,11 +17,11 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@Service
|
||||
public class WorldDestination implements Destination<WorldDestinationInstance> {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final LocationManipulation locationManipulation;
|
||||
|
||||
@Inject
|
||||
public WorldDestination(MVWorldManager worldManager, LocationManipulation locationManipulation) {
|
||||
public WorldDestination(WorldManager worldManager, LocationManipulation locationManipulation) {
|
||||
this.worldManager = worldManager;
|
||||
this.locationManipulation = locationManipulation;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public class WorldDestination implements Destination<WorldDestinationInstance> {
|
|||
}
|
||||
|
||||
String worldName = items[0];
|
||||
MVWorld world = this.worldManager.getMVWorld(worldName);
|
||||
LoadedMultiverseWorld world = this.worldManager.getLoadedWorld(worldName).getOrNull();
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.onarandombox.MultiverseCore.destination.core;
|
||||
|
||||
import com.onarandombox.MultiverseCore.api.DestinationInstance;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Vector;
|
||||
|
@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class WorldDestinationInstance implements DestinationInstance {
|
||||
private final MVWorld world;
|
||||
private final LoadedMultiverseWorld world;
|
||||
private final String direction;
|
||||
private final float yaw;
|
||||
|
||||
|
@ -18,7 +18,7 @@ public class WorldDestinationInstance implements DestinationInstance {
|
|||
*
|
||||
* @param world The world to teleport to.
|
||||
*/
|
||||
public WorldDestinationInstance(@NotNull MVWorld world, @Nullable String direction, float yaw) {
|
||||
public WorldDestinationInstance(@NotNull LoadedMultiverseWorld world, @Nullable String direction, float yaw) {
|
||||
this.world = world;
|
||||
this.direction = direction;
|
||||
this.yaw = yaw;
|
||||
|
@ -59,8 +59,8 @@ public class WorldDestinationInstance implements DestinationInstance {
|
|||
@Override
|
||||
public @NotNull String serialise() {
|
||||
if (this.direction != null) {
|
||||
return this.world.getCBWorld().getName() + ":" + this.direction;
|
||||
return this.world.getName() + ":" + this.direction;
|
||||
}
|
||||
return this.world.getCBWorld().getName();
|
||||
return this.world.getName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.onarandombox.MultiverseCore.economy;
|
||||
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
|
@ -98,7 +98,7 @@ public class MVEconomist {
|
|||
* @param player the player to deposit currency into.
|
||||
* @param world the world to take entry fee from.
|
||||
*/
|
||||
public void payEntryFee(Player player, MVWorld world) {
|
||||
public void payEntryFee(Player player, LoadedMultiverseWorld world) {
|
||||
payEntryFee(player, world.getPrice(), world.getCurrency());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package com.onarandombox.MultiverseCore.listeners;
|
||||
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.inject.InjectableListener;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
@ -17,13 +15,13 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@Service
|
||||
public class MVChatListener implements InjectableListener {
|
||||
private final MVCoreConfig config;
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final MVPlayerListener playerListener;
|
||||
|
||||
@Inject
|
||||
public MVChatListener(
|
||||
MVCoreConfig config,
|
||||
MVWorldManager worldManager,
|
||||
WorldManager worldManager,
|
||||
MVPlayerListener playerListener
|
||||
) {
|
||||
this.config = config;
|
||||
|
@ -40,31 +38,28 @@ public class MVChatListener implements InjectableListener {
|
|||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether the Server is set to prefix the chat with the World name.
|
||||
// If not we do nothing, if so we need to check if the World has an Alias.
|
||||
if (config.isEnablePrefixChat()) {
|
||||
String world = playerListener.getPlayerWorld().get(event.getPlayer().getName());
|
||||
if (world == null) {
|
||||
world = event.getPlayer().getWorld().getName();
|
||||
playerListener.getPlayerWorld().put(event.getPlayer().getName(), world);
|
||||
}
|
||||
String prefix = "";
|
||||
// If we're not a MV world, don't do anything
|
||||
if (!this.worldManager.isMVWorld(world)) {
|
||||
return;
|
||||
}
|
||||
MVWorld mvworld = this.worldManager.getMVWorld(world);
|
||||
if (mvworld.isHidden()) {
|
||||
return;
|
||||
}
|
||||
prefix = mvworld.getColoredWorldString();
|
||||
String chat = event.getFormat();
|
||||
|
||||
String prefixChatFormat = config.getPrefixChatFormat();
|
||||
prefixChatFormat = prefixChatFormat.replace("%world%", prefix).replace("%chat%", chat);
|
||||
prefixChatFormat = ChatColor.translateAlternateColorCodes('&', prefixChatFormat);
|
||||
|
||||
event.setFormat(prefixChatFormat);
|
||||
if (!config.isEnablePrefixChat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String world = playerListener.getPlayerWorld().get(event.getPlayer().getName());
|
||||
if (world == null) {
|
||||
world = event.getPlayer().getWorld().getName();
|
||||
playerListener.getPlayerWorld().put(event.getPlayer().getName(), world);
|
||||
}
|
||||
|
||||
String prefix = this.worldManager.getLoadedWorld(world)
|
||||
.map((mvworld) -> mvworld.isHidden() ? "" : mvworld.getAlias())
|
||||
.getOrElse("");
|
||||
String chat = event.getFormat();
|
||||
|
||||
String prefixChatFormat = config.getPrefixChatFormat();
|
||||
prefixChatFormat = prefixChatFormat.replace("%world%", prefix).replace("%chat%", chat);
|
||||
prefixChatFormat = ChatColor.translateAlternateColorCodes('&', prefixChatFormat);
|
||||
|
||||
event.setFormat(prefixChatFormat);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,20 +8,15 @@
|
|||
package com.onarandombox.MultiverseCore.listeners;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.WorldPurger;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.inject.InjectableListener;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldPurger;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.event.entity.EntityPortalEvent;
|
||||
import org.bukkit.event.entity.EntityRegainHealthEvent;
|
||||
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
|
@ -33,17 +28,14 @@ import org.jvnet.hk2.annotations.Service;
|
|||
*/
|
||||
@Service
|
||||
public class MVEntityListener implements InjectableListener {
|
||||
private final MVCoreConfig config;
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final WorldPurger worldPurger;
|
||||
|
||||
@Inject
|
||||
public MVEntityListener(
|
||||
@NotNull MVCoreConfig config,
|
||||
@NotNull MVWorldManager worldManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull WorldPurger worldPurger
|
||||
) {
|
||||
this.config = config;
|
||||
this.worldManager = worldManager;
|
||||
this.worldPurger = worldPurger;
|
||||
}
|
||||
|
@ -57,16 +49,15 @@ public class MVEntityListener implements InjectableListener {
|
|||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
if (event.getEntity() instanceof Player) {
|
||||
Player p = (Player) event.getEntity();
|
||||
MVWorld w = this.worldManager.getMVWorld(p.getWorld().getName());
|
||||
if (w != null && !w.getHunger()) {
|
||||
// If the world has hunger set to false, do not let the level go down
|
||||
if (event.getFoodLevel() < ((Player) event.getEntity()).getFoodLevel()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
if (!(event.getEntity() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
worldManager.getLoadedWorld(player.getWorld())
|
||||
.peek((world) -> {
|
||||
if (!world.getHunger() && event.getFoodLevel() < player.getFoodLevel()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,14 +66,15 @@ public class MVEntityListener implements InjectableListener {
|
|||
*/
|
||||
@EventHandler
|
||||
public void entityRegainHealth(EntityRegainHealthEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
if (event.isCancelled() || event.getRegainReason() != RegainReason.REGEN) {
|
||||
return;
|
||||
}
|
||||
RegainReason reason = event.getRegainReason();
|
||||
MVWorld world = this.worldManager.getMVWorld(event.getEntity().getLocation().getWorld());
|
||||
if (world != null && reason == RegainReason.REGEN && !world.getAutoHeal()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
worldManager.getLoadedWorld(event.getEntity().getWorld())
|
||||
.peek((world) -> {
|
||||
if (!world.getAutoHeal()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,45 +83,24 @@ public class MVEntityListener implements InjectableListener {
|
|||
*/
|
||||
@EventHandler
|
||||
public void creatureSpawn(CreatureSpawnEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if the Creature is spawned by a plugin, we don't want to prevent this behaviour.
|
||||
// TODO: Allow the egg thing to be a config param. Doubt this will be per world; seems silly.
|
||||
if (event.getSpawnReason() == SpawnReason.CUSTOM || event.getSpawnReason() == SpawnReason.SPAWNER_EGG
|
||||
if (event.getSpawnReason() == SpawnReason.CUSTOM
|
||||
|| event.getSpawnReason() == SpawnReason.SPAWNER_EGG
|
||||
|| event.getSpawnReason() == SpawnReason.BREEDING) {
|
||||
return;
|
||||
}
|
||||
|
||||
World world = event.getEntity().getWorld();
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
|
||||
// Check if it's a world which we are meant to be managing.
|
||||
if (!(this.worldManager.isMVWorld(world.getName())))
|
||||
return;
|
||||
|
||||
EntityType type = event.getEntityType();
|
||||
/**
|
||||
* Handle people with non-standard animals: ie a patched craftbukkit.
|
||||
*/
|
||||
if (type == null || type.getName() == null) {
|
||||
Logging.finer("Found a null typed creature.");
|
||||
return;
|
||||
}
|
||||
|
||||
MVWorld mvworld = this.worldManager.getMVWorld(world.getName());
|
||||
event.setCancelled(this.worldPurger.shouldWeKillThisCreature(mvworld, event.getEntity()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles portal search radius adjustment.
|
||||
* @param event The Event that was fired.
|
||||
*/
|
||||
@EventHandler
|
||||
public void entityPortal(EntityPortalEvent event) {
|
||||
if (event.isCancelled() || event.getTo() == null) {
|
||||
return;
|
||||
}
|
||||
if (!config.isUsingCustomPortalSearch()) {
|
||||
event.setSearchRadius(config.getCustomPortalSearchRadius());
|
||||
}
|
||||
worldManager.getLoadedWorld(event.getEntity().getWorld())
|
||||
.peek((world) -> {
|
||||
if (this.worldPurger.shouldWeKillThisCreature(world, event.getEntity())) {
|
||||
Logging.finer("Cancelling Creature Spawn Event for: " + event.getEntity());
|
||||
event.setCancelled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,25 +7,24 @@
|
|||
|
||||
package com.onarandombox.MultiverseCore.listeners;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
|
||||
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
|
||||
import com.onarandombox.MultiverseCore.economy.MVEconomist;
|
||||
import com.onarandombox.MultiverseCore.event.MVRespawnEvent;
|
||||
import com.onarandombox.MultiverseCore.inject.InjectableListener;
|
||||
import com.onarandombox.MultiverseCore.permissions.CorePermissionsChecker;
|
||||
import com.onarandombox.MultiverseCore.teleportation.TeleportQueue;
|
||||
import com.onarandombox.MultiverseCore.utils.result.ResultChain;
|
||||
import com.onarandombox.MultiverseCore.world.entrycheck.EntryFeeResult;
|
||||
import com.onarandombox.MultiverseCore.world.entrycheck.WorldEntryCheckerProvider;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.entrycheck.EntryFeeResult;
|
||||
import com.onarandombox.MultiverseCore.worldnew.entrycheck.WorldEntryCheckerProvider;
|
||||
import io.vavr.control.Option;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import org.bukkit.GameMode;
|
||||
|
@ -45,6 +44,10 @@ import org.bukkit.event.player.PlayerTeleportEvent;
|
|||
import org.bukkit.plugin.Plugin;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Multiverse's Listener for players.
|
||||
*/
|
||||
|
@ -52,7 +55,7 @@ import org.jvnet.hk2.annotations.Service;
|
|||
public class MVPlayerListener implements InjectableListener {
|
||||
private final Plugin plugin;
|
||||
private final MVCoreConfig config;
|
||||
private final Provider<MVWorldManager> worldManagerProvider;
|
||||
private final Provider<WorldManager> worldManagerProvider;
|
||||
private final SafeTTeleporter safeTTeleporter;
|
||||
private final Server server;
|
||||
private final TeleportQueue teleportQueue;
|
||||
|
@ -60,6 +63,7 @@ public class MVPlayerListener implements InjectableListener {
|
|||
private final WorldEntryCheckerProvider worldEntryCheckerProvider;
|
||||
private final Provider<MVCommandManager> commandManagerProvider;
|
||||
private final CorePermissionsChecker permissionsChecker;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
|
||||
private final Map<String, String> playerWorld = new ConcurrentHashMap<String, String>();
|
||||
|
||||
|
@ -67,14 +71,15 @@ public class MVPlayerListener implements InjectableListener {
|
|||
public MVPlayerListener(
|
||||
MultiverseCore plugin,
|
||||
MVCoreConfig config,
|
||||
Provider<MVWorldManager> worldManagerProvider,
|
||||
Provider<WorldManager> worldManagerProvider,
|
||||
SafeTTeleporter safeTTeleporter,
|
||||
Server server,
|
||||
TeleportQueue teleportQueue,
|
||||
MVEconomist economist,
|
||||
WorldEntryCheckerProvider worldEntryCheckerProvider,
|
||||
Provider<MVCommandManager> commandManagerProvider,
|
||||
CorePermissionsChecker permissionsChecker
|
||||
CorePermissionsChecker permissionsChecker,
|
||||
DestinationsProvider destinationsProvider
|
||||
) {
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
|
@ -86,9 +91,10 @@ public class MVPlayerListener implements InjectableListener {
|
|||
this.worldEntryCheckerProvider = worldEntryCheckerProvider;
|
||||
this.commandManagerProvider = commandManagerProvider;
|
||||
this.permissionsChecker = permissionsChecker;
|
||||
this.destinationsProvider = destinationsProvider;
|
||||
}
|
||||
|
||||
private MVWorldManager getWorldManager() {
|
||||
private WorldManager getWorldManager() {
|
||||
return worldManagerProvider.get();
|
||||
}
|
||||
|
||||
|
@ -110,7 +116,7 @@ public class MVPlayerListener implements InjectableListener {
|
|||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void playerRespawn(PlayerRespawnEvent event) {
|
||||
World world = event.getPlayer().getWorld();
|
||||
MVWorld mvWorld = getWorldManager().getMVWorld(world.getName());
|
||||
LoadedMultiverseWorld mvWorld = getWorldManager().getLoadedWorld(world.getName()).getOrNull();
|
||||
// If it's not a World MV manages we stop.
|
||||
if (mvWorld == null) {
|
||||
return;
|
||||
|
@ -122,15 +128,15 @@ public class MVPlayerListener implements InjectableListener {
|
|||
}
|
||||
|
||||
// Get the instance of the World the player should respawn at.
|
||||
MVWorld respawnWorld = null;
|
||||
if (getWorldManager().isMVWorld(mvWorld.getRespawnToWorld())) {
|
||||
respawnWorld = getWorldManager().getMVWorld(mvWorld.getRespawnToWorld());
|
||||
LoadedMultiverseWorld respawnWorld = null;
|
||||
if (getWorldManager().isLoadedWorld(mvWorld.getRespawnWorld())) {
|
||||
respawnWorld = getWorldManager().getLoadedWorld(mvWorld.getRespawnWorld()).getOrNull();
|
||||
}
|
||||
|
||||
// If it's null then it either means the World doesn't exist or the value is blank, so we don't handle it.
|
||||
// NOW: We'll always handle it to get more accurate spawns
|
||||
if (respawnWorld != null) {
|
||||
world = respawnWorld.getCBWorld();
|
||||
world = respawnWorld.getBukkitWorld().getOrNull();
|
||||
}
|
||||
// World has been set to the appropriate world
|
||||
Location respawnLocation = getMostAccurateRespawnLocation(world);
|
||||
|
@ -141,7 +147,7 @@ public class MVPlayerListener implements InjectableListener {
|
|||
}
|
||||
|
||||
private Location getMostAccurateRespawnLocation(World w) {
|
||||
MVWorld mvw = getWorldManager().getMVWorld(w.getName());
|
||||
LoadedMultiverseWorld mvw = getWorldManager().getLoadedWorld(w.getName()).getOrNull();
|
||||
if (mvw != null) {
|
||||
return mvw.getSpawnLocation();
|
||||
}
|
||||
|
@ -154,26 +160,33 @@ public class MVPlayerListener implements InjectableListener {
|
|||
*/
|
||||
@EventHandler
|
||||
public void playerJoin(PlayerJoinEvent event) {
|
||||
Player p = event.getPlayer();
|
||||
if (!p.hasPlayedBefore()) {
|
||||
Logging.finer("Player joined for the FIRST time!");
|
||||
if (config.getFirstSpawnOverride()) {
|
||||
Logging.fine("Moving NEW player to(firstspawnoverride): "
|
||||
+ getWorldManager().getFirstSpawnWorld().getSpawnLocation());
|
||||
this.sendPlayerToDefaultWorld(p);
|
||||
}
|
||||
Player player = event.getPlayer();
|
||||
LoadedMultiverseWorld world = getWorldManager().getLoadedWorld(player.getWorld()).getOrNull();
|
||||
if (world == null) {
|
||||
Logging.finer("Player joined in a world that is not managed by Multiverse.");
|
||||
return;
|
||||
} else {
|
||||
Logging.finer("Player joined AGAIN!");
|
||||
if (config.getEnforceAccess() // check this only if we're enforcing access!
|
||||
&& !permissionsChecker.hasWorldAccessPermission(p, getWorldManager().getFirstSpawnWorld())) {
|
||||
p.sendMessage("[MV] - Sorry you can't be in this world anymore!");
|
||||
this.sendPlayerToDefaultWorld(p);
|
||||
}
|
||||
}
|
||||
|
||||
Option.of(destinationsProvider.parseDestination(config.getFirstSpawnLocation()))
|
||||
.peek(parsedDestination -> {
|
||||
if (!player.hasPlayedBefore()) {
|
||||
Logging.finer("Player joined for the FIRST time!");
|
||||
if (config.getFirstSpawnOverride()) {
|
||||
Logging.fine("Moving NEW player to(firstspawnoverride): %s", config.getFirstSpawnLocation());
|
||||
this.sendPlayerToDefaultWorld(player, parsedDestination);
|
||||
}
|
||||
} else {
|
||||
Logging.finer("Player joined AGAIN!");
|
||||
if (worldEntryCheckerProvider.forSender(player).canAccessWorld(world).isFailure()) {
|
||||
player.sendMessage("[MV] - Sorry you can't be in this world anymore!");
|
||||
this.sendPlayerToDefaultWorld(player, parsedDestination);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle the Players GameMode setting for the new world.
|
||||
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
|
||||
playerWorld.put(p.getName(), p.getWorld().getName());
|
||||
playerWorld.put(player.getName(), player.getWorld().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,8 +226,8 @@ public class MVPlayerListener implements InjectableListener {
|
|||
}
|
||||
Logging.finer("Inferred sender '" + teleporter + "' from name '"
|
||||
+ teleporterName + "', fetched from name '" + teleportee.getName() + "'");
|
||||
MVWorld fromWorld = getWorldManager().getMVWorld(event.getFrom().getWorld().getName());
|
||||
MVWorld toWorld = getWorldManager().getMVWorld(event.getTo().getWorld().getName());
|
||||
LoadedMultiverseWorld fromWorld = getWorldManager().getLoadedWorld(event.getFrom().getWorld().getName()).getOrNull();
|
||||
LoadedMultiverseWorld toWorld = getWorldManager().getLoadedWorld(event.getTo().getWorld().getName()).getOrNull();
|
||||
if (toWorld == null) {
|
||||
Logging.fine("Player '" + teleportee.getName() + "' is teleporting to world '"
|
||||
+ event.getTo().getWorld().getName() + "' which is not managed by Multiverse-Core. No further "
|
||||
|
@ -291,8 +304,8 @@ public class MVPlayerListener implements InjectableListener {
|
|||
event.setSearchRadius(config.getCustomPortalSearchRadius());
|
||||
}
|
||||
|
||||
MVWorld fromWorld = getWorldManager().getMVWorld(event.getFrom().getWorld().getName());
|
||||
MVWorld toWorld = getWorldManager().getMVWorld(event.getTo().getWorld().getName());
|
||||
LoadedMultiverseWorld fromWorld = getWorldManager().getLoadedWorld(event.getFrom().getWorld().getName()).getOrNull();
|
||||
LoadedMultiverseWorld toWorld = getWorldManager().getLoadedWorld(event.getTo().getWorld().getName()).getOrNull();
|
||||
if (event.getFrom().getWorld().equals(event.getTo().getWorld())) {
|
||||
// The player is Portaling to the same world.
|
||||
Logging.finer("Player '" + event.getPlayer().getName() + "' is portaling to the same world.");
|
||||
|
@ -308,13 +321,13 @@ public class MVPlayerListener implements InjectableListener {
|
|||
Logging.fine("Teleport result: %s", entryResult);
|
||||
}
|
||||
|
||||
private void sendPlayerToDefaultWorld(final Player player) {
|
||||
private void sendPlayerToDefaultWorld(final Player player, ParsedDestination parsedDestination) {
|
||||
// Remove the player 1 tick after the login. I'm sure there's GOT to be a better way to do this...
|
||||
this.server.getScheduler().scheduleSyncDelayedTask(this.plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.teleport(getWorldManager().getFirstSpawnWorld().getSpawnLocation());
|
||||
safeTTeleporter.safelyTeleportAsync(getCommandManager().getCommandIssuer(player), player, parsedDestination);
|
||||
}
|
||||
}, 1L);
|
||||
}
|
||||
|
@ -322,7 +335,7 @@ public class MVPlayerListener implements InjectableListener {
|
|||
// FOLLOWING 2 Methods and Private class handle Per Player GameModes.
|
||||
private void handleGameModeAndFlight(Player player, World world) {
|
||||
|
||||
MVWorld mvWorld = getWorldManager().getMVWorld(world.getName());
|
||||
LoadedMultiverseWorld mvWorld = getWorldManager().getLoadedWorld(world.getName()).getOrNull();
|
||||
if (mvWorld != null) {
|
||||
this.handleGameModeAndFlight(player, mvWorld);
|
||||
} else {
|
||||
|
@ -336,7 +349,7 @@ public class MVPlayerListener implements InjectableListener {
|
|||
* @param player The {@link Player}.
|
||||
* @param world The world the player is in.
|
||||
*/
|
||||
public void handleGameModeAndFlight(final Player player, final MVWorld world) {
|
||||
public void handleGameModeAndFlight(final Player player, final LoadedMultiverseWorld world) {
|
||||
// We perform this task one tick later to MAKE SURE that the player actually reaches the
|
||||
// destination world, otherwise we'd be changing the player mode if they havent moved anywhere.
|
||||
this.server.getScheduler().scheduleSyncDelayedTask(this.plugin,
|
||||
|
@ -345,7 +358,7 @@ public class MVPlayerListener implements InjectableListener {
|
|||
public void run() {
|
||||
if (!permissionsChecker.hasGameModeBypassPermission(player, world)) {
|
||||
// Check that the player is in the new world and they haven't been teleported elsewhere or the event cancelled.
|
||||
if (player.getWorld() == world.getCBWorld()) {
|
||||
if (player.getWorld() == world.getBukkitWorld().getOrNull()) {
|
||||
Logging.fine("Handling gamemode for player: %s, Changing to %s", player.getName(), world.getGameMode().toString());
|
||||
Logging.finest("From World: %s", player.getWorld());
|
||||
Logging.finest("To World: %s", world);
|
||||
|
|
|
@ -8,17 +8,20 @@
|
|||
package com.onarandombox.MultiverseCore.listeners;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.inject.InjectableListener;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.PortalType;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.EntityPortalEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.world.PortalCreateEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
/**
|
||||
|
@ -27,10 +30,12 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@Service
|
||||
public class MVPortalListener implements InjectableListener {
|
||||
|
||||
private MVWorldManager worldManager;
|
||||
private final MVCoreConfig config;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public MVPortalListener(MVWorldManager worldManager) {
|
||||
public MVPortalListener(@NotNull MVCoreConfig config, @NotNull WorldManager worldManager) {
|
||||
this.config = config;
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
|
@ -42,7 +47,7 @@ public class MVPortalListener implements InjectableListener {
|
|||
public void portalForm(PortalCreateEvent event) {
|
||||
Logging.fine("Attempting to create portal at '%s' with reason: %s", event.getWorld().getName(), event.getReason());
|
||||
|
||||
MVWorld world = this.worldManager.getMVWorld(event.getWorld());
|
||||
LoadedMultiverseWorld world = this.worldManager.getLoadedWorld(event.getWorld()).getOrNull();
|
||||
if (world == null) {
|
||||
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PortalCreateEvent.", event.getWorld().getName());
|
||||
return;
|
||||
|
@ -75,7 +80,7 @@ public class MVPortalListener implements InjectableListener {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!world.getAllowedPortals().isPortalAllowed(targetType)) {
|
||||
if (!world.getPortalForm().isPortalAllowed(targetType)) {
|
||||
Logging.fine("Cancelling creation of %s portal because portalForm disallows.", targetType);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
@ -98,16 +103,30 @@ public class MVPortalListener implements InjectableListener {
|
|||
return;
|
||||
}
|
||||
|
||||
MVWorld world = this.worldManager.getMVWorld(event.getPlayer().getWorld());
|
||||
LoadedMultiverseWorld world = this.worldManager.getLoadedWorld(event.getPlayer().getWorld()).getOrNull();
|
||||
if (world == null) {
|
||||
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PlayerInteractEvent.",
|
||||
event.getPlayer().getWorld().getName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!world.getAllowedPortals().isPortalAllowed(PortalType.ENDER)) {
|
||||
if (!world.getPortalForm().isPortalAllowed(PortalType.ENDER)) {
|
||||
Logging.fine("Cancelling creation of ENDER portal because portalForm disallows.");
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles portal search radius adjustment.
|
||||
* @param event The Event that was fired.
|
||||
*/
|
||||
@EventHandler
|
||||
public void entityPortal(EntityPortalEvent event) {
|
||||
if (event.isCancelled() || event.getTo() == null) {
|
||||
return;
|
||||
}
|
||||
if (!config.isUsingCustomPortalSearch()) {
|
||||
event.setSearchRadius(config.getCustomPortalSearchRadius());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
package com.onarandombox.MultiverseCore.listeners;
|
||||
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.inject.InjectableListener;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.weather.ThunderChangeEvent;
|
||||
|
@ -22,10 +22,10 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@Service
|
||||
public class MVWeatherListener implements InjectableListener {
|
||||
|
||||
private MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public MVWeatherListener(MVWorldManager worldManager) {
|
||||
public MVWeatherListener(WorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
|
@ -35,14 +35,16 @@ public class MVWeatherListener implements InjectableListener {
|
|||
*/
|
||||
@EventHandler
|
||||
public void weatherChange(WeatherChangeEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
if (event.isCancelled() || !event.toWeatherState()) {
|
||||
return;
|
||||
}
|
||||
MVWorld world = this.worldManager.getMVWorld(event.getWorld().getName());
|
||||
if (world != null) {
|
||||
// If it's going to start raining and we have weather disabled
|
||||
event.setCancelled((event.toWeatherState() && !world.isWeatherEnabled()));
|
||||
}
|
||||
worldManager.getLoadedWorld(event.getWorld())
|
||||
.peek((world) -> {
|
||||
if (!world.getAllowWeather()) {
|
||||
Logging.fine("Cancelling weather for %s as getAllowWeather is false", world.getName());
|
||||
event.setCancelled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,13 +53,15 @@ public class MVWeatherListener implements InjectableListener {
|
|||
*/
|
||||
@EventHandler
|
||||
public void thunderChange(ThunderChangeEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
if (event.isCancelled() || !event.toThunderState()) {
|
||||
return;
|
||||
}
|
||||
MVWorld world = this.worldManager.getMVWorld(event.getWorld().getName());
|
||||
if (world != null) {
|
||||
// If it's going to start raining and we have weather disabled
|
||||
event.setCancelled((event.toThunderState() && !world.isWeatherEnabled()));
|
||||
}
|
||||
worldManager.getLoadedWorld(event.getWorld())
|
||||
.peek((world) -> {
|
||||
if (!world.getAllowWeather()) {
|
||||
Logging.fine("Cancelling thunder for %s as getAllowWeather is false", world.getName());
|
||||
event.setCancelled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
|
||||
* Multiverse 2 is licensed under the BSD License. *
|
||||
* For more information please check the README.md file included *
|
||||
* with this project. *
|
||||
******************************************************************************/
|
||||
|
||||
package com.onarandombox.MultiverseCore.listeners;
|
||||
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.inject.InjectableListener;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
@Service
|
||||
public class MVWorldInitListener implements InjectableListener {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public MVWorldInitListener(MVWorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void initWorld(WorldInitEvent event) {
|
||||
if (!worldManager.isKeepingSpawnInMemory(event.getWorld())) {
|
||||
event.getWorld().setKeepSpawnInMemory(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,12 +7,15 @@
|
|||
|
||||
package com.onarandombox.MultiverseCore.listeners;
|
||||
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.inject.InjectableListener;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.UnloadWorldOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.LoadFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.UnloadFailureReason;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
@ -23,47 +26,46 @@ import org.jvnet.hk2.annotations.Service;
|
|||
@Service
|
||||
public class MVWorldListener implements InjectableListener {
|
||||
|
||||
private MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public MVWorldListener(MVWorldManager worldManager) {
|
||||
public MVWorldListener(WorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when Bukkit fires off a WorldUnloadEvent.
|
||||
*
|
||||
* @param event The Event that was fired.
|
||||
*/
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void unloadWorld(WorldUnloadEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
if (event.getWorld() instanceof World) {
|
||||
World world = (World) event.getWorld();
|
||||
if (world != null) {
|
||||
this.worldManager.unloadWorld(world.getName(), false);
|
||||
}
|
||||
}
|
||||
worldManager.getLoadedWorld(event.getWorld().getName())
|
||||
.peek(world -> worldManager.unloadWorld(UnloadWorldOptions.world(world)).onFailure(failure -> {
|
||||
if (failure.getFailureReason() != UnloadFailureReason.WORLD_ALREADY_UNLOADING) {
|
||||
Logging.severe("Failed to unload world: " + failure);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when Bukkit fires off a WorldLoadEvent.
|
||||
*
|
||||
* @param event The Event that was fired.
|
||||
*/
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void loadWorld(WorldLoadEvent event) {
|
||||
World world = event.getWorld();
|
||||
if (world != null) {
|
||||
if (this.worldManager.getUnloadedWorlds().contains(world.getName())) {
|
||||
this.worldManager.loadWorld(world.getName());
|
||||
}
|
||||
MVWorld mvWorld = worldManager.getMVWorld(world);
|
||||
if (mvWorld != null) {
|
||||
// This is where we can temporarily fix those pesky property issues!
|
||||
world.setPVP(mvWorld.isPVPEnabled());
|
||||
world.setDifficulty(mvWorld.getDifficulty());
|
||||
}
|
||||
}
|
||||
worldManager.getUnloadedWorld(event.getWorld().getName())
|
||||
.peek(world -> {
|
||||
Logging.fine("Loading world: " + world.getName());
|
||||
worldManager.loadWorld(world).onFailure(failure -> {
|
||||
if (failure.getFailureReason() != LoadFailureReason.WORLD_ALREADY_LOADING) {
|
||||
Logging.severe("Failed to load world: " + failure);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,37 @@
|
|||
package com.onarandombox.MultiverseCore.permissions;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.MultiverseWorld;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
@Service
|
||||
public class CorePermissionsChecker {
|
||||
public boolean hasWorldAccessPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
|
||||
public boolean hasWorldAccessPermission(@NotNull CommandSender sender, @NotNull MultiverseWorld world) {
|
||||
return hasPermission(sender, concatPermission(CorePermissions.WORLD_ACCESS, world.getName()));
|
||||
}
|
||||
|
||||
public boolean hasWorldExemptPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
|
||||
@Deprecated // TODO: Remove old MVWorld
|
||||
public boolean hasWorldAccessPermission(@NotNull CommandSender sender, @NotNull com.onarandombox.MultiverseCore.api.MVWorld world) {
|
||||
return hasPermission(sender, concatPermission(CorePermissions.WORLD_ACCESS, world.getName()));
|
||||
}
|
||||
|
||||
public boolean hasWorldExemptPermission(@NotNull CommandSender sender, @NotNull LoadedMultiverseWorld world) {
|
||||
return hasPermission(sender, concatPermission(CorePermissions.WORLD_EXEMPT, world.getName()));
|
||||
}
|
||||
|
||||
public boolean hasPlayerLimitBypassPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
|
||||
public boolean hasPlayerLimitBypassPermission(@NotNull CommandSender sender, @NotNull LoadedMultiverseWorld world) {
|
||||
return hasPermission(sender, concatPermission(CorePermissions.PLAYERLIMIT_BYPASS, world.getName()));
|
||||
}
|
||||
|
||||
public boolean hasGameModeBypassPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
|
||||
public boolean hasGameModeBypassPermission(@NotNull CommandSender sender, @NotNull LoadedMultiverseWorld world) {
|
||||
return hasPermission(sender, concatPermission(CorePermissions.GAMEMODE_BYPASS, world.getName()));
|
||||
}
|
||||
|
||||
@Deprecated // TODO: Remove old MVWorld
|
||||
public boolean hasGameModeBypassPermission(@NotNull CommandSender sender, @NotNull com.onarandombox.MultiverseCore.api.MVWorld world) {
|
||||
return hasPermission(sender, concatPermission(CorePermissions.GAMEMODE_BYPASS, world.getName()));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package com.onarandombox.MultiverseCore.placeholders;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.economy.MVEconomist;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import io.vavr.control.Option;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.inject.Inject;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -19,11 +19,11 @@ import org.jvnet.hk2.annotations.Service;
|
|||
public class MultiverseCorePlaceholders extends PlaceholderExpansion {
|
||||
|
||||
private final MultiverseCore plugin;
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final MVEconomist economist;
|
||||
|
||||
@Inject
|
||||
public MultiverseCorePlaceholders(MultiverseCore plugin, MVWorldManager worldManager, MVEconomist economist) {
|
||||
public MultiverseCorePlaceholders(MultiverseCore plugin, WorldManager worldManager, MVEconomist economist) {
|
||||
this.plugin = plugin;
|
||||
this.worldManager = worldManager;
|
||||
this.economist = economist;
|
||||
|
@ -74,31 +74,30 @@ public class MultiverseCorePlaceholders extends PlaceholderExpansion {
|
|||
}
|
||||
|
||||
final var placeholder = paramsArray[0];
|
||||
Optional<MVWorld> targetWorld;
|
||||
Option<LoadedMultiverseWorld> targetWorld;
|
||||
|
||||
// If no world is defined, use the player's world
|
||||
if (paramsArray.length == 1) {
|
||||
if (!offlinePlayer.isOnline()) {
|
||||
return null;
|
||||
}
|
||||
targetWorld = Optional.ofNullable(worldManager.getMVWorld(((Player)offlinePlayer).getWorld()));
|
||||
targetWorld = worldManager.getLoadedWorld(((Player)offlinePlayer).getWorld());
|
||||
} else {
|
||||
targetWorld = Optional.ofNullable(worldManager.getMVWorld(paramsArray[1]));
|
||||
targetWorld = worldManager.getLoadedWorld(paramsArray[1]);
|
||||
}
|
||||
|
||||
// Fail if world is null
|
||||
return targetWorld.map(world -> getWorldPlaceHolderValue(placeholder, world))
|
||||
.orElse(null);
|
||||
return targetWorld.map(world -> getWorldPlaceHolderValue(placeholder, world)).getOrNull();
|
||||
}
|
||||
|
||||
private @Nullable String getWorldPlaceHolderValue(@NotNull String placeholder, @NotNull MVWorld world) {
|
||||
private @Nullable String getWorldPlaceHolderValue(@NotNull String placeholder, @NotNull LoadedMultiverseWorld world) {
|
||||
// Switch to find what specific placeholder we want
|
||||
switch (placeholder.toLowerCase()) {
|
||||
case "alias" -> {
|
||||
return world.getColoredWorldString();
|
||||
return world.getAlias();
|
||||
}
|
||||
case "animalspawn" -> {
|
||||
return String.valueOf(world.canAnimalsSpawn());
|
||||
return String.valueOf(world.getSpawningAnimals());
|
||||
}
|
||||
case "autoheal" -> {
|
||||
return String.valueOf(world.getAutoHeal());
|
||||
|
@ -131,7 +130,7 @@ public class MultiverseCorePlaceholders extends PlaceholderExpansion {
|
|||
return String.valueOf(world.getHunger());
|
||||
}
|
||||
case "monstersspawn" -> {
|
||||
return String.valueOf(world.canMonstersSpawn());
|
||||
return String.valueOf(world.getSpawningMonsters());
|
||||
}
|
||||
case "name" -> {
|
||||
return world.getName();
|
||||
|
@ -143,19 +142,20 @@ public class MultiverseCorePlaceholders extends PlaceholderExpansion {
|
|||
return String.valueOf(world.getPrice());
|
||||
}
|
||||
case "pvp" -> {
|
||||
return String.valueOf(world.isPVPEnabled());
|
||||
return String.valueOf(world.getPvp());
|
||||
}
|
||||
case "seed" -> {
|
||||
return String.valueOf(world.getSeed());
|
||||
}
|
||||
case "time" -> {
|
||||
return world.getTime();
|
||||
}
|
||||
// TODO: Time is removed, not sure if it's worth adding back
|
||||
// case "time" -> {
|
||||
// return world.getTime();
|
||||
// }
|
||||
case "type" -> {
|
||||
return world.getWorldType().toString().toLowerCase();
|
||||
return world.getBukkitWorld().map(World::getWorldType).map(Enum::name).getOrElse("null");
|
||||
}
|
||||
case "weather" -> {
|
||||
return String.valueOf(world.isWeatherEnabled());
|
||||
return String.valueOf(world.getAllowWeather());
|
||||
}
|
||||
default -> {
|
||||
warning("Unknown placeholder: " + placeholder);
|
||||
|
|
|
@ -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,
|
||||
|
@ -16,7 +18,6 @@ public enum MVCorei18n implements MessageKeyProvider {
|
|||
|
||||
// clone command
|
||||
CLONE_CLONING,
|
||||
CLONE_FAILED,
|
||||
CLONE_SUCCESS,
|
||||
|
||||
// Coordinates command
|
||||
|
@ -36,13 +37,10 @@ public enum MVCorei18n implements MessageKeyProvider {
|
|||
CREATE_PROPERTIES_GENERATOR,
|
||||
CREATE_PROPERTIES_STRUCTURES,
|
||||
CREATE_LOADING,
|
||||
CREATE_FAILED,
|
||||
CREATE_SUCCESS,
|
||||
|
||||
// delete command
|
||||
DELETE_DELETING,
|
||||
DELETE_FAILED,
|
||||
DELETE_SUCCESS,
|
||||
DELETE_PROMPT,
|
||||
|
||||
// Dumps command
|
||||
|
@ -62,28 +60,21 @@ public enum MVCorei18n implements MessageKeyProvider {
|
|||
|
||||
// import command
|
||||
IMPORT_IMPORTING,
|
||||
IMPORT_FAILED,
|
||||
IMPORT_SUCCESS,
|
||||
|
||||
// load command
|
||||
LOAD_LOADING,
|
||||
LOAD_FAILED,
|
||||
LOAD_SUCCESS,
|
||||
|
||||
// regen command
|
||||
REGEN_REGENERATING,
|
||||
REGEN_FAILED,
|
||||
REGEN_SUCCESS,
|
||||
REGEN_PROMPT,
|
||||
REGEN_SUCCESS,
|
||||
|
||||
// reload command
|
||||
RELOAD_RELOADING,
|
||||
RELOAD_SUCCESS,
|
||||
|
||||
// remove command
|
||||
REMOVE_FAILED,
|
||||
REMOVE_SUCCESS,
|
||||
|
||||
// root MV command
|
||||
ROOT_TITLE,
|
||||
ROOT_HELP,
|
||||
|
@ -93,7 +84,6 @@ public enum MVCorei18n implements MessageKeyProvider {
|
|||
|
||||
// unload command
|
||||
UNLOAD_UNLOADING,
|
||||
UNLOAD_FAILURE,
|
||||
UNLOAD_SUCCESS,
|
||||
|
||||
// debug command
|
||||
|
@ -111,11 +101,50 @@ public enum MVCorei18n implements MessageKeyProvider {
|
|||
ENTRYCHECK_EXCEEDPLAYERLIMIT,
|
||||
ENTRYCHECK_NOWORLDACCESS,
|
||||
|
||||
// world manager result
|
||||
CLONEWORLD_INVALIDWORLDNAME,
|
||||
CLONEWORLD_WORLDEXISTFOLDER,
|
||||
CLONEWORLD_WORLDEXISTUNLOADED,
|
||||
CLONEWORLD_WORLDEXISTLOADED,
|
||||
CLONEWORLD_COPYFAILED,
|
||||
|
||||
CREATEWORLD_INVALIDWORLDNAME,
|
||||
CREATEWORLD_WORLDEXISTFOLDER,
|
||||
CREATEWORLD_WORLDEXISTUNLOADED,
|
||||
CREATEWORLD_WORLDEXISTLOADED,
|
||||
CREATEWORLD_BUKKITCREATIONFAILED,
|
||||
|
||||
DELETE_SUCCESS,
|
||||
DELETEWORLD_WORLDNONEXISTENT,
|
||||
DELETEWORLD_LOADFAILED,
|
||||
DELETEWORLD_WORLDFOLDERNOTFOUND,
|
||||
DELETEWORLD_FAILEDTODELETEFOLDER,
|
||||
|
||||
IMPORTWORLD_INVALIDWORLDNAME,
|
||||
IMPORTWORLD_WORLDFOLDERINVALID,
|
||||
IMPORTWORLD_WORLDEXISTUNLOADED,
|
||||
IMPORTWORLD_WORLDEXISTLOADED,
|
||||
IMPORTWORLD_BUKKITCREATIONFAILED,
|
||||
|
||||
LOADWORLD_WORLDALREADYLOADING,
|
||||
LOADWORLD_WORLDNONEXISTENT,
|
||||
LOADWORLD_WORLDEXISTFOLDER,
|
||||
LOADWORLD_WORLDEXISTLOADED,
|
||||
LOADWORLD_BUKKITCREATIONFAILED,
|
||||
|
||||
REMOVEWORLD_REMOVED,
|
||||
REMOVEWORLD_WORLDNONEXISTENT,
|
||||
|
||||
UNLOADWORLD_WORLDALREADYUNLOADING,
|
||||
UNLOADWORLD_WORLDNONEXISTENT,
|
||||
UNLOADWORLD_WORLDUNLOADED,
|
||||
UNLOADWORLD_BUKKITUNLOADFAILED,
|
||||
|
||||
// generic
|
||||
GENERIC_SUCCESS,
|
||||
GENERIC_FAILURE
|
||||
GENERIC_FAILURE;
|
||||
|
||||
;
|
||||
// END CHECKSTYLE-SUPPRESSION: Javadoc
|
||||
|
||||
private final MessageKey key = MessageKey.of("mv-core." + this.name().replace('_', '.').toLowerCase());
|
||||
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package com.onarandombox.MultiverseCore.utils.metrics;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.inject.Inject;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
|
@ -15,29 +11,24 @@ import org.bstats.bukkit.Metrics;
|
|||
import org.bukkit.World;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Service
|
||||
public class MetricsConfigurator {
|
||||
|
||||
private static final int PLUGIN_ID = 7765;
|
||||
private static final String NO_GENERATOR_NAME = "N/A";
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
private final Metrics metrics;
|
||||
|
||||
@Inject
|
||||
private MetricsConfigurator(MultiverseCore plugin, MVWorldManager worldManager) {
|
||||
private MetricsConfigurator(MultiverseCore plugin, WorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
this.metrics = new Metrics(plugin, PLUGIN_ID);
|
||||
}
|
||||
|
||||
private MVWorldManager getWorldManager() {
|
||||
return worldManager;
|
||||
}
|
||||
|
||||
private Collection<MVWorld> getMVWorlds() {
|
||||
return getWorldManager().getMVWorlds();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void initMetrics() {
|
||||
try {
|
||||
|
@ -54,20 +45,20 @@ public class MetricsConfigurator {
|
|||
|
||||
private void addCustomGeneratorsMetric() {
|
||||
addAdvancedPieMetric("custom_generators", map -> {
|
||||
for (MVWorld w : getMVWorlds()) {
|
||||
for (LoadedMultiverseWorld w : worldManager.getLoadedWorlds()) {
|
||||
MetricsHelper.incrementCount(map, getGeneratorName(w));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getGeneratorName(MVWorld world) {
|
||||
private String getGeneratorName(LoadedMultiverseWorld world) {
|
||||
String gen = world.getGenerator();
|
||||
return (gen != null && !gen.equalsIgnoreCase("null")) ? gen.split(":")[0] : NO_GENERATOR_NAME;
|
||||
}
|
||||
|
||||
private void addEnvironmentsMetric() {
|
||||
addAdvancedPieMetric("environments", map -> {
|
||||
for (MVWorld w : getMVWorlds()) {
|
||||
for (LoadedMultiverseWorld w : worldManager.getLoadedWorlds()) {
|
||||
MetricsHelper.incrementCount(map, titleCaseEnv(w.getEnvironment()));
|
||||
}
|
||||
});
|
||||
|
@ -80,9 +71,8 @@ public class MetricsConfigurator {
|
|||
|
||||
private void addWorldCountMetric() {
|
||||
addMultiLineMetric("world_count", map -> {
|
||||
int loadedWorldsCount = getMVWorlds().size();
|
||||
map.put("Loaded worlds", loadedWorldsCount);
|
||||
map.put("Total number of worlds", loadedWorldsCount + getWorldManager().getUnloadedWorlds().size());
|
||||
map.put("Loaded worlds", worldManager.getLoadedWorlds().size());
|
||||
map.put("Total number of worlds", worldManager.getWorlds().size());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,338 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
* Represents an attempt to process a value that can fail with a reason that has a localized message.
|
||||
*
|
||||
* @param <T> The type of the value.
|
||||
* @param <F> The type of failure reason.
|
||||
*/
|
||||
public sealed interface Attempt<T, F extends FailureReason> permits Attempt.Success, Attempt.Failure {
|
||||
|
||||
/**
|
||||
* Creates a new success attempt.
|
||||
*
|
||||
* @param value The value.
|
||||
* @param <T> The type of the value.
|
||||
* @param <F> The type of failure reason.
|
||||
* @return The new success attempt.
|
||||
*/
|
||||
static <T, F extends FailureReason> Attempt<T, F> 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 <T> The type of the value.
|
||||
* @param <F> The type of failure reason.
|
||||
* @return The new failure attempt.
|
||||
*/
|
||||
static <T, F extends FailureReason> Attempt<T, F> 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 <T> The type of the value.
|
||||
* @param <F> The type of failure reason.
|
||||
* @return The new failure attempt.
|
||||
*/
|
||||
static <T, F extends FailureReason> Attempt<T, F> 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<T, F> peek(Consumer<T> consumer) {
|
||||
if (this instanceof Success) {
|
||||
consumer.accept(get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the value to another value if this is a success attempt.
|
||||
*
|
||||
* @param mapper The mapper.
|
||||
* @param <U> The type of the new value.
|
||||
* @return The new attempt.
|
||||
*/
|
||||
default <U> Attempt<U, F> map(Function<? super T, ? extends U> mapper) {
|
||||
if (this instanceof Success) {
|
||||
return new Success<>(mapper.apply(get()));
|
||||
} else {
|
||||
return new Failure<>(getFailureReason(), getFailureMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the value to another attempt if this is a success attempt.
|
||||
*
|
||||
* @param mapper The mapper.
|
||||
* @param <U> The type of the new value.
|
||||
* @return The new attempt.
|
||||
*/
|
||||
default <U> Attempt<U, F> map(Supplier<? extends U> mapper) {
|
||||
if (this instanceof Success) {
|
||||
return new Success<>(mapper.get());
|
||||
} else {
|
||||
return new Failure<>(getFailureReason(), getFailureMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the value to another attempt with the same fail reason if this is a success attempt.
|
||||
*
|
||||
* @param mapper The mapper.
|
||||
* @param <U> The type of the new value.
|
||||
* @return The new attempt.
|
||||
*/
|
||||
default <U> Attempt<U, F> mapAttempt(Function<? super T, Attempt<U, F>> mapper) {
|
||||
if (this instanceof Success) {
|
||||
return mapper.apply(get());
|
||||
} else {
|
||||
return new Failure<>(getFailureReason(), getFailureMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the value to another attempt with the same fail reason if this is a success attempt.
|
||||
*
|
||||
* @param mapper The mapper.
|
||||
* @param <U> The type of the new value.
|
||||
* @return The new attempt.
|
||||
*/
|
||||
default <U> Attempt<U, F> mapAttempt(Supplier<Attempt<U, F>> mapper) {
|
||||
if (this instanceof Success) {
|
||||
return mapper.get();
|
||||
} else {
|
||||
return new Failure<>(getFailureReason(), getFailureMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps to another attempt with a different fail reason.
|
||||
*
|
||||
* @param failureReason The new fail reason.
|
||||
* @param <UF> The type of the new fail reason.
|
||||
* @return The new attempt.
|
||||
*/
|
||||
default <UF extends FailureReason> Attempt<T, UF> transform(UF failureReason) {
|
||||
if (this instanceof Success) {
|
||||
return new Success<>(get());
|
||||
} else {
|
||||
return new Failure<>(failureReason, getFailureMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls either the failure or success function depending on the result type.
|
||||
*
|
||||
* @param failureMapper The failure function.
|
||||
* @param successMapper The success function.
|
||||
* @param <N> The type of the new value.
|
||||
* @return The result of the function.
|
||||
*/
|
||||
default <N> N fold(Function<Failure<T, F>, N> failureMapper, Function<T, N> successMapper) {
|
||||
if (this instanceof Success) {
|
||||
return successMapper.apply(get());
|
||||
} else {
|
||||
return failureMapper.apply((Failure<T, F>) this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given runnable if this is a success attempt.
|
||||
*
|
||||
* @param runnable The runnable.
|
||||
* @return This attempt.
|
||||
*/
|
||||
default Attempt<T, F> onSuccess(Runnable runnable) {
|
||||
if (this instanceof Success) {
|
||||
runnable.run();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given consumer if this is a success attempt.
|
||||
*
|
||||
* @param consumer The consumer with the value.
|
||||
* @return This attempt.
|
||||
*/
|
||||
default Attempt<T, F> onSuccess(Consumer<T> consumer) {
|
||||
if (this instanceof Success) {
|
||||
consumer.accept(get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given consumer if this is a failure attempt.
|
||||
*
|
||||
* @param runnable The runnable.
|
||||
* @return This attempt.
|
||||
*/
|
||||
default Attempt<T, F> onFailure(Runnable runnable) {
|
||||
if (this instanceof Failure) {
|
||||
runnable.run();
|
||||
}
|
||||
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<T, F> onFailure(Consumer<Failure<T, F>> consumer) {
|
||||
if (this instanceof Failure) {
|
||||
consumer.accept((Failure<T, F>) this);
|
||||
}
|
||||
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<T, F> onFailureReason(Consumer<F> consumer) {
|
||||
if (this instanceof Failure) {
|
||||
consumer.accept(getFailureReason());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a successful attempt with a value.
|
||||
*
|
||||
* @param <T> The type of the value.
|
||||
* @param <F> The type of failure reason.
|
||||
*/
|
||||
final class Success<T, F extends FailureReason> implements Attempt<T, F> {
|
||||
private final T value;
|
||||
|
||||
Success(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public F getFailureReason() {
|
||||
throw new UnsupportedOperationException("No failure reason as attempt is a success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getFailureMessage() {
|
||||
throw new UnsupportedOperationException("No failure message as attempt is a success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Success{"
|
||||
+ "value=" + value
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a failed attempt with a reason.
|
||||
*
|
||||
* @param <T> The type of the value.
|
||||
* @param <F> The type of failure reason.
|
||||
*/
|
||||
final class Failure<T, F extends FailureReason> implements Attempt<T, F> {
|
||||
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 UnsupportedOperationException("No value as attempt is a failure");
|
||||
}
|
||||
|
||||
@Override
|
||||
public F getFailureReason() {
|
||||
return failureReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getFailureMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Failure{"
|
||||
+ "reason=" + failureReason
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,40 +6,139 @@ import org.jetbrains.annotations.NotNull;
|
|||
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public sealed interface Result<S extends SuccessReason, F extends FailureReason> permits Result.Success, Result.Failure {
|
||||
static <F extends FailureReason, S extends SuccessReason> Result<S, F> success(S successReason, MessageReplacement...replacements) {
|
||||
/**
|
||||
* Represents result of an operation with a reason for success or failure that has localized messages.
|
||||
*
|
||||
* @param <S> The type of success reason.
|
||||
* @param <F> The type of failure reason.
|
||||
*/
|
||||
public sealed interface Result<S extends SuccessReason, F extends FailureReason>
|
||||
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 <F> The type of failure reason.
|
||||
* @param <S> The type of success reason.
|
||||
* @return The new success result.
|
||||
*/
|
||||
static <F extends FailureReason, S extends SuccessReason> Result<S, F> success(
|
||||
S successReason, MessageReplacement... replacements) {
|
||||
return new Success<>(successReason, replacements);
|
||||
}
|
||||
|
||||
static <F extends FailureReason, S extends SuccessReason> Result<S, F> failure(F failureReason, MessageReplacement...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 <F> The type of failure reason.
|
||||
* @param <S> The type of success reason.
|
||||
* @return The new success result.
|
||||
*/
|
||||
static <F extends FailureReason, S extends SuccessReason> Result<S, F> 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 <F> The type of failure reason.
|
||||
* @param <S> The type of success reason.
|
||||
* @return The new failure result.
|
||||
*/
|
||||
static <F extends FailureReason, S extends SuccessReason> Result<S, F> failure(
|
||||
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 <F> The type of failure reason.
|
||||
* @param <S> The type of success reason.
|
||||
* @return The new failure result.
|
||||
*/
|
||||
static <F extends FailureReason, S extends SuccessReason> Result<S, F> 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<S, F> onSuccess(Consumer<S> consumer) {
|
||||
if (this.isSuccess()) {
|
||||
consumer.accept(this.getSuccessReason());
|
||||
/**
|
||||
* Executes the given consumer if this result is a success.
|
||||
*
|
||||
* @param consumer The consumer with success object.
|
||||
* @return This result.
|
||||
*/
|
||||
default Result<S, F> onSuccess(Consumer<Success<S, F>> consumer) {
|
||||
if (this instanceof Success) {
|
||||
consumer.accept((Success<S, F>) this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
default Result<S, F> onFailure(Consumer<F> consumer) {
|
||||
if (this.isFailure()) {
|
||||
consumer.accept(this.getFailureReason());
|
||||
/**
|
||||
* Executes the given consumer if this result is a failure.
|
||||
*
|
||||
* @param consumer The consumer with failure object.
|
||||
* @return This result.
|
||||
*/
|
||||
default Result<S, F> onFailure(Consumer<Failure<S, F>> consumer) {
|
||||
if (this instanceof Failure) {
|
||||
consumer.accept((Failure<S, F>) this);
|
||||
}
|
||||
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<S, F> onSuccessReason(S successReason, Consumer<S> consumer) {
|
||||
if (this.isSuccess() && this.getSuccessReason() == successReason) {
|
||||
consumer.accept(this.getSuccessReason());
|
||||
|
@ -47,6 +146,13 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
|
|||
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<S, F> onFailureReason(F failureReason, Consumer<F> consumer) {
|
||||
if (this.isFailure() && this.getFailureReason() == failureReason) {
|
||||
consumer.accept(this.getFailureReason());
|
||||
|
@ -54,13 +160,67 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
|
|||
return this;
|
||||
}
|
||||
|
||||
final class Success<F extends FailureReason, S extends SuccessReason> implements Result<S, F> {
|
||||
private final S successReason;
|
||||
private final MessageReplacement[] replacements;
|
||||
/**
|
||||
* 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<S, F> onSuccessThen(Function<Success<S, F>, Result<S, F>> function) {
|
||||
if (this instanceof Success) {
|
||||
return function.apply((Success<S, F>) this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Success(S successReason, MessageReplacement[] replacements) {
|
||||
/**
|
||||
* 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<S, F> onFailureThen(Function<Failure<S, F>, Result<S, F>> function) {
|
||||
if (this instanceof Failure) {
|
||||
return function.apply((Failure<S, F>) this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <R> The type of the result.
|
||||
* @return The result of the function.
|
||||
*/
|
||||
default <R> R fold(Function<Failure<S, F>, R> failureFunc, Function<Success<S, F>, R> successFunc) {
|
||||
if (this instanceof Failure) {
|
||||
return failureFunc.apply((Failure<S, F>) this);
|
||||
} else if (this instanceof Success) {
|
||||
return successFunc.apply((Success<S, F>) this);
|
||||
}
|
||||
throw new IllegalStateException("Unknown result type: " + this.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* The class for a successful result.
|
||||
*
|
||||
* @param <F> The type of failure reason.
|
||||
* @param <S> The type of success reason.
|
||||
*/
|
||||
final class Success<S extends SuccessReason, F extends FailureReason> implements Result<S, F> {
|
||||
private final S successReason;
|
||||
private final Message message;
|
||||
|
||||
Success(S successReason, Message message) {
|
||||
this.successReason = successReason;
|
||||
this.replacements = replacements;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
Success(S successReason, MessageReplacement[] replacements) {
|
||||
this.successReason = successReason;
|
||||
this.message = Message.of(successReason, "Success!", replacements);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,29 +240,40 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
|
|||
|
||||
@Override
|
||||
public F getFailureReason() {
|
||||
throw new NoSuchElementException("No reason for failure");
|
||||
throw new UnsupportedOperationException("No reason for success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Message getReasonMessage() {
|
||||
return Message.of(successReason, "Success!", replacements);
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Success{" +
|
||||
"reason=" + successReason +
|
||||
'}';
|
||||
return "Success{"
|
||||
+ "reason=" + successReason
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class for a failed result.
|
||||
*
|
||||
* @param <S> The type of success reason.
|
||||
* @param <F> The type of failure reason.
|
||||
*/
|
||||
final class Failure<S extends SuccessReason, F extends FailureReason> implements Result<S, F> {
|
||||
private final F failureReason;
|
||||
private final MessageReplacement[] replacements;
|
||||
private final Message message;
|
||||
|
||||
public Failure(F failureReason, MessageReplacement[] replacements) {
|
||||
Failure(F failureReason, Message message) {
|
||||
this.failureReason = failureReason;
|
||||
this.replacements = replacements;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
Failure(F failureReason, MessageReplacement[] replacements) {
|
||||
this.failureReason = failureReason;
|
||||
this.message = Message.of(failureReason, "Failed!", replacements);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,7 +288,7 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
|
|||
|
||||
@Override
|
||||
public S getSuccessReason() {
|
||||
throw new NoSuchElementException("No reason for success");
|
||||
throw new UnsupportedOperationException("No reason for failure");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,14 +298,14 @@ public sealed interface Result<S extends SuccessReason, F extends FailureReason>
|
|||
|
||||
@Override
|
||||
public @NotNull Message getReasonMessage() {
|
||||
return Message.of(failureReason, "Success!", replacements);
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Failure{" +
|
||||
"reason=" + failureReason +
|
||||
'}';
|
||||
return "Failure{"
|
||||
+ "reason=" + failureReason
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.utils.result;
|
|
@ -24,7 +24,7 @@ import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
|
|||
import com.onarandombox.MultiverseCore.listeners.MVPlayerListener;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.EnglishChatColor;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.SpawnLocation;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.SpawnLocation;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.SpawnSettings;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.WorldPropertyValidator;
|
||||
import me.main__.util.SerializationConfig.ChangeDeniedException;
|
||||
|
@ -342,7 +342,7 @@ public class SimpleMVWorld implements MVWorld {
|
|||
for (Player p : server.getWorld(getName()).getPlayers()) {
|
||||
Logging.finer(String.format("Setting %s's GameMode to %s",
|
||||
p.getName(), newValue.toString()));
|
||||
playerListener.handleGameModeAndFlight(p, SimpleMVWorld.this);
|
||||
//playerListener.handleGameModeAndFlight(p, SimpleMVWorld.this);
|
||||
}
|
||||
return super.validateChange(property, newValue, oldValue, object);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import com.onarandombox.MultiverseCore.world.configuration.EntryFee;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.SpawnLocation;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.SpawnLocation;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.SpawnSettings;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.WorldPropertyValidator;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.api.BlockSafety;
|
||||
import com.onarandombox.MultiverseCore.api.LocationManipulation;
|
||||
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.NullLocation;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.SpawnLocation;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig;
|
||||
import io.vavr.control.Option;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Extension of {@link MultiverseWorld} that represents a world that is currently loaded with bukkit world object.
|
||||
*/
|
||||
public class LoadedMultiverseWorld extends MultiverseWorld {
|
||||
private static final int SPAWN_LOCATION_SEARCH_TOLERANCE = 16;
|
||||
private static final int SPAWN_LOCATION_SEARCH_RADIUS = 16;
|
||||
|
||||
private final UUID worldUid;
|
||||
|
||||
private final BlockSafety blockSafety;
|
||||
private final SafeTTeleporter safetyTeleporter;
|
||||
private final LocationManipulation locationManipulation;
|
||||
|
||||
LoadedMultiverseWorld(
|
||||
@NotNull World world,
|
||||
@NotNull WorldConfig worldConfig,
|
||||
@NotNull BlockSafety blockSafety,
|
||||
@NotNull SafeTTeleporter safetyTeleporter,
|
||||
@NotNull LocationManipulation locationManipulation) {
|
||||
super(world.getName(), worldConfig);
|
||||
this.worldUid = world.getUID();
|
||||
this.blockSafety = blockSafety;
|
||||
this.safetyTeleporter = safetyTeleporter;
|
||||
this.locationManipulation = locationManipulation;
|
||||
|
||||
setupWorldConfig(world);
|
||||
setupSpawnLocation(world);
|
||||
}
|
||||
|
||||
private void setupWorldConfig(World world) {
|
||||
worldConfig.setMVWorld(this);
|
||||
worldConfig.load();
|
||||
worldConfig.setEnvironment(world.getEnvironment());
|
||||
worldConfig.setSeed(world.getSeed());
|
||||
}
|
||||
|
||||
private void setupSpawnLocation(World world) {
|
||||
Location spawnLocation = worldConfig.getSpawnLocation();
|
||||
if (spawnLocation == null || spawnLocation instanceof NullLocation) {
|
||||
SpawnLocation newLocation = new SpawnLocation(readSpawnFromWorld(world));
|
||||
worldConfig.setSpawnLocation(newLocation);
|
||||
}
|
||||
}
|
||||
|
||||
private Location readSpawnFromWorld(World world) {
|
||||
Location location = world.getSpawnLocation();
|
||||
|
||||
// Verify that location was safe
|
||||
if (blockSafety.playerCanSpawnHereSafely(location)) {
|
||||
return location;
|
||||
}
|
||||
|
||||
if (!this.getAdjustSpawn()) {
|
||||
Logging.fine("Spawn location from world.dat file was unsafe!!");
|
||||
Logging.fine("NOT adjusting spawn for '" + this.getAlias() + "' because you told me not to.");
|
||||
Logging.fine("To turn on spawn adjustment for this world simply type:");
|
||||
Logging.fine("/mvm set adjustspawn true " + this.getAlias());
|
||||
return location;
|
||||
}
|
||||
|
||||
// The location is not safe, so we need to find a better one.
|
||||
Logging.warning("Spawn location from world.dat file was unsafe. Adjusting...");
|
||||
Logging.warning("Original Location: " + locationManipulation.strCoordsRaw(location));
|
||||
Location newSpawn = safetyTeleporter.getSafeLocation(location,
|
||||
SPAWN_LOCATION_SEARCH_TOLERANCE, SPAWN_LOCATION_SEARCH_RADIUS);
|
||||
// I think we could also do this, as I think this is what Notch does.
|
||||
// Not sure how it will work in the nether...
|
||||
//Location newSpawn = this.spawnLocation.getWorld().getHighestBlockAt(this.spawnLocation).getLocation();
|
||||
if (newSpawn != null) {
|
||||
Logging.info("New Spawn for '%s' is located at: %s",
|
||||
this.getName(), locationManipulation.locationToString(newSpawn));
|
||||
return newSpawn;
|
||||
}
|
||||
|
||||
// If it's a standard end world, let's check in a better place:
|
||||
Logging.fine("Checking for a safe location using top block...");
|
||||
Location newerSpawn;
|
||||
newerSpawn = blockSafety.getTopBlock(new Location(world, 0, 0, 0));
|
||||
if (newerSpawn != null) {
|
||||
Logging.info("New Spawn for '%s' is located at: %s",
|
||||
this.getName(), locationManipulation.locationToString(newerSpawn));
|
||||
return newerSpawn;
|
||||
}
|
||||
|
||||
Logging.severe("Safe spawn NOT found!!!");
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Bukkit world object that this world describes.
|
||||
*
|
||||
* @return Bukkit world object.
|
||||
*/
|
||||
public Option<World> getBukkitWorld() {
|
||||
return Option.of(Bukkit.getWorld(worldUid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of this world.
|
||||
*
|
||||
* @return Type of this world.
|
||||
*/
|
||||
public Option<WorldType> getWorldType() {
|
||||
//noinspection deprecation
|
||||
return getBukkitWorld().map(World::getWorldType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not structures are being generated.
|
||||
*
|
||||
* @return True if structures are being generated.
|
||||
*/
|
||||
public Option<Boolean> canGenerateStructures() {
|
||||
return getBukkitWorld().map(World::canGenerateStructures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all players in this World.
|
||||
*
|
||||
* @return A list of all Players currently residing in this world
|
||||
*/
|
||||
public Option<List<Player>> getPlayers() {
|
||||
return getBukkitWorld().map(World::getPlayers);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
void setWorldConfig(WorldConfig worldConfig) {
|
||||
super.setWorldConfig(worldConfig);
|
||||
setupWorldConfig(getBukkitWorld().get());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoadedMultiverseWorld{"
|
||||
+ "name='" + worldName + "', "
|
||||
+ "env='" + getEnvironment() + "', "
|
||||
+ "type='" + getWorldType().getOrNull() + "', "
|
||||
+ "gen='" + getGenerator() + "'"
|
||||
+ '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,672 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a world handled by Multiverse which has all the custom properties provided by Multiverse.
|
||||
*/
|
||||
public class MultiverseWorld {
|
||||
|
||||
protected final String worldName;
|
||||
protected WorldConfig worldConfig;
|
||||
|
||||
MultiverseWorld(String worldName, WorldConfig worldConfig) {
|
||||
this.worldName = worldName;
|
||||
this.worldConfig = worldConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this world. The name cannot be changed.
|
||||
* <br/>
|
||||
* Note for plugin developers: Usually {@link #getAlias()}
|
||||
* is what you want to use instead of this method.
|
||||
*
|
||||
* @return The name of the world as a String.
|
||||
*/
|
||||
public String getName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this world is loaded.
|
||||
*
|
||||
* @return True if the world is loaded, else false.
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return worldConfig.hasMVWorld();
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames() {
|
||||
return worldConfig.getConfigurablePropertyNames();
|
||||
}
|
||||
|
||||
public Try<Object> getProperty(String name) {
|
||||
return worldConfig.getProperty(name);
|
||||
}
|
||||
|
||||
public Try<Void> setProperty(String name, Object value) {
|
||||
return worldConfig.setProperty(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not Multiverse should auto-adjust the spawn for this world.
|
||||
*
|
||||
* @return True if Multiverse should adjust the spawn, false if not.
|
||||
*/
|
||||
public boolean getAdjustSpawn() {
|
||||
return worldConfig.getAdjustSpawn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not Multiverse should auto-adjust the spawn for this world.
|
||||
*
|
||||
* @param adjustSpawn True if multiverse should adjust the spawn, false if not.
|
||||
*/
|
||||
public Try<Void> setAdjustSpawn(boolean adjustSpawn) {
|
||||
return worldConfig.setAdjustSpawn(adjustSpawn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the alias of this world.
|
||||
* <br/>
|
||||
* This alias allows users to have a world named "world" but show up in the list as "FernIsland"
|
||||
*
|
||||
* @return The alias of the world as a String.
|
||||
*/
|
||||
public String getAlias() {
|
||||
return Strings.isNullOrEmpty(worldConfig.getAlias()) ? worldName : worldConfig.getAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the alias of the world.
|
||||
*
|
||||
* @param alias A string that is the new alias.
|
||||
*/
|
||||
public Try<Void> setAlias(String alias) {
|
||||
return worldConfig.setAlias(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not players are allowed to fly in this world.
|
||||
*
|
||||
* @return True if players allowed to fly in this world.
|
||||
*/
|
||||
public boolean getAllowFlight() {
|
||||
return worldConfig.getAllowFlight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not players are allowed to fly in this world.
|
||||
*
|
||||
* @param allowFlight True to allow flight in this world.
|
||||
*/
|
||||
public Try<Void> setAllowFlight(boolean allowFlight) {
|
||||
return worldConfig.setAllowFlight(allowFlight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether weather is enabled in this world.
|
||||
*
|
||||
* @return True if weather events will occur, false if not.
|
||||
*/
|
||||
public boolean getAllowWeather() {
|
||||
return worldConfig.getAllowWeather();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not there will be weather events in a given world.
|
||||
* If set to false, Multiverse will disable the weather in the world immediately.
|
||||
*
|
||||
* @param allowWeather True if weather events should occur in a world, false if not.
|
||||
*/
|
||||
public Try<Void> setAllowWeather(boolean allowWeather) {
|
||||
return worldConfig.setAllowWeather(allowWeather);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not a world will auto-heal players if the difficulty is on peaceful.
|
||||
*
|
||||
* @return True if the world should heal (default), false if not.
|
||||
*/
|
||||
public boolean getAutoHeal() {
|
||||
return worldConfig.getAutoHeal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not a world will auto-heal players if the difficulty is on peaceful.
|
||||
*
|
||||
* @param autoHeal True if the world will heal.
|
||||
*/
|
||||
public Try<Void> setAutoHeal(boolean autoHeal) {
|
||||
return worldConfig.setAutoHeal(autoHeal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not Multiverse should auto-load this world.
|
||||
*
|
||||
* @return True if Multiverse should auto-load this world.
|
||||
*/
|
||||
public boolean getAutoLoad() {
|
||||
return worldConfig.getAutoLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not Multiverse should auto-load this world.
|
||||
* <br/>
|
||||
* True is default.
|
||||
*
|
||||
* @param autoLoad True if multiverse should autoload this world the spawn, false if not.
|
||||
*/
|
||||
public Try<Void> setAutoLoad(boolean autoLoad) {
|
||||
return worldConfig.setAutoLoad(autoLoad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not a player who dies in this world will respawn in their
|
||||
* bed or follow the normal respawn pattern.
|
||||
*
|
||||
* @return True if players dying in this world should respawn at their bed.
|
||||
*/
|
||||
public boolean getBedRespawn() {
|
||||
return worldConfig.getBedRespawn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not a player who dies in this world will respawn in their
|
||||
* bed or follow the normal respawn pattern.
|
||||
* <br/>
|
||||
* True is default.
|
||||
*
|
||||
* @param bedRespawn True if players dying in this world respawn at their bed.
|
||||
*/
|
||||
public Try<Void> setBedRespawn(boolean bedRespawn) {
|
||||
return worldConfig.setBedRespawn(bedRespawn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of currency that will be used when users enter this world. A value of null indicates a non-item
|
||||
* based currency is used.
|
||||
*
|
||||
* @return The type of currency that will be used when users enter this world.
|
||||
*/
|
||||
public Material getCurrency() {
|
||||
return worldConfig.getEntryFeeCurrency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of item that will be required given the price is not 0.
|
||||
* Use a value of null to specify a non-item based currency.
|
||||
*
|
||||
* @param currency The Type of currency that will be used when users enter this world.
|
||||
*/
|
||||
public Try<Void> setCurrency(Material currency) {
|
||||
return worldConfig.setEntryFeeCurrency(currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the difficulty of this world.
|
||||
*
|
||||
* @return The difficulty of this world.
|
||||
*/
|
||||
public Difficulty getDifficulty() {
|
||||
return worldConfig.getDifficulty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the difficulty of this world and returns {@code true} on success.
|
||||
* Valid string values are either an integer of difficulty(0-3) or
|
||||
* the name that resides in the Bukkit enum, ex. PEACEFUL
|
||||
*
|
||||
* @param difficulty The new difficulty.
|
||||
*/
|
||||
public Try<Void> setDifficulty(Difficulty difficulty) {
|
||||
return worldConfig.setDifficulty(difficulty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the environment of this world. You cannot change this after world creation.
|
||||
*
|
||||
* @return A {@link World.Environment}.
|
||||
*/
|
||||
public World.Environment getEnvironment() {
|
||||
return worldConfig.getEnvironment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GameMode of this world.
|
||||
*
|
||||
* @return The GameMode of this world.
|
||||
*/
|
||||
public GameMode getGameMode() {
|
||||
return worldConfig.getGameMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the game mode of this world.
|
||||
*
|
||||
* @param gameMode The new {@link GameMode}.
|
||||
*/
|
||||
public Try<Void> setGameMode(GameMode gameMode) {
|
||||
return worldConfig.setGameMode(gameMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the generator string of this world. You cannot change this after world creation.
|
||||
*
|
||||
* @return The name of the generator.
|
||||
*/
|
||||
public String getGenerator() {
|
||||
return worldConfig.getGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not this world will display in chat, mvw and mvl regardless if a user has the
|
||||
* access permissions to go to this world.
|
||||
*
|
||||
* @return True if the world will be hidden, false if not.
|
||||
*/
|
||||
public boolean isHidden() {
|
||||
return worldConfig.isHidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not this world will display in chat, mvw and mvl regardless if a user has the
|
||||
* access permissions to go to this world.
|
||||
*
|
||||
* @param hidden True if the world should be hidden, false if not.
|
||||
*/
|
||||
public Try<Void> setHidden(boolean hidden) {
|
||||
return worldConfig.setHidden(hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not the hunger level of players will go down in a world.
|
||||
*
|
||||
* @return True if it will go down, false if it will remain steady.
|
||||
*/
|
||||
public boolean getHunger() {
|
||||
return worldConfig.getHunger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the hunger level of players will go down in a world.
|
||||
*
|
||||
* @param hunger True if hunger will go down, false to keep it at the level they entered a world with.
|
||||
*/
|
||||
public Try<Void> setHunger(boolean hunger) {
|
||||
return worldConfig.setHunger(hunger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not CraftBukkit is keeping the chunks for this world in memory.
|
||||
*
|
||||
* @return True if CraftBukkit is keeping spawn chunks in memory.
|
||||
*/
|
||||
public boolean getKeepSpawnInMemory() {
|
||||
return worldConfig.getKeepSpawnInMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, tells Craftbukkit to keep a worlds spawn chunks loaded in memory (default: true)
|
||||
* If not, CraftBukkit will attempt to free memory when players have not used that world.
|
||||
* This will not happen immediately.
|
||||
*
|
||||
* @param keepSpawnInMemory If true, CraftBukkit will keep the spawn chunks loaded in memory.
|
||||
*/
|
||||
public Try<Void> setKeepSpawnInMemory(boolean keepSpawnInMemory) {
|
||||
return worldConfig.setKeepSpawnInMemory(keepSpawnInMemory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player limit for this world after which players without an override
|
||||
* permission node will not be allowed in. A value of -1 or less signifies no limit
|
||||
*
|
||||
* @return The player limit
|
||||
*/
|
||||
public int getPlayerLimit() {
|
||||
return worldConfig.getPlayerLimit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player limit for this world after which players without an override
|
||||
* permission node will not be allowed in. A value of -1 or less signifies no limit
|
||||
*
|
||||
* @param playerLimit The new limit
|
||||
*/
|
||||
public Try<Void> setPlayerLimit(int playerLimit) {
|
||||
return worldConfig.setPlayerLimit(playerLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets which type(s) of portals are allowed to be constructed in this world.
|
||||
*
|
||||
* @return The type of portals that are allowed.
|
||||
*/
|
||||
public AllowedPortalType getPortalForm() {
|
||||
return worldConfig.getPortalForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets The types of portals that are allowed in this world.
|
||||
*
|
||||
* @param portalForm The type of portals allowed in this world.
|
||||
*/
|
||||
public Try<Void> setPortalForm(AllowedPortalType portalForm) {
|
||||
return worldConfig.setPortalForm(portalForm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of currency it requires to enter this world.
|
||||
*
|
||||
* @return The amount it costs to enter this world.
|
||||
*/
|
||||
public double getPrice() {
|
||||
return worldConfig.getEntryFeeAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the price for entry to this world.
|
||||
* You can think of this like an amount.
|
||||
* The type can be set with {@link #setCurrency(Material)}
|
||||
*
|
||||
* @param price The Amount of money/item to enter the world.
|
||||
*/
|
||||
public Try<Void> setPrice(double price) {
|
||||
return worldConfig.setEntryFeeAmount(price);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not PVP is enabled in this world in some form (fake or not).
|
||||
*
|
||||
* @return True if players can take damage from other players.
|
||||
*/
|
||||
public boolean getPvp() {
|
||||
return worldConfig.getPvp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn pvp on or off. This setting is used to set the world's PVP mode.
|
||||
*
|
||||
* @param pvp True to enable PVP damage, false to disable it.
|
||||
*/
|
||||
public Try<Void> setPvp(boolean pvp) {
|
||||
return worldConfig.setPvp(pvp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world name players will respawn in if they die in this one.
|
||||
*
|
||||
* @return A world name that exists on the server.
|
||||
*/
|
||||
public String getRespawnWorldName() {
|
||||
return worldConfig.getRespawnWorld();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world players will respawn in if they die in this one.
|
||||
*
|
||||
* @return A world that exists on the server.
|
||||
*/
|
||||
public @Nullable World getRespawnWorld() {
|
||||
return Bukkit.getWorld(worldConfig.getRespawnWorld());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world players will respawn in if they die in this one.
|
||||
* Returns true upon success, false upon failure.
|
||||
*
|
||||
* @param respawnWorld The name of a world that exists on the server.
|
||||
*/
|
||||
public Try<Void> setRespawnWorld(World respawnWorld) {
|
||||
return worldConfig.setRespawnWorld(respawnWorld.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world players will respawn in if they die in this one.
|
||||
* Returns true upon success, false upon failure.
|
||||
*
|
||||
* @param respawnWorld The name of a world that exists on the server.
|
||||
*/
|
||||
public Try<Void> setRespawnWorld(MultiverseWorld respawnWorld) {
|
||||
return worldConfig.setRespawnWorld(respawnWorld.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world players will respawn in if they die in this one.
|
||||
* Returns true upon success, false upon failure.
|
||||
*
|
||||
* @param respawnWorld The name of a world that exists on the server.
|
||||
*/
|
||||
public Try<Void> setRespawnWorld(String respawnWorld) {
|
||||
return worldConfig.setRespawnWorld(respawnWorld);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scaling value of this world.Really only has an effect if you use
|
||||
* Multiverse-NetherPortals.
|
||||
*
|
||||
* @return This world's non-negative, non-zero scale.
|
||||
*/
|
||||
public double getScale() {
|
||||
return worldConfig.getScale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scale of this world. Really only has an effect if you use
|
||||
* Multiverse-NetherPortals. TODO: we are removing mvnp.
|
||||
*
|
||||
* @param scale A scaling value, cannot be negative or 0.
|
||||
*/
|
||||
public Try<Void> setScale(double scale) {
|
||||
return worldConfig.setScale(scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world seed of this world. This cannot be changed after world creation.
|
||||
*
|
||||
* @return The Long version of the seed.
|
||||
*/
|
||||
public long getSeed() {
|
||||
return worldConfig.getSeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the spawn location of this world.
|
||||
*
|
||||
* @return The spawn location of this world.
|
||||
*/
|
||||
public Location getSpawnLocation() {
|
||||
return worldConfig.getSpawnLocation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the spawn location for a world.
|
||||
*
|
||||
* @param spawnLocation The spawn location for a world.
|
||||
*/
|
||||
public Try<Void> setSpawnLocation(Location spawnLocation) {
|
||||
return worldConfig.setSpawnLocation(spawnLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not animals are allowed to spawn in this world.
|
||||
*
|
||||
* @return True if ANY animal can, false if no animals can spawn.
|
||||
*/
|
||||
public boolean getSpawningAnimals() {
|
||||
return worldConfig.getSpawningAnimals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not animals can spawn.
|
||||
* <br/>
|
||||
* If there are values in {@link #getSpawningAnimalsExceptions()} and this is false,
|
||||
* those animals become the exceptions, and will spawn
|
||||
*
|
||||
* @param spawningAnimals True to allow spawning of monsters, false to prevent.
|
||||
*/
|
||||
public Try<Void> setSpawningAnimals(boolean spawningAnimals) {
|
||||
return worldConfig.setSpawningAnimals(spawningAnimals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of ticks between animal spawns.
|
||||
*
|
||||
* @return The amount of ticks between animal spawns.
|
||||
*/
|
||||
public int getSpawningAnimalsTicks() {
|
||||
return worldConfig.getSpawningAnimalsTicks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of ticks between animal spawns. Set to -1 to use bukkit default.
|
||||
*
|
||||
* @param spawningAnimalsAmount The amount of ticks between animal spawns.
|
||||
* @return Result of setting property.
|
||||
*/
|
||||
public Try<Void> setSpawningAnimalsTicks(int spawningAnimalsAmount) {
|
||||
return worldConfig.setSpawningAnimalsTicks(spawningAnimalsAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of animals. This list always negates the {@link #getSpawningAnimals()} result.
|
||||
*
|
||||
* @return A list of animals that will spawn if {@link #getSpawningAnimals()} is false.
|
||||
*/
|
||||
public List<String> getSpawningAnimalsExceptions() {
|
||||
return worldConfig.getSpawningAnimalsExceptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of animals that will spawn if {@link #getSpawningAnimals()} is false.
|
||||
*
|
||||
* @param spawningAnimalsExceptions The list of animals that will spawn if {@link #getSpawningAnimals()} is false.
|
||||
* @return Result of setting property.
|
||||
*/
|
||||
public Try<Void> setSpawningAnimalsExceptions(List<String> spawningAnimalsExceptions) {
|
||||
return worldConfig.setSpawningAnimalsExceptions(spawningAnimalsExceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not monsters are allowed to spawn in this world.
|
||||
*
|
||||
* @return True if ANY monster can, false if no monsters can spawn.
|
||||
*/
|
||||
public boolean getSpawningMonsters() {
|
||||
return worldConfig.getSpawningMonsters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not monsters can spawn.
|
||||
* If there are values in {@link #getSpawningMonstersExceptions()} and this is false,
|
||||
* those monsters become the exceptions, and will spawn
|
||||
*
|
||||
* @param spawningMonsters True to allow spawning of monsters, false to prevent.
|
||||
* @return Result of setting property.
|
||||
*/
|
||||
public Try<Void> setSpawningMonsters(boolean spawningMonsters) {
|
||||
return worldConfig.setSpawningMonsters(spawningMonsters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of ticks between monster spawns.
|
||||
*
|
||||
* @return The amount of ticks between monster spawns.
|
||||
*/
|
||||
public int getSpawningMonstersTicks() {
|
||||
return worldConfig.getSpawningMonstersTicks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of ticks between monster spawns. Set to -1 to use bukkit default.
|
||||
*
|
||||
* @param spawningMonstersAmount The amount of ticks between monster spawns.
|
||||
* @return Result of setting property.
|
||||
*/
|
||||
public Try<Void> setSpawningMonstersTicks(int spawningMonstersAmount) {
|
||||
return worldConfig.setSpawningMonstersTicks(spawningMonstersAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of monsters. This list always negates the {@link #getSpawningMonsters()} result.
|
||||
*
|
||||
* @return A list of monsters that will spawn if {@link #getSpawningMonsters()} is false.
|
||||
*/
|
||||
public List<String> getSpawningMonstersExceptions() {
|
||||
return worldConfig.getSpawningMonstersExceptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of monsters that will spawn if {@link #getSpawningMonsters()} is false.
|
||||
*
|
||||
* @param spawningMonstersExceptions The list of monsters that will spawn if {@link #getSpawningMonsters()}
|
||||
* is false.
|
||||
* @return Result of setting property.
|
||||
*/
|
||||
public Try<Void> setSpawningMonstersExceptions(List<String> spawningMonstersExceptions) {
|
||||
return worldConfig.setSpawningMonstersExceptions(spawningMonstersExceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all the worlds that players CANNOT travel to from this world,regardless of their access
|
||||
* permissions.
|
||||
*
|
||||
* @return A List of world names.
|
||||
*/
|
||||
public List<String> getWorldBlacklist() {
|
||||
return worldConfig.getWorldBlacklist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of worlds that players CANNOT travel to from this world, regardless of their access permissions.
|
||||
*
|
||||
* @param worldBlacklist A List of world names.
|
||||
* @return Result of setting property.
|
||||
*/
|
||||
public Try<Void> setWorldBlacklist(List<String> worldBlacklist) {
|
||||
return worldConfig.setWorldBlacklist(worldBlacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world config. Only for internal use.
|
||||
*
|
||||
* @return The world config.
|
||||
*/
|
||||
WorldConfig getWorldConfig() {
|
||||
return worldConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world config. Only for internal use.
|
||||
*
|
||||
* @param worldConfig The world config.
|
||||
*/
|
||||
void setWorldConfig(WorldConfig worldConfig) {
|
||||
this.worldConfig = worldConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MultiverseWorld{"
|
||||
+ "name='" + worldName + "', "
|
||||
+ "env='" + getEnvironment() + "', "
|
||||
+ "gen='" + getGenerator() + "'"
|
||||
+ '}';
|
||||
}
|
||||
}
|
|
@ -1,69 +1,872 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.google.common.base.Strings;
|
||||
import com.onarandombox.MultiverseCore.api.BlockSafety;
|
||||
import com.onarandombox.MultiverseCore.api.LocationManipulation;
|
||||
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
|
||||
import com.onarandombox.MultiverseCore.utils.message.MessageReplacement;
|
||||
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.WorldsConfigFile;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.generators.GeneratorProvider;
|
||||
import com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.GameRulesStore;
|
||||
import com.onarandombox.MultiverseCore.worldnew.helpers.DataTransfer;
|
||||
import com.onarandombox.MultiverseCore.worldnew.helpers.FilesManipulator;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.CloneWorldOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.ImportWorldOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.KeepWorldSettingsOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.RegenWorldOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.UnloadWorldOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.CloneFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.CreateFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.DeleteFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.ImportFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.LoadFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.RegenFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.RemoveFailureReason;
|
||||
import com.onarandombox.MultiverseCore.worldnew.reasons.UnloadFailureReason;
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Service
|
||||
import static com.onarandombox.MultiverseCore.utils.message.MessageReplacement.replace;
|
||||
import static com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.WorldBorderStore;
|
||||
import static com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.WorldConfigStore;
|
||||
|
||||
/**
|
||||
* This manager contains all the world managing functions that your heart desires.
|
||||
*/
|
||||
@Service // SUPPRESS CHECKSTYLE: ClassFanOutComplexity This is the world manager, it's going to be complex.
|
||||
public class WorldManager {
|
||||
private final WorldsConfigFile worldsConfigFile;
|
||||
|
||||
private static final List<String> CLONE_IGNORE_FILES = Arrays.asList("uid.dat", "session.lock");
|
||||
|
||||
private final Map<String, MultiverseWorld> worldsMap;
|
||||
private final Map<String, LoadedMultiverseWorld> loadedWorldsMap;
|
||||
private final List<String> unloadTracker;
|
||||
private final List<String> loadTracker;
|
||||
private final WorldsConfigManager worldsConfigManager;
|
||||
private final WorldNameChecker worldNameChecker;
|
||||
private final GeneratorProvider generatorProvider;
|
||||
private final FilesManipulator filesManipulator;
|
||||
private final BlockSafety blockSafety;
|
||||
private final SafeTTeleporter safetyTeleporter;
|
||||
private final LocationManipulation locationManipulation;
|
||||
|
||||
@Inject
|
||||
WorldManager(@NotNull WorldsConfigFile worldsConfigFile) {
|
||||
this.worldsConfigFile = worldsConfigFile;
|
||||
this.worldsConfigFile.load();
|
||||
WorldManager(
|
||||
@NotNull WorldsConfigManager worldsConfigManager,
|
||||
@NotNull WorldNameChecker worldNameChecker,
|
||||
@NotNull GeneratorProvider generatorProvider,
|
||||
@NotNull FilesManipulator filesManipulator,
|
||||
@NotNull BlockSafety blockSafety,
|
||||
@NotNull SafeTTeleporter safetyTeleporter,
|
||||
@NotNull LocationManipulation locationManipulation) {
|
||||
this.worldsMap = new HashMap<>();
|
||||
this.loadedWorldsMap = new HashMap<>();
|
||||
this.unloadTracker = new ArrayList<>();
|
||||
this.loadTracker = new ArrayList<>();
|
||||
|
||||
this.worldsConfigManager = worldsConfigManager;
|
||||
this.worldNameChecker = worldNameChecker;
|
||||
this.generatorProvider = generatorProvider;
|
||||
this.filesManipulator = filesManipulator;
|
||||
this.blockSafety = blockSafety;
|
||||
this.safetyTeleporter = safetyTeleporter;
|
||||
this.locationManipulation = locationManipulation;
|
||||
}
|
||||
|
||||
public void loadAllWorlds() {
|
||||
for (String worldName : worldsConfigFile.getAllWorldsInConfig()) {
|
||||
Logging.fine("Loading world: " + worldName);
|
||||
loadWorld(worldName);
|
||||
/**
|
||||
* Loads all worlds from the worlds config.
|
||||
*
|
||||
* @return The result of the load.
|
||||
*/
|
||||
public Try<Void> initAllWorlds() {
|
||||
return updateWorldsFromConfig().andThenTry(() -> {
|
||||
loadDefaultWorlds();
|
||||
autoLoadWorlds();
|
||||
saveWorldsConfig();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current set of worlds to match the worlds config.
|
||||
*
|
||||
* @return A successful Try if the worlds.yml config was loaded successfully.
|
||||
*/
|
||||
private Try<Void> updateWorldsFromConfig() {
|
||||
return worldsConfigManager.load().mapTry(result -> {
|
||||
loadNewWorldConfigs(result._1());
|
||||
removeWorldsNotInConfigs(result._2());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private void loadNewWorldConfigs(Collection<WorldConfig> newWorldConfigs) {
|
||||
newWorldConfigs.forEach(worldConfig -> getWorld(worldConfig.getWorldName())
|
||||
.peek(unloadedWorld -> unloadedWorld.setWorldConfig(worldConfig))
|
||||
.onEmpty(() -> {
|
||||
MultiverseWorld mvWorld = new MultiverseWorld(worldConfig.getWorldName(), worldConfig);
|
||||
worldsMap.put(mvWorld.getName(), mvWorld);
|
||||
}));
|
||||
}
|
||||
|
||||
private void removeWorldsNotInConfigs(Collection<String> removedWorlds) {
|
||||
removedWorlds.forEach(worldName -> removeWorld(worldName)
|
||||
.onFailure(failure -> Logging.severe("Failed to unload world %s: %s", worldName, failure))
|
||||
.onSuccess(success -> Logging.fine("Unloaded world %s as it was removed from config", worldName)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load worlds that are already loaded by bukkit before Multiverse-Core is loaded.
|
||||
*/
|
||||
private void loadDefaultWorlds() {
|
||||
Bukkit.getWorlds().forEach(bukkitWorld -> {
|
||||
if (isWorld(bukkitWorld.getName())) {
|
||||
return;
|
||||
}
|
||||
importWorld(ImportWorldOptions.worldName(bukkitWorld.getName())
|
||||
.environment(bukkitWorld.getEnvironment())
|
||||
.generator(generatorProvider.getDefaultGeneratorForWorld(bukkitWorld.getName())));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all worlds that are set to autoload.
|
||||
*/
|
||||
private void autoLoadWorlds() {
|
||||
getWorlds().forEach(world -> {
|
||||
if (isLoadedWorld(world) || !world.getAutoLoad()) {
|
||||
return;
|
||||
}
|
||||
loadWorld(world).onFailure(failure -> Logging.severe("Failed to load world %s: %s",
|
||||
world.getName(), failure));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new world.
|
||||
*
|
||||
* @param options The options for customizing the creation of a new world.
|
||||
* @return The result of the creation.
|
||||
*/
|
||||
public Attempt<LoadedMultiverseWorld, CreateFailureReason> createWorld(CreateWorldOptions options) {
|
||||
return validateCreateWorldOptions(options).mapAttempt(this::createValidatedWorld);
|
||||
}
|
||||
|
||||
private Attempt<CreateWorldOptions, CreateFailureReason> validateCreateWorldOptions(
|
||||
CreateWorldOptions options) {
|
||||
if (!worldNameChecker.isValidWorldName(options.worldName())) {
|
||||
return worldActionResult(CreateFailureReason.INVALID_WORLDNAME, options.worldName());
|
||||
} else if (getLoadedWorld(options.worldName()).isDefined()) {
|
||||
return worldActionResult(CreateFailureReason.WORLD_EXIST_LOADED, options.worldName());
|
||||
} else if (getWorld(options.worldName()).isDefined()) {
|
||||
return worldActionResult(CreateFailureReason.WORLD_EXIST_UNLOADED, options.worldName());
|
||||
} else if (hasWorldFolder(options.worldName())) {
|
||||
return worldActionResult(CreateFailureReason.WORLD_EXIST_FOLDER, options.worldName());
|
||||
}
|
||||
return worldActionResult(options);
|
||||
}
|
||||
|
||||
private boolean hasWorldFolder(String worldName) {
|
||||
File worldFolder = new File(Bukkit.getWorldContainer(), worldName);
|
||||
return worldFolder.exists();
|
||||
}
|
||||
|
||||
private Attempt<LoadedMultiverseWorld, CreateFailureReason> createValidatedWorld(
|
||||
CreateWorldOptions options) {
|
||||
String parsedGenerator = parseGenerator(options.worldName(), options.generator());
|
||||
WorldCreator worldCreator = WorldCreator.name(options.worldName())
|
||||
.environment(options.environment())
|
||||
.generateStructures(options.generateStructures())
|
||||
.generator(parsedGenerator)
|
||||
.seed(options.seed())
|
||||
.type(options.worldType());
|
||||
return createBukkitWorld(worldCreator).fold(
|
||||
exception -> worldActionResult(CreateFailureReason.BUKKIT_CREATION_FAILED,
|
||||
options.worldName(), exception),
|
||||
world -> {
|
||||
LoadedMultiverseWorld loadedWorld = newLoadedMultiverseWorld(
|
||||
world,
|
||||
parsedGenerator,
|
||||
options.useSpawnAdjust());
|
||||
return worldActionResult(loadedWorld);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports an existing world folder.
|
||||
*
|
||||
* @param options The options for customizing the import of an existing world folder.
|
||||
* @return The result of the import.
|
||||
*/
|
||||
public Attempt<LoadedMultiverseWorld, ImportFailureReason> importWorld(
|
||||
ImportWorldOptions options) {
|
||||
return validateImportWorldOptions(options).mapAttempt(this::doImportWorld);
|
||||
}
|
||||
|
||||
private Attempt<ImportWorldOptions, ImportFailureReason> validateImportWorldOptions(
|
||||
ImportWorldOptions options) {
|
||||
String worldName = options.worldName();
|
||||
if (!worldNameChecker.isValidWorldName(worldName)) {
|
||||
return worldActionResult(ImportFailureReason.INVALID_WORLDNAME, worldName);
|
||||
} else if (!worldNameChecker.isValidWorldFolder(worldName)) {
|
||||
return worldActionResult(ImportFailureReason.WORLD_FOLDER_INVALID, worldName);
|
||||
} else if (isLoadedWorld(worldName)) {
|
||||
return worldActionResult(ImportFailureReason.WORLD_EXIST_LOADED, worldName);
|
||||
} else if (isWorld(worldName)) {
|
||||
return worldActionResult(ImportFailureReason.WORLD_EXIST_UNLOADED, worldName);
|
||||
}
|
||||
return worldActionResult(options);
|
||||
}
|
||||
|
||||
private Attempt<LoadedMultiverseWorld, ImportFailureReason> 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(ImportFailureReason.BUKKIT_CREATION_FAILED,
|
||||
options.worldName(), exception),
|
||||
world -> {
|
||||
LoadedMultiverseWorld loadedWorld = newLoadedMultiverseWorld(world,
|
||||
parsedGenerator,
|
||||
options.useSpawnAdjust());
|
||||
return worldActionResult(loadedWorld);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses generator string and defaults to generator in bukkit.yml if not specified.
|
||||
*
|
||||
* @param worldName The name of the world.
|
||||
* @param generator The input generator string.
|
||||
* @return The parsed generator string.
|
||||
*/
|
||||
private @Nullable String parseGenerator(@NotNull String worldName, @Nullable String generator) {
|
||||
return Strings.isNullOrEmpty(generator)
|
||||
? generatorProvider.getDefaultGeneratorForWorld(worldName)
|
||||
: generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new loaded multiverseWorld from a bukkit world.
|
||||
*
|
||||
* @param world The bukkit world to create a multiverse world from.
|
||||
* @param generator The generator string.
|
||||
* @param adjustSpawn Whether to adjust spawn.
|
||||
*/
|
||||
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);
|
||||
|
||||
MultiverseWorld mvWorld = new MultiverseWorld(world.getName(), worldConfig);
|
||||
worldsMap.put(mvWorld.getName(), mvWorld);
|
||||
|
||||
LoadedMultiverseWorld loadedWorld = new LoadedMultiverseWorld(
|
||||
world,
|
||||
worldConfig,
|
||||
blockSafety,
|
||||
safetyTeleporter,
|
||||
locationManipulation);
|
||||
loadedWorldsMap.put(loadedWorld.getName(), loadedWorld);
|
||||
saveWorldsConfig();
|
||||
return loadedWorld;
|
||||
}
|
||||
|
||||
public void addWorld(String worldName) {
|
||||
WorldConfig worldConfig = worldsConfigFile.getWorldConfig(worldName);
|
||||
// TODO: Implement logic
|
||||
/**
|
||||
* Loads an existing world in config.
|
||||
*
|
||||
* @param worldName The name of the world to load.
|
||||
* @return The result of the load.
|
||||
*/
|
||||
public Attempt<LoadedMultiverseWorld, LoadFailureReason> loadWorld(@NotNull String worldName) {
|
||||
return getWorld(worldName)
|
||||
.map(this::loadWorld)
|
||||
.getOrElse(() -> worldNameChecker.isValidWorldFolder(worldName)
|
||||
? worldActionResult(LoadFailureReason.WORLD_EXIST_FOLDER, worldName)
|
||||
: worldActionResult(LoadFailureReason.WORLD_NON_EXISTENT, worldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an existing world in config.
|
||||
*
|
||||
* @param world The world to load.
|
||||
* @return The result of the load.
|
||||
*/
|
||||
public Attempt<LoadedMultiverseWorld, LoadFailureReason> loadWorld(@NotNull MultiverseWorld world) {
|
||||
return validateWorldToLoad(world).mapAttempt(this::doLoadWorld);
|
||||
}
|
||||
|
||||
private Attempt<MultiverseWorld, LoadFailureReason> 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(LoadFailureReason.WORLD_ALREADY_LOADING, mvWorld.getName());
|
||||
} else if (isLoadedWorld(mvWorld)) {
|
||||
Logging.severe("World already loaded: " + mvWorld.getName());
|
||||
return worldActionResult(LoadFailureReason.WORLD_EXIST_LOADED, mvWorld.getName());
|
||||
}
|
||||
return worldActionResult(mvWorld);
|
||||
}
|
||||
|
||||
private Attempt<LoadedMultiverseWorld, LoadFailureReason> 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(LoadFailureReason.BUKKIT_CREATION_FAILED,
|
||||
mvWorld.getName(), exception),
|
||||
world -> {
|
||||
WorldConfig worldConfig = worldsConfigManager.getWorldConfig(mvWorld.getName()).get();
|
||||
LoadedMultiverseWorld loadedWorld = new LoadedMultiverseWorld(
|
||||
world,
|
||||
worldConfig,
|
||||
blockSafety,
|
||||
safetyTeleporter,
|
||||
locationManipulation);
|
||||
loadedWorldsMap.put(loadedWorld.getName(), loadedWorld);
|
||||
saveWorldsConfig();
|
||||
return worldActionResult(loadedWorld);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads an existing multiverse world. It will still remain as an unloaded world.
|
||||
*
|
||||
* @param options The options for customizing the unloading of a world.
|
||||
* @return The result of the unload action.
|
||||
*/
|
||||
public Attempt<MultiverseWorld, UnloadFailureReason> unloadWorld(@NotNull UnloadWorldOptions options) {
|
||||
LoadedMultiverseWorld world = options.world();
|
||||
|
||||
if (unloadTracker.contains(world.getName())) {
|
||||
// This is to prevent recursive calls by WorldUnloadEvent
|
||||
Logging.fine("World already unloading: " + world.getName());
|
||||
return worldActionResult(UnloadFailureReason.WORLD_ALREADY_UNLOADING, world.getName());
|
||||
}
|
||||
|
||||
if (options.removePlayers()) {
|
||||
removePlayersFromWorld(world);
|
||||
}
|
||||
|
||||
return unloadBukkitWorld(world.getBukkitWorld().getOrNull(), options.saveBukkitWorld()).fold(
|
||||
exception -> worldActionResult(UnloadFailureReason.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(UnloadFailureReason.WORLD_NON_EXISTENT, world.getName());
|
||||
},
|
||||
mvWorld -> {
|
||||
Logging.fine("Removed MultiverseWorld from map: " + world.getName());
|
||||
mvWorld.getWorldConfig().deferenceMVWorld();
|
||||
return worldActionResult(getWorld(mvWorld.getName()).get());
|
||||
}));
|
||||
}
|
||||
|
||||
private void removePlayersFromWorld(@NotNull LoadedMultiverseWorld world) {
|
||||
world.getPlayers().peek(players -> players.forEach(player -> {
|
||||
Location spawnLocation = Bukkit.getWorlds().get(0).getSpawnLocation();
|
||||
if (player.isOnline()) {
|
||||
Logging.fine("Teleporting player '%s' to world spawn: %s", player.getName(), spawnLocation);
|
||||
safetyTeleporter.safelyTeleport(null, player, spawnLocation, true);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing multiverse world. It will be deleted from the worlds config and will no longer be an
|
||||
* unloaded world. World files will not be deleted.
|
||||
*
|
||||
* @param worldName The name of the world to remove.
|
||||
* @return The result of the remove.
|
||||
*/
|
||||
public Attempt<String, RemoveFailureReason> removeWorld(
|
||||
@NotNull String worldName) {
|
||||
return getWorld(worldName)
|
||||
.map(this::removeWorld)
|
||||
.getOrElse(() -> worldActionResult(RemoveFailureReason.WORLD_NON_EXISTENT, worldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing multiverse world. It will be deleted from the worlds config and will no longer be an
|
||||
* unloaded world. World files will not be deleted.
|
||||
*
|
||||
* @param world The multiverse world to remove.
|
||||
* @return The result of the remove.
|
||||
*/
|
||||
public Attempt<String, RemoveFailureReason> removeWorld(@NotNull MultiverseWorld world) {
|
||||
return getLoadedWorld(world).fold(
|
||||
() -> removeWorldFromConfig(world),
|
||||
this::removeWorld);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing multiverse world. It will be deleted from the worlds config and will no longer be an
|
||||
* unloaded world. World files will not be deleted.
|
||||
*
|
||||
* @param loadedWorld The multiverse world to remove.
|
||||
* @return The result of the remove.
|
||||
*/
|
||||
public Attempt<String, RemoveFailureReason> removeWorld(@NotNull LoadedMultiverseWorld loadedWorld) {
|
||||
// TODO: Config option on removePlayers
|
||||
return unloadWorld(UnloadWorldOptions.world(loadedWorld).removePlayers(true))
|
||||
.transform(RemoveFailureReason.UNLOAD_FAILED)
|
||||
.mapAttempt(this::removeWorldFromConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing multiverse world from the world's config. It will no longer be a world known to Multiverse.
|
||||
*
|
||||
* @param world The multiverse world to remove.
|
||||
* @return The result of the remove.
|
||||
*/
|
||||
private Attempt<String, RemoveFailureReason> removeWorldFromConfig(@NotNull MultiverseWorld world) {
|
||||
// Remove world from config
|
||||
worldsMap.remove(world.getName());
|
||||
worldsConfigManager.deleteWorldConfig(world.getName());
|
||||
saveWorldsConfig();
|
||||
|
||||
return worldActionResult(world.getName());
|
||||
}
|
||||
|
||||
public void loadWorld(String worldName) {
|
||||
WorldConfig worldConfig = worldsConfigFile.getWorldConfig(worldName);
|
||||
// TODO: Implement logic
|
||||
/**
|
||||
* Deletes an existing multiverse world entirely. World will be loaded if it is not already loaded.
|
||||
* Warning: This will delete all world files.
|
||||
*
|
||||
* @param worldName The name of the world to delete.
|
||||
* @return The result of the delete action.
|
||||
*/
|
||||
public Attempt<String, DeleteFailureReason> deleteWorld(@NotNull String worldName) {
|
||||
return getWorld(worldName)
|
||||
.map(this::deleteWorld)
|
||||
.getOrElse(() -> worldActionResult(DeleteFailureReason.WORLD_NON_EXISTENT, worldName));
|
||||
}
|
||||
|
||||
public void unloadWorld() {
|
||||
// TODO: Implement logic
|
||||
/**
|
||||
* Deletes an existing multiverse world entirely. World will be loaded if it is not already loaded.
|
||||
* Warning: This will delete all world files.
|
||||
*
|
||||
* @param world The world to delete.
|
||||
* @return The result of the delete action.
|
||||
*/
|
||||
public Attempt<String, DeleteFailureReason> deleteWorld(@NotNull MultiverseWorld world) {
|
||||
return getLoadedWorld(world).fold(
|
||||
() -> loadWorld(world)
|
||||
.transform(DeleteFailureReason.LOAD_FAILED)
|
||||
.mapAttempt(this::deleteWorld),
|
||||
this::deleteWorld);
|
||||
}
|
||||
|
||||
public void removeWorld(String worldName) {
|
||||
// TODO: Implement logic
|
||||
worldsConfigFile.deleteWorldConfigSection(worldName);
|
||||
saveWorldsConfig();
|
||||
/**
|
||||
* Deletes an existing multiverse world entirely. Warning: This will delete all world files.
|
||||
*
|
||||
* @param world The multiverse world to delete.
|
||||
* @return The result of the delete action.
|
||||
*/
|
||||
public Attempt<String, DeleteFailureReason> deleteWorld(@NotNull LoadedMultiverseWorld world) {
|
||||
// TODO: Possible config options to keep certain files
|
||||
AtomicReference<File> worldFolder = new AtomicReference<>();
|
||||
return validateWorldToDelete(world)
|
||||
.peek(worldFolder::set)
|
||||
.mapAttempt(() -> removeWorld(world).transform(DeleteFailureReason.REMOVE_FAILED))
|
||||
.mapAttempt(() -> filesManipulator.deleteFolder(worldFolder.get()).fold(
|
||||
exception -> worldActionResult(DeleteFailureReason.FAILED_TO_DELETE_FOLDER,
|
||||
world.getName(), exception),
|
||||
success -> worldActionResult(world.getName())));
|
||||
}
|
||||
|
||||
public void deleteWorld(String worldName) {
|
||||
// TODO: Implement logic
|
||||
worldsConfigFile.deleteWorldConfigSection(worldName);
|
||||
saveWorldsConfig();
|
||||
private Attempt<File, DeleteFailureReason> 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(DeleteFailureReason.WORLD_FOLDER_NOT_FOUND, world.getName());
|
||||
}
|
||||
return worldActionResult(worldFolder);
|
||||
}
|
||||
|
||||
public void getMVWorld(String worldName) {
|
||||
// TODO: Implement logic
|
||||
/**
|
||||
* Clones an existing multiverse world.
|
||||
*
|
||||
* @param options The options for customizing the cloning of a world.
|
||||
* @return The result of the clone.
|
||||
*/
|
||||
public Attempt<LoadedMultiverseWorld, CloneFailureReason> cloneWorld(@NotNull CloneWorldOptions options) {
|
||||
return cloneWorldValidateWorld(options)
|
||||
.mapAttempt(this::cloneWorldCopyFolder)
|
||||
.mapAttempt(validatedOptions -> {
|
||||
ImportWorldOptions importWorldOptions = ImportWorldOptions
|
||||
.worldName(validatedOptions.newWorldName())
|
||||
.environment(validatedOptions.world().getEnvironment())
|
||||
.generator(validatedOptions.world().getGenerator());
|
||||
return importWorld(importWorldOptions).transform(CloneFailureReason.IMPORT_FAILED);
|
||||
})
|
||||
.onSuccess(newWorld -> {
|
||||
cloneWorldTransferData(options, newWorld);
|
||||
if (options.keepWorldConfig()) {
|
||||
newWorld.setSpawnLocation(options.world().getSpawnLocation());
|
||||
}
|
||||
saveWorldsConfig();
|
||||
});
|
||||
}
|
||||
|
||||
public void getUnloadedWorld(String worldName) {
|
||||
// TODO: Implement logic
|
||||
private Attempt<CloneWorldOptions, CloneFailureReason> cloneWorldValidateWorld(
|
||||
@NotNull CloneWorldOptions options) {
|
||||
String newWorldName = options.newWorldName();
|
||||
if (!worldNameChecker.isValidWorldName(newWorldName)) {
|
||||
Logging.severe("Invalid world name: " + newWorldName);
|
||||
return worldActionResult(CloneFailureReason.INVALID_WORLDNAME, newWorldName);
|
||||
}
|
||||
if (worldNameChecker.isValidWorldFolder(newWorldName)) {
|
||||
return worldActionResult(CloneFailureReason.WORLD_EXIST_FOLDER, newWorldName);
|
||||
}
|
||||
if (isLoadedWorld(newWorldName)) {
|
||||
Logging.severe("World already loaded when attempting to clone: " + newWorldName);
|
||||
return worldActionResult(CloneFailureReason.WORLD_EXIST_LOADED, newWorldName);
|
||||
}
|
||||
if (isWorld(newWorldName)) {
|
||||
Logging.severe("World already exist unloaded: " + newWorldName);
|
||||
return worldActionResult(CloneFailureReason.WORLD_EXIST_UNLOADED, newWorldName);
|
||||
}
|
||||
return worldActionResult(options);
|
||||
}
|
||||
|
||||
public void saveWorldsConfig() {
|
||||
worldsConfigFile.save();
|
||||
private Attempt<CloneWorldOptions, CloneFailureReason> cloneWorldCopyFolder(
|
||||
@NotNull CloneWorldOptions options) {
|
||||
File worldFolder = options.world().getBukkitWorld().map(World::getWorldFolder).get();
|
||||
File newWorldFolder = new File(Bukkit.getWorldContainer(), options.newWorldName());
|
||||
return filesManipulator.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES).fold(
|
||||
exception -> worldActionResult(CloneFailureReason.COPY_FAILED,
|
||||
options.world().getName(), exception),
|
||||
success -> worldActionResult(options));
|
||||
}
|
||||
|
||||
private void cloneWorldTransferData(@NotNull CloneWorldOptions options, @NotNull LoadedMultiverseWorld newWorld) {
|
||||
DataTransfer<LoadedMultiverseWorld> dataTransfer = transferData(options, options.world());
|
||||
dataTransfer.pasteAllTo(newWorld);
|
||||
}
|
||||
|
||||
private DataTransfer<LoadedMultiverseWorld> transferData(
|
||||
@NotNull KeepWorldSettingsOptions options, @NotNull LoadedMultiverseWorld world) {
|
||||
DataTransfer<LoadedMultiverseWorld> dataTransfer = new DataTransfer<>();
|
||||
|
||||
if (options.keepWorldConfig()) {
|
||||
dataTransfer.addDataStore(new WorldConfigStore(), world);
|
||||
}
|
||||
if (options.keepGameRule()) {
|
||||
dataTransfer.addDataStore(new GameRulesStore(), world);
|
||||
}
|
||||
if (options.keepWorldBorder()) {
|
||||
dataTransfer.addDataStore(new WorldBorderStore(), world);
|
||||
}
|
||||
|
||||
return dataTransfer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerates a world.
|
||||
*
|
||||
* @param options The options for customizing the regeneration of a world.
|
||||
* @return The result of the regeneration.
|
||||
*/
|
||||
public Attempt<LoadedMultiverseWorld, RegenFailureReason> regenWorld(@NotNull RegenWorldOptions options) {
|
||||
LoadedMultiverseWorld world = options.world();
|
||||
List<Player> playersInWorld = world.getPlayers().getOrElse(Collections.emptyList());
|
||||
DataTransfer<LoadedMultiverseWorld> dataTransfer = transferData(options, world);
|
||||
boolean shouldKeepSpawnLocation = options.keepWorldConfig() && options.seed() == world.getSeed();
|
||||
Location spawnLocation = world.getSpawnLocation();
|
||||
|
||||
CreateWorldOptions createWorldOptions = CreateWorldOptions.worldName(world.getName())
|
||||
.environment(world.getEnvironment())
|
||||
.generateStructures(world.canGenerateStructures().getOrElse(true))
|
||||
.generator(world.getGenerator())
|
||||
.seed(options.seed())
|
||||
.useSpawnAdjust(!shouldKeepSpawnLocation && world.getAdjustSpawn())
|
||||
.worldType(world.getWorldType().getOrElse(WorldType.NORMAL));
|
||||
|
||||
return deleteWorld(world)
|
||||
.transform(RegenFailureReason.DELETE_FAILED)
|
||||
.mapAttempt(() -> createWorld(createWorldOptions).transform(RegenFailureReason.CREATE_FAILED))
|
||||
.onSuccess(newWorld -> {
|
||||
dataTransfer.pasteAllTo(newWorld);
|
||||
if (shouldKeepSpawnLocation) {
|
||||
// Special case for spawn location to prevent unsafe location if world was regen using a
|
||||
// different seed.
|
||||
newWorld.setSpawnLocation(spawnLocation);
|
||||
}
|
||||
teleportPlayersToWorld(playersInWorld, newWorld);
|
||||
saveWorldsConfig();
|
||||
});
|
||||
}
|
||||
|
||||
private void teleportPlayersToWorld(@NotNull List<Player> players, @NotNull LoadedMultiverseWorld world) {
|
||||
players.forEach(player -> {
|
||||
Location spawnLocation = world.getSpawnLocation();
|
||||
if (player.isOnline()) {
|
||||
safetyTeleporter.safelyTeleport(null, player, spawnLocation, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T, F extends FailureReason> Attempt<T, F> worldActionResult(@NotNull T value) {
|
||||
return Attempt.success(value);
|
||||
}
|
||||
|
||||
private <T, F extends FailureReason> Attempt<T, F> worldActionResult(
|
||||
@NotNull F failureReason, @NotNull String worldName) {
|
||||
return Attempt.failure(failureReason, replaceWorldName(worldName));
|
||||
}
|
||||
|
||||
private <T, F extends FailureReason> Attempt<T, F> worldActionResult(
|
||||
@NotNull F failureReason, @NotNull String worldName, @NotNull Throwable error) {
|
||||
// TODO: Localize error message if its a MultiverseException
|
||||
return Attempt.failure(failureReason, replaceWorldName(worldName), replaceError(error.getMessage()));
|
||||
}
|
||||
|
||||
private MessageReplacement replaceWorldName(@NotNull String worldName) {
|
||||
return replace("{world}").with(worldName);
|
||||
}
|
||||
|
||||
private MessageReplacement replaceError(@NotNull String errorMessage) {
|
||||
return replace("{error}").with(errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bukkit world.
|
||||
*
|
||||
* @param worldCreator The world parameters.
|
||||
* @return The created world.
|
||||
*/
|
||||
private Try<World> createBukkitWorld(WorldCreator worldCreator) {
|
||||
return Try.of(() -> {
|
||||
this.loadTracker.add(worldCreator.name());
|
||||
World world = worldCreator.createWorld();
|
||||
if (world == null) {
|
||||
// TODO: Localize this
|
||||
throw new Exception("World created returned null!");
|
||||
}
|
||||
Logging.fine("Bukkit created world: " + world.getName());
|
||||
return world;
|
||||
}).onFailure(exception -> {
|
||||
Logging.severe("Failed to create bukkit world: " + worldCreator.name());
|
||||
exception.printStackTrace();
|
||||
}).andFinally(() -> this.loadTracker.remove(worldCreator.name()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads a bukkit world.
|
||||
*
|
||||
* @param world The bukkit world to unload.
|
||||
* @return The unloaded world.
|
||||
*/
|
||||
private Try<Void> unloadBukkitWorld(World world, boolean save) {
|
||||
return Try.run(() -> {
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
unloadTracker.add(world.getName());
|
||||
if (!Bukkit.unloadWorld(world, save)) {
|
||||
// TODO: Localize this, maybe with MultiverseException
|
||||
throw new Exception("Is this the default world? You can't unload the default world!");
|
||||
}
|
||||
Logging.fine("Bukkit unloaded world: " + world.getName());
|
||||
}).onFailure(exception -> {
|
||||
Logging.severe("Failed to unload bukkit world: " + world.getName());
|
||||
exception.printStackTrace();
|
||||
}).andFinally(() -> unloadTracker.remove(world.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all potential worlds that can be loaded from the server folders.
|
||||
* Checks based on folder contents and name.
|
||||
*
|
||||
* @return A list of all potential worlds.
|
||||
*/
|
||||
public List<String> getPotentialWorlds() {
|
||||
File[] files = Bukkit.getWorldContainer().listFiles();
|
||||
if (files == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Arrays.stream(files)
|
||||
.filter(file -> !isWorld(file.getName()))
|
||||
.filter(worldNameChecker::isValidWorldFolder)
|
||||
.map(File::getName)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a world that is not loaded.
|
||||
*
|
||||
* @param worldName The name of the world to get.
|
||||
* @return The world if it exists.
|
||||
*/
|
||||
public Option<MultiverseWorld> getUnloadedWorld(@Nullable String worldName) {
|
||||
return isLoadedWorld(worldName) ? Option.none() : Option.of(worldsMap.get(worldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all worlds that are not loaded.
|
||||
*
|
||||
* @return A list of all worlds that are not loaded.
|
||||
*/
|
||||
public Collection<MultiverseWorld> getUnloadedWorlds() {
|
||||
return worldsMap.values().stream().filter(world -> !world.isLoaded()).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a world is a world that is not loaded.
|
||||
*
|
||||
* @param worldName The name of the world to check.
|
||||
* @return True if the world is a world that is not loaded.
|
||||
*/
|
||||
public boolean isUnloadedWorld(@Nullable String worldName) {
|
||||
return !isLoadedWorld(worldName) && isWorld(worldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a world that may or may not be loaded. It will an {@link LoadedMultiverseWorld} if the world is loaded,
|
||||
* otherwise returns an {@link MultiverseWorld} instance.
|
||||
*
|
||||
* @param worldName The name of the world to get.
|
||||
* @return The world if it exists.
|
||||
*/
|
||||
public Option<MultiverseWorld> getWorld(@Nullable String worldName) {
|
||||
return getLoadedWorld(worldName).fold(() -> getUnloadedWorld(worldName), Option::of);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Get a list of all worlds that may or may not be loaded. It will an {@link LoadedMultiverseWorld} if the world
|
||||
* is loaded, otherwise you will get an {@link MultiverseWorld} instance.</p>
|
||||
*
|
||||
* <p>If you want only unloaded worlds, use {@link #getUnloadedWorlds()}. If you want only loaded worlds, use
|
||||
* {@link #getLoadedWorlds()}.</p>
|
||||
*
|
||||
* @return A list of all worlds that may or may not be loaded.
|
||||
*/
|
||||
public Collection<MultiverseWorld> getWorlds() {
|
||||
return worldsMap.values().stream()
|
||||
.map(world -> getLoadedWorld(world).fold(() -> world, loadedWorld -> loadedWorld))
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a world is a world is known to multiverse, but may or may not be loaded.
|
||||
*
|
||||
* @param worldName The name of the world to check.
|
||||
* @return True if the world is a world is known to multiverse, but may or may not be loaded.
|
||||
*/
|
||||
public boolean isWorld(@Nullable String worldName) {
|
||||
return worldsMap.containsKey(worldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a multiverse world that is loaded.
|
||||
*
|
||||
* @param world The bukkit world that should be loaded.
|
||||
* @return The multiverse world if it exists.
|
||||
*/
|
||||
public Option<LoadedMultiverseWorld> getLoadedWorld(@Nullable World world) {
|
||||
return world == null ? Option.none() : Option.of(loadedWorldsMap.get(world.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a multiverse world that is loaded.
|
||||
*
|
||||
* @param world The world that should be loaded.
|
||||
* @return The multiverse world if it exists.
|
||||
*/
|
||||
public Option<LoadedMultiverseWorld> getLoadedWorld(@Nullable MultiverseWorld world) {
|
||||
return world == null ? Option.none() : Option.of(loadedWorldsMap.get(world.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a multiverse world that is loaded.
|
||||
*
|
||||
* @param worldName The name of the world to get.
|
||||
* @return The multiverse world if it exists.
|
||||
*/
|
||||
public Option<LoadedMultiverseWorld> getLoadedWorld(@Nullable String worldName) {
|
||||
return Option.of(loadedWorldsMap.get(worldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all multiverse worlds that are loaded.
|
||||
*
|
||||
* @return A list of all multiverse worlds that are loaded.
|
||||
*/
|
||||
public Collection<LoadedMultiverseWorld> getLoadedWorlds() {
|
||||
return loadedWorldsMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a world is a multiverse world that is loaded.
|
||||
*
|
||||
* @param world The bukkit world to check.
|
||||
* @return True if the world is a multiverse world that is loaded.
|
||||
*/
|
||||
public boolean isLoadedWorld(@Nullable World world) {
|
||||
return world != null && isLoadedWorld(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a world is a multiverse world that is loaded.
|
||||
*
|
||||
* @param world The world to check.
|
||||
* @return True if the world is a multiverse world that is loaded.
|
||||
*/
|
||||
public boolean isLoadedWorld(@Nullable MultiverseWorld world) {
|
||||
return world != null && isLoadedWorld(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a world is a multiverse world that is loaded.
|
||||
*
|
||||
* @param worldName The name of the world to check.
|
||||
* @return True if the world is a multiverse world that is loaded.
|
||||
*/
|
||||
public boolean isLoadedWorld(@Nullable String worldName) {
|
||||
return loadedWorldsMap.containsKey(worldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the worlds.yml config.
|
||||
*
|
||||
* @return true if it had successfully saved the file.
|
||||
*/
|
||||
public boolean saveWorldsConfig() {
|
||||
return worldsConfigManager.save()
|
||||
.onFailure(failure -> {
|
||||
Logging.severe("Failed to save worlds config: %s", failure);
|
||||
failure.printStackTrace();
|
||||
})
|
||||
.isSuccess();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* <p>Utility class in helping to check the status of a world name and it's associated world folder.</p>
|
||||
*
|
||||
* <p>Note this is for preliminary checks and better command output. A valid result will suggest but not
|
||||
* 100% determine that a world name can be created, loaded or imported.</p>
|
||||
*/
|
||||
@Service
|
||||
public class WorldNameChecker {
|
||||
|
||||
private static final Pattern WORLD_NAME_PATTERN = Pattern.compile("[a-zA-Z0-9/._-]+");
|
||||
private static final Set<String> BLACKLIST_NAMES = Set.of(
|
||||
"cache",
|
||||
"config",
|
||||
"crash-reports",
|
||||
"logs",
|
||||
"plugins",
|
||||
"versions");
|
||||
|
||||
/**
|
||||
* Checks if a world name is valid.
|
||||
*
|
||||
* @param worldName The world name to check on.
|
||||
* @return True if check result is valid, else false.
|
||||
*/
|
||||
public boolean isValidWorldName(@Nullable String worldName) {
|
||||
return checkName(worldName) == NameStatus.VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the current validity status of a world name.
|
||||
*
|
||||
* @param worldName The world name to check on.
|
||||
* @return The resulting name status.
|
||||
*/
|
||||
@NotNull
|
||||
public NameStatus checkName(@Nullable String worldName) {
|
||||
if (BLACKLIST_NAMES.contains(worldName)) {
|
||||
return NameStatus.BLACKLISTED;
|
||||
}
|
||||
if (worldName == null || !WORLD_NAME_PATTERN.matcher(worldName).matches()) {
|
||||
return NameStatus.INVALID_CHARS;
|
||||
}
|
||||
return NameStatus.VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a world name has a valid world folder.
|
||||
*
|
||||
* @param worldName The world name to check on.
|
||||
* @return True if check result is valid, else false.
|
||||
*/
|
||||
public boolean isValidWorldFolder(@Nullable String worldName) {
|
||||
return checkFolder(worldName) == FolderStatus.VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a world folder is valid.
|
||||
*
|
||||
* @param worldFolder The world folder to check on.
|
||||
* @return True if check result is valid, else false.
|
||||
*/
|
||||
public boolean isValidWorldFolder(@Nullable File worldFolder) {
|
||||
return checkFolder(worldFolder) == FolderStatus.VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the current folder status for a world name.
|
||||
*
|
||||
* @param worldName The world name to check on.
|
||||
* @return The resulting folder status.
|
||||
*/
|
||||
@NotNull
|
||||
public FolderStatus checkFolder(@Nullable String worldName) {
|
||||
if (worldName == null) {
|
||||
return FolderStatus.DOES_NOT_EXIST;
|
||||
}
|
||||
File worldFolder = new File(Bukkit.getWorldContainer(), worldName);
|
||||
return checkFolder(worldFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the current folder status.
|
||||
*
|
||||
* @param worldFolder The world folder to check on.
|
||||
* @return The resulting folder status.
|
||||
*/
|
||||
@NotNull
|
||||
public FolderStatus checkFolder(@Nullable File worldFolder) {
|
||||
if (worldFolder == null || !worldFolder.exists() || !worldFolder.isDirectory()) {
|
||||
return FolderStatus.DOES_NOT_EXIST;
|
||||
}
|
||||
if (!folderHasDat(worldFolder)) {
|
||||
return FolderStatus.NOT_A_WORLD;
|
||||
}
|
||||
return FolderStatus.VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* A very basic check to see if a folder has a level.dat file. If it does, we can safely assume
|
||||
* it's a world folder.
|
||||
*
|
||||
* @param worldFolder The File that may be a world.
|
||||
* @return True if it looks like a world, else false.
|
||||
*/
|
||||
private boolean folderHasDat(@NotNull File worldFolder) {
|
||||
File[] files = worldFolder.listFiles((file, name) -> name.toLowerCase().endsWith(".dat"));
|
||||
return files != null && files.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result after checking validity of world name.
|
||||
*/
|
||||
public enum NameStatus {
|
||||
/**
|
||||
* Name is valid.
|
||||
*/
|
||||
VALID,
|
||||
|
||||
/**
|
||||
* Name not valid as it contains invalid characters.
|
||||
*/
|
||||
INVALID_CHARS,
|
||||
|
||||
/**
|
||||
* Name not valid as it is deemed blacklisted.
|
||||
*/
|
||||
BLACKLISTED
|
||||
}
|
||||
|
||||
/**
|
||||
* Result after checking validity of world folder.
|
||||
*/
|
||||
public enum FolderStatus {
|
||||
/**
|
||||
* Folder is valid.
|
||||
*/
|
||||
VALID,
|
||||
|
||||
/**
|
||||
* Folder exist, but contents in it doesnt look like a world.
|
||||
*/
|
||||
NOT_A_WORLD,
|
||||
|
||||
/**
|
||||
* Folder does not exist.
|
||||
*/
|
||||
DOES_NOT_EXIST
|
||||
}
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Ambient;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Ghast;
|
||||
import org.bukkit.entity.Golem;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.Phantom;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.Slime;
|
||||
import org.bukkit.entity.Squid;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
// TODO: This entire class is a mess.
|
||||
/**
|
||||
* Used to remove animals from worlds that don't belong there.
|
||||
*/
|
||||
@Service
|
||||
public class WorldPurger {
|
||||
|
||||
/**
|
||||
* Synchronizes the given worlds with their settings.
|
||||
*
|
||||
* @param worlds A list of {@link LoadedMultiverseWorld}
|
||||
*/
|
||||
public void purgeWorlds(@Nullable List<LoadedMultiverseWorld> worlds) {
|
||||
if (worlds == null || worlds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (LoadedMultiverseWorld world : worlds) {
|
||||
this.purgeWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #purgeWorld(LoadedMultiverseWorld, java.util.List, boolean, boolean)} that takes
|
||||
* the settings from the world-config.
|
||||
*
|
||||
* @param world The {@link LoadedMultiverseWorld}.
|
||||
*/
|
||||
public void purgeWorld(@Nullable LoadedMultiverseWorld world) {
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
ArrayList<String> allMobs = new ArrayList<>(world.getSpawningAnimalsExceptions());
|
||||
allMobs.addAll(world.getSpawningMonstersExceptions());
|
||||
purgeWorld(world, allMobs, !world.getSpawningAnimals(), !world.getSpawningMonsters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all animals/monsters that do not belong to a world according to the config.
|
||||
*
|
||||
* @param world The {@link LoadedMultiverseWorld}.
|
||||
* @param thingsToKill A {@link List} of animals/monsters to be killed.
|
||||
* @param negateAnimals Whether the monsters in the list should be negated.
|
||||
* @param negateMonsters Whether the animals in the list should be negated.
|
||||
*/
|
||||
public void purgeWorld(
|
||||
LoadedMultiverseWorld world,
|
||||
List<String> thingsToKill,
|
||||
boolean negateAnimals,
|
||||
boolean negateMonsters) {
|
||||
purgeWorld(world, thingsToKill, negateAnimals, negateMonsters, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all animals/monsters that do not belong to a world according to the config.
|
||||
*
|
||||
* @param world The {@link LoadedMultiverseWorld}.
|
||||
* @param thingsToKill A {@link List} of animals/monsters to be killed.
|
||||
* @param negateAnimals Whether the monsters in the list should be negated.
|
||||
* @param negateMonsters Whether the animals in the list should be negated.
|
||||
* @param sender The {@link CommandSender} that initiated the action. He will/should be notified.
|
||||
*/
|
||||
public void purgeWorld(
|
||||
@Nullable LoadedMultiverseWorld world,
|
||||
@NotNull List<String> thingsToKill,
|
||||
boolean negateAnimals,
|
||||
boolean negateMonsters,
|
||||
CommandSender sender) {
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
World bukkitWorld = world.getBukkitWorld().getOrNull();
|
||||
if (bukkitWorld == null) {
|
||||
return;
|
||||
}
|
||||
int projectilesKilled = 0;
|
||||
int entitiesKilled = 0;
|
||||
boolean specifiedAll = thingsToKill.contains("ALL");
|
||||
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
|
||||
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
|
||||
List<Entity> worldEntities = bukkitWorld.getEntities();
|
||||
List<LivingEntity> livingEntities = new ArrayList<LivingEntity>(worldEntities.size());
|
||||
List<Projectile> projectiles = new ArrayList<Projectile>(worldEntities.size());
|
||||
for (final Entity e : worldEntities) {
|
||||
if (e instanceof Projectile p) {
|
||||
if (p.getShooter() != null) {
|
||||
projectiles.add((Projectile) e);
|
||||
}
|
||||
} else if (e instanceof LivingEntity) {
|
||||
livingEntities.add((LivingEntity) e);
|
||||
}
|
||||
}
|
||||
for (final LivingEntity e : livingEntities) {
|
||||
if (killDecision(e, thingsToKill, negateAnimals, negateMonsters, specifiedAnimals, specifiedMonsters)) {
|
||||
final Iterator<Projectile> it = projectiles.iterator();
|
||||
while (it.hasNext()) {
|
||||
final Projectile p = it.next();
|
||||
if (Objects.equals(p.getShooter(), e)) {
|
||||
p.remove();
|
||||
it.remove();
|
||||
projectilesKilled++;
|
||||
}
|
||||
}
|
||||
e.remove();
|
||||
entitiesKilled++;
|
||||
}
|
||||
}
|
||||
if (sender != null) {
|
||||
sender.sendMessage(entitiesKilled + " entities purged from the world '" + world.getName() + "' along with "
|
||||
+ projectilesKilled + " projectiles that belonged to them.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the specified creature should be killed and automatically reads the params from a world object.
|
||||
*
|
||||
* @param world The world.
|
||||
* @param entity The creature.
|
||||
* @return {@code true} if the creature should be killed, otherwise {@code false}.
|
||||
*/
|
||||
public boolean shouldWeKillThisCreature(@NotNull LoadedMultiverseWorld world, @NotNull Entity entity) {
|
||||
ArrayList<String> allMobs = new ArrayList<>(world.getSpawningAnimalsExceptions());
|
||||
allMobs.addAll(world.getSpawningMonstersExceptions());
|
||||
return this.shouldWeKillThisCreature(entity, allMobs, !world.getSpawningAnimals(), !world.getSpawningMonsters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the specified creature should be killed.
|
||||
*
|
||||
* @param entity The creature.
|
||||
* @param thingsToKill A {@link List} of animals/monsters to be killed.
|
||||
* @param negateAnimals Whether the monsters in the list should be negated.
|
||||
* @param negateMonsters Whether the animals in the list should be negated.
|
||||
* @return {@code true} if the creature should be killed, otherwise {@code false}.
|
||||
*/
|
||||
public boolean shouldWeKillThisCreature(
|
||||
Entity entity,
|
||||
List<String> thingsToKill,
|
||||
boolean negateAnimals,
|
||||
boolean negateMonsters) {
|
||||
boolean specifiedAll = thingsToKill.contains("ALL");
|
||||
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
|
||||
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
|
||||
return this.killDecision(
|
||||
entity,
|
||||
thingsToKill,
|
||||
negateAnimals,
|
||||
negateMonsters,
|
||||
specifiedAnimals,
|
||||
specifiedMonsters);
|
||||
}
|
||||
|
||||
private boolean killDecision(
|
||||
Entity entity,
|
||||
List<String> thingsToKill,
|
||||
boolean negateAnimals,
|
||||
boolean negateMonsters,
|
||||
boolean specifiedAnimals,
|
||||
boolean specifiedMonsters) {
|
||||
boolean negate = false;
|
||||
boolean specified = false;
|
||||
if (entity instanceof Golem
|
||||
|| entity instanceof Squid
|
||||
|| entity instanceof Animals
|
||||
|| entity instanceof Ambient) {
|
||||
// it's an animal
|
||||
if (specifiedAnimals && !negateAnimals) {
|
||||
Logging.finest("Removing an entity because I was told to remove all animals in world %s: %s",
|
||||
entity.getWorld().getName(), entity);
|
||||
return true;
|
||||
}
|
||||
if (specifiedAnimals) {
|
||||
specified = true;
|
||||
}
|
||||
negate = negateAnimals;
|
||||
} else if (entity instanceof Monster
|
||||
|| entity instanceof Ghast
|
||||
|| entity instanceof Slime
|
||||
|| entity instanceof Phantom) {
|
||||
// it's a monster
|
||||
if (specifiedMonsters && !negateMonsters) {
|
||||
Logging.finest("Removing an entity because I was told to remove all monsters in world %s: %s",
|
||||
entity.getWorld().getName(), entity);
|
||||
return true;
|
||||
}
|
||||
if (specifiedMonsters) {
|
||||
specified = true;
|
||||
}
|
||||
negate = negateMonsters;
|
||||
}
|
||||
for (String s : thingsToKill) {
|
||||
EntityType type = EntityType.fromName(s);
|
||||
if (type != null && type.equals(entity.getType())) {
|
||||
specified = true;
|
||||
if (!negate) {
|
||||
Logging.finest(
|
||||
"Removing an entity because it WAS specified and we are NOT negating in world %s: %s",
|
||||
entity.getWorld().getName(), entity);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!specified && negate) {
|
||||
Logging.finest("Removing an entity because it was NOT specified and we ARE negating in world %s: %s",
|
||||
entity.getWorld().getName(), entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.config;
|
||||
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.MigratorAction;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
class LegacyAliasMigrator implements MigratorAction {
|
||||
@Override
|
||||
public void migrate(ConfigurationSection config) {
|
||||
AtomicReference<String> alias = new AtomicReference<>(config.getString("alias", ""));
|
||||
if (alias.get().isEmpty()) return;
|
||||
|
||||
String color = config.getString("color", "");
|
||||
String style = config.getString("style", "");
|
||||
|
||||
Try.of(() -> Enum.valueOf(EnglishChatColor.class, color.toUpperCase()))
|
||||
.map(c -> c.color)
|
||||
.onSuccess(c -> {
|
||||
if (c != ChatColor.WHITE) {
|
||||
alias.set("&" + c.getChar() + alias.get());
|
||||
}
|
||||
});
|
||||
|
||||
Try.of(() -> Enum.valueOf(EnglishChatStyle.class, style.toUpperCase()))
|
||||
.map(c -> c.color)
|
||||
.onSuccess(s -> {
|
||||
if (s != null) {
|
||||
alias.set("&" + s.getChar() + alias.get());
|
||||
}
|
||||
});
|
||||
|
||||
config.set("alias", alias.get());
|
||||
config.set("color", null);
|
||||
config.set("style", null);
|
||||
}
|
||||
|
||||
private enum EnglishChatColor {
|
||||
// BEGIN CHECKSTYLE-SUPPRESSION: JavadocVariable
|
||||
AQUA(ChatColor.AQUA),
|
||||
BLACK(ChatColor.BLACK),
|
||||
BLUE(ChatColor.BLUE),
|
||||
DARKAQUA(ChatColor.DARK_AQUA),
|
||||
DARKBLUE(ChatColor.DARK_BLUE),
|
||||
DARKGRAY(ChatColor.DARK_GRAY),
|
||||
DARKGREEN(ChatColor.DARK_GREEN),
|
||||
DARKPURPLE(ChatColor.DARK_PURPLE),
|
||||
DARKRED(ChatColor.DARK_RED),
|
||||
GOLD(ChatColor.GOLD),
|
||||
GRAY(ChatColor.GRAY),
|
||||
GREEN(ChatColor.GREEN),
|
||||
LIGHTPURPLE(ChatColor.LIGHT_PURPLE),
|
||||
RED(ChatColor.RED),
|
||||
YELLOW(ChatColor.YELLOW),
|
||||
WHITE(ChatColor.WHITE);
|
||||
// END CHECKSTYLE-SUPPRESSION: JavadocVariable
|
||||
|
||||
private final ChatColor color;
|
||||
//private final String text;
|
||||
|
||||
EnglishChatColor(ChatColor color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
private enum EnglishChatStyle {
|
||||
// BEGIN CHECKSTYLE-SUPPRESSION: JavadocVariable
|
||||
/**
|
||||
* No style.
|
||||
*/
|
||||
NORMAL(null),
|
||||
MAGIC(ChatColor.MAGIC),
|
||||
BOLD(ChatColor.BOLD),
|
||||
STRIKETHROUGH(ChatColor.STRIKETHROUGH),
|
||||
UNDERLINE(ChatColor.UNDERLINE),
|
||||
ITALIC(ChatColor.ITALIC);
|
||||
// END CHECKSTYLE-SUPPRESSION: JavadocVariable
|
||||
|
||||
private final ChatColor color;
|
||||
|
||||
EnglishChatStyle(ChatColor color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.config;
|
||||
|
||||
import com.onarandombox.MultiverseCore.world.SimpleMVWorld;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Null-location.
|
||||
*/
|
||||
@SerializableAs("MVNullLocation (It's a bug if you see this in your config file)")
|
||||
public final class NullLocation extends SpawnLocation {
|
||||
private static final NullLocation INSTANCE = new NullLocation();
|
||||
|
||||
/**
|
||||
* Get the default null location instance.
|
||||
*
|
||||
* @return The instance.
|
||||
*/
|
||||
public static NullLocation get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private NullLocation() {
|
||||
super(0, -1, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Location clone() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> serialize() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Let Bukkit be able to deserialize this.
|
||||
*
|
||||
* @param args The map.
|
||||
* @return The deserialized object.
|
||||
*/
|
||||
public static SimpleMVWorld.NullLocation deserialize(Map<String, Object> args) {
|
||||
return new SimpleMVWorld.NullLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Vector toVector() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Location{null}";
|
||||
}
|
||||
}
|
|
@ -1,9 +1,4 @@
|
|||
package com.onarandombox.MultiverseCore.world.configuration;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
package com.onarandombox.MultiverseCore.worldnew.config;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
|
@ -11,6 +6,12 @@ import org.bukkit.World;
|
|||
import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Just like a regular {@link Location}, however {@code world} is usually {@code null}
|
||||
|
@ -20,14 +21,35 @@ import org.bukkit.configuration.serialization.SerializableAs;
|
|||
public class SpawnLocation extends Location implements ConfigurationSerializable {
|
||||
private Reference<World> worldRef;
|
||||
|
||||
/**
|
||||
* Constructs a new Location with the given coordinates.
|
||||
*
|
||||
* @param x The x-coordinate of this new location
|
||||
* @param y The y-coordinate of this new location
|
||||
* @param z The z-coordinate of this new location
|
||||
*/
|
||||
public SpawnLocation(double x, double y, double z) {
|
||||
super(null, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Location with the given coordinates and direction.
|
||||
*
|
||||
* @param x The x-coordinate of this new location
|
||||
* @param y The y-coordinate of this new location
|
||||
* @param z The z-coordinate of this new location
|
||||
* @param yaw The absolute rotation on the x-plane, in degrees
|
||||
* @param pitch The absolute rotation on the y-plane, in degrees
|
||||
*/
|
||||
public SpawnLocation(double x, double y, double z, float yaw, float pitch) {
|
||||
super(null, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Location from an existing Location.
|
||||
*
|
||||
* @param loc The location to clone.
|
||||
*/
|
||||
public SpawnLocation(Location loc) {
|
||||
this(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
|
||||
}
|
||||
|
@ -52,38 +74,43 @@ public class SpawnLocation extends Location implements ConfigurationSerializable
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
if ((this.worldRef != null) && (this.worldRef.get() != null))
|
||||
return this.worldRef.get().getChunkAt(this);
|
||||
return null;
|
||||
public @NotNull Chunk getChunk() {
|
||||
World world = this.worldRef != null ? this.worldRef.get() : null;
|
||||
if (world != null) {
|
||||
return world.getChunkAt(this);
|
||||
}
|
||||
throw new IllegalStateException("World is null");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Block getBlock() {
|
||||
if ((this.worldRef != null) && (this.worldRef.get() != null))
|
||||
return this.worldRef.get().getBlockAt(this);
|
||||
return null;
|
||||
public @NotNull Block getBlock() {
|
||||
World world = this.worldRef != null ? this.worldRef.get() : null;
|
||||
if (world != null) {
|
||||
return world.getBlockAt(this);
|
||||
}
|
||||
throw new IllegalStateException("World is null");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> serialized = new HashMap<String, Object>(5); // SUPPRESS CHECKSTYLE: MagicNumberCheck
|
||||
serialized.put("x", this.getX());
|
||||
serialized.put("y", this.getY());
|
||||
serialized.put("z", this.getZ());
|
||||
serialized.put("pitch", this.getPitch());
|
||||
serialized.put("yaw", this.getYaw());
|
||||
return serialized;
|
||||
public @NotNull Map<String, Object> serialize() {
|
||||
return new HashMap<>() {{
|
||||
put("x", getX());
|
||||
put("y", getY());
|
||||
put("z", getZ());
|
||||
put("pitch", getPitch());
|
||||
put("yaw", getYaw());
|
||||
}};
|
||||
}
|
||||
|
||||
/**
|
||||
* Let Bukkit be able to deserialize this.
|
||||
*
|
||||
* @param args The map.
|
||||
* @return The deserialized object.
|
||||
*/
|
|
@ -2,29 +2,116 @@ package com.onarandombox.MultiverseCore.worldnew.config;
|
|||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.handle.ConfigurationSectionHandle;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.BooleanMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.IntegerMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.LongMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.MoveMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.NullStringMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.VersionMigrator;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class WorldConfig {
|
||||
/**
|
||||
* Represents a world configuration.
|
||||
*/
|
||||
public final class WorldConfig {
|
||||
|
||||
private final String worldName;
|
||||
private final WorldConfigNodes configNodes;
|
||||
private final ConfigurationSectionHandle configHandle;
|
||||
|
||||
public WorldConfig(@NotNull final ConfigurationSection configSection) {
|
||||
WorldConfig(@NotNull String worldName, @NotNull final ConfigurationSection configSection) {
|
||||
this.worldName = worldName;
|
||||
this.configNodes = new WorldConfigNodes();
|
||||
// TODO: Config migration and version
|
||||
this.configHandle = ConfigurationSectionHandle.builder(configSection)
|
||||
.logger(Logging.getLogger())
|
||||
.nodes(configNodes.getNodes())
|
||||
.migrator(ConfigMigrator.builder(configNodes.VERSION)
|
||||
.addVersionMigrator(initialVersionMigrator())
|
||||
.build())
|
||||
.build();
|
||||
this.configHandle.load();
|
||||
load();
|
||||
}
|
||||
|
||||
private VersionMigrator initialVersionMigrator() {
|
||||
return VersionMigrator.builder(1.0)
|
||||
.addAction(MoveMigratorAction.of("adjustSpawn", "adjust-spawn"))
|
||||
.addAction(BooleanMigratorAction.of("adjust-spawn"))
|
||||
.addAction(MoveMigratorAction.of("allowFlight", "allow-flight"))
|
||||
.addAction(BooleanMigratorAction.of("allow-flight"))
|
||||
.addAction(MoveMigratorAction.of("allowWeather", "allow-weather"))
|
||||
.addAction(BooleanMigratorAction.of("allow-weather"))
|
||||
.addAction(MoveMigratorAction.of("autoHeal", "auto-heal"))
|
||||
.addAction(BooleanMigratorAction.of("auto-heal"))
|
||||
.addAction(MoveMigratorAction.of("autoLoad", "auto-load"))
|
||||
.addAction(BooleanMigratorAction.of("auto-load"))
|
||||
.addAction(MoveMigratorAction.of("bedRespawn", "bed-respawn"))
|
||||
.addAction(BooleanMigratorAction.of("bed-respawn"))
|
||||
//.addAction(MoveMigratorAction.of("difficulty", "difficulty"))
|
||||
.addAction(MoveMigratorAction.of("entryfee.amount", "entry-fee.amount"))
|
||||
.addAction(MoveMigratorAction.of("entryfee.currency", "entry-fee.currency"))
|
||||
//.addAction(MoveMigratorAction.of("environment", "environment"))
|
||||
.addAction(MoveMigratorAction.of("gameMode", "gamemode"))
|
||||
//.addAction(MoveMigratorAction.of("generator", "generator"))
|
||||
.addAction(NullStringMigratorAction.of("generator"))
|
||||
//.addAction(MoveMigratorAction.of("hidden", "hidden"))
|
||||
.addAction(BooleanMigratorAction.of("hidden"))
|
||||
//.addAction(MoveMigratorAction.of("hunger", "hunger"))
|
||||
.addAction(BooleanMigratorAction.of("hunger"))
|
||||
.addAction(MoveMigratorAction.of("keepSpawnInMemory", "keep-spawn-in-memory"))
|
||||
.addAction(BooleanMigratorAction.of("keep-spawn-in-memory"))
|
||||
.addAction(MoveMigratorAction.of("playerLimit", "player-limit"))
|
||||
.addAction(IntegerMigratorAction.of("player-limit"))
|
||||
.addAction(MoveMigratorAction.of("portalForm", "portal-form"))
|
||||
//.addAction(MoveMigratorAction.of("pvp", "pvp"))
|
||||
.addAction(BooleanMigratorAction.of("pvp"))
|
||||
.addAction(MoveMigratorAction.of("respawnWorld", "respawn-world"))
|
||||
//.addAction(MoveMigratorAction.of("scale", "scale"))
|
||||
//.addAction(MoveMigratorAction.of("seed", "seed"))
|
||||
.addAction(LongMigratorAction.of("seed"))
|
||||
.addAction(MoveMigratorAction.of("spawnLocation", "spawn-location"))
|
||||
//.addAction(MoveMigratorAction.of("spawning.animals.spawn", "spawning.animals.spawn"))
|
||||
.addAction(BooleanMigratorAction.of("spawning.animals.spawn"))
|
||||
.addAction(MoveMigratorAction.of("spawning.animals.amount", "spawning.animals.tick-rate"))
|
||||
.addAction(IntegerMigratorAction.of("spawning.animals.tick-rate"))
|
||||
//.addAction(MoveMigratorAction.of("spawning.animals.exceptions", "spawning.animals.exceptions"))
|
||||
//.addAction(MoveMigratorAction.of("spawning.monsters.spawn", "spawning.monsters.spawn"))
|
||||
.addAction(BooleanMigratorAction.of("spawning.monsters.spawn"))
|
||||
.addAction(MoveMigratorAction.of("spawning.monsters.amount", "spawning.monsters.tick-rate"))
|
||||
.addAction(IntegerMigratorAction.of("spawning.monsters.tick-rate"))
|
||||
//.addAction(MoveMigratorAction.of("spawning.monsters.exceptions", "spawning.monsters.exceptions"))
|
||||
.addAction(MoveMigratorAction.of("worldBlacklist", "world-blacklist"))
|
||||
.addAction(new LegacyAliasMigrator())
|
||||
.build();
|
||||
}
|
||||
|
||||
public Try<Void> load() {
|
||||
return configHandle.load();
|
||||
}
|
||||
|
||||
public Try<Void> load(ConfigurationSection section) {
|
||||
return configHandle.load(section);
|
||||
}
|
||||
|
||||
public String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames() {
|
||||
return configNodes.getNodes().getNames();
|
||||
}
|
||||
|
||||
public Try<Object> getProperty(String name) {
|
||||
|
@ -83,6 +170,14 @@ public class WorldConfig {
|
|||
return configHandle.set(configNodes.AUTO_LOAD, autoLoad);
|
||||
}
|
||||
|
||||
public boolean getBedRespawn() {
|
||||
return configHandle.get(configNodes.BED_RESPAWN);
|
||||
}
|
||||
|
||||
public Try<Void> setBedRespawn(boolean bedRespawn) {
|
||||
return configHandle.set(configNodes.BED_RESPAWN, bedRespawn);
|
||||
}
|
||||
|
||||
public Difficulty getDifficulty() {
|
||||
return configHandle.get(configNodes.DIFFICULTY);
|
||||
}
|
||||
|
@ -91,6 +186,22 @@ public class WorldConfig {
|
|||
return configHandle.set(configNodes.DIFFICULTY, difficulty);
|
||||
}
|
||||
|
||||
public double getEntryFeeAmount() {
|
||||
return configHandle.get(configNodes.ENTRY_FEE_AMOUNT);
|
||||
}
|
||||
|
||||
public Try<Void> setEntryFeeAmount(double entryFeeAmount) {
|
||||
return configHandle.set(configNodes.ENTRY_FEE_AMOUNT, entryFeeAmount);
|
||||
}
|
||||
|
||||
public Material getEntryFeeCurrency() {
|
||||
return configHandle.get(configNodes.ENTRY_FEE_CURRENCY);
|
||||
}
|
||||
|
||||
public Try<Void> setEntryFeeCurrency(Material entryFeeCurrency) {
|
||||
return configHandle.set(configNodes.ENTRY_FEE_CURRENCY, entryFeeCurrency);
|
||||
}
|
||||
|
||||
public World.Environment getEnvironment() {
|
||||
return configHandle.get(configNodes.ENVIRONMENT);
|
||||
}
|
||||
|
@ -99,11 +210,11 @@ public class WorldConfig {
|
|||
return configHandle.set(configNodes.ENVIRONMENT, environment);
|
||||
}
|
||||
|
||||
public GameMode getGamemode() {
|
||||
public GameMode getGameMode() {
|
||||
return configHandle.get(configNodes.GAMEMODE);
|
||||
}
|
||||
|
||||
public Try<Void> setGamemode(GameMode gamemode) {
|
||||
public Try<Void> setGameMode(GameMode gamemode) {
|
||||
return configHandle.set(configNodes.GAMEMODE, gamemode);
|
||||
}
|
||||
|
||||
|
@ -179,19 +290,87 @@ public class WorldConfig {
|
|||
return configHandle.set(configNodes.SCALE, scale);
|
||||
}
|
||||
|
||||
public @Nullable String getSeed() {
|
||||
public long getSeed() {
|
||||
return configHandle.get(configNodes.SEED);
|
||||
}
|
||||
|
||||
public Try<Void> setSeed(String seed) {
|
||||
public Try<Void> setSeed(long seed) {
|
||||
return configHandle.set(configNodes.SEED, seed);
|
||||
}
|
||||
|
||||
public List<String> getWorldBlacklist() {
|
||||
return (List<String>) configHandle.get(configNodes.WORLD_BLACKLIST);
|
||||
public Location getSpawnLocation() {
|
||||
return configHandle.get(configNodes.SPAWN_LOCATION);
|
||||
}
|
||||
|
||||
public void setWorldBlacklist(List<String> worldBlacklist) {
|
||||
configHandle.set(configNodes.WORLD_BLACKLIST, worldBlacklist);
|
||||
public Try<Void> setSpawnLocation(Location spawnLocation) {
|
||||
return configHandle.set(configNodes.SPAWN_LOCATION, spawnLocation);
|
||||
}
|
||||
|
||||
public boolean getSpawningAnimals() {
|
||||
return configHandle.get(configNodes.SPAWNING_ANIMALS);
|
||||
}
|
||||
|
||||
public Try<Void> setSpawningAnimals(boolean spawningAnimals) {
|
||||
return configHandle.set(configNodes.SPAWNING_ANIMALS, spawningAnimals);
|
||||
}
|
||||
|
||||
public int getSpawningAnimalsTicks() {
|
||||
return configHandle.get(configNodes.SPAWNING_ANIMALS_TICKS);
|
||||
}
|
||||
|
||||
public Try<Void> setSpawningAnimalsTicks(int spawningAnimalsAmount) {
|
||||
return configHandle.set(configNodes.SPAWNING_ANIMALS_TICKS, spawningAnimalsAmount);
|
||||
}
|
||||
|
||||
public List<String> getSpawningAnimalsExceptions() {
|
||||
return configHandle.get(configNodes.SPAWNING_ANIMALS_EXCEPTIONS);
|
||||
}
|
||||
|
||||
public Try<Void> setSpawningAnimalsExceptions(List<String> spawningAnimalsExceptions) {
|
||||
return configHandle.set(configNodes.SPAWNING_ANIMALS_EXCEPTIONS, spawningAnimalsExceptions);
|
||||
}
|
||||
|
||||
public boolean getSpawningMonsters() {
|
||||
return configHandle.get(configNodes.SPAWNING_MONSTERS);
|
||||
}
|
||||
|
||||
public Try<Void> setSpawningMonsters(boolean spawningMonsters) {
|
||||
return configHandle.set(configNodes.SPAWNING_MONSTERS, spawningMonsters);
|
||||
}
|
||||
|
||||
public int getSpawningMonstersTicks() {
|
||||
return configHandle.get(configNodes.SPAWNING_MONSTERS_TICKS);
|
||||
}
|
||||
|
||||
public Try<Void> setSpawningMonstersTicks(int spawningMonstersAmount) {
|
||||
return configHandle.set(configNodes.SPAWNING_MONSTERS_TICKS, spawningMonstersAmount);
|
||||
}
|
||||
|
||||
public List<String> getSpawningMonstersExceptions() {
|
||||
return configHandle.get(configNodes.SPAWNING_MONSTERS_EXCEPTIONS);
|
||||
}
|
||||
|
||||
public Try<Void> setSpawningMonstersExceptions(List<String> spawningMonstersExceptions) {
|
||||
return configHandle.set(configNodes.SPAWNING_MONSTERS_EXCEPTIONS, spawningMonstersExceptions);
|
||||
}
|
||||
|
||||
public List<String> getWorldBlacklist() {
|
||||
return configHandle.get(configNodes.WORLD_BLACKLIST);
|
||||
}
|
||||
|
||||
public Try<Void> setWorldBlacklist(List<String> worldBlacklist) {
|
||||
return configHandle.set(configNodes.WORLD_BLACKLIST, worldBlacklist);
|
||||
}
|
||||
|
||||
public void setMVWorld(@NotNull LoadedMultiverseWorld world) {
|
||||
configNodes.world = world;
|
||||
}
|
||||
|
||||
public boolean hasMVWorld() {
|
||||
return configNodes.world != null;
|
||||
}
|
||||
|
||||
public void deferenceMVWorld() {
|
||||
configNodes.world = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,24 @@ import com.onarandombox.MultiverseCore.configuration.node.ConfigNode;
|
|||
import com.onarandombox.MultiverseCore.configuration.node.Node;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents nodes in a world configuration.
|
||||
*/
|
||||
public class WorldConfigNodes {
|
||||
static final double CONFIG_VERSION = 1.0;
|
||||
|
||||
private final NodeGroup nodes = new NodeGroup();
|
||||
LoadedMultiverseWorld world = null;
|
||||
|
||||
WorldConfigNodes() {
|
||||
}
|
||||
|
@ -26,109 +35,195 @@ public class WorldConfigNodes {
|
|||
return node;
|
||||
}
|
||||
|
||||
public final ConfigNode<Boolean> ADJUST_SPAWN = node(ConfigNode.builder("adjust-spawn", Boolean.class)
|
||||
final ConfigNode<Boolean> ADJUST_SPAWN = node(ConfigNode.builder("adjust-spawn", Boolean.class)
|
||||
.defaultValue(false)
|
||||
.name("adjust-spawn")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<String> ALIAS = node(ConfigNode.builder("alias", String.class)
|
||||
final ConfigNode<String> ALIAS = node(ConfigNode.builder("alias", String.class)
|
||||
.defaultValue("")
|
||||
.name("alias")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> ALLOW_FLIGHT = node(ConfigNode.builder("allow-flight", Boolean.class)
|
||||
final ConfigNode<Boolean> ALLOW_FLIGHT = node(ConfigNode.builder("allow-flight", Boolean.class)
|
||||
.defaultValue(false)
|
||||
.name("allow-flight")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> ALLOW_WEATHER = node(ConfigNode.builder("allow-weather", Boolean.class)
|
||||
final ConfigNode<Boolean> ALLOW_WEATHER = node(ConfigNode.builder("allow-weather", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("allow-weather")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> {
|
||||
if (!world.isClearWeather() && !newValue) {
|
||||
world.setThundering(false);
|
||||
world.setStorm(false);
|
||||
}
|
||||
});
|
||||
})
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> AUTO_HEAL = node(ConfigNode.builder("auto-heal", Boolean.class)
|
||||
final ConfigNode<Boolean> AUTO_HEAL = node(ConfigNode.builder("auto-heal", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("auto-heal")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> AUTO_LOAD = node(ConfigNode.builder("auto-load", Boolean.class)
|
||||
final ConfigNode<Boolean> AUTO_LOAD = node(ConfigNode.builder("auto-load", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("auto-load")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Difficulty> DIFFICULTY = node(ConfigNode.builder("difficulty", Difficulty.class)
|
||||
final ConfigNode<Boolean> BED_RESPAWN = node(ConfigNode.builder("bed-respawn", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.build());
|
||||
|
||||
final ConfigNode<Difficulty> DIFFICULTY = node(ConfigNode.builder("difficulty", Difficulty.class)
|
||||
.defaultValue(Difficulty.NORMAL)
|
||||
.name("difficulty")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> world.setDifficulty(newValue));
|
||||
})
|
||||
.build());
|
||||
|
||||
public final ConfigNode<World.Environment> ENVIRONMENT = node(ConfigNode.builder("environment", World.Environment.class)
|
||||
final ConfigNode<Double> ENTRY_FEE_AMOUNT = node(ConfigNode.builder("entry-fee.amount", Double.class)
|
||||
.defaultValue(0.0)
|
||||
.name("entryfee-amount")
|
||||
.build());
|
||||
|
||||
final ConfigNode<Material> ENTRY_FEE_CURRENCY = node(ConfigNode.builder("entry-fee.currency", Material.class)
|
||||
.defaultValue(Material.AIR) // TODO: Convert from material ID
|
||||
.name("entryfee-currency")
|
||||
.build());
|
||||
|
||||
final ConfigNode<World.Environment> ENVIRONMENT = node(ConfigNode
|
||||
.builder("environment", World.Environment.class)
|
||||
.defaultValue(World.Environment.NORMAL)
|
||||
.name("environment")
|
||||
.name(null)
|
||||
.build());
|
||||
|
||||
public final ConfigNode<GameMode> GAMEMODE = node(ConfigNode.builder("gamemode", GameMode.class)
|
||||
final ConfigNode<GameMode> GAMEMODE = node(ConfigNode.builder("gamemode", GameMode.class)
|
||||
.defaultValue(GameMode.SURVIVAL)
|
||||
.name("gamemode")
|
||||
// TODO: Set all gamemodes of players in world to this gamemode
|
||||
.build());
|
||||
|
||||
public final ConfigNode<String> GENERATOR = node(ConfigNode.builder("generator", String.class)
|
||||
.defaultValue("")
|
||||
.name("generator")
|
||||
final ConfigNode<String> GENERATOR = node(ConfigNode.builder("generator", String.class)
|
||||
.defaultValue("@error") // this should be set on world creation
|
||||
.name(null)
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> HIDDEN = node(ConfigNode.builder("hidden", Boolean.class)
|
||||
final ConfigNode<Boolean> HIDDEN = node(ConfigNode.builder("hidden", Boolean.class)
|
||||
.defaultValue(false)
|
||||
.name("hidden")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> HUNGER = node(ConfigNode.builder("hunger", Boolean.class)
|
||||
final ConfigNode<Boolean> HUNGER = node(ConfigNode.builder("hunger", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("hunger")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> KEEP_SPAWN_IN_MEMORY = node(ConfigNode.builder("keep-spawn-in-memory", Boolean.class)
|
||||
final ConfigNode<Boolean> KEEP_SPAWN_IN_MEMORY = node(ConfigNode
|
||||
.builder("keep-spawn-in-memory", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("keep-spawn-in-memory")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> world.setKeepSpawnInMemory(newValue));
|
||||
})
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Integer> PLAYER_LIMIT = node(ConfigNode.builder("player-limit", Integer.class)
|
||||
final ConfigNode<Integer> PLAYER_LIMIT = node(ConfigNode.builder("player-limit", Integer.class)
|
||||
.defaultValue(-1)
|
||||
.name("player-limit")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<AllowedPortalType> PORTAL_FORM = node(ConfigNode.builder("portal-form", AllowedPortalType.class)
|
||||
final ConfigNode<AllowedPortalType> PORTAL_FORM = node(ConfigNode
|
||||
.builder("portal-form", AllowedPortalType.class)
|
||||
.defaultValue(AllowedPortalType.ALL)
|
||||
.name("portal-form")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Boolean> PVP = node(ConfigNode.builder("pvp", Boolean.class)
|
||||
final ConfigNode<Boolean> PVP = node(ConfigNode.builder("pvp", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("pvp")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> world.setPVP(newValue));
|
||||
})
|
||||
.build());
|
||||
|
||||
public final ConfigNode<String> RESPAWN_WORLD = node(ConfigNode.builder("respawn-world", String.class)
|
||||
final ConfigNode<String> RESPAWN_WORLD = node(ConfigNode.builder("respawn-world", String.class)
|
||||
.defaultValue("")
|
||||
.name("respawn-world")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<Double> SCALE = node(ConfigNode.builder("scale", Double.class)
|
||||
final ConfigNode<Double> SCALE = node(ConfigNode.builder("scale", Double.class)
|
||||
.defaultValue(1.0)
|
||||
.name("scale")
|
||||
.build());
|
||||
|
||||
public final ConfigNode<String> SEED = node(ConfigNode.builder("seed", String.class)
|
||||
.defaultValue("")
|
||||
.name("seed")
|
||||
final ConfigNode<Long> SEED = node(ConfigNode.builder("seed", Long.class)
|
||||
.defaultValue(Long.MIN_VALUE)
|
||||
.name(null)
|
||||
.build());
|
||||
|
||||
public final ConfigNode<List> WORLD_BLACKLIST = node(ConfigNode.builder("world-blacklist", List.class)
|
||||
final ConfigNode<Location> SPAWN_LOCATION = node(ConfigNode.builder("spawn-location", Location.class)
|
||||
.defaultValue(NullLocation.get())
|
||||
.name(null)
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
if (newValue == null || newValue instanceof NullLocation) return;
|
||||
world.getBukkitWorld().peek(bukkitWorld -> {
|
||||
bukkitWorld.setSpawnLocation(newValue.getBlockX(), newValue.getBlockY(), newValue.getBlockZ());
|
||||
newValue.setWorld(bukkitWorld);
|
||||
});
|
||||
})
|
||||
.build());
|
||||
|
||||
final ConfigNode<Boolean> SPAWNING_ANIMALS = node(ConfigNode.builder("spawning.animals.spawn", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("spawning-animals")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> world.setSpawnFlags(world.getAllowMonsters(), newValue));
|
||||
})
|
||||
.build());
|
||||
|
||||
final ConfigNode<Integer> SPAWNING_ANIMALS_TICKS = node(ConfigNode
|
||||
.builder("spawning.animals.tick-rate", Integer.class)
|
||||
.defaultValue(-1)
|
||||
.name("spawning-animals-ticks")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> world.setTicksPerAnimalSpawns(newValue));
|
||||
})
|
||||
.build());
|
||||
|
||||
final ConfigNode<List> SPAWNING_ANIMALS_EXCEPTIONS = node(ConfigNode
|
||||
.builder("spawning.animals.exceptions", List.class)
|
||||
.defaultValue(new ArrayList<>())
|
||||
.name("world-blacklist")
|
||||
.name("spawning-animals-exceptions")
|
||||
.build());
|
||||
|
||||
// TODO: Migrate color and style into alias
|
||||
// TODO: spawning
|
||||
// TODO: entryfee
|
||||
// TODO: spawnLocation
|
||||
// TODO: worldBlacklist
|
||||
final ConfigNode<Boolean> SPAWNING_MONSTERS = node(ConfigNode
|
||||
.builder("spawning.monsters.spawn", Boolean.class)
|
||||
.defaultValue(true)
|
||||
.name("spawning-monsters")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> world.setSpawnFlags(newValue, world.getAllowAnimals()));
|
||||
})
|
||||
.build());
|
||||
|
||||
final ConfigNode<Integer> SPAWNING_MONSTERS_TICKS = node(ConfigNode
|
||||
.builder("spawning.monsters.tick-rate", Integer.class)
|
||||
.defaultValue(-1)
|
||||
.name("spawning-monsters-ticks")
|
||||
.onSetValue((oldValue, newValue) -> {
|
||||
if (world == null) return;
|
||||
world.getBukkitWorld().peek(world -> world.setTicksPerMonsterSpawns(newValue));
|
||||
})
|
||||
.build());
|
||||
|
||||
final ConfigNode<List> SPAWNING_MONSTERS_EXCEPTIONS = node(ConfigNode
|
||||
.builder("spawning.monsters.exceptions", List.class)
|
||||
.defaultValue(new ArrayList<>())
|
||||
.name("spawning-monsters-exceptions")
|
||||
.build());
|
||||
|
||||
final ConfigNode<List> WORLD_BLACKLIST = node(ConfigNode.builder("world-blacklist", List.class)
|
||||
.defaultValue(new ArrayList<>())
|
||||
.build());
|
||||
|
||||
final ConfigNode<Double> VERSION = node(ConfigNode.builder("version", Double.class)
|
||||
.defaultValue(CONFIG_VERSION)
|
||||
.name(null)
|
||||
.build());
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.config;
|
||||
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
@Service
|
||||
public class WorldsConfigFile {
|
||||
private static final String CONFIG_FILENAME = "worlds2.yml";
|
||||
|
||||
private final File worldConfigFile;
|
||||
private YamlConfiguration worldConfig;
|
||||
|
||||
@Inject
|
||||
public WorldsConfigFile(@NotNull MultiverseCore core) {
|
||||
worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
// TODO: Migration from old worlds.yml
|
||||
worldConfig = YamlConfiguration.loadConfiguration(worldConfigFile);
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return worldConfig != null;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
worldConfig.save(worldConfigFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<String> getAllWorldsInConfig() {
|
||||
return worldConfig.getKeys(false);
|
||||
}
|
||||
|
||||
public ConfigurationSection getWorldConfigSection(String worldName) {
|
||||
return worldConfig.isConfigurationSection(worldName)
|
||||
? worldConfig.getConfigurationSection(worldName) : worldConfig.createSection(worldName);
|
||||
}
|
||||
|
||||
public WorldConfig getWorldConfig(String worldName) {
|
||||
return new WorldConfig(getWorldConfigSection(worldName));
|
||||
}
|
||||
|
||||
public void deleteWorldConfigSection(String worldName) {
|
||||
worldConfig.set(worldName, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.config;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import io.vavr.Tuple2;
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Manages the worlds.yml file.
|
||||
*/
|
||||
@Service
|
||||
public final class WorldsConfigManager {
|
||||
private static final String CONFIG_FILENAME = "worlds2.yml"; // TODO: Rename to worlds.yml
|
||||
|
||||
private final Map<String, WorldConfig> worldConfigMap;
|
||||
private final File worldConfigFile;
|
||||
private YamlConfiguration worldsConfig;
|
||||
|
||||
@Inject
|
||||
WorldsConfigManager(@NotNull MultiverseCore core) {
|
||||
worldConfigMap = new HashMap<>();
|
||||
worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the worlds.yml file and creates a WorldConfig for each world in the file if it doesn't already exist.
|
||||
*
|
||||
* @return A tuple containing a list of the new WorldConfigs added and a list of the worlds removed from the config.
|
||||
*/
|
||||
public Try<Tuple2<List<WorldConfig>, List<String>>> load() {
|
||||
return Try.of(() -> {
|
||||
loadWorldYmlFile();
|
||||
return parseNewAndRemovedWorlds();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the worlds.yml file.
|
||||
*
|
||||
* @throws IOException If an error occurs while loading the file.
|
||||
* @throws InvalidConfigurationException If the file is not a valid YAML file.
|
||||
*/
|
||||
private void loadWorldYmlFile() throws IOException, InvalidConfigurationException {
|
||||
boolean exists = worldConfigFile.exists();
|
||||
if (!exists && !worldConfigFile.createNewFile()) {
|
||||
throw new IllegalStateException("Could not create worlds.yml config file");
|
||||
}
|
||||
if (exists) {
|
||||
migrateRemoveOldConfigSerializable();
|
||||
}
|
||||
worldsConfig = new YamlConfiguration();
|
||||
worldsConfig.load(worldConfigFile);
|
||||
}
|
||||
|
||||
private void migrateRemoveOldConfigSerializable() {
|
||||
Try.of(() -> Files.readString(worldConfigFile.toPath()))
|
||||
.mapTry(configData -> {
|
||||
if (!configData.contains("==: MVWorld")) {
|
||||
throw new ConfigMigratedException();
|
||||
}
|
||||
return configData.replace(" ==: MVWorld\n", "")
|
||||
.replace(" ==: MVSpawnSettings\n", "")
|
||||
.replace(" ==: MVSpawnSubSettings\n", "")
|
||||
.replace(" ==: MVEntryFee\n", "");
|
||||
})
|
||||
.andThenTry(configData -> Files.writeString(worldConfigFile.toPath(), configData))
|
||||
.andThenTry(() -> {
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(worldConfigFile);
|
||||
List<ConfigurationSection> worlds = config.getConfigurationSection("worlds")
|
||||
.getKeys(false)
|
||||
.stream()
|
||||
.map(worldName -> config.getConfigurationSection("worlds." + worldName))
|
||||
.toList();
|
||||
|
||||
config.set("worlds", null);
|
||||
|
||||
for (ConfigurationSection world : worlds) {
|
||||
config.createSection(world.getName(), world.getValues(true));
|
||||
}
|
||||
config.save(worldConfigFile);
|
||||
})
|
||||
.onFailure(e -> {
|
||||
if (e instanceof ConfigMigratedException) {
|
||||
Logging.fine("Config already migrated");
|
||||
return;
|
||||
}
|
||||
Logging.warning("Failed to migrate old worlds.yml file: %s", e.getMessage());
|
||||
e.printStackTrace();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the worlds.yml file and creates a WorldConfig for each world in the file if it doesn't already exist.
|
||||
*
|
||||
* @return A tuple containing a list of the new WorldConfigs added and a list of the worlds removed from the config.
|
||||
*/
|
||||
private Tuple2<List<WorldConfig>, List<String>> parseNewAndRemovedWorlds() {
|
||||
Set<String> allWorldsInConfig = worldsConfig.getKeys(false);
|
||||
List<WorldConfig> newWorldsAdded = new ArrayList<>();
|
||||
|
||||
for (String worldName : allWorldsInConfig) {
|
||||
getWorldConfig(worldName)
|
||||
.peek(config -> config.load(getWorldConfigSection(worldName)))
|
||||
.onEmpty(() -> {
|
||||
WorldConfig newWorldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName));
|
||||
worldConfigMap.put(worldName, newWorldConfig);
|
||||
newWorldsAdded.add(newWorldConfig);
|
||||
});
|
||||
}
|
||||
|
||||
List<String> worldsRemoved = worldConfigMap.keySet().stream()
|
||||
.filter(worldName -> !allWorldsInConfig.contains(worldName))
|
||||
.toList();
|
||||
|
||||
for (String s : worldsRemoved) {
|
||||
worldConfigMap.remove(s);
|
||||
}
|
||||
|
||||
return new Tuple2<>(newWorldsAdded, worldsRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the worlds.yml file has been loaded.
|
||||
*
|
||||
* @return Whether the worlds.yml file has been loaded.
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return worldsConfig != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the worlds.yml file.
|
||||
*
|
||||
* @return Whether the save was successful or the error that occurred.
|
||||
*/
|
||||
public Try<Void> save() {
|
||||
return Try.run(() -> worldsConfig.save(worldConfigFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link WorldConfig} instance of all worlds in the worlds.yml file.
|
||||
*
|
||||
* @param worldName The name of the world to check.
|
||||
* @return The {@link WorldConfig} instance of the world, or empty option if it doesn't exist.
|
||||
*/
|
||||
public @NotNull Option<WorldConfig> getWorldConfig(@NotNull String worldName) {
|
||||
return Option.of(worldConfigMap.get(worldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new world to the worlds.yml file. If a world with the given name already exists, an exception is thrown.
|
||||
*
|
||||
* @param worldName The name of the world to add.
|
||||
* @return The newly created {@link WorldConfig} instance.
|
||||
*/
|
||||
public @NotNull WorldConfig addWorldConfig(@NotNull String worldName) {
|
||||
if (worldConfigMap.containsKey(worldName)) {
|
||||
throw new IllegalArgumentException("WorldConfig for world " + worldName + " already exists.");
|
||||
}
|
||||
WorldConfig worldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName));
|
||||
worldConfigMap.put(worldName, worldConfig);
|
||||
return worldConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the world config for the given world.
|
||||
*
|
||||
* @param worldName The name of the world to delete.
|
||||
*/
|
||||
public void deleteWorldConfig(@NotNull String worldName) {
|
||||
worldConfigMap.remove(worldName);
|
||||
worldsConfig.set(worldName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ConfigurationSection} for the given world in the worlds.yml file. If the section doesn't exist,
|
||||
* it is created.
|
||||
*
|
||||
* @param worldName The name of the world.
|
||||
* @return The {@link ConfigurationSection} for the given world.
|
||||
*/
|
||||
private ConfigurationSection getWorldConfigSection(String worldName) {
|
||||
return worldsConfig.isConfigurationSection(worldName)
|
||||
? worldsConfig.getConfigurationSection(worldName) : worldsConfig.createSection(worldName);
|
||||
}
|
||||
|
||||
private static final class ConfigMigratedException extends RuntimeException {
|
||||
private ConfigMigratedException() {
|
||||
super("Config migrated");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.config;
|
|
@ -1,4 +1,4 @@
|
|||
package com.onarandombox.MultiverseCore.world.entrycheck;
|
||||
package com.onarandombox.MultiverseCore.worldnew.entrycheck;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
|
@ -6,13 +6,22 @@ import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
|||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
|
||||
|
||||
/**
|
||||
* Result of a world blacklist check.
|
||||
*/
|
||||
public class BlacklistResult {
|
||||
/**
|
||||
* Success reasons for a blacklist check.
|
||||
*/
|
||||
public enum Success implements SuccessReason {
|
||||
UNKNOWN_FROM_WORLD,
|
||||
BYPASSED_BLACKLISTED,
|
||||
NOT_BLACKLISTED
|
||||
}
|
||||
|
||||
/**
|
||||
* Failure reasons for a blacklist check.
|
||||
*/
|
||||
public enum Failure implements FailureReason {
|
||||
BLACKLISTED(MVCorei18n.ENTRYCHECK_BLACKLISTED);
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
package com.onarandombox.MultiverseCore.world.entrycheck;
|
||||
|
||||
package com.onarandombox.MultiverseCore.worldnew.entrycheck;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
|
@ -7,7 +6,13 @@ import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
|||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
|
||||
|
||||
/**
|
||||
* Result of a world entry fee check.
|
||||
*/
|
||||
public class EntryFeeResult {
|
||||
/**
|
||||
* Success reasons for an entry fee check.
|
||||
*/
|
||||
public enum Success implements SuccessReason {
|
||||
FREE_ENTRY,
|
||||
ENOUGH_MONEY,
|
||||
|
@ -15,6 +20,9 @@ public class EntryFeeResult {
|
|||
CONSOLE_OR_BLOCK_COMMAND_SENDER
|
||||
}
|
||||
|
||||
/**
|
||||
* Failure reasons for an entry fee check.
|
||||
*/
|
||||
public enum Failure implements FailureReason {
|
||||
NOT_ENOUGH_MONEY(MVCorei18n.ENTRYCHECK_NOTENOUGHMONEY),
|
||||
CANNOT_PAY_ENTRY_FEE(MVCorei18n.ENTRYCHECK_CANNOTPAYENTRYFEE);
|
|
@ -1,4 +1,4 @@
|
|||
package com.onarandombox.MultiverseCore.world.entrycheck;
|
||||
package com.onarandombox.MultiverseCore.worldnew.entrycheck;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
|
@ -6,13 +6,22 @@ import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
|||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
|
||||
|
||||
/**
|
||||
* Result of a world player limit check.
|
||||
*/
|
||||
public class PlayerLimitResult {
|
||||
/**
|
||||
* Success reasons for a player limit check.
|
||||
*/
|
||||
public enum Success implements SuccessReason {
|
||||
NO_PLAYERLIMIT,
|
||||
WITHIN_PLAYERLIMIT,
|
||||
BYPASS_PLAYERLIMIT
|
||||
}
|
||||
|
||||
/**
|
||||
* Failure reasons for a player limit check.
|
||||
*/
|
||||
public enum Failure implements FailureReason {
|
||||
EXCEED_PLAYERLIMIT(MVCorei18n.ENTRYCHECK_EXCEEDPLAYERLIMIT);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.onarandombox.MultiverseCore.world.entrycheck;
|
||||
package com.onarandombox.MultiverseCore.worldnew.entrycheck;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
|
@ -6,12 +6,21 @@ import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
|||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
import com.onarandombox.MultiverseCore.utils.result.SuccessReason;
|
||||
|
||||
/**
|
||||
* Result of a world access check.
|
||||
*/
|
||||
public class WorldAccessResult {
|
||||
/**
|
||||
* Success reasons for a world access check.
|
||||
*/
|
||||
public enum Success implements SuccessReason {
|
||||
NO_ENFORCE_WORLD_ACCESS,
|
||||
HAS_WORLD_ACCESS
|
||||
}
|
||||
|
||||
/**
|
||||
* Failure reasons for a world access check.
|
||||
*/
|
||||
public enum Failure implements FailureReason {
|
||||
NO_WORLD_ACCESS(MVCorei18n.ENTRYCHECK_NOWORLDACCESS);
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
package com.onarandombox.MultiverseCore.world.entrycheck;
|
||||
package com.onarandombox.MultiverseCore.worldnew.entrycheck;
|
||||
|
||||
import com.onarandombox.MultiverseCore.api.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.economy.MVEconomist;
|
||||
import com.onarandombox.MultiverseCore.permissions.CorePermissionsChecker;
|
||||
import com.onarandombox.MultiverseCore.utils.result.Result;
|
||||
import com.onarandombox.MultiverseCore.utils.result.ResultChain;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.EntryFee;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.MultiverseWorld;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
|
@ -15,8 +17,13 @@ import org.bukkit.entity.Player;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static com.onarandombox.MultiverseCore.utils.message.MessageReplacement.replace;
|
||||
|
||||
/**
|
||||
* Checks if a player can enter a world.
|
||||
*/
|
||||
public class WorldEntryChecker {
|
||||
private final @NotNull MVCoreConfig config;
|
||||
private final @NotNull MVEconomist economist;
|
||||
|
@ -24,23 +31,39 @@ public class WorldEntryChecker {
|
|||
|
||||
private final @NotNull CommandSender sender;
|
||||
|
||||
public WorldEntryChecker(
|
||||
WorldEntryChecker(
|
||||
@NotNull MVCoreConfig config,
|
||||
@NotNull CorePermissionsChecker permissionsChecker,
|
||||
@NotNull MVEconomist economist,
|
||||
@NotNull CommandSender sender
|
||||
) {
|
||||
@NotNull CommandSender sender) {
|
||||
this.config = config;
|
||||
this.permissionsChecker = permissionsChecker;
|
||||
this.economist = economist;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public ResultChain canStayInWorld(@NotNull MVWorld world) {
|
||||
return canEnterWorld(null, world);
|
||||
/**
|
||||
* Checks if the sender have access to be in the world.
|
||||
*
|
||||
* @param world The world to check.
|
||||
* @return The result of the check.
|
||||
*/
|
||||
public ResultChain canStayInWorld(@NotNull LoadedMultiverseWorld world) {
|
||||
return ResultChain.builder()
|
||||
.then(() -> canAccessWorld(world))
|
||||
.then(() -> isWithinPlayerLimit(world))
|
||||
.build();
|
||||
}
|
||||
|
||||
public ResultChain canEnterWorld(@Nullable MVWorld fromWorld, @NotNull MVWorld toWorld) {
|
||||
/**
|
||||
* Checks if the sender can enter the given world.
|
||||
*
|
||||
* @param fromWorld The world the sender is coming from.
|
||||
* @param toWorld The world the sender is going to.
|
||||
* @return The result of the check.
|
||||
*/
|
||||
public ResultChain canEnterWorld(
|
||||
@Nullable LoadedMultiverseWorld fromWorld, @NotNull LoadedMultiverseWorld toWorld) {
|
||||
return ResultChain.builder()
|
||||
.then(() -> canAccessWorld(toWorld))
|
||||
.then(() -> isWithinPlayerLimit(toWorld))
|
||||
|
@ -49,7 +72,13 @@ public class WorldEntryChecker {
|
|||
.build();
|
||||
}
|
||||
|
||||
public Result<WorldAccessResult.Success, WorldAccessResult.Failure> canAccessWorld(@NotNull MVWorld world) {
|
||||
/**
|
||||
* Checks if the sender can access the given world.
|
||||
*
|
||||
* @param world The world to check.
|
||||
* @return The result of the check.
|
||||
*/
|
||||
public Result<WorldAccessResult.Success, WorldAccessResult.Failure> canAccessWorld(@NotNull MultiverseWorld world) {
|
||||
if (!config.getEnforceAccess()) {
|
||||
return Result.success(WorldAccessResult.Success.NO_ENFORCE_WORLD_ACCESS);
|
||||
}
|
||||
|
@ -58,7 +87,14 @@ public class WorldEntryChecker {
|
|||
: Result.failure(WorldAccessResult.Failure.NO_WORLD_ACCESS);
|
||||
}
|
||||
|
||||
public Result<PlayerLimitResult.Success, PlayerLimitResult.Failure> isWithinPlayerLimit(@NotNull MVWorld world) {
|
||||
/**
|
||||
* Checks if the sender is within the player limit of the given world.
|
||||
*
|
||||
* @param world The world to check.
|
||||
* @return The result of the check.
|
||||
*/
|
||||
public Result<PlayerLimitResult.Success, PlayerLimitResult.Failure> isWithinPlayerLimit(
|
||||
@NotNull LoadedMultiverseWorld world) {
|
||||
final int playerLimit = world.getPlayerLimit();
|
||||
if (playerLimit <= -1) {
|
||||
return Result.success(PlayerLimitResult.Success.NO_PLAYERLIMIT);
|
||||
|
@ -66,12 +102,23 @@ public class WorldEntryChecker {
|
|||
if (permissionsChecker.hasPlayerLimitBypassPermission(sender, world)) {
|
||||
return Result.success(PlayerLimitResult.Success.BYPASS_PLAYERLIMIT);
|
||||
}
|
||||
return playerLimit > world.getCBWorld().getPlayers().size()
|
||||
int numberOfPlayersInWorld = world.getBukkitWorld().map(World::getPlayers)
|
||||
.map(Collection::size)
|
||||
.getOrElse(0);
|
||||
return playerLimit > numberOfPlayersInWorld
|
||||
? Result.success(PlayerLimitResult.Success.WITHIN_PLAYERLIMIT)
|
||||
: Result.failure(PlayerLimitResult.Failure.EXCEED_PLAYERLIMIT);
|
||||
}
|
||||
|
||||
public Result<BlacklistResult.Success, BlacklistResult.Failure> isNotBlacklisted(@Nullable MVWorld fromWorld, @NotNull MVWorld toWorld) {
|
||||
/**
|
||||
* Checks if the sender is not blacklisted from the given world.
|
||||
*
|
||||
* @param fromWorld The world the sender is coming from.
|
||||
* @param toWorld The world the sender is going to.
|
||||
* @return The result of the check.
|
||||
*/
|
||||
public Result<BlacklistResult.Success, BlacklistResult.Failure> isNotBlacklisted(
|
||||
@Nullable LoadedMultiverseWorld fromWorld, @NotNull LoadedMultiverseWorld toWorld) {
|
||||
if (fromWorld == null) {
|
||||
return Result.success(BlacklistResult.Success.UNKNOWN_FROM_WORLD);
|
||||
}
|
||||
|
@ -80,7 +127,13 @@ public class WorldEntryChecker {
|
|||
: Result.success(BlacklistResult.Success.NOT_BLACKLISTED);
|
||||
}
|
||||
|
||||
public Result<EntryFeeResult.Success, EntryFeeResult.Failure> canPayEntryFee(MVWorld world) {
|
||||
/**
|
||||
* Checks if the sender can pay the entry fee for the given world.
|
||||
*
|
||||
* @param world The world to check.
|
||||
* @return The result of the check.
|
||||
*/
|
||||
public Result<EntryFeeResult.Success, EntryFeeResult.Failure> canPayEntryFee(LoadedMultiverseWorld world) {
|
||||
double price = world.getPrice();
|
||||
Material currency = world.getCurrency();
|
||||
if (price == 0D && (currency == null || currency == EntryFee.DISABLED_MATERIAL)) {
|
||||
|
@ -97,6 +150,8 @@ public class WorldEntryChecker {
|
|||
}
|
||||
return economist.isPlayerWealthyEnough(player, price, currency)
|
||||
? Result.success(EntryFeeResult.Success.ENOUGH_MONEY)
|
||||
: Result.failure(EntryFeeResult.Failure.NOT_ENOUGH_MONEY, replace("{amount}").with("$##")); // TODO: Money formatting
|
||||
: Result.failure(EntryFeeResult.Failure.NOT_ENOUGH_MONEY,
|
||||
replace("{amount}").with("$##"));
|
||||
// TODO: Money formatting
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.onarandombox.MultiverseCore.world.entrycheck;
|
||||
package com.onarandombox.MultiverseCore.worldnew.entrycheck;
|
||||
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.economy.MVEconomist;
|
||||
|
@ -19,8 +19,7 @@ public class WorldEntryCheckerProvider {
|
|||
WorldEntryCheckerProvider(
|
||||
@NotNull MVCoreConfig config,
|
||||
@NotNull MVEconomist economist,
|
||||
@NotNull CorePermissionsChecker permissionsChecker
|
||||
) {
|
||||
@NotNull CorePermissionsChecker permissionsChecker) {
|
||||
this.config = config;
|
||||
this.economist = economist;
|
||||
this.permissionsChecker = permissionsChecker;
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.entrycheck;
|
|
@ -0,0 +1,65 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.generators;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* <p>A generator API for Multiverse.</p>
|
||||
*
|
||||
* <p>Any generator plugin can register themselves to Multiverse. This will provide Multiverse with addition
|
||||
* information about your generator plugin such as generator id suggestions, example usages and link to more
|
||||
* info on your generator plugin.</p>
|
||||
*/
|
||||
public interface GeneratorPlugin {
|
||||
/**
|
||||
* <p>Suggest possible generator ids. To be used in command tab-completion.</p>
|
||||
*
|
||||
* <p>These suggestions can be static without relying on currentIdInput, or dynamically changed based
|
||||
* on the currentIdInput.</p>
|
||||
*
|
||||
* @param currentIdInput The current state user input. This may be null or empty if user has not started
|
||||
* any input for generator id.
|
||||
* @return Collection of suggested generator ids.
|
||||
*/
|
||||
@NotNull Collection<String> suggestIds(@Nullable String currentIdInput);
|
||||
|
||||
/**
|
||||
* <p>Gets command usages that users can try to generate a world with your generator plugin. Returning null means
|
||||
* you do not wish to show any usage examples for your generator plugin.</p>
|
||||
*
|
||||
* <p>An example command: '/mv create myworld normal -g CoolGen:FunWorld'</p>
|
||||
*
|
||||
* <p>Notes on usage of this method:</p>
|
||||
* <ul>
|
||||
* <li>Feel free to have colors in your command usage, but not Multiverse won't parse color codes for you.</li>
|
||||
* <li>Please include the starting slash '/' in your usage examples.</li>
|
||||
* <li>We suggest keeping the usage to at most 5 examples.</li>
|
||||
* <li>This should not be a full explanation on all your generator plugin, just basics usages to get people
|
||||
* started. For full guide, you can use {@link #getInfoLink()} to direct users.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return A collection of command usage examples.
|
||||
*/
|
||||
@Nullable Collection<String> getExampleUsages();
|
||||
|
||||
/**
|
||||
* <p>Gets a link with more information on your generator plugin. Returning null means you do not wish to link
|
||||
* users to any website related to your generator plugin.</p>
|
||||
*
|
||||
* <p>An example info: 'Click on https://www.amazinggenerator.io ;)'</p>
|
||||
*
|
||||
* <p>Some suggested places you can link to are: spigot resource page, github repo or your own plugin site.</p>
|
||||
*
|
||||
* @return Link to more info on your generator plugin.
|
||||
*/
|
||||
@Nullable String getInfoLink();
|
||||
|
||||
/**
|
||||
* Gets the java plugin for this generator. In short, return your own generator plugin instance.
|
||||
*
|
||||
* @return The associated plugin for this generator.
|
||||
*/
|
||||
@NotNull String getPluginName();
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.generators;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.onarandombox.MultiverseCore.utils.file.FileUtils.getBukkitConfig;
|
||||
|
||||
/**
|
||||
* Parse the default world generators from the bukkit config and load any generator plugins.
|
||||
* Helps in suggesting and validating generator strings.
|
||||
*/
|
||||
@Service
|
||||
public class GeneratorProvider implements Listener {
|
||||
private final Map<String, String> defaultGenerators;
|
||||
private final Map<String, GeneratorPlugin> generatorPlugins;
|
||||
|
||||
@Inject
|
||||
GeneratorProvider(@NotNull MultiverseCore multiverseCore) {
|
||||
defaultGenerators = new HashMap<>();
|
||||
generatorPlugins = new HashMap<>();
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, multiverseCore);
|
||||
loadDefaultWorldGenerators();
|
||||
loadPluginGenerators();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the default world generators string from the bukkit config.
|
||||
*/
|
||||
private void loadDefaultWorldGenerators() {
|
||||
File bukkitConfigFile = getBukkitConfig();
|
||||
if (bukkitConfigFile == null) {
|
||||
Logging.warning("Any default world generators will not be loaded!");
|
||||
return;
|
||||
}
|
||||
|
||||
FileConfiguration bukkitConfig = YamlConfiguration.loadConfiguration(bukkitConfigFile);
|
||||
ConfigurationSection worldSection = bukkitConfig.getConfigurationSection("worlds");
|
||||
if (worldSection != null) {
|
||||
Set<String> keys = worldSection.getKeys(false);
|
||||
keys.forEach(key -> defaultGenerators.put(key, bukkitConfig.getString("worlds." + key + ".generator", "")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find generator plugins from plugins loaded and register them.
|
||||
*/
|
||||
private void loadPluginGenerators() {
|
||||
Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(plugin -> {
|
||||
if (testIsGeneratorPlugin(plugin)) {
|
||||
registerGeneratorPlugin(new SimpleGeneratorPlugin(plugin.getName()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test if a plugin is a generator plugin.
|
||||
*
|
||||
* @param plugin The plugin to test.
|
||||
* @return True if the plugin is a generator plugin, else false.
|
||||
*/
|
||||
private boolean testIsGeneratorPlugin(Plugin plugin) {
|
||||
String worldName = Bukkit.getWorlds().stream().findFirst().map(World::getName).orElse("world");
|
||||
return Try.of(() -> plugin.getDefaultWorldGenerator(worldName, "") != null)
|
||||
.recover(IllegalArgumentException.class, true)
|
||||
.recover(throwable -> {
|
||||
Logging.warning("Plugin %s threw an exception when testing if it is a generator plugin!",
|
||||
plugin.getName());
|
||||
throwable.printStackTrace();
|
||||
return false;
|
||||
}).getOrElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default generator for a world from the bukkit.yml config.
|
||||
*
|
||||
* @param worldName The name of the world.
|
||||
* @return The default generator string for the world, or null if none.
|
||||
*/
|
||||
public @Nullable String getDefaultGeneratorForWorld(String worldName) {
|
||||
return defaultGenerators.getOrDefault(worldName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to register a plugin as {@link SimpleGeneratorPlugin}.
|
||||
*
|
||||
* @param generatorPlugin The plugin to register.
|
||||
* @return True if registered successfully, else false.
|
||||
*/
|
||||
public boolean registerGeneratorPlugin(@NotNull GeneratorPlugin generatorPlugin) {
|
||||
var registeredGenerator = generatorPlugins.get(generatorPlugin.getPluginName());
|
||||
if (registeredGenerator == null || registeredGenerator instanceof SimpleGeneratorPlugin) {
|
||||
generatorPlugins.put(generatorPlugin.getPluginName(), generatorPlugin);
|
||||
return true;
|
||||
}
|
||||
Logging.severe("Generator plugin with name %s is already registered!", generatorPlugin.getPluginName());
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a plugin.
|
||||
*
|
||||
* @param pluginName The plugin to unregister.
|
||||
* @return True if the plugin was present and now unregistered, else false.
|
||||
*/
|
||||
public boolean unregisterGeneratorPlugin(@NotNull String pluginName) {
|
||||
if (generatorPlugins.containsKey(pluginName)) {
|
||||
generatorPlugins.remove(pluginName);
|
||||
return true;
|
||||
}
|
||||
Logging.severe("Generator plugin with name %s is not registered!", pluginName);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a plugin is registered as a generator plugin.
|
||||
*
|
||||
* @param pluginName The name of the plugin.
|
||||
* @return True if the plugin is registered, else false.
|
||||
*/
|
||||
public boolean isGeneratorPluginRegistered(@NotNull String pluginName) {
|
||||
return generatorPlugins.containsKey(pluginName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a generator plugin by name.
|
||||
*
|
||||
* @param pluginName The name of the plugin.
|
||||
* @return The generator plugin, or null if not registered.
|
||||
*/
|
||||
public @Nullable GeneratorPlugin getGeneratorPlugin(@NotNull String pluginName) {
|
||||
return generatorPlugins.get(pluginName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto complete generator strings, used in command tab completion.
|
||||
*
|
||||
* @param currentInput The current input from the user.
|
||||
* @return A collection of suggestions.
|
||||
*/
|
||||
public Collection<String> suggestGeneratorString(@Nullable String currentInput) {
|
||||
String[] genSpilt = currentInput == null ? new String[0] : currentInput.split(":", 2);
|
||||
List<String> suggestions = new ArrayList<>(generatorPlugins.keySet());
|
||||
if (genSpilt.length < 2) {
|
||||
return suggestions;
|
||||
}
|
||||
GeneratorPlugin generatorPlugin = generatorPlugins.get(genSpilt[0]);
|
||||
if (generatorPlugin == null) {
|
||||
return suggestions;
|
||||
}
|
||||
suggestions.addAll(generatorPlugin.suggestIds(genSpilt[1]).stream().map(id -> genSpilt[0] + ":" + id).toList());
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to plugins enabled to see if they are generator plugins.
|
||||
*
|
||||
* @param event The plugin enable event.
|
||||
*/
|
||||
@EventHandler
|
||||
private void onPluginEnable(PluginEnableEvent event) {
|
||||
if (!testIsGeneratorPlugin(event.getPlugin())) {
|
||||
Logging.finest("Plugin %s is not a generator plugin.", event.getPlugin().getName());
|
||||
return;
|
||||
}
|
||||
if (!registerGeneratorPlugin(new SimpleGeneratorPlugin(event.getPlugin().getName()))) {
|
||||
Logging.severe("Failed to register generator plugin %s!", event.getPlugin().getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to plugins disabled to see if they are generator plugins. If so, unregister them.
|
||||
*
|
||||
* @param event The plugin disable event.
|
||||
*/
|
||||
@EventHandler
|
||||
private void onPluginDisable(PluginDisableEvent event) {
|
||||
if (!isGeneratorPluginRegistered(event.getPlugin().getName())) {
|
||||
Logging.finest("Plugin %s is not a generator plugin.", event.getPlugin().getName());
|
||||
return;
|
||||
}
|
||||
if (!unregisterGeneratorPlugin(event.getPlugin().getName())) {
|
||||
Logging.severe("Failed to unregister generator plugin %s!", event.getPlugin().getName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.generators;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* A default implementation of {@link GeneratorPlugin} for those generator plugins that do not provide their own
|
||||
* custom {@link GeneratorPlugin} implementation to Multiverse.
|
||||
*/
|
||||
public final class SimpleGeneratorPlugin implements GeneratorPlugin {
|
||||
private final String pluginName;
|
||||
|
||||
SimpleGeneratorPlugin(@NotNull String pluginName) {
|
||||
this.pluginName = pluginName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Collection<String> suggestIds(@Nullable String currentIdInput) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @Nullable Collection<String> getExampleUsages() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @Nullable String getInfoLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String getPluginName() {
|
||||
return pluginName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.generators;
|
|
@ -0,0 +1,160 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.helpers;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A data store for storing and restoring data from an object.
|
||||
*
|
||||
* @param <T> The type of the object to store data from.
|
||||
*/
|
||||
@Service
|
||||
public interface DataStore<T> {
|
||||
/**
|
||||
* Stores the data from the given object in this {@link DataStore} instance.
|
||||
*
|
||||
* @param object The object to copy data from.
|
||||
* @return This {@link DataStore} instance.
|
||||
*/
|
||||
DataStore<T> copyFrom(T object);
|
||||
|
||||
/**
|
||||
* Copies the data from this {@link DataStore} instance to the given object.
|
||||
*
|
||||
* @param object The object to paste data to.
|
||||
* @return This {@link DataStore} instance.
|
||||
*/
|
||||
DataStore<T> pasteTo(T object);
|
||||
|
||||
/**
|
||||
* A {@link DataStore} for storing and restoring game rules for a multiverse world.
|
||||
*/
|
||||
class GameRulesStore implements DataStore<LoadedMultiverseWorld> {
|
||||
private Map<GameRule<?>, Object> gameRuleMap;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public GameRulesStore copyFrom(LoadedMultiverseWorld world) {
|
||||
this.gameRuleMap = new HashMap<>();
|
||||
world.getBukkitWorld().peek(bukkitWorld -> {
|
||||
Arrays.stream(GameRule.values()).forEach(gameRule -> {
|
||||
Object value = bukkitWorld.getGameRuleValue(gameRule);
|
||||
gameRuleMap.put(gameRule, value);
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public GameRulesStore pasteTo(LoadedMultiverseWorld world) {
|
||||
if (gameRuleMap == null) {
|
||||
return this;
|
||||
}
|
||||
world.getBukkitWorld().peek(bukkitWorld -> gameRuleMap.forEach((gameRule, value) -> {
|
||||
setGameRuleValue(bukkitWorld, gameRule, value).onFailure(e -> {
|
||||
Logging.warning("Failed to set game rule " + gameRule.getName() + " to " + value);
|
||||
e.printStackTrace();
|
||||
});
|
||||
}));
|
||||
return this;
|
||||
}
|
||||
|
||||
private <T> Try<Void> setGameRuleValue(World world, GameRule<T> gameRule, Object value) {
|
||||
return Try.run(() -> world.setGameRule(gameRule, (T) value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link DataStore} for storing and restoring world properties for a multiverse world.
|
||||
*/
|
||||
class WorldConfigStore implements DataStore<LoadedMultiverseWorld> {
|
||||
private Map<String, Object> configMap;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public WorldConfigStore copyFrom(LoadedMultiverseWorld world) {
|
||||
this.configMap = new HashMap<>();
|
||||
world.getConfigurablePropertyNames().forEach(name -> world.getProperty(name)
|
||||
.peek(value -> configMap.put(name, value)).onFailure(e -> {
|
||||
Logging.warning("Failed to get property " + name + " from world "
|
||||
+ world.getName() + ": " + e.getMessage());
|
||||
}));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public WorldConfigStore pasteTo(LoadedMultiverseWorld world) {
|
||||
if (configMap == null) {
|
||||
return this;
|
||||
}
|
||||
configMap.forEach((name, value) -> {
|
||||
world.setProperty(name, value).onFailure(e -> {
|
||||
Logging.warning("Failed to set property %s to %s for world %s: %s",
|
||||
name, value, world.getName(), e.getMessage());
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link DataStore} for storing and restoring world border properties for a multiverse world.
|
||||
*/
|
||||
class WorldBorderStore implements DataStore<LoadedMultiverseWorld> {
|
||||
private double borderCenterX;
|
||||
private double borderCenterZ;
|
||||
private double borderDamageAmount;
|
||||
private double borderDamageBuffer;
|
||||
private double borderSize;
|
||||
private int borderTimeRemaining;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public WorldBorderStore copyFrom(LoadedMultiverseWorld world) {
|
||||
world.getBukkitWorld().peek(bukkitWorld -> {
|
||||
borderCenterX = bukkitWorld.getWorldBorder().getCenter().getX();
|
||||
borderCenterZ = bukkitWorld.getWorldBorder().getCenter().getZ();
|
||||
borderDamageAmount = bukkitWorld.getWorldBorder().getDamageAmount();
|
||||
borderDamageBuffer = bukkitWorld.getWorldBorder().getDamageBuffer();
|
||||
borderSize = bukkitWorld.getWorldBorder().getSize();
|
||||
borderTimeRemaining = bukkitWorld.getWorldBorder().getWarningTime();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public WorldBorderStore pasteTo(LoadedMultiverseWorld world) {
|
||||
world.getBukkitWorld().peek(bukkitWorld -> {
|
||||
bukkitWorld.getWorldBorder().setCenter(borderCenterX, borderCenterZ);
|
||||
bukkitWorld.getWorldBorder().setDamageAmount(borderDamageAmount);
|
||||
bukkitWorld.getWorldBorder().setDamageBuffer(borderDamageBuffer);
|
||||
bukkitWorld.getWorldBorder().setSize(borderSize);
|
||||
bukkitWorld.getWorldBorder().setWarningTime(borderTimeRemaining);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.helpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A data transfer for storing and restoring data from multiple {@link DataStore} from one object to another.
|
||||
*
|
||||
* @param <T> The type of the object to transfer data from and to.
|
||||
*/
|
||||
public class DataTransfer<T> {
|
||||
private final List<DataStore<T>> dataStores;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DataTransfer} instance.
|
||||
*/
|
||||
public DataTransfer() {
|
||||
this.dataStores = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link DataStore} to this {@link DataTransfer} instance.
|
||||
*
|
||||
* @param dataStore The {@link DataStore} to add.
|
||||
* @param object The object to copy data from.
|
||||
* @return This {@link DataTransfer} instance.
|
||||
*/
|
||||
public DataTransfer<T> addDataStore(DataStore<T> dataStore, T object) {
|
||||
this.dataStores.add(dataStore.copyFrom(object));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the data from all {@link DataStore} instances in this {@link DataTransfer} instance to the given object.
|
||||
*
|
||||
* @param object The object to paste data to.
|
||||
* @return This {@link DataTransfer} instance.
|
||||
*/
|
||||
public DataTransfer<T> pasteAllTo(T object) {
|
||||
this.dataStores.forEach(dataStore -> dataStore.pasteTo(object));
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.helpers;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import io.vavr.control.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
|
||||
|
||||
/**
|
||||
* A helper class for manipulating files and folders.
|
||||
*/
|
||||
@Service
|
||||
public class FilesManipulator {
|
||||
|
||||
/**
|
||||
* Deletes the given folder completely.
|
||||
*
|
||||
* @param file The folder to delete.
|
||||
* @return A {@link Try} that will contain {@code null} if the folder was deleted successfully, or an exception if
|
||||
* the folder could not be deleted.
|
||||
*/
|
||||
public Try<Void> deleteFolder(File file) {
|
||||
return deleteFolder(file.toPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given folder completely.
|
||||
*
|
||||
* @param path The folder to delete.
|
||||
* @return A {@link Try} that will contain {@code null} if the folder was deleted successfully, or an exception if
|
||||
* the folder could not be deleted.
|
||||
*/
|
||||
public Try<Void> deleteFolder(Path path) {
|
||||
try (Stream<Path> files = Files.walk(path)) {
|
||||
files.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
|
||||
return Try.success(null);
|
||||
} catch (IOException e) {
|
||||
Logging.severe("Failed to delete folder: " + path.toAbsolutePath());
|
||||
e.printStackTrace();
|
||||
return Try.failure(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the content of the given folder to the given target folder.
|
||||
*
|
||||
* @param sourceDir The folder to copy.
|
||||
* @param targetDir The target folder to copy to.
|
||||
* @return A {@link Try} that will contain {@code null} if the folder was copied successfully, or an exception if
|
||||
* the folder could not be copied.
|
||||
*/
|
||||
public Try<Void> copyFolder(File sourceDir, File targetDir) {
|
||||
return copyFolder(sourceDir.toPath(), targetDir.toPath(), Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies most of the content of the given folder to the given target folder, except the list of excluded files
|
||||
* specified.
|
||||
*
|
||||
* @param sourceDir The folder to copy.
|
||||
* @param targetDir The target folder to copy to.
|
||||
* @param excludeFiles The list of files to exclude from copying.
|
||||
* @return A {@link Try} that will contain {@code null} if the folder was copied successfully, or an exception if
|
||||
*/
|
||||
public Try<Void> copyFolder(File sourceDir, File targetDir, List<String> excludeFiles) {
|
||||
return copyFolder(sourceDir.toPath(), targetDir.toPath(), excludeFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the content of the given folder to the given target folder.
|
||||
*
|
||||
* @param sourceDir The folder to copy.
|
||||
* @param targetDir The target folder to copy to.
|
||||
* @return A {@link Try} that will contain {@code null} if the folder was copied successfully, or an exception if
|
||||
* the folder could not be copied.
|
||||
*/
|
||||
public Try<Void> copyFolder(Path sourceDir, Path targetDir) {
|
||||
return copyFolder(sourceDir, targetDir, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies most of the content of the given folder to the given target folder, except the list of excluded files
|
||||
* specified.
|
||||
*
|
||||
* @param sourceDir The folder to copy.
|
||||
* @param targetDir The target folder to copy to.
|
||||
* @param excludeFiles The list of files to exclude from copying.
|
||||
* @return A {@link Try} that will contain {@code null} if the folder was copied successfully, or an exception if
|
||||
*/
|
||||
public Try<Void> copyFolder(Path sourceDir, Path targetDir, List<String> excludeFiles) {
|
||||
return Try.run(() -> Files.walkFileTree(sourceDir, new CopyDirFileVisitor(sourceDir, targetDir, excludeFiles)))
|
||||
.onFailure(e -> {
|
||||
Logging.severe("Failed to copy folder: " + sourceDir.toAbsolutePath());
|
||||
e.printStackTrace();
|
||||
});
|
||||
}
|
||||
|
||||
private static final class CopyDirFileVisitor extends SimpleFileVisitor<Path> {
|
||||
|
||||
private final Path sourceDir;
|
||||
private final Path targetDir;
|
||||
private final List<String> excludeFiles;
|
||||
|
||||
private CopyDirFileVisitor(@NotNull Path sourceDir, @NotNull Path targetDir, @NotNull List<String> excludeFiles) {
|
||||
this.sourceDir = sourceDir;
|
||||
this.targetDir = targetDir;
|
||||
this.excludeFiles = excludeFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||
Path newDir = targetDir.resolve(sourceDir.relativize(dir));
|
||||
if (!Files.isDirectory(newDir)) {
|
||||
Files.createDirectory(newDir);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
// Pass files that are set to ignore
|
||||
if (excludeFiles.contains(file.getFileName().toString())) {
|
||||
Logging.finest("Ignoring file: " + file.getFileName());
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
// Copy the files
|
||||
Path targetFile = targetDir.resolve(sourceDir.relativize(file));
|
||||
Files.copy(file, targetFile, COPY_ATTRIBUTES);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.helpers;
|
|
@ -0,0 +1,118 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.options;
|
||||
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Options for customizing the cloning of a world.
|
||||
*/
|
||||
public final class CloneWorldOptions implements KeepWorldSettingsOptions {
|
||||
|
||||
/**
|
||||
* Creates a new {@link CloneWorldOptions} instance with the given world.
|
||||
*
|
||||
* @param world The world to clone.
|
||||
* @param newWorldName The name of the new world.
|
||||
* @return A new {@link CloneWorldOptions} instance.
|
||||
*/
|
||||
public static CloneWorldOptions fromTo(LoadedMultiverseWorld world, String newWorldName) {
|
||||
return new CloneWorldOptions(world, newWorldName);
|
||||
}
|
||||
|
||||
private final LoadedMultiverseWorld world;
|
||||
private final String newWorldName;
|
||||
private boolean keepGameRule = true;
|
||||
private boolean keepWorldConfig = true;
|
||||
|
||||
private boolean keepWorldBorder = true;
|
||||
|
||||
CloneWorldOptions(LoadedMultiverseWorld world, String newWorldName) {
|
||||
this.world = world;
|
||||
this.newWorldName = newWorldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world to clone.
|
||||
*
|
||||
* @return The world to clone.
|
||||
*/
|
||||
public LoadedMultiverseWorld world() {
|
||||
return world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the new world.
|
||||
*
|
||||
* @return The name of the new world.
|
||||
*/
|
||||
public String newWorldName() {
|
||||
return newWorldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to keep the game rule of the world during cloning.
|
||||
*
|
||||
* @param keepGameRuleInput Whether to keep the game rule of the world during cloning.
|
||||
* @return This {@link CloneWorldOptions} instance.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull CloneWorldOptions keepGameRule(boolean keepGameRuleInput) {
|
||||
this.keepGameRule = keepGameRuleInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to keep the game rule of the world during cloning.
|
||||
*
|
||||
* @return Whether to keep the game rule of the world during cloning.
|
||||
*/
|
||||
@Override
|
||||
public boolean keepGameRule() {
|
||||
return keepGameRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to keep the world config of the world during cloning.
|
||||
*
|
||||
* @param keepWorldConfigInput Whether to keep the world config of the world.
|
||||
* @return This {@link CloneWorldOptions} instance.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull CloneWorldOptions keepWorldConfig(boolean keepWorldConfigInput) {
|
||||
this.keepWorldConfig = keepWorldConfigInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to keep the world config of the world during cloning.
|
||||
*
|
||||
* @return Whether to keep the world config of the world during cloning.
|
||||
*/
|
||||
@Override
|
||||
public boolean keepWorldConfig() {
|
||||
return keepWorldConfig;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether to keep the world border of the world during cloning.
|
||||
*
|
||||
* @param keepWorldBorderInput Whether to keep the world border of the world.
|
||||
* @return This {@link CloneWorldOptions} instance.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull CloneWorldOptions keepWorldBorder(boolean keepWorldBorderInput) {
|
||||
this.keepWorldBorder = keepWorldBorderInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to keep the world border of the world during cloning.
|
||||
*
|
||||
* @return Whether to keep the world border of the world during cloning.
|
||||
*/
|
||||
@Override
|
||||
public boolean keepWorldBorder() {
|
||||
return keepWorldBorder;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.options;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Options for customizing the creation of a new world.
|
||||
*/
|
||||
public class CreateWorldOptions {
|
||||
|
||||
/**
|
||||
* Creates a new {@link CreateWorldOptions} instance with the given world name.
|
||||
*
|
||||
* @param worldName The name of the world to create.
|
||||
* @return A new {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public static @NotNull CreateWorldOptions worldName(@NotNull String worldName) {
|
||||
return new CreateWorldOptions(worldName);
|
||||
}
|
||||
|
||||
private final String worldName;
|
||||
private World.Environment environment = World.Environment.NORMAL;
|
||||
private boolean generateStructures = true;
|
||||
private String generator = null;
|
||||
private long seed;
|
||||
private boolean useSpawnAdjust = true;
|
||||
private WorldType worldType = WorldType.NORMAL;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CreateWorldOptions} instance with the given world name.
|
||||
*
|
||||
* @param worldName The name of the world to create.
|
||||
*/
|
||||
CreateWorldOptions(@NotNull String worldName) {
|
||||
this.worldName = worldName;
|
||||
this.seed = (new Random()).nextLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the world to create.
|
||||
*
|
||||
* @return The name of the world to create.
|
||||
*/
|
||||
public @NotNull String worldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the environment of the world to create.
|
||||
*
|
||||
* @param environmentInput The environment of the world to create.
|
||||
* @return This {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull CreateWorldOptions environment(@NotNull World.Environment environmentInput) {
|
||||
this.environment = environmentInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the environment of the world to create.
|
||||
*
|
||||
* @return The environment of the world to create.
|
||||
*/
|
||||
public @NotNull World.Environment environment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether structures such as NPC villages should be generated.
|
||||
*
|
||||
* @param generateStructuresInput Whether structures such as NPC villages should be generated.
|
||||
* @return This {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull CreateWorldOptions generateStructures(boolean generateStructuresInput) {
|
||||
this.generateStructures = generateStructuresInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether structures such as NPC villages should be generated.
|
||||
*
|
||||
* @return Whether structures such as NPC villages should be generated.
|
||||
*/
|
||||
public boolean generateStructures() {
|
||||
return generateStructures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom generator plugin and its parameters.
|
||||
*
|
||||
* @param generatorInput The custom generator plugin and its parameters.
|
||||
* @return This {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull CreateWorldOptions generator(@Nullable String generatorInput) {
|
||||
this.generator = generatorInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom generator plugin and its parameters.
|
||||
*
|
||||
* @return The custom generator plugin and its parameters.
|
||||
*/
|
||||
public @Nullable String generator() {
|
||||
return generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the seed of the world to create. If the seed is a number, it will be parsed as a long. Otherwise, it will be
|
||||
* hashed.
|
||||
*
|
||||
* @param seedInput The seed of the world to create.
|
||||
* @return This {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull CreateWorldOptions seed(@Nullable String seedInput) {
|
||||
if (seedInput == null) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
this.seed = Long.parseLong(seedInput);
|
||||
} catch (NumberFormatException numberformatexception) {
|
||||
this.seed = seedInput.hashCode();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the seed of the world to create.
|
||||
*
|
||||
* @param seedInput The seed of the world to create.
|
||||
* @return This {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull CreateWorldOptions seed(long seedInput) {
|
||||
this.seed = seedInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the seed of the world to create.
|
||||
*
|
||||
* @return The seed of the world to create.
|
||||
*/
|
||||
public long seed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether multiverse will search for a safe spawn location.
|
||||
*
|
||||
* @param useSpawnAdjustInput Whether multiverse will search for a safe spawn location.
|
||||
* @return This {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull CreateWorldOptions useSpawnAdjust(boolean useSpawnAdjustInput) {
|
||||
this.useSpawnAdjust = useSpawnAdjustInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether multiverse will search for a safe spawn location.
|
||||
*
|
||||
* @return Whether multiverse will search for a safe spawn location.
|
||||
*/
|
||||
public boolean useSpawnAdjust() {
|
||||
return useSpawnAdjust;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world type.
|
||||
*
|
||||
* @param worldTypeInput The world type.
|
||||
* @return This {@link CreateWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull CreateWorldOptions worldType(@NotNull WorldType worldTypeInput) {
|
||||
this.worldType = worldTypeInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world type.
|
||||
*
|
||||
* @return The world type.
|
||||
*/
|
||||
public @NotNull WorldType worldType() {
|
||||
return worldType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.options;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Options for customizing the import of a new world.
|
||||
*/
|
||||
public class ImportWorldOptions {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ImportWorldOptions} instance with the given world name.
|
||||
*
|
||||
* @param worldName The name of the world to create.
|
||||
* @return A new {@link ImportWorldOptions} instance.
|
||||
*/
|
||||
public static @NotNull ImportWorldOptions worldName(@NotNull String worldName) {
|
||||
return new ImportWorldOptions(worldName);
|
||||
}
|
||||
|
||||
private final String worldName;
|
||||
private World.Environment environment = World.Environment.NORMAL;
|
||||
private String generator = null;
|
||||
private boolean useSpawnAdjust = true;
|
||||
|
||||
ImportWorldOptions(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the world to create.
|
||||
*
|
||||
* @return The name of the world to create.
|
||||
*/
|
||||
public @NotNull String worldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the environment of the world to create.
|
||||
*
|
||||
* @param environmentInput The environment of the world to create.
|
||||
* @return This {@link ImportWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull ImportWorldOptions environment(@NotNull World.Environment environmentInput) {
|
||||
this.environment = environmentInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the environment of the world to create.
|
||||
*
|
||||
* @return The environment of the world to create.
|
||||
*/
|
||||
public @NotNull World.Environment environment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom generator plugin and its parameters.
|
||||
*
|
||||
* @param generatorInput The custom generator plugin and its parameters.
|
||||
* @return This {@link ImportWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull ImportWorldOptions generator(@Nullable String generatorInput) {
|
||||
this.generator = generatorInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom generator plugin and its parameters.
|
||||
*
|
||||
* @return The custom generator plugin and its parameters.
|
||||
*/
|
||||
public @Nullable String generator() {
|
||||
return generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether multiverse will search for a safe spawn location.
|
||||
*
|
||||
* @param useSpawnAdjustInput Whether multiverse will search for a safe spawn location.
|
||||
* @return This {@link ImportWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull ImportWorldOptions useSpawnAdjust(boolean useSpawnAdjustInput) {
|
||||
this.useSpawnAdjust = useSpawnAdjustInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether multiverse will search for a safe spawn location.
|
||||
*
|
||||
* @return Whether multiverse will search for a safe spawn location.
|
||||
*/
|
||||
public boolean useSpawnAdjust() {
|
||||
return useSpawnAdjust;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.options;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Options for customizing the keeping of world settings. Used by clone and regen.
|
||||
*/
|
||||
public sealed interface KeepWorldSettingsOptions permits CloneWorldOptions, RegenWorldOptions {
|
||||
|
||||
/**
|
||||
* Sets whether to keep the game rule of the world.
|
||||
*
|
||||
* @param keepGameRuleInput Whether to keep the game rule of the world.
|
||||
* @return This {@link KeepWorldSettingsOptions} instance.
|
||||
*/
|
||||
@NotNull KeepWorldSettingsOptions keepGameRule(boolean keepGameRuleInput);
|
||||
|
||||
/**
|
||||
* Gets whether to keep the game rule of the world.
|
||||
*
|
||||
* @return Whether to keep the game rule of the world.
|
||||
*/
|
||||
boolean keepGameRule();
|
||||
|
||||
/**
|
||||
* Sets whether to keep the world config of the world.
|
||||
*
|
||||
* @param keepWorldConfigInput Whether to keep the world config of the world.
|
||||
* @return This {@link KeepWorldSettingsOptions} instance.
|
||||
*/
|
||||
@NotNull KeepWorldSettingsOptions keepWorldConfig(boolean keepWorldConfigInput);
|
||||
|
||||
/**
|
||||
* Gets whether to keep the world config of the world.
|
||||
*
|
||||
* @return Whether to keep the world config of the world.
|
||||
*/
|
||||
boolean keepWorldConfig();
|
||||
|
||||
/**
|
||||
* Sets whether to keep the world border of the world.
|
||||
*
|
||||
* @param keepWorldBorderInput Whether to keep the world border of the world.
|
||||
* @return This {@link KeepWorldSettingsOptions} instance.
|
||||
*/
|
||||
@NotNull KeepWorldSettingsOptions keepWorldBorder(boolean keepWorldBorderInput);
|
||||
|
||||
/**
|
||||
* Gets whether to keep the world border of the world.
|
||||
*
|
||||
* @return Whether to keep the world border of the world.
|
||||
*/
|
||||
boolean keepWorldBorder();
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.options;
|
||||
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Options for customizing the regeneration of a world.
|
||||
*/
|
||||
public final class RegenWorldOptions implements KeepWorldSettingsOptions {
|
||||
|
||||
/**
|
||||
* Creates a new {@link RegenWorldOptions} instance with the given world.
|
||||
*
|
||||
* @param world The world to regenerate.
|
||||
* @return A new {@link RegenWorldOptions} instance.
|
||||
*/
|
||||
public static @NotNull RegenWorldOptions world(@NotNull LoadedMultiverseWorld world) {
|
||||
return new RegenWorldOptions(world);
|
||||
}
|
||||
|
||||
private final LoadedMultiverseWorld world;
|
||||
private boolean keepGameRule = true;
|
||||
private boolean keepWorldConfig = true;
|
||||
|
||||
private boolean keepWorldBorder = true;
|
||||
private boolean randomSeed = false;
|
||||
private long seed = Long.MIN_VALUE;
|
||||
|
||||
RegenWorldOptions(@NotNull LoadedMultiverseWorld world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world to regenerate.
|
||||
*
|
||||
* @return The world to regenerate.
|
||||
*/
|
||||
public @NotNull LoadedMultiverseWorld world() {
|
||||
return world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to keep the game rule of the world during regeneration.
|
||||
*
|
||||
* @param keepGameRuleInput Whether to keep the game rule of the world during regeneration.
|
||||
* @return This {@link RegenWorldOptions} instance.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull RegenWorldOptions keepGameRule(boolean keepGameRuleInput) {
|
||||
this.keepGameRule = keepGameRuleInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to keep the game rule of the world during regeneration.
|
||||
*
|
||||
* @return Whether to keep the game rule of the world during regeneration.
|
||||
*/
|
||||
@Override
|
||||
public boolean keepGameRule() {
|
||||
return keepGameRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to keep the world config of the world during regeneration.
|
||||
*
|
||||
* @param keepWorldConfigInput Whether to keep the world config of the world during regeneration.
|
||||
* @return This {@link RegenWorldOptions} instance.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull RegenWorldOptions keepWorldConfig(boolean keepWorldConfigInput) {
|
||||
this.keepWorldConfig = keepWorldConfigInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to keep the world config of the world during regeneration.
|
||||
*
|
||||
* @return Whether to keep the world config of the world during regeneration.
|
||||
*/
|
||||
@Override
|
||||
public boolean keepWorldConfig() {
|
||||
return keepWorldConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to keep the world border of the world during regeneration.
|
||||
*
|
||||
* @param keepWorldBorderInput Whether to keep the world border of the world.
|
||||
* @return This {@link RegenWorldOptions} instance.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull RegenWorldOptions keepWorldBorder(boolean keepWorldBorderInput) {
|
||||
this.keepWorldBorder = keepWorldBorderInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to keep the world border of the world during regeneration.
|
||||
*
|
||||
* @return Whether to keep the world border of the world during regeneration.
|
||||
*/
|
||||
@Override
|
||||
public boolean keepWorldBorder() {
|
||||
return keepWorldBorder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to use a random seed for the world to regenerate. Cannot be set to true when seed is set.
|
||||
*
|
||||
* @param randomSeedInput Whether to use a random seed for the world to regenerate.
|
||||
* @return This {@link RegenWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull RegenWorldOptions randomSeed(boolean randomSeedInput) {
|
||||
if (randomSeedInput && seed != Long.MIN_VALUE) {
|
||||
throw new IllegalStateException("Cannot set randomSeed to true when seed is set");
|
||||
}
|
||||
this.randomSeed = randomSeedInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to use a random seed for the world to regenerate.
|
||||
*
|
||||
* @return Whether to use a random seed for the world to regenerate.
|
||||
*/
|
||||
public boolean randomSeed() {
|
||||
return randomSeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the seed for the world to regenerate. Random seed will be disabled.
|
||||
*
|
||||
* @param seedInput The seed for the world to regenerate.
|
||||
* @return This {@link RegenWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull RegenWorldOptions seed(@Nullable String seedInput) {
|
||||
if (seedInput == null) {
|
||||
this.seed = Long.MIN_VALUE;
|
||||
return this;
|
||||
}
|
||||
if (randomSeed) {
|
||||
randomSeed(false);
|
||||
}
|
||||
try {
|
||||
this.seed = Long.parseLong(seedInput);
|
||||
} catch (NumberFormatException numberformatexception) {
|
||||
this.seed = seedInput.hashCode();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the seed for the world to regenerate. Random seed will be disabled.
|
||||
*
|
||||
* @param seedInput The seed for the world to regenerate.
|
||||
* @return This {@link RegenWorldOptions} instance.
|
||||
*/
|
||||
public @NotNull RegenWorldOptions seed(long seedInput) {
|
||||
this.seed = seedInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the seed for the world to regenerate.
|
||||
*
|
||||
* @return The seed for the world to regenerate.
|
||||
*/
|
||||
public long seed() {
|
||||
if (randomSeed) {
|
||||
return new Random().nextLong();
|
||||
} else if (seed == Long.MIN_VALUE) {
|
||||
return world.getSeed();
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.options;
|
||||
|
||||
import com.onarandombox.MultiverseCore.worldnew.LoadedMultiverseWorld;
|
||||
|
||||
/**
|
||||
* Options for customizing the unloading of a world.
|
||||
*/
|
||||
public class UnloadWorldOptions {
|
||||
|
||||
/**
|
||||
* Creates a new {@link UnloadWorldOptions} instance with the given world.
|
||||
*
|
||||
* @param world The world to unload.
|
||||
* @return A new {@link UnloadWorldOptions} instance.
|
||||
*/
|
||||
public static UnloadWorldOptions world(LoadedMultiverseWorld world) {
|
||||
return new UnloadWorldOptions(world);
|
||||
}
|
||||
|
||||
private final LoadedMultiverseWorld world;
|
||||
private boolean removePlayers = false;
|
||||
private boolean saveBukkitWorld = true;
|
||||
|
||||
UnloadWorldOptions(LoadedMultiverseWorld world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world to unload.
|
||||
*
|
||||
* @return The world to unload.
|
||||
*/
|
||||
public LoadedMultiverseWorld world() {
|
||||
return world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to teleport the players out from the world before unloading.
|
||||
*
|
||||
* @param removePlayersInput Whether to remove players from the world before unloading.
|
||||
* @return This {@link UnloadWorldOptions} instance.
|
||||
*/
|
||||
public UnloadWorldOptions removePlayers(boolean removePlayersInput) {
|
||||
this.removePlayers = removePlayersInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to teleport the players out from the world before unloading.
|
||||
*
|
||||
* @return Whether to remove players from the world before unloading.
|
||||
*/
|
||||
public boolean removePlayers() {
|
||||
return removePlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to save the bukkit world before unloading.
|
||||
*
|
||||
* @param saveBukkitWorldInput Whether to save the bukkit world before unloading.
|
||||
* @return This {@link UnloadWorldOptions} instance.
|
||||
*/
|
||||
public UnloadWorldOptions saveBukkitWorld(boolean saveBukkitWorldInput) {
|
||||
this.saveBukkitWorld = saveBukkitWorldInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether to save the bukkit world before unloading.
|
||||
*
|
||||
* @return Whether to save the bukkit world before unloading.
|
||||
*/
|
||||
public boolean saveBukkitWorld() {
|
||||
return saveBukkitWorld;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.options;
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew;
|
|
@ -0,0 +1,52 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world clone operation.
|
||||
*/
|
||||
public enum CloneFailureReason implements FailureReason {
|
||||
/**
|
||||
* The world name is invalid.
|
||||
*/
|
||||
INVALID_WORLDNAME(MVCorei18n.CLONEWORLD_INVALIDWORLDNAME),
|
||||
|
||||
/**
|
||||
* The target new world folder already exists.
|
||||
*/
|
||||
WORLD_EXIST_FOLDER(MVCorei18n.CLONEWORLD_WORLDEXISTFOLDER),
|
||||
|
||||
/**
|
||||
* The target new world is already exist but unloaded.
|
||||
*/
|
||||
WORLD_EXIST_UNLOADED(MVCorei18n.CLONEWORLD_WORLDEXISTUNLOADED),
|
||||
|
||||
/**
|
||||
* The target new world is already loaded.
|
||||
*/
|
||||
WORLD_EXIST_LOADED(MVCorei18n.CLONEWORLD_WORLDEXISTLOADED),
|
||||
|
||||
/**
|
||||
* Failed to copy the world folder contents.
|
||||
*/
|
||||
COPY_FAILED(MVCorei18n.CLONEWORLD_COPYFAILED),
|
||||
|
||||
/**
|
||||
* Failed to import the new world.
|
||||
*/
|
||||
IMPORT_FAILED(MVCorei18n.GENERIC_FAILURE);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
CloneFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world creation operation.
|
||||
*/
|
||||
public enum CreateFailureReason implements FailureReason {
|
||||
/**
|
||||
* The world name is invalid.
|
||||
*/
|
||||
INVALID_WORLDNAME(MVCorei18n.CREATEWORLD_INVALIDWORLDNAME),
|
||||
|
||||
/**
|
||||
* The target new world folder already exists.
|
||||
*/
|
||||
WORLD_EXIST_FOLDER(MVCorei18n.CREATEWORLD_WORLDEXISTFOLDER),
|
||||
|
||||
/**
|
||||
* The target new world is already exist but unloaded.
|
||||
*/
|
||||
WORLD_EXIST_UNLOADED(MVCorei18n.CREATEWORLD_WORLDEXISTUNLOADED),
|
||||
|
||||
/**
|
||||
* The target new world is already exist and loaded.
|
||||
*/
|
||||
WORLD_EXIST_LOADED(MVCorei18n.CREATEWORLD_WORLDEXISTLOADED),
|
||||
|
||||
/**
|
||||
* Bukkit API failed to create the world.
|
||||
*/
|
||||
BUKKIT_CREATION_FAILED(MVCorei18n.CREATEWORLD_BUKKITCREATIONFAILED);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
CreateFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world deletion operation.
|
||||
*/
|
||||
public enum DeleteFailureReason implements FailureReason {
|
||||
/**
|
||||
* The world does not exist.
|
||||
*/
|
||||
WORLD_NON_EXISTENT(MVCorei18n.DELETEWORLD_WORLDNONEXISTENT),
|
||||
|
||||
/**
|
||||
* The world could not be loaded.
|
||||
*/
|
||||
LOAD_FAILED(MVCorei18n.DELETEWORLD_LOADFAILED),
|
||||
|
||||
/**
|
||||
* The world could not be unloaded.
|
||||
*/
|
||||
WORLD_FOLDER_NOT_FOUND(MVCorei18n.DELETEWORLD_WORLDFOLDERNOTFOUND),
|
||||
|
||||
/**
|
||||
* The world could not be removed.
|
||||
*/
|
||||
REMOVE_FAILED(MVCorei18n.GENERIC_FAILURE),
|
||||
|
||||
/**
|
||||
* The world folder could not be deleted.
|
||||
*/
|
||||
FAILED_TO_DELETE_FOLDER(MVCorei18n.DELETEWORLD_FAILEDTODELETEFOLDER);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
DeleteFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world import operation.
|
||||
*/
|
||||
public enum ImportFailureReason implements FailureReason {
|
||||
/**
|
||||
* The world name is invalid.
|
||||
*/
|
||||
INVALID_WORLDNAME(MVCorei18n.IMPORTWORLD_INVALIDWORLDNAME),
|
||||
|
||||
/**
|
||||
* The world folder is invalid.
|
||||
*/
|
||||
WORLD_FOLDER_INVALID(MVCorei18n.IMPORTWORLD_WORLDFOLDERINVALID),
|
||||
|
||||
/**
|
||||
* The target world folder already exists. You should load it instead.
|
||||
*/
|
||||
WORLD_EXIST_UNLOADED(MVCorei18n.IMPORTWORLD_WORLDEXISTUNLOADED),
|
||||
|
||||
/**
|
||||
* The target world is already exist and loaded.
|
||||
*/
|
||||
WORLD_EXIST_LOADED(MVCorei18n.IMPORTWORLD_WORLDEXISTLOADED),
|
||||
|
||||
/**
|
||||
* Bukkit API failed to create the world.
|
||||
*/
|
||||
BUKKIT_CREATION_FAILED(MVCorei18n.IMPORTWORLD_BUKKITCREATIONFAILED);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
ImportFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world loading operation.
|
||||
*/
|
||||
public enum LoadFailureReason implements FailureReason {
|
||||
/**
|
||||
* Loading operation is underway.
|
||||
*/
|
||||
WORLD_ALREADY_LOADING(MVCorei18n.LOADWORLD_WORLDALREADYLOADING),
|
||||
|
||||
/**
|
||||
* The world does not exist.
|
||||
*/
|
||||
WORLD_NON_EXISTENT(MVCorei18n.LOADWORLD_WORLDNONEXISTENT),
|
||||
|
||||
/**
|
||||
* The world folder exists but is not known to Multiverse.
|
||||
*/
|
||||
WORLD_EXIST_FOLDER(MVCorei18n.LOADWORLD_WORLDEXISTFOLDER),
|
||||
|
||||
/**
|
||||
* The world is already loaded.
|
||||
*/
|
||||
WORLD_EXIST_LOADED(MVCorei18n.LOADWORLD_WORLDEXISTLOADED),
|
||||
|
||||
/**
|
||||
* Bukkit API failed to create the world.
|
||||
*/
|
||||
BUKKIT_CREATION_FAILED(MVCorei18n.LOADWORLD_BUKKITCREATIONFAILED);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
LoadFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world regeneration operation.
|
||||
*/
|
||||
public enum RegenFailureReason implements FailureReason {
|
||||
/**
|
||||
* The world does not exist.
|
||||
*/
|
||||
DELETE_FAILED(MVCorei18n.GENERIC_FAILURE),
|
||||
|
||||
/**
|
||||
* The new world could not be created.
|
||||
*/
|
||||
CREATE_FAILED(MVCorei18n.GENERIC_FAILURE);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
RegenFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world removal operation.
|
||||
*/
|
||||
public enum RemoveFailureReason implements FailureReason {
|
||||
/**
|
||||
* The world does not exist.
|
||||
*/
|
||||
WORLD_NON_EXISTENT(MVCorei18n.REMOVEWORLD_WORLDNONEXISTENT),
|
||||
|
||||
/**
|
||||
* The world could not be unloaded.
|
||||
*/
|
||||
UNLOAD_FAILED(MVCorei18n.GENERIC_FAILURE);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
RemoveFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.utils.result.FailureReason;
|
||||
|
||||
/**
|
||||
* Result of a world unloading operation.
|
||||
*/
|
||||
public enum UnloadFailureReason implements FailureReason {
|
||||
/**
|
||||
* Unloading operation is underway.
|
||||
*/
|
||||
WORLD_ALREADY_UNLOADING(MVCorei18n.UNLOADWORLD_WORLDALREADYUNLOADING),
|
||||
|
||||
/**
|
||||
* The world does not exist.
|
||||
*/
|
||||
WORLD_NON_EXISTENT(MVCorei18n.UNLOADWORLD_WORLDNONEXISTENT),
|
||||
|
||||
/**
|
||||
* The world is already unloaded.
|
||||
*/
|
||||
WORLD_UNLOADED(MVCorei18n.UNLOADWORLD_WORLDUNLOADED),
|
||||
|
||||
/**
|
||||
* Bukkit API failed to unload the world.
|
||||
*/
|
||||
BUKKIT_UNLOAD_FAILED(MVCorei18n.UNLOADWORLD_BUKKITUNLOADFAILED);
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
UnloadFailureReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package com.onarandombox.MultiverseCore.worldnew.reasons;
|
|
@ -13,8 +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.failed=World could not be cloned! &fSee console for more details.
|
||||
mv-core.clone.success=Cloned world '{world}'!
|
||||
mv-core.clone.success=&aWorld cloned to '{world}'!
|
||||
|
||||
# /mv confirm
|
||||
mv-core.confirm.description=Confirms dangerous commands before executing them.
|
||||
|
@ -41,8 +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.failed=Failed to create world '{worldName}'! &fSee console for details.
|
||||
mv-core.create.success=&aWorld '{worldName}' created successfully!
|
||||
mv-core.create.success=&aWorld '{world}' created!
|
||||
|
||||
# /mv debug
|
||||
mv-core.debug.info.description=Show the current debug level.
|
||||
|
@ -55,9 +53,8 @@ mv-core.debug.change.level.description=Debug level to set to.
|
|||
# /mv delete
|
||||
mv-core.delete.description=Deletes a world on your server PERMANENTLY.
|
||||
mv-core.delete.deleting=Deleting world '{world}'...
|
||||
mv-core.delete.failed=There was an issue deleting '{world}'! &fPlease check console for errors.
|
||||
mv-core.delete.success=&aWorld {world} was deleted!
|
||||
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
|
||||
|
@ -84,24 +81,21 @@ 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.failed=Failed! &fSee console for more details.
|
||||
mv-core.import.success=&aComplete!
|
||||
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.failed=Error trying to load world '{world}'!
|
||||
mv-core.load.success=&aLoaded 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.
|
||||
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.failed=There was an issue regenerating '{world}'! &fPlease check console for errors.
|
||||
mv-core.regen.success=&aWorld {world} was regenerated!
|
||||
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.
|
||||
|
@ -111,8 +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.failed=Error trying to remove world from config!
|
||||
mv-core.remove.success=&aWorld '{world}' is removed from config!
|
||||
mv-core.remove.success=&aWorld '{world}' removed!
|
||||
|
||||
# /mv
|
||||
mv-core.root.title=&a{name} version {version}
|
||||
|
@ -128,8 +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.failure=Error unloading world '{world}'! &fSee console for more details.
|
||||
mv-core.unload.success=&aUnloaded world '{world}'!
|
||||
mv-core.unload.success=&aWorld '{world}' unloaded!
|
||||
|
||||
# /mv usage
|
||||
mv-core.usage.description=Show Multiverse-Core command usage.
|
||||
|
@ -145,6 +137,43 @@ mv-core.entrycheck.cannotpayentryfee=you do not have the ability to pay entry fe
|
|||
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.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.invalidworldname=World '{world}' contains invalid characters!
|
||||
mv-core.createworld.worldexistfolder=World '{world}' already exists in server folders!&f Type '&a/mv import {world} <environment>&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.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.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.worldalreadyloading=World '{world}' is already loading! Please wait...
|
||||
mv-core.loadworld.worldnonexistent=World '{world}' not found! Use '&a/mv create {world} <environment>&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} <environment>&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.removeworld.worldnonexistent=World '{world}' not found!
|
||||
|
||||
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!
|
||||
mv-core.unloadworld.bukkitunloadfailed=Bukkit failed to unload world '{world}': {error}\n&fSee console for more details.
|
||||
|
||||
# generic
|
||||
mv-core.generic.success=Success!
|
||||
mv-core.generic.failure=Failed!
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue