diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/UnsafeCallWrapper.java b/src/main/java/com/onarandombox/MultiverseCore/utils/UnsafeCallWrapper.java new file mode 100644 index 00000000..d4b7b6da --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/UnsafeCallWrapper.java @@ -0,0 +1,39 @@ +package com.onarandombox.MultiverseCore.utils; + +import com.dumptruckman.minecraft.util.Logging; + +import java.util.concurrent.Callable; + +/** + * Wraps calls that could result in exceptions that are not Multiverse's fault. + */ +public final class UnsafeCallWrapper { + private UnsafeCallWrapper() { + throw new UnsupportedOperationException(); + } + + /** + * Wraps calls that could result in exceptions that are not Multiverse's fault. + * + * @param callable The potentially unsafe call. + * @param plugin The plugin that's probably the culprit. + * @param action What MV was attempting to do (error message, format string). + * @param formatArgs The formatting arguments for the error message. + * The exception that was thrown will be appended to these objects. + * @param The type of the return value. + * @return The return value or null if the call failed. + */ + public static T wrap(Callable callable, String plugin, String action, Object... formatArgs) { + try { + // We're ready to catch you! JUMP! + return callable.call(); + } catch (Throwable t) { + Object[] actualFormatArgs = new Object[formatArgs.length + 1]; + System.arraycopy(formatArgs, 0, actualFormatArgs, 0, formatArgs.length); + actualFormatArgs[formatArgs.length] = t; + Logging.warning(action, actualFormatArgs); + Logging.warning("This is a bug in %s, NOT a bug in Multiverse!", plugin); + return null; + } + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java index b062d3a1..4a164f90 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java @@ -42,6 +42,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.Stack; +import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -241,16 +242,21 @@ public class WorldManager implements MVWorldManager { * {@inheritDoc} */ @Override - public ChunkGenerator getChunkGenerator(String generator, String generatorID, String worldName) { + public ChunkGenerator getChunkGenerator(String generator, final String generatorID, final String worldName) { if (generator == null) { return null; } - Plugin myPlugin = this.plugin.getServer().getPluginManager().getPlugin(generator); + final Plugin myPlugin = this.plugin.getServer().getPluginManager().getPlugin(generator); if (myPlugin == null) { return null; } else { - return myPlugin.getDefaultWorldGenerator(worldName, generatorID); + return UnsafeCallWrapper.wrap(new Callable() { + @Override + public ChunkGenerator call() throws Exception { + return myPlugin.getDefaultWorldGenerator(worldName, generatorID); + } + }, myPlugin.getName(), "Failed to get the default chunk generator: %s"); } } @@ -363,24 +369,25 @@ public class WorldManager implements MVWorldManager { if (!worldsFromTheConfig.containsKey(name)) throw new IllegalArgumentException("That world doesn't exist!"); - WorldProperties world = worldsFromTheConfig.get(name); - WorldCreator creator = WorldCreator.name(name); + final WorldProperties world = worldsFromTheConfig.get(name); + final WorldCreator creator = WorldCreator.name(name); creator.environment(world.getEnvironment()).seed(world.getSeed()); if (type != null) { creator.type(type); } - if ((world.getGenerator() != null) && (!world.getGenerator().equals("null"))) { - try { - creator.generator(world.getGenerator()); - } catch (Throwable t) { - Logging.warning("Failed to set the generator for world '%s' to '%s': %s", name, world.getGenerator(), t); - Logging.warning("This is a bug in the generator plugin, NOT a bug in Multiverse!", name); - return false; - } - } - return doLoad(creator, ignoreExists); + boolean generatorSuccess = true; + if ((world.getGenerator() != null) && (!world.getGenerator().equals("null"))) + generatorSuccess = null != UnsafeCallWrapper.wrap(new Callable() { + @Override + public Object call() throws Exception { + creator.generator(world.getGenerator()); + return new Object(); + } + }, "the generator plugin", "Failed to set the generator for world '%s' to '%s': %s", name, world.getGenerator()); + + return generatorSuccess && doLoad(creator, ignoreExists); } private boolean doLoad(WorldCreator creator, boolean ignoreExists) {