diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java
index df00fbe6..3861a39b 100644
--- a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java
+++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java
@@ -77,6 +77,8 @@ import com.onarandombox.MultiverseCore.destination.PlayerDestination;
import com.onarandombox.MultiverseCore.destination.WorldDestination;
import com.onarandombox.MultiverseCore.event.MVDebugModeEvent;
import com.onarandombox.MultiverseCore.event.MVVersionEvent;
+import com.onarandombox.MultiverseCore.generators.GeneratorManager;
+import com.onarandombox.MultiverseCore.api.MVGeneratorManager;
import com.onarandombox.MultiverseCore.listeners.MVAsyncPlayerChatListener;
import com.onarandombox.MultiverseCore.listeners.MVChatListener;
import com.onarandombox.MultiverseCore.listeners.MVEntityListener;
@@ -213,6 +215,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Configurations
private FileConfiguration multiverseConfig = null;
+ private MVGeneratorManager generatorManager;
private final MVWorldManager worldManager = new WorldManager(this);
// Setup the block/player/entity listener.
@@ -280,7 +283,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
this.messaging = new MVMessaging();
this.economist = new MVEconomist(this);
// Load the defaultWorldGenerators
- this.worldManager.getDefaultWorldGenerators();
+ this.generatorManager = new GeneratorManager(this);
this.registerEvents();
// Setup Permissions, we'll do an initial check for the Permissions plugin then fall back on isOP().
@@ -1014,6 +1017,14 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
this.serverFolder = newServerFolder;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public MVGeneratorManager getMVGeneratorManager() {
+ return generatorManager;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java
index ff8513d4..ba62372b 100644
--- a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java
+++ b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java
@@ -94,6 +94,13 @@ public interface Core {
*/
DestinationFactory getDestFactory();
+ /**
+ * Gets the class responsible for managing world generators plugins installed on the server.
+ *
+ * @return A valid {@link MVGeneratorManager}.
+ */
+ MVGeneratorManager getMVGeneratorManager();
+
/**
* Gets the primary class responsible for managing Multiverse Worlds.
*
diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/GeneratorPlugin.java b/src/main/java/com/onarandombox/MultiverseCore/api/GeneratorPlugin.java
new file mode 100644
index 00000000..07dcbb36
--- /dev/null
+++ b/src/main/java/com/onarandombox/MultiverseCore/api/GeneratorPlugin.java
@@ -0,0 +1,101 @@
+package com.onarandombox.MultiverseCore.api;
+
+import org.bukkit.generator.ChunkGenerator;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+/**
+ *
A generator API for Multiverse.
+ *
+ * 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.
+ *
+ * To register your plugin, implement this class and see {@link MVGeneratorManager#register(GeneratorPlugin)}.
+ */
+public interface GeneratorPlugin {
+
+ /**
+ * Suggest possible generator ids. To be used in command tab-completion.
+ *
+ * These suggestions can be static without relying on currentIdInput, or dynamically changed based
+ * on the currentIdInput.
+ *
+ * @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 suggestIds(@Nullable String currentIdInput);
+
+ /**
+ * Gets a default or any valid {@link ChunkGenerator}.
+ *
+ * This is used on {@link MVGeneratorManager#register(GeneratorPlugin)} to prove to Multiverse that
+ * you are a valid generator plugin. If this returns null or throw an exception, your generator plugin
+ * will not be registered.
+ *
+ * @return A {@link ChunkGenerator} if possible, else null.
+ * @throws Exception When an error occurs in getting {@link ChunkGenerator}.
+ */
+ @Nullable
+ ChunkGenerator getDefaultChunkGenerator() throws Exception;
+
+ /**
+ * Gets a chunk generator based on a world name and id specified.
+ *
+ * If this returns null or throw an exception, it will indicate to Multiverse that there is either an issue
+ * with your plugin, or the generator id given is invalid.
+ *
+ * @param id Target generator id.
+ * @param worldName Target world name to use generator on.
+ * @return A {@link ChunkGenerator} if possible, else null.
+ * @throws Exception When an error occurs in getting a {@link ChunkGenerator}.
+ */
+ @Nullable
+ ChunkGenerator getChunkGenerator(String id, String worldName) throws Exception;
+
+ /**
+ * 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.
+ *
+ * An example command: '/mv create myworld normal -g CoolGen:FunWorld'
+ *
+ * Notes on usage of this method:
+ *
+ * - Feel free to have colors in your command usage, but not Multiverse won't parse color codes for you.
+ * - Please include the starting slash '/' in your usage examples.
+ * - We suggest keeping the usage to at most 5 examples.
+ * - 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.
+ *
+ *
+ * @return A collection of command usage examples.
+ */
+ @Nullable
+ Collection getExampleUsages();
+
+ /**
+ * 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.
+ *
+ * An example info: 'Click on https://www.amazinggenerator.io ;)'
+ *
+ * Some suggested places you can link to are: spigot resource page, github repo or your own plugin site.
+ *
+ * @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
+ Plugin getPlugin();
+}
diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVGeneratorManager.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVGeneratorManager.java
new file mode 100644
index 00000000..aa94ba95
--- /dev/null
+++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVGeneratorManager.java
@@ -0,0 +1,134 @@
+package com.onarandombox.MultiverseCore.api;
+
+import org.bukkit.generator.ChunkGenerator;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * API for handling generator plugins installed on the user's server.
+ */
+public interface MVGeneratorManager {
+
+ /**
+ * Register a generator plugin.
+ *
+ * @param generatorPlugin The {@link GeneratorPlugin} to register.
+ * @return True if successfully registered, else false.
+ */
+ boolean register(@NotNull GeneratorPlugin generatorPlugin);
+
+ /**
+ * Check if a given generator string is valid.
+ *
+ * @param genString The generator string to check on.
+ * @param worldName The target world name to generate on.
+ * @return True if valid, else false.
+ */
+ boolean isValidGenerator(@NotNull String genString, @NotNull String worldName);
+
+ /**
+ * Check if a given generator string is valid with reason of failure with {@link TestResult}.
+ *
+ * @param genString The generator string to check on.
+ * @param worldName The target world name to generate on.
+ * @return Result of the validation.
+ */
+ @NotNull
+ TestResult validateGenerator(@NotNull String genString, @NotNull String worldName);
+
+ /**
+ * Checks if a plugin is a registered generator plugin.
+ *
+ * @param genPlugin The plugin to check on.
+ * @return True if is valid, else false.
+ */
+ boolean isGeneratorPlugin(@NotNull Plugin genPlugin);
+
+ /**
+ * Checks if a plugin is a registered generator plugin.
+ *
+ * @param pluginName The plugin name to check on.
+ * @return True if is valid, else false.
+ */
+ boolean isGeneratorPlugin(@NotNull String pluginName);
+
+ /**
+ * Gets the {@link GeneratorPlugin} for a given plugin if present.
+ *
+ * @param genPlugin The plugin that is associated to a {@link GeneratorPlugin}.
+ * @return The {@link GeneratorPlugin} if present, else null.
+ */
+ @Nullable
+ GeneratorPlugin getGeneratorPlugin(@NotNull Plugin genPlugin);
+
+ /**
+ * Gets the {@link GeneratorPlugin} for a given plugin if present.
+ *
+ * @param pluginName The plugin name that is associated to a {@link GeneratorPlugin}.
+ * @return The {@link GeneratorPlugin} if present, else null.
+ */
+ @Nullable
+ GeneratorPlugin getGeneratorPlugin(@NotNull String pluginName);
+
+ /**
+ * Gets all registered {@link GeneratorPlugin}.
+ *
+ * @return A collection of registered generator plugins.
+ */
+ @NotNull
+ Collection getGeneratorPlugins();
+
+ /**
+ * Gets all registered plugin names associate with {@link GeneratorPlugin}.
+ *
+ * @return A collection of registered generator plugin names.
+ */
+ @NotNull
+ Collection getGeneratorPluginNames();
+
+ /**
+ * Gets the default world generator string defined in 'bukkit.yml' for a given world.
+ *
+ * @param worldName The world to get default generator of.
+ * @return The generator string if present, else null.
+ */
+ @Nullable
+ String getDefaultWorldGen(String worldName);
+
+ /**
+ * Gets all the world generator strings defined in 'bukkit.yml'.
+ *
+ * @return Map if world names and its respective default world generator strings.
+ */
+ @NotNull
+ Map getDefaultWorldGens();
+
+ /**
+ * Results from validating a generator.
+ */
+ enum TestResult {
+ /**
+ * Successfully got {@link ChunkGenerator} from the world generator plugin.
+ */
+ VALID,
+
+ /**
+ * Exceptions thrown while trying to get {@link ChunkGenerator} from the world generator plugin.
+ */
+ ERRORS,
+
+ /**
+ * Plugin is present on the server, but doesnt look like a world generator.
+ */
+ INVALID_GENERATOR,
+
+ /**
+ * Plugin not installed on the server.
+ */
+ PLUGIN_DOES_NOT_EXIST
+ }
+}
diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java
index 3eb96e2d..98f4d729 100644
--- a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java
+++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java
@@ -7,6 +7,7 @@
package com.onarandombox.MultiverseCore.api;
+import com.onarandombox.MultiverseCore.generators.GeneratorManager;
import com.onarandombox.MultiverseCore.utils.PurgeWorlds;
import com.onarandombox.MultiverseCore.utils.SimpleWorldPurger;
import org.bukkit.World;
@@ -154,7 +155,9 @@ public interface MVWorldManager {
* @param generatorID The generator id.
* @param worldName The worldName to use as the default.
* @return A {@link ChunkGenerator} or null
+ * @deprecated Use {@link MVGeneratorManager#validateGenerator(String, String)}
*/
+ @Deprecated
ChunkGenerator getChunkGenerator(String generator, String generatorID, String worldName);
/**
@@ -249,7 +252,9 @@ public interface MVWorldManager {
/**
* This method populates an internal list and needs to be called after multiverse initialization.
+ * @deprecated This is now done by {@link GeneratorManager}.
*/
+ @Deprecated
void getDefaultWorldGenerators();
/**
diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java
index 87bdacab..c6bb7328 100644
--- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java
+++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java
@@ -9,6 +9,7 @@ package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
+import com.onarandombox.MultiverseCore.api.MVGeneratorManager;
import com.pneumaticraft.commandhandler.CommandHandler;
import org.bukkit.ChatColor;
import org.bukkit.World.Environment;
@@ -18,8 +19,6 @@ import org.bukkit.command.CommandSender;
import org.bukkit.permissions.PermissionDefault;
import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
@@ -98,14 +97,26 @@ public class CreateCommand extends MultiverseCommand {
}
// Determine if the generator is valid. #918
if (generator != null) {
- List genarray = new ArrayList(Arrays.asList(generator.split(":")));
- if (genarray.size() < 2) {
- // If there was only one arg specified, pad with another empty one.
- genarray.add("");
- }
- if (this.worldManager.getChunkGenerator(genarray.get(0), genarray.get(1), "test") == null) {
+ MVGeneratorManager.TestResult result = this.plugin.getMVGeneratorManager().validateGenerator(generator, worldName);
+ if (result != MVGeneratorManager.TestResult.VALID) {
// We have an invalid generator.
- sender.sendMessage("Invalid generator! '" + generator + "'. " + ChatColor.RED + "Aborting world creation.");
+ switch (result) {
+ case ERRORS:
+ sender.sendMessage("An issue occurred while validating generator string '" + generator +
+ "'! This may indicate an issue with your generator plugin or an invalid generator id. Check console for errors!");
+ break;
+ case INVALID_GENERATOR:
+ sender.sendMessage("Invalid generator string '" + generator +
+ "'! The generator id you use is probably not supported by your generator plugin.");
+ break;
+ case PLUGIN_DOES_NOT_EXIST:
+ sender.sendMessage("That generator plugin is not installed on your server!");
+ break;
+ default:
+ sender.sendMessage("Invalid generator string '" + generator + "'!");
+ break;
+ }
+ sender.sendMessage(ChatColor.RED + "Aborting world creation...");
return;
}
}
diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java
index 72d4379b..05f20e39 100644
--- a/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java
+++ b/src/main/java/com/onarandombox/MultiverseCore/commands/GeneratorCommand.java
@@ -9,12 +9,19 @@ package com.onarandombox.MultiverseCore.commands;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
+import com.onarandombox.MultiverseCore.api.GeneratorPlugin;
+import com.onarandombox.MultiverseCore.generators.SimpleGeneratorPlugin;
+import net.milkbowl.vault.chat.Chat;
+import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
+import org.bukkit.generator.ChunkGenerator;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
/**
@@ -25,36 +32,70 @@ public class GeneratorCommand extends MultiverseCommand {
public GeneratorCommand(MultiverseCore plugin) {
super(plugin);
this.setName("World Information");
- this.setCommandUsage("/mv generators");
- this.setArgRange(0, 0);
+ this.setCommandUsage("/mv generators [plugin]");
+ this.setArgRange(0, 1);
this.addKey("mv generators");
this.addKey("mvgenerators");
this.addKey("mv gens");
this.addKey("mvgens");
this.addCommandExample("/mv generators");
- this.setPermission("multiverse.core.generator", "Returns a list of Loaded Generator Plugins.", PermissionDefault.OP);
+ this.addCommandExample("/mv generators VoidGenerator");
+ this.setPermission("multiverse.core.generator", "Returns info of Loaded Generator Plugins.", PermissionDefault.OP);
}
@Override
public void runCommand(CommandSender sender, List args) {
- Logging.info("PLEASE IGNORE the 'Plugin X does not contain any generators' message below!");
- Plugin[] plugins = this.plugin.getServer().getPluginManager().getPlugins();
- List generators = new ArrayList();
- for (Plugin p : plugins) {
- if (p.isEnabled() && p.getDefaultWorldGenerator("world", "") != null) {
- generators.add(p.getDescription().getName());
- }
+ if (args.size() == 0) {
+ listKnownGenerators(sender);
+ return;
}
+ showGeneratorDetails(sender, args.get(0));
+ }
+
+ private void listKnownGenerators(CommandSender sender) {
sender.sendMessage(ChatColor.AQUA + "--- Loaded Generator Plugins ---");
- String loadedGens = "";
+ StringBuilder loadedGens = new StringBuilder();
boolean altColor = false;
- for (String s : generators) {
- loadedGens += (altColor ? ChatColor.YELLOW : ChatColor.WHITE) + s + " ";
+ for (String s : this.plugin.getMVGeneratorManager().getGeneratorPluginNames()) {
+ loadedGens.append(altColor ? ChatColor.YELLOW : ChatColor.WHITE).append(s).append(' ');
altColor = !altColor;
}
if (loadedGens.length() == 0) {
- loadedGens = ChatColor.RED + "No Generator Plugins found.";
+ loadedGens.append(ChatColor.RED).append("No Generator Plugins found.");
+ }
+ sender.sendMessage(loadedGens.toString());
+ }
+
+ private void showGeneratorDetails(CommandSender sender, String pluginName) {
+ Plugin genPlugin = Bukkit.getPluginManager().getPlugin(pluginName);
+ if (genPlugin == null) {
+ sender.sendMessage(ChatColor.RED + "You do not have a plugin named '"+ pluginName + "' on your server.");
+ return;
+ }
+
+ GeneratorPlugin generatorPlugin = this.plugin.getMVGeneratorManager().getGeneratorPlugin(genPlugin);
+ if (generatorPlugin == null) {
+ sender.sendMessage(ChatColor.RED + "'" + pluginName + "' does not look like a generator plugin.");
+ return;
+ }
+
+ sender.sendMessage(ChatColor.AQUA + "--- Info on " + generatorPlugin.getPlugin().getName() + " ---");
+ boolean hasAddInfo = false;
+
+ Collection exampleUsages = generatorPlugin.getExampleUsages();
+ if (exampleUsages != null && exampleUsages.size() > 0) {
+ hasAddInfo = true;
+ sender.sendMessage("Usages:");
+ exampleUsages.forEach(sender::sendMessage);
+ }
+ String infoLink = generatorPlugin.getInfoLink();
+ if (infoLink != null) {
+ hasAddInfo = true;
+ sender.sendMessage("More Info: " + infoLink);
+ }
+
+ if (!hasAddInfo) {
+ sender.sendMessage(ChatColor.RED + "'" + pluginName + "' did not provide additional info to Multiverse.");
}
- sender.sendMessage(loadedGens);
}
}
diff --git a/src/main/java/com/onarandombox/MultiverseCore/generators/GeneratorManager.java b/src/main/java/com/onarandombox/MultiverseCore/generators/GeneratorManager.java
new file mode 100644
index 00000000..c30b77cb
--- /dev/null
+++ b/src/main/java/com/onarandombox/MultiverseCore/generators/GeneratorManager.java
@@ -0,0 +1,311 @@
+package com.onarandombox.MultiverseCore.generators;
+
+import com.dumptruckman.minecraft.util.Logging;
+import com.onarandombox.MultiverseCore.MultiverseCore;
+import com.onarandombox.MultiverseCore.api.GeneratorPlugin;
+import com.onarandombox.MultiverseCore.api.MVGeneratorManager;
+import org.bukkit.Bukkit;
+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.generator.ChunkGenerator;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+/**
+ * Default implementation of {@link MVGeneratorManager} to facilitate the detection and management of generator
+ * plugins installed on user's server.
+ */
+public class GeneratorManager implements MVGeneratorManager {
+
+ private final MultiverseCore plugin;
+ private final Map defaultGens;
+ private Map generatorPluginMap;
+
+ public GeneratorManager(MultiverseCore plugin) {
+ this.plugin = plugin;
+ this.defaultGens = new HashMap<>();
+ loadDefaultWorldGenerators();
+ findAndRegisterAllGeneratorPlugins();
+ Bukkit.getPluginManager().registerEvents(new GeneratorListener(), this.plugin);
+ }
+
+ /**
+ * Loads default generator strings defined in 'bukkit.yml'.
+ */
+ private void loadDefaultWorldGenerators() {
+ this.generatorPluginMap = new HashMap<>();
+
+ File[] files = this.plugin.getServerFolder().listFiles((file, s) -> s.equalsIgnoreCase("bukkit.yml"));
+ if (files == null || files.length != 1) {
+ Logging.fine("Could not read 'bukkit.yml'. Any Default worldgenerators will not be loaded!");
+ return;
+ }
+
+ FileConfiguration bukkitConfig = YamlConfiguration.loadConfiguration(files[0]);
+ if (!bukkitConfig.isConfigurationSection("worlds")) {
+ Logging.fine("'bukkit.yml' missing worlds config section. No default generators found!");
+ return;
+ }
+
+ Set keys = bukkitConfig.getConfigurationSection("worlds").getKeys(false);
+ for (String key : keys) {
+ this.defaultGens.put(key, bukkitConfig.getString("worlds." + key + ".generator", ""));
+ }
+
+ this.generatorPluginMap = Collections.unmodifiableMap(this.generatorPluginMap);
+ }
+
+ /**
+ * Register all generator plugins detected.
+ */
+ private void findAndRegisterAllGeneratorPlugins() {
+ Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(this::register);
+ }
+
+ /**
+ * Attempts to register a plugin as {@link SimpleGeneratorPlugin}.
+ *
+ * @param genPlugin The plugin to register.
+ * @return True if registered successfully, else false.
+ */
+ private boolean register(@NotNull Plugin genPlugin) {
+ return this.register(genPlugin, SimpleGeneratorPlugin.DEFAULT_TEST_ID);
+ }
+
+ /**
+ * Attempts to register a plugin as {@link SimpleGeneratorPlugin}.
+ *
+ * @param genPlugin The plugin to register.
+ * @param id Generator Id to test for valid chunk generator.
+ * @return True if registered successfully, else false.
+ */
+ private boolean register(@NotNull Plugin genPlugin, String id) {
+ Logging.finer("Attempting to register %s as a generator...", genPlugin.getName());
+ if (this.isGeneratorPlugin(genPlugin)) {
+ return false;
+ }
+ if (!simpleTestGen(genPlugin, id)) {
+ Logging.finer("%s is probably not a generator plugin!", genPlugin.getName());
+ return false;
+ }
+ this.generatorPluginMap.put(genPlugin.getName(), new SimpleGeneratorPlugin(genPlugin));
+ Logging.finer("Registered %s as a simple generator plugin.", genPlugin.getName());
+ return true;
+ }
+
+ /**
+ * Basic test to see if plugin is a valid generator.
+ *
+ * @param generator The potential generator plugin.
+ * @param id Generator Id to test for valid chunk generator.
+ * @return True if plugin is a valid generator, else false.
+ */
+ private boolean simpleTestGen(@Nullable Plugin generator, String id) {
+ if (generator == null) {
+ return false;
+ }
+
+ // Since we are unsure if the plugin is even suppose to be a generator, we assume any error means its
+ // not a generator plugin.
+ try {
+ return generator.getDefaultWorldGenerator(SimpleGeneratorPlugin.TEST_WORLDNAME, id) != null;
+ } catch (Exception ignore) {
+ return false;
+ }
+ }
+
+ /**
+ * Unregisters a plugin.
+ *
+ * @param genPlugin The plugin to unregister.
+ * @return True if the plugin was present and now unregistered, else false.
+ */
+ private boolean unregister(@NotNull Plugin genPlugin) {
+ return this.generatorPluginMap.remove(genPlugin.getName()) != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean register(@NotNull GeneratorPlugin generatorPlugin) {
+ Plugin genPlugin = generatorPlugin.getPlugin();
+
+ // Make sure not registered before.
+ GeneratorPlugin registeredGeneratorPlugin = this.getGeneratorPlugin(genPlugin);
+ if (registeredGeneratorPlugin != null) {
+ if (!(registeredGeneratorPlugin instanceof SimpleGeneratorPlugin)) {
+ throw new IllegalStateException("You cannot register plugin for '" + genPlugin.getName() + "' twice!");
+ }
+ // If it's auto registration by MV, we can remove in favour of the custom one.
+ this.unregister(genPlugin);
+ }
+
+ if (this.safelyTestGenerator(genPlugin, generatorPlugin::getDefaultChunkGenerator) != TestResult.VALID) {
+ return false;
+ }
+
+ this.generatorPluginMap.put(genPlugin.getName(), generatorPlugin);
+ Logging.fine("Registered %s as a simple generator plugin.", genPlugin.getName());
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isValidGenerator(@NotNull String genString, @NotNull String worldName) {
+ return validateGenerator(genString, worldName) == TestResult.VALID;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @NotNull
+ public TestResult validateGenerator(@NotNull String genString, @NotNull String worldName) {
+ String[] genArray = genString.split(":", 2);
+ String pluginName = genArray[0];
+ String id = (genArray.length == 1) ? "" : genArray[1];
+
+ Plugin genPlugin = Bukkit.getPluginManager().getPlugin(pluginName);
+ if (genPlugin == null) {
+ return TestResult.PLUGIN_DOES_NOT_EXIST;
+ }
+
+ if (!this.isGeneratorPlugin(genPlugin)) {
+ // Tries to register again with specific Id defined.
+ if (!this.register(genPlugin, id)) {
+ return TestResult.INVALID_GENERATOR;
+ }
+ }
+
+ GeneratorPlugin generatorPlugin = this.getGeneratorPlugin(genPlugin);
+ if (generatorPlugin == null) {
+ return TestResult.INVALID_GENERATOR;
+ }
+
+ TestResult testResult = safelyTestGenerator(generatorPlugin.getPlugin(), () -> generatorPlugin.getChunkGenerator(id, worldName));
+ if (testResult == TestResult.VALID && generatorPlugin instanceof SimpleGeneratorPlugin) {
+ ((SimpleGeneratorPlugin) generatorPlugin).addKnownWorkingId(id);
+ }
+ return testResult;
+ }
+
+ /**
+ * Tries to get chunk generator with wrapper to catch any exceptions that may occur.
+ *
+ * @param genPlugin The generator plugin.
+ * @param genGetter Logic to get the chunk generator.
+ * @return VALID if successfully got a not-null chunk generator, INVALID_GENERATOR if null,
+ * ERRORS if exception is thrown.
+ */
+ @NotNull
+ private TestResult safelyTestGenerator(Plugin genPlugin, Callable genGetter) {
+ TestResult result = this.plugin.getUnsafeCallWrapper().wrap(
+ () -> genGetter.call() == null ? TestResult.INVALID_GENERATOR : TestResult.VALID,
+ genPlugin.getName(),
+ "Failed to get the chunk generator: %s"
+ );
+ return (result == null) ? TestResult.ERRORS : result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isGeneratorPlugin(@NotNull Plugin genPlugin) {
+ return this.isGeneratorPlugin(genPlugin.getName());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isGeneratorPlugin(@NotNull String pluginName) {
+ return this.generatorPluginMap.containsKey(pluginName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @Nullable
+ public GeneratorPlugin getGeneratorPlugin(@NotNull Plugin genPlugin) {
+ return this.getGeneratorPlugin(genPlugin.getName());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @Nullable
+ public GeneratorPlugin getGeneratorPlugin(@NotNull String pluginName) {
+ return this.generatorPluginMap.get(pluginName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @NotNull
+ public Collection getGeneratorPlugins() {
+ return this.generatorPluginMap.values();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @NotNull
+ public Collection getGeneratorPluginNames() {
+ return this.generatorPluginMap.keySet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @Nullable
+ public String getDefaultWorldGen(String worldName) {
+ return this.defaultGens.get(worldName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @NotNull
+ public Map getDefaultWorldGens() {
+ return this.defaultGens;
+ }
+
+ /**
+ * Listen to when a plugin enables/disable to register and unregister accordingly.
+ */
+ private class GeneratorListener implements Listener {
+ @EventHandler
+ public void onEnable(PluginEnableEvent event) {
+ register(event.getPlugin());
+ }
+
+ @EventHandler
+ public void onDisable(PluginDisableEvent event) {
+ unregister(event.getPlugin());
+ }
+ }
+}
diff --git a/src/main/java/com/onarandombox/MultiverseCore/generators/SimpleGeneratorPlugin.java b/src/main/java/com/onarandombox/MultiverseCore/generators/SimpleGeneratorPlugin.java
new file mode 100644
index 00000000..74cb5c76
--- /dev/null
+++ b/src/main/java/com/onarandombox/MultiverseCore/generators/SimpleGeneratorPlugin.java
@@ -0,0 +1,94 @@
+package com.onarandombox.MultiverseCore.generators;
+
+import com.onarandombox.MultiverseCore.api.GeneratorPlugin;
+import org.bukkit.generator.ChunkGenerator;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A default implementation of {@link GeneratorPlugin} for those generator plugins that do not provide their own
+ * custom {@link GeneratorPlugin} implementation to Multiverse.
+ */
+public class SimpleGeneratorPlugin implements GeneratorPlugin {
+
+ public static String TEST_WORLDNAME = "test";
+ public static String DEFAULT_TEST_ID = "";
+
+ private final Plugin plugin;
+ private final List workingIds;
+
+ SimpleGeneratorPlugin(Plugin plugin) {
+ this(plugin, DEFAULT_TEST_ID);
+ }
+
+ SimpleGeneratorPlugin(Plugin plugin, String testedId) {
+ this.plugin = plugin;
+ this.workingIds = new ArrayList<>();
+ this.workingIds.add(testedId);
+ }
+
+ /**
+ * Adds a known generator id that was tested to be working.
+ *
+ * @param id The known working generator id.
+ */
+ void addKnownWorkingId(String id) {
+ if (!this.workingIds.contains(id)) {
+ this.workingIds.add(id);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Collection suggestIds(@Nullable String currentIdInput) {
+ return this.workingIds;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @Nullable ChunkGenerator getDefaultChunkGenerator() throws Exception {
+ return this.plugin.getDefaultWorldGenerator(TEST_WORLDNAME, this.workingIds.get(0));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @Nullable ChunkGenerator getChunkGenerator(String id, String worldName) throws Exception {
+ return this.plugin.getDefaultWorldGenerator(worldName, id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @Nullable Collection getExampleUsages() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return
+ */
+ @Override
+ public @Nullable String getInfoLink() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Plugin getPlugin() {
+ return this.plugin;
+ }
+}
diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java
index 3979b7cb..2cf4d1b4 100644
--- a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java
+++ b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java
@@ -74,6 +74,7 @@ public class WorldManager implements MVWorldManager {
* {@inheritDoc}
*/
@Override
+ @Deprecated
public void getDefaultWorldGenerators() {
this.defaultGens = new HashMap();
File[] files = this.plugin.getServerFolder().listFiles(new FilenameFilter() {
@@ -301,6 +302,7 @@ public class WorldManager implements MVWorldManager {
* {@inheritDoc}
*/
@Override
+ @Deprecated
public ChunkGenerator getChunkGenerator(String generator, final String generatorID, final String worldName) {
if (generator == null) {
return null;
@@ -694,10 +696,7 @@ public class WorldManager implements MVWorldManager {
for (World w : myWorlds) {
String name = w.getName();
if (!worldsFromTheConfig.containsKey(name)) {
- String generator = null;
- if (this.defaultGens.containsKey(name)) {
- generator = this.defaultGens.get(name);
- }
+ String generator = this.plugin.getMVGeneratorManager().getDefaultWorldGen(name);
this.addWorld(name, w.getEnvironment(), String.valueOf(w.getSeed()), w.getWorldType(), w.canGenerateStructures(), generator);
}
}
diff --git a/src/test/java/com/onarandombox/MultiverseCore/TestWorldStuff.java b/src/test/java/com/onarandombox/MultiverseCore/TestWorldStuff.java
index 05957c84..10eeb8d4 100644
--- a/src/test/java/com/onarandombox/MultiverseCore/TestWorldStuff.java
+++ b/src/test/java/com/onarandombox/MultiverseCore/TestWorldStuff.java
@@ -207,7 +207,7 @@ public class TestWorldStuff {
assertEquals(0, creator.getCore().getMVWorldManager().getMVWorlds().size());
// Verify
- verify(mockCommandSender).sendMessage("Invalid generator! 'BogusGen'. " + ChatColor.RED + "Aborting world creation.");
+ verify(mockCommandSender).sendMessage("That generator plugin is not installed on your server!");
}
@Test