From 8fb73347e4f948164950b3910938a99f657069de Mon Sep 17 00:00:00 2001
From: sk89q
Date: Fri, 4 Apr 2014 20:53:58 -0700
Subject: [PATCH] Implemented PlatformManager, Platform over old platform
registration method.
---
.../bukkit/BukkitServerInterface.java | 22 +-
.../worldedit/bukkit/WorldEditPlugin.java | 31 +-
.../worldedit/forge/ForgeServerInterface.java | 14 +-
.../sk89q/worldedit/forge/WorldEditMod.java | 10 +-
.../com/sk89q/worldedit/ServerInterface.java | 44 +-
.../java/com/sk89q/worldedit/WorldEdit.java | 385 ++++--------------
.../worldedit/event/AbstractCancellable.java | 39 ++
.../sk89q/worldedit/event/Cancellable.java | 42 ++
.../event/platform/CommandEvent.java | 67 +++
.../extension/platform/CommandManager.java | 343 ++++++++++++++++
.../extension/platform/Platform.java | 89 ++++
.../extension/platform/PlatformManager.java | 162 ++++++++
.../platform/PlatformRejectionException.java | 49 +++
.../platform/ServerInterfaceAdapter.java | 93 +++++
.../util/logging/DynamicStreamHandler.java | 179 ++++++++
.../util/{ => logging}/LogFormat.java | 6 +-
.../util/logging/WorldEditPrefixHandler.java | 59 +++
.../worldedit/spout/SpoutServerInterface.java | 6 +
.../worldedit/spout/WorldEditPlugin.java | 8 +-
19 files changed, 1275 insertions(+), 373 deletions(-)
create mode 100644 src/main/java/com/sk89q/worldedit/event/AbstractCancellable.java
create mode 100644 src/main/java/com/sk89q/worldedit/event/Cancellable.java
create mode 100644 src/main/java/com/sk89q/worldedit/event/platform/CommandEvent.java
create mode 100644 src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
create mode 100644 src/main/java/com/sk89q/worldedit/extension/platform/Platform.java
create mode 100644 src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java
create mode 100644 src/main/java/com/sk89q/worldedit/extension/platform/PlatformRejectionException.java
create mode 100644 src/main/java/com/sk89q/worldedit/extension/platform/ServerInterfaceAdapter.java
create mode 100644 src/main/java/com/sk89q/worldedit/util/logging/DynamicStreamHandler.java
rename src/main/java/com/sk89q/worldedit/util/{ => logging}/LogFormat.java (95%)
create mode 100644 src/main/java/com/sk89q/worldedit/util/logging/WorldEditPrefixHandler.java
diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java
index c650044bd..955f7d84d 100644
--- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java
+++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java
@@ -19,28 +19,23 @@
package com.sk89q.worldedit.bukkit;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
import com.sk89q.bukkit.util.CommandInfo;
import com.sk89q.bukkit.util.CommandRegistration;
import com.sk89q.minecraft.util.commands.Command;
-
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.CommandsManager;
-import com.sk89q.worldedit.LocalPlayer;
+import com.sk89q.worldedit.*;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
-import com.sk89q.worldedit.BiomeTypes;
-import com.sk89q.worldedit.LocalWorld;
-import com.sk89q.worldedit.ServerInterface;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
public class BukkitServerInterface extends ServerInterface {
public Server server;
@@ -119,6 +114,11 @@ public class BukkitServerInterface extends ServerInterface {
dynamicCommands.register(toRegister);
}
+ @Override
+ public LocalConfiguration getConfiguration() {
+ return plugin.getLocalConfiguration();
+ }
+
public void unregisterCommands() {
dynamicCommands.unregisterCommands();
}
diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java
index 9c64464e7..2a84f875c 100644
--- a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java
+++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java
@@ -25,12 +25,12 @@ import com.sk89q.worldedit.*;
import com.sk89q.worldedit.bukkit.selections.CuboidSelection;
import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection;
import com.sk89q.worldedit.bukkit.selections.Selection;
+import com.sk89q.worldedit.extension.platform.PlatformRejectionException;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
-import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -40,7 +40,6 @@ import java.io.*;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-import java.util.logging.Handler;
import java.util.zip.ZipEntry;
/**
@@ -104,16 +103,22 @@ public class WorldEditPlugin extends JavaPlugin {
// Setup interfaces
server = new BukkitServerInterface(this, getServer());
- controller = new WorldEdit(server, config);
- WorldEdit.logger.setParent(Bukkit.getLogger());
- api = new WorldEditAPI(this);
- getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
- getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL);
- // Now we can register events!
- getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
+ controller = WorldEdit.getInstance();
+ try {
+ controller.getPlatformManager().register(server);
+ api = new WorldEditAPI(this);
+ getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
+ getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL);
+ // Now we can register events!
+ getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
- getServer().getScheduler().runTaskTimerAsynchronously(this,
- new SessionTimer(controller, getServer()), 120, 120);
+ getServer().getScheduler().runTaskTimerAsynchronously(this,
+ new SessionTimer(controller, getServer()), 120, 120);
+ } catch (PlatformRejectionException e) {
+ throw new RuntimeException(
+ "WorldEdit rejected the Bukkit implementation of WorldEdit! This is strange and should " +
+ "not have happened. Please report this error.", e);
+ }
}
private void copyNmsBlockClasses(File target) {
@@ -149,9 +154,7 @@ public class WorldEditPlugin extends JavaPlugin {
@Override
public void onDisable() {
controller.clearSessions();
- for (Handler h : controller.commandLogger.getHandlers()) {
- h.close();
- }
+ controller.getPlatformManager().unregister(server);
config.unload();
server.unregisterCommands();
this.getServer().getScheduler().cancelTasks(this);
diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgeServerInterface.java b/src/forge/java/com/sk89q/worldedit/forge/ForgeServerInterface.java
index 0bee6be0d..b5a62f1af 100644
--- a/src/forge/java/com/sk89q/worldedit/forge/ForgeServerInterface.java
+++ b/src/forge/java/com/sk89q/worldedit/forge/ForgeServerInterface.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import com.sk89q.worldedit.LocalConfiguration;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.ServerCommandManager;
@@ -40,10 +41,12 @@ import com.sk89q.worldedit.ServerInterface;
import cpw.mods.fml.common.FMLCommonHandler;
public class ForgeServerInterface extends ServerInterface {
- private MinecraftServer server;
- private ForgeBiomeTypes biomes;
+ private final WorldEditMod mod;
+ private final MinecraftServer server;
+ private final ForgeBiomeTypes biomes;
- public ForgeServerInterface() {
+ public ForgeServerInterface(WorldEditMod mod) {
+ this.mod = mod;
this.server = FMLCommonHandler.instance().getMinecraftServerInstance();
this.biomes = new ForgeBiomeTypes();
}
@@ -114,4 +117,9 @@ public class ForgeServerInterface extends ServerInterface {
});
}
}
+
+ @Override
+ public LocalConfiguration getConfiguration() {
+ return mod.getConfig();
+ }
}
diff --git a/src/forge/java/com/sk89q/worldedit/forge/WorldEditMod.java b/src/forge/java/com/sk89q/worldedit/forge/WorldEditMod.java
index 753ee1584..37b446050 100644
--- a/src/forge/java/com/sk89q/worldedit/forge/WorldEditMod.java
+++ b/src/forge/java/com/sk89q/worldedit/forge/WorldEditMod.java
@@ -28,6 +28,7 @@ import java.util.jar.JarFile;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
+import com.sk89q.worldedit.extension.platform.PlatformRejectionException;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
@@ -92,8 +93,13 @@ public class WorldEditMod {
@EventHandler
public void serverStarting(FMLServerStartingEvent event) {
- this.server = new ForgeServerInterface();
- this.controller = new WorldEdit(this.server, this.config);
+ this.server = new ForgeServerInterface(this);
+ this.controller = WorldEdit.getInstance();
+ try {
+ controller.getPlatformManager().register(server);
+ } catch (PlatformRejectionException e) {
+ throw new RuntimeException("Failed to register with WorldEdit", e);
+ }
}
public ForgeConfiguration getConfig() {
diff --git a/src/main/java/com/sk89q/worldedit/ServerInterface.java b/src/main/java/com/sk89q/worldedit/ServerInterface.java
index 3d40e8f40..bc6d4610b 100644
--- a/src/main/java/com/sk89q/worldedit/ServerInterface.java
+++ b/src/main/java/com/sk89q/worldedit/ServerInterface.java
@@ -21,6 +21,7 @@ package com.sk89q.worldedit;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandsManager;
+import com.sk89q.worldedit.extension.platform.Platform;
import java.util.Collections;
import java.util.List;
@@ -29,58 +30,27 @@ import java.util.List;
*
* @author sk89q
*/
-public abstract class ServerInterface {
- /**
- * Resolves an item name to its ID.
- *
- * @param name The name to look up
- * @return The id that corresponds to the name, or -1 if no such ID exists
- */
- public abstract int resolveItem(String name);
+public abstract class ServerInterface implements Platform {
- /**
- * Checks if a mob type is valid.
- *
- * @param type The mob type name to check
- * @return Whether the name is a valid mod bype
- */
- public abstract boolean isValidMobType(String type);
-
- /**
- * Reload WorldEdit configuration.
- */
- public abstract void reload();
-
- /**
- * Returns all available biomes.
- *
- * @return
- */
- public abstract BiomeTypes getBiomes();
-
- /**
- * Schedules the given task
to be invoked once every period
ticks
- * after an initial delay of delay
ticks.
- *
- * @param delay Delay in server ticks before executing first repeat
- * @param period Period in server ticks of the task
- * @param task Task to be executed
- * @return Task id number (-1 if scheduling failed)
- */
+ @Override
public int schedule(long delay, long period, Runnable task) {
return -1;
}
+ @Override
public List getWorlds() {
return Collections.emptyList();
}
+ @Override
@Deprecated
public void onCommandRegistration(List commands) {
// Do nothing :)
}
+ @Override
public void onCommandRegistration(List commands, CommandsManager manager) {
onCommandRegistration(commands);
}
+
}
diff --git a/src/main/java/com/sk89q/worldedit/WorldEdit.java b/src/main/java/com/sk89q/worldedit/WorldEdit.java
index 0240ad6a5..db7fe81ac 100644
--- a/src/main/java/com/sk89q/worldedit/WorldEdit.java
+++ b/src/main/java/com/sk89q/worldedit/WorldEdit.java
@@ -19,17 +19,16 @@
package com.sk89q.worldedit;
-import com.sk89q.minecraft.util.commands.*;
-import com.sk89q.minecraft.util.commands.Console;
-import com.sk89q.util.StringUtil;
+import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
-import com.sk89q.worldedit.blocks.ItemType;
-import com.sk89q.worldedit.command.*;
import com.sk89q.worldedit.command.tool.*;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
+import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.extension.input.ParserContext;
+import com.sk89q.worldedit.extension.platform.Platform;
+import com.sk89q.worldedit.extension.platform.PlatformManager;
import com.sk89q.worldedit.extension.registry.BlockRegistry;
import com.sk89q.worldedit.extension.registry.MaskRegistry;
import com.sk89q.worldedit.extension.registry.PatternRegistry;
@@ -44,35 +43,41 @@ import com.sk89q.worldedit.scripting.CraftScriptEngine;
import com.sk89q.worldedit.scripting.RhinoCraftScriptEngine;
import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.session.request.Request;
-import com.sk89q.worldedit.util.LogFormat;
import com.sk89q.worldedit.util.eventbus.EventBus;
+import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
import javax.script.ScriptException;
import java.io.*;
-import java.lang.reflect.Method;
-import java.util.*;
-import java.util.logging.FileHandler;
-import java.util.logging.Level;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import java.util.logging.Logger;
-import java.util.regex.Matcher;
import static com.google.common.base.Preconditions.checkNotNull;
/**
- * The current instance of WorldEdit.
+ * The entry point and container for a working implementation of WorldEdit.
+ *
+ * An instance handles event handling; block, mask, pattern, etc. registration;
+ * the management of sessions; the creation of {@link EditSession}s; and more.
+ * In order to use WorldEdit, at least one {@link Platform} must be registered
+ * with WorldEdit using {@link PlatformManager#register(Platform)} on the
+ * manager retrieved using {@link WorldEdit#getPlatformManager()}.
+ *
+ * An instance of WorldEdit can be retrieved using the static
+ * method {@link WorldEdit#getInstance()}, which is shared among all
+ * platforms within the same classloader hierarchy.
*/
public class WorldEdit {
- public static final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
- public final Logger commandLogger = Logger.getLogger("Minecraft.WorldEdit.CommandLogger");
+ public static final Logger logger = Logger.getLogger(WorldEdit.class.getCanonicalName());
- private static WorldEdit instance;
+ private final static WorldEdit instance = new WorldEdit();
private static String version;
- private final ServerInterface server;
- private final LocalConfiguration config;
- private final CommandsManager commands;
private final EventBus eventBus = new EventBus();
+ private final PlatformManager platformManager = new PlatformManager(this);
private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus);
private final SessionManager sessions = new SessionManager(this);
@@ -81,139 +86,41 @@ public class WorldEdit {
private final PatternRegistry patternRegistry = new PatternRegistry(this);
static {
+ WorldEditPrefixHandler.register("com.sk89q.worldedit");
getVersion();
}
+ private WorldEdit() {
+ }
+
/**
- * Construct an instance of WorldEdit.
+ * Gets the current instance of this class.
+ *
+ * An instance will always be available, but no platform may yet be
+ * registered with WorldEdit, meaning that a number of operations
+ * may fail. However, event handlers can be registered.
*
- * @param server
- * @param config
- */
- public WorldEdit(ServerInterface server, final LocalConfiguration config) {
- instance = this;
- this.server = server;
- this.config = config;
-
- if (!config.logFile.equals("")) {
- try {
- FileHandler logFileHandler;
- logFileHandler = new FileHandler(new File(config.getWorkingDirectory(),
- config.logFile).getAbsolutePath(), true);
- logFileHandler.setFormatter(new LogFormat());
- commandLogger.addHandler(logFileHandler);
- } catch (IOException e) {
- logger.log(Level.WARNING, "Could not use command log file " + config.logFile + ": "
- + e.getMessage());
- }
- }
-
- commands = new CommandsManager() {
- @Override
- protected void checkPermission(LocalPlayer player, Method method) throws CommandException {
- if (!player.isPlayer() && !method.isAnnotationPresent(Console.class)) {
- throw new UnhandledCommandException();
- }
-
- super.checkPermission(player, method);
- }
-
- @Override
- public boolean hasPermission(LocalPlayer player, String perm) {
- return player.hasPermission(perm);
- }
-
- @Override
- public void invokeMethod(Method parent, String[] args,
- LocalPlayer player, Method method, Object instance,
- Object[] methodArgs, int level) throws CommandException {
- if (config.logCommands) {
- final Logging loggingAnnotation = method.getAnnotation(Logging.class);
-
- final Logging.LogMode logMode;
- if (loggingAnnotation == null) {
- logMode = null;
- } else {
- logMode = loggingAnnotation.value();
- }
-
- String msg = "WorldEdit: " + player.getName();
- if (player.isPlayer()) {
- msg += " (in \"" + player.getWorld().getName() + "\")";
- }
- msg += ": " + StringUtil.joinString(args, " ");
- if (logMode != null && player.isPlayer()) {
- Vector position = player.getPosition();
- final LocalSession session = getSession(player);
- switch (logMode) {
- case PLACEMENT:
- try {
- position = session.getPlacementPosition(player);
- } catch (IncompleteRegionException e) {
- break;
- }
- /* FALL-THROUGH */
-
- case POSITION:
- msg += " - Position: " + position;
- break;
-
- case ALL:
- msg += " - Position: " + position;
- /* FALL-THROUGH */
-
- case ORIENTATION_REGION:
- msg += " - Orientation: " + player.getCardinalDirection().name();
- /* FALL-THROUGH */
-
- case REGION:
- try {
- msg += " - Region: " + session.getSelection(player.getWorld());
- } catch (IncompleteRegionException e) {
- break;
- }
- break;
- }
- }
- commandLogger.info(msg);
- }
- super.invokeMethod(parent, args, player, method, instance, methodArgs, level);
- }
- };
-
- commands.setInjector(new SimpleInjector(this));
-
- reg(BiomeCommands.class);
- reg(ChunkCommands.class);
- reg(ClipboardCommands.class);
- reg(GeneralCommands.class);
- reg(GenerationCommands.class);
- reg(HistoryCommands.class);
- reg(NavigationCommands.class);
- reg(RegionCommands.class);
- reg(ScriptingCommands.class);
- reg(SelectionCommands.class);
- reg(SnapshotUtilCommands.class);
- reg(ToolUtilCommands.class);
- reg(ToolCommands.class);
- reg(UtilityCommands.class);
- }
-
- private void reg(Class> clazz) {
- server.onCommandRegistration(commands.registerAndReturn(clazz), commands);
- }
-
- /**
- * Gets the current instance of this class
- *
- * @return
+ * @return an instance of WorldEdit.
*/
public static WorldEdit getInstance() {
return instance;
}
+ /**
+ * Get the platform manager, where platforms (that implement WorldEdit)
+ * can be registered and information about registered platforms can
+ * be queried.
+ *
+ * @return the platform manager
+ */
+ public PlatformManager getPlatformManager() {
+ return platformManager;
+ }
+
/**
* Get the event bus for WorldEdit.
+ *
+ * Event handlers can be registered on the event bus.
*
* @return the event bus
*/
@@ -487,7 +394,7 @@ public class WorldEdit {
String filePath = f.getCanonicalPath();
String dirPath = dir.getCanonicalPath();
- if (!filePath.substring(0, dirPath.length()).equals(dirPath) && !config.allowSymlinks) {
+ if (!filePath.substring(0, dirPath.length()).equals(dirPath) && !getConfiguration().allowSymlinks) {
throw new FilenameResolutionException(filename,
"Path is outside allowable root");
}
@@ -500,27 +407,27 @@ public class WorldEdit {
}
public int getMaximumPolygonalPoints(LocalPlayer player) {
- if (player.hasPermission("worldedit.limit.unrestricted") || config.maxPolygonalPoints < 0) {
- return config.defaultMaxPolygonalPoints;
+ if (player.hasPermission("worldedit.limit.unrestricted") || getConfiguration().maxPolygonalPoints < 0) {
+ return getConfiguration().defaultMaxPolygonalPoints;
}
- if (config.defaultMaxPolygonalPoints < 0) {
- return config.maxPolygonalPoints;
+ if (getConfiguration().defaultMaxPolygonalPoints < 0) {
+ return getConfiguration().maxPolygonalPoints;
}
- return Math.min(config.defaultMaxPolygonalPoints, config.maxPolygonalPoints);
+ return Math.min(getConfiguration().defaultMaxPolygonalPoints, getConfiguration().maxPolygonalPoints);
}
public int getMaximumPolyhedronPoints(LocalPlayer player) {
- if (player.hasPermission("worldedit.limit.unrestricted") || config.maxPolyhedronPoints < 0) {
- return config.defaultMaxPolyhedronPoints;
+ if (player.hasPermission("worldedit.limit.unrestricted") || getConfiguration().maxPolyhedronPoints < 0) {
+ return getConfiguration().defaultMaxPolyhedronPoints;
}
- if (config.defaultMaxPolyhedronPoints < 0) {
- return config.maxPolyhedronPoints;
+ if (getConfiguration().defaultMaxPolyhedronPoints < 0) {
+ return getConfiguration().maxPolyhedronPoints;
}
- return Math.min(config.defaultMaxPolyhedronPoints, config.maxPolyhedronPoints);
+ return Math.min(getConfiguration().defaultMaxPolyhedronPoints, getConfiguration().maxPolyhedronPoints);
}
/**
@@ -530,7 +437,7 @@ public class WorldEdit {
* @throws MaxRadiusException
*/
public void checkMaxRadius(double radius) throws MaxRadiusException {
- if (config.maxRadius > 0 && radius > config.maxRadius) {
+ if (getConfiguration().maxRadius > 0 && radius > getConfiguration().maxRadius) {
throw new MaxRadiusException();
}
}
@@ -542,7 +449,7 @@ public class WorldEdit {
* @throws MaxBrushRadiusException
*/
public void checkMaxBrushRadius(double radius) throws MaxBrushRadiusException {
- if (config.maxBrushRadius > 0 && radius > config.maxBrushRadius) {
+ if (getConfiguration().maxBrushRadius > 0 && radius > getConfiguration().maxBrushRadius) {
throw new MaxBrushRadiusException();
}
}
@@ -560,7 +467,7 @@ public class WorldEdit {
return f;
}
- return new File(config.getWorkingDirectory(), path);
+ return new File(getConfiguration().getWorkingDirectory(), path);
}
/**
@@ -761,14 +668,14 @@ public class WorldEdit {
* @return the commands
*/
public Map getCommands() {
- return commands.getCommands();
+ return getCommandsManager().getCommands();
}
/**
* @return the commands
*/
public CommandsManager getCommandsManager() {
- return commands;
+ return getPlatformManager().getCommandManager().getCommands();
}
/**
@@ -813,8 +720,8 @@ public class WorldEdit {
* @return
*/
public boolean handleArmSwing(LocalPlayer player) {
- if (player.getItemInHand() == config.navigationWand) {
- if (config.navigationWandMaxDistance <= 0) {
+ if (player.getItemInHand() == getConfiguration().navigationWand) {
+ if (getConfiguration().navigationWandMaxDistance <= 0) {
return false;
}
@@ -822,7 +729,7 @@ public class WorldEdit {
return false;
}
- WorldVector pos = player.getSolidBlockTrace(config.navigationWandMaxDistance);
+ WorldVector pos = player.getSolidBlockTrace(getConfiguration().navigationWandMaxDistance);
if (pos != null) {
player.findFreePosition(pos);
} else {
@@ -836,7 +743,7 @@ public class WorldEdit {
Tool tool = session.getTool(player.getItemInHand());
if (tool != null && tool instanceof DoubleActionTraceTool) {
if (tool.canUse(player)) {
- ((DoubleActionTraceTool) tool).actSecondary(server, config, player, session);
+ ((DoubleActionTraceTool) tool).actSecondary(getServer(), getConfiguration(), player, session);
return true;
}
}
@@ -851,8 +758,8 @@ public class WorldEdit {
* @return
*/
public boolean handleRightClick(LocalPlayer player) {
- if (player.getItemInHand() == config.navigationWand) {
- if (config.navigationWandMaxDistance <= 0) {
+ if (player.getItemInHand() == getConfiguration().navigationWand) {
+ if (getConfiguration().navigationWandMaxDistance <= 0) {
return false;
}
@@ -872,7 +779,7 @@ public class WorldEdit {
Tool tool = session.getTool(player.getItemInHand());
if (tool != null && tool instanceof TraceTool) {
if (tool.canUse(player)) {
- ((TraceTool) tool).actPrimary(server, config, player, session);
+ ((TraceTool) tool).actPrimary(getServer(), getConfiguration(), player, session);
return true;
}
}
@@ -890,7 +797,7 @@ public class WorldEdit {
public boolean handleBlockRightClick(LocalPlayer player, WorldVector clicked) {
LocalSession session = getSession(player);
- if (player.getItemInHand() == config.wandItem) {
+ if (player.getItemInHand() == getConfiguration().wandItem) {
if (!session.isToolControlEnabled()) {
return false;
}
@@ -910,7 +817,7 @@ public class WorldEdit {
Tool tool = session.getTool(player.getItemInHand());
if (tool != null && tool instanceof BlockTool) {
if (tool.canUse(player)) {
- ((BlockTool) tool).actPrimary(server, config, player, session, clicked);
+ ((BlockTool) tool).actPrimary(getServer(), getConfiguration(), player, session, clicked);
return true;
}
}
@@ -928,7 +835,7 @@ public class WorldEdit {
public boolean handleBlockLeftClick(LocalPlayer player, WorldVector clicked) {
LocalSession session = getSession(player);
- if (player.getItemInHand() == config.wandItem) {
+ if (player.getItemInHand() == getConfiguration().wandItem) {
if (!session.isToolControlEnabled()) {
return false;
}
@@ -948,14 +855,14 @@ public class WorldEdit {
if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) {
final BlockTool superPickaxe = session.getSuperPickaxe();
if (superPickaxe != null && superPickaxe.canUse(player)) {
- return superPickaxe.actPrimary(server, config, player, session, clicked);
+ return superPickaxe.actPrimary(getServer(), getConfiguration(), player, session, clicked);
}
}
Tool tool = session.getTool(player.getItemInHand());
if (tool != null && tool instanceof DoubleActionBlockTool) {
if (tool.canUse(player)) {
- ((DoubleActionBlockTool) tool).actSecondary(server, config, player, session, clicked);
+ ((DoubleActionBlockTool) tool).actSecondary(getServer(), getConfiguration(), player, session, clicked);
return true;
}
}
@@ -963,8 +870,6 @@ public class WorldEdit {
return false;
}
- private static final java.util.regex.Pattern numberFormatExceptionPattern = java.util.regex.Pattern.compile("^For input string: \"(.*)\"$");
-
/**
*
* @param player
@@ -972,135 +877,13 @@ public class WorldEdit {
* @return whether the command was processed
*/
public boolean handleCommand(LocalPlayer player, String[] split) {
- Request.reset();
-
- try {
- split = commandDetection(split);
-
- // No command found!
- if (!commands.hasCommand(split[0])) {
- return false;
- }
-
- LocalSession session = getSession(player);
- EditSession editSession = session.createEditSession(player);
- editSession.enableQueue();
-
- session.tellVersion(player);
-
- long start = System.currentTimeMillis();
-
- try {
- commands.execute(split, player, session, player, editSession);
- } catch (CommandPermissionsException e) {
- player.printError("You don't have permission to do this.");
- } catch (MissingNestedCommandException e) {
- player.printError(e.getUsage());
- } catch (CommandUsageException e) {
- player.printError(e.getMessage());
- player.printError(e.getUsage());
- } catch (PlayerNeededException e) {
- player.printError(e.getMessage());
- } catch (WrappedCommandException e) {
- throw e.getCause();
- } catch (UnhandledCommandException e) {
- player.printError("Command could not be handled; invalid sender!");
- return false;
- } finally {
- session.remember(editSession);
- editSession.flushQueue();
-
- if (config.profile) {
- long time = System.currentTimeMillis() - start;
- int changed = editSession.getBlockChangeCount();
- if (time > 0) {
- double throughput = changed / (time / 1000.0);
- player.printDebug((time / 1000.0) + "s elapsed (history: "
- + changed + " changed; "
- + Math.round(throughput) + " blocks/sec).");
- } else {
- player.printDebug((time / 1000.0) + "s elapsed.");
- }
- }
-
- flushBlockBag(player, editSession);
- }
- } catch (NumberFormatException e) {
- final Matcher matcher = numberFormatExceptionPattern.matcher(e.getMessage());
-
- if (matcher.matches()) {
- player.printError("Number expected; string \"" + matcher.group(1) + "\" given.");
- } else {
- player.printError("Number expected; string given.");
- }
- } catch (IncompleteRegionException e) {
- player.printError("Make a region selection first.");
- } catch (UnknownItemException e) {
- player.printError("Block name '" + e.getID() + "' was not recognized.");
- } catch (InvalidItemException e) {
- player.printError(e.getMessage());
- } catch (DisallowedItemException e) {
- player.printError("Block '" + e.getID() + "' not allowed (see WorldEdit configuration).");
- } catch (MaxChangedBlocksException e) {
- player.printError("Max blocks changed in an operation reached ("
- + e.getBlockLimit() + ").");
- } catch (MaxBrushRadiusException e) {
- player.printError("Maximum allowed brush size: " + config.maxBrushRadius);
- } catch (MaxRadiusException e) {
- player.printError("Maximum allowed size: " + config.maxRadius);
- } catch (UnknownDirectionException e) {
- player.printError("Unknown direction: " + e.getDirection());
- } catch (InsufficientArgumentsException e) {
- player.printError(e.getMessage());
- } catch (EmptyClipboardException e) {
- player.printError("Your clipboard is empty. Use //copy first.");
- } catch (InvalidFilenameException e) {
- player.printError("Filename '" + e.getFilename() + "' invalid: "
- + e.getMessage());
- } catch (FilenameResolutionException e) {
- player.printError("File '" + e.getFilename() + "' resolution error: "
- + e.getMessage());
- } catch (InvalidToolBindException e) {
- player.printError("Can't bind tool to "
- + ItemType.toHeldName(e.getItemId()) + ": " + e.getMessage());
- } catch (FileSelectionAbortedException e) {
- player.printError("File selection aborted.");
- } catch (WorldEditException e) {
- player.printError(e.getMessage());
- } catch (Throwable excp) {
- player.printError("Please report this error: [See console]");
- player.printRaw(excp.getClass().getName() + ": " + excp.getMessage());
- excp.printStackTrace();
- }
-
- return true;
+ CommandEvent event = new CommandEvent(player, split);
+ getEventBus().post(event);
+ return event.isCancelled();
}
public String[] commandDetection(String[] split) {
- Request.reset();
-
- split[0] = split[0].substring(1);
-
- // Quick script shortcut
- if (split[0].matches("^[^/].*\\.js$")) {
- String[] newSplit = new String[split.length + 1];
- System.arraycopy(split, 0, newSplit, 1, split.length);
- newSplit[0] = "cs";
- newSplit[1] = newSplit[1];
- split = newSplit;
- }
-
- String searchCmd = split[0].toLowerCase();
-
- // Try to detect the command
- if (commands.hasCommand(searchCmd)) {
- } else if (config.noDoubleSlash && commands.hasCommand("/" + searchCmd)) {
- split[0] = "/" + split[0];
- } else if (split[0].length() >= 2 && split[0].charAt(0) == '/'
- && commands.hasCommand(searchCmd.substring(1))) {
- split[0] = split[0].substring(1);
- }
- return split;
+ return getPlatformManager().getCommandManager().commandDetection(split);
}
/**
@@ -1152,7 +935,7 @@ public class WorldEdit {
LocalSession session = getSession(player);
CraftScriptContext scriptContext =
- new CraftScriptContext(this, server, config, session, player, args);
+ new CraftScriptContext(this, getServer(), getConfiguration(), session, player, args);
CraftScriptEngine engine = null;
@@ -1164,7 +947,7 @@ public class WorldEdit {
return;
}
- engine.setTimeLimit(config.scriptTimeout);
+ engine.setTimeLimit(getConfiguration().scriptTimeout);
Map vars = new HashMap();
vars.put("argv", args);
@@ -1196,19 +979,19 @@ public class WorldEdit {
/**
* Get Worldedit's configuration.
*
- * @return
+ * @return a configuration
*/
public LocalConfiguration getConfiguration() {
- return config;
+ return getPlatformManager().getConfiguration();
}
/**
* Get the server interface.
*
- * @return
+ * @return the server interface
*/
public ServerInterface getServer() {
- return server;
+ return getPlatformManager().getServerInterface();
}
/**
diff --git a/src/main/java/com/sk89q/worldedit/event/AbstractCancellable.java b/src/main/java/com/sk89q/worldedit/event/AbstractCancellable.java
new file mode 100644
index 000000000..673b251c5
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/event/AbstractCancellable.java
@@ -0,0 +1,39 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.event;
+
+/**
+ * An abstract implementation of {@link Cancellable} that has all
+ * of {@link Cancellable}'s methods implemented.
+ */
+public abstract class AbstractCancellable implements Cancellable {
+
+ private boolean cancelled;
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+}
diff --git a/src/main/java/com/sk89q/worldedit/event/Cancellable.java b/src/main/java/com/sk89q/worldedit/event/Cancellable.java
new file mode 100644
index 000000000..35f142e7e
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/event/Cancellable.java
@@ -0,0 +1,42 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.event;
+
+/**
+ * Marks an event that has a cancellable state. The meaning of cancellation
+ * depends on the event.
+ */
+public interface Cancellable {
+
+ /**
+ * Returns whether the event has been cancelled.
+ *
+ * @return true if cancelled
+ */
+ boolean isCancelled();
+
+ /**
+ * Set whether the event has been cancelled.
+ *
+ * @param cancelled true if cancelled
+ */
+ void setCancelled(boolean cancelled);
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/event/platform/CommandEvent.java b/src/main/java/com/sk89q/worldedit/event/platform/CommandEvent.java
new file mode 100644
index 000000000..0cba50b7e
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/event/platform/CommandEvent.java
@@ -0,0 +1,67 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.event.platform;
+
+import com.sk89q.worldedit.LocalPlayer;
+import com.sk89q.worldedit.event.AbstractCancellable;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * This class is currently only for internal use. Do not post or catch this event.
+ */
+public class CommandEvent extends AbstractCancellable {
+
+ private final LocalPlayer player;
+ private final String[] args;
+
+ /**
+ * Create a new instance.
+ *
+ * @param player the player
+ * @param args the arguments
+ */
+ public CommandEvent(LocalPlayer player, String[] args) {
+ checkNotNull(player);
+ checkNotNull(args);
+
+ this.player = player;
+ this.args = args;
+ }
+
+ /**
+ * Get the player.
+ *
+ * @return the player
+ */
+ public LocalPlayer getPlayer() {
+ return player;
+ }
+
+ /**
+ * Get the arguments.
+ *
+ * @return the arguments
+ */
+ public String[] getArguments() {
+ return args;
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
new file mode 100644
index 000000000..6eb9f8994
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
@@ -0,0 +1,343 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.extension.platform;
+
+import com.sk89q.minecraft.util.commands.*;
+import com.sk89q.util.StringUtil;
+import com.sk89q.worldedit.*;
+import com.sk89q.worldedit.blocks.ItemType;
+import com.sk89q.worldedit.command.*;
+import com.sk89q.worldedit.event.platform.CommandEvent;
+import com.sk89q.worldedit.session.request.Request;
+import com.sk89q.worldedit.util.logging.LogFormat;
+import com.sk89q.worldedit.util.eventbus.Subscribe;
+import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.logging.*;
+import java.util.regex.Matcher;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Handles the registration and invocation of commands.
+ *
+ * This class is primarily for internal usage.
+ */
+public final class CommandManager {
+
+ private static final Logger logger = Logger.getLogger(CommandManager.class.getCanonicalName());
+ private static final java.util.regex.Pattern numberFormatExceptionPattern = java.util.regex.Pattern.compile("^For input string: \"(.*)\"$");
+
+ private final WorldEdit worldEdit;
+ private final CommandsManager commands;
+ private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
+
+ /**
+ * Create a new instance.
+ *
+ * @param worldEdit the WorldEdit instance
+ */
+ CommandManager(final WorldEdit worldEdit) {
+ checkNotNull(worldEdit);
+ this.worldEdit = worldEdit;
+
+ // Register this instance for command events
+ worldEdit.getEventBus().register(this);
+
+ // Setup the logger
+ logger.addHandler(dynamicHandler);
+ dynamicHandler.setFormatter(new LogFormat());
+
+ // Set up the commands manager
+ commands = new CommandsManagerImpl();
+ commands.setInjector(new SimpleInjector(worldEdit));
+ }
+
+ void register(Platform platform) {
+ logger.log(Level.FINE, "Registering commands with " + platform.getClass().getCanonicalName());
+
+ LocalConfiguration config = platform.getConfiguration();
+ boolean logging = config.logCommands;
+ String path = config.logFile;
+
+ // Register log
+ if (!logging || path.isEmpty()) {
+ dynamicHandler.setHandler(null);
+ } else {
+ File file = new File(config.getWorkingDirectory(), path);
+
+ logger.log(Level.INFO, "Logging WorldEdit commands to " + file.getAbsolutePath());
+
+ try {
+ dynamicHandler.setHandler(new FileHandler(file.getAbsolutePath(), true));
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "Could not use command log file " + path + ": " + e.getMessage());
+ }
+ }
+
+ register(platform, BiomeCommands.class);
+ register(platform, ChunkCommands.class);
+ register(platform, ClipboardCommands.class);
+ register(platform, GeneralCommands.class);
+ register(platform, GenerationCommands.class);
+ register(platform, HistoryCommands.class);
+ register(platform, NavigationCommands.class);
+ register(platform, RegionCommands.class);
+ register(platform, ScriptingCommands.class);
+ register(platform, SelectionCommands.class);
+ register(platform, SnapshotUtilCommands.class);
+ register(platform, ToolUtilCommands.class);
+ register(platform, ToolCommands.class);
+ register(platform, UtilityCommands.class);
+ }
+
+ void unregister() {
+ dynamicHandler.setHandler(null);
+ }
+
+ private void register(Platform platform, Class> clazz) {
+ platform.onCommandRegistration(commands.registerAndReturn(clazz), commands);
+ }
+
+ public CommandsManager getCommands() {
+ return commands;
+ }
+
+ public String[] commandDetection(String[] split) {
+ Request.reset();
+
+ split[0] = split[0].substring(1);
+
+ // Quick script shortcut
+ if (split[0].matches("^[^/].*\\.js$")) {
+ String[] newSplit = new String[split.length + 1];
+ System.arraycopy(split, 0, newSplit, 1, split.length);
+ newSplit[0] = "cs";
+ newSplit[1] = newSplit[1];
+ split = newSplit;
+ }
+
+ String searchCmd = split[0].toLowerCase();
+
+ // Try to detect the command
+ if (commands.hasCommand(searchCmd)) {
+ } else if (worldEdit.getConfiguration().noDoubleSlash && commands.hasCommand("/" + searchCmd)) {
+ split[0] = "/" + split[0];
+ } else if (split[0].length() >= 2 && split[0].charAt(0) == '/'
+ && commands.hasCommand(searchCmd.substring(1))) {
+ split[0] = split[0].substring(1);
+ }
+
+ return split;
+ }
+
+ @Subscribe
+ public void handleCommand(CommandEvent event) {
+ Request.reset();
+
+ LocalPlayer player = event.getPlayer();
+ String[] split = event.getArguments();
+
+ try {
+ split = commandDetection(split);
+
+ // No command found!
+ if (!commands.hasCommand(split[0])) {
+ return;
+ }
+
+ LocalSession session = worldEdit.getSession(player);
+ EditSession editSession = session.createEditSession(player);
+ editSession.enableQueue();
+
+ session.tellVersion(player);
+
+ long start = System.currentTimeMillis();
+
+ try {
+ commands.execute(split, player, session, player, editSession);
+ } catch (CommandPermissionsException e) {
+ player.printError("You don't have permission to do this.");
+ } catch (MissingNestedCommandException e) {
+ player.printError(e.getUsage());
+ } catch (CommandUsageException e) {
+ player.printError(e.getMessage());
+ player.printError(e.getUsage());
+ } catch (PlayerNeededException e) {
+ player.printError(e.getMessage());
+ } catch (WrappedCommandException e) {
+ throw e.getCause();
+ } catch (UnhandledCommandException e) {
+ player.printError("Command could not be handled; invalid sender!");
+ event.setCancelled(true);
+ return;
+ } finally {
+ session.remember(editSession);
+ editSession.flushQueue();
+
+ if (worldEdit.getConfiguration().profile) {
+ long time = System.currentTimeMillis() - start;
+ int changed = editSession.getBlockChangeCount();
+ if (time > 0) {
+ double throughput = changed / (time / 1000.0);
+ player.printDebug((time / 1000.0) + "s elapsed (history: "
+ + changed + " changed; "
+ + Math.round(throughput) + " blocks/sec).");
+ } else {
+ player.printDebug((time / 1000.0) + "s elapsed.");
+ }
+ }
+
+ worldEdit.flushBlockBag(player, editSession);
+ }
+ } catch (NumberFormatException e) {
+ final Matcher matcher = numberFormatExceptionPattern.matcher(e.getMessage());
+
+ if (matcher.matches()) {
+ player.printError("Number expected; string \"" + matcher.group(1) + "\" given.");
+ } else {
+ player.printError("Number expected; string given.");
+ }
+ } catch (IncompleteRegionException e) {
+ player.printError("Make a region selection first.");
+ } catch (UnknownItemException e) {
+ player.printError("Block name '" + e.getID() + "' was not recognized.");
+ } catch (InvalidItemException e) {
+ player.printError(e.getMessage());
+ } catch (DisallowedItemException e) {
+ player.printError("Block '" + e.getID() + "' not allowed (see WorldEdit configuration).");
+ } catch (MaxChangedBlocksException e) {
+ player.printError("Max blocks changed in an operation reached ("
+ + e.getBlockLimit() + ").");
+ } catch (MaxBrushRadiusException e) {
+ player.printError("Maximum allowed brush size: " + worldEdit.getConfiguration().maxBrushRadius);
+ } catch (MaxRadiusException e) {
+ player.printError("Maximum allowed size: " + worldEdit.getConfiguration().maxRadius);
+ } catch (UnknownDirectionException e) {
+ player.printError("Unknown direction: " + e.getDirection());
+ } catch (InsufficientArgumentsException e) {
+ player.printError(e.getMessage());
+ } catch (EmptyClipboardException e) {
+ player.printError("Your clipboard is empty. Use //copy first.");
+ } catch (InvalidFilenameException e) {
+ player.printError("Filename '" + e.getFilename() + "' invalid: "
+ + e.getMessage());
+ } catch (FilenameResolutionException e) {
+ player.printError("File '" + e.getFilename() + "' resolution error: "
+ + e.getMessage());
+ } catch (InvalidToolBindException e) {
+ player.printError("Can't bind tool to "
+ + ItemType.toHeldName(e.getItemId()) + ": " + e.getMessage());
+ } catch (FileSelectionAbortedException e) {
+ player.printError("File selection aborted.");
+ } catch (WorldEditException e) {
+ player.printError(e.getMessage());
+ } catch (Throwable excp) {
+ player.printError("Please report this error: [See console]");
+ player.printRaw(excp.getClass().getName() + ": " + excp.getMessage());
+ excp.printStackTrace();
+ }
+
+ event.setCancelled(true);
+ }
+
+ private class CommandsManagerImpl extends CommandsManager {
+ @Override
+ protected void checkPermission(LocalPlayer player, Method method) throws CommandException {
+ if (!player.isPlayer() && !method.isAnnotationPresent(Console.class)) {
+ throw new UnhandledCommandException();
+ }
+
+ super.checkPermission(player, method);
+ }
+
+ @Override
+ public boolean hasPermission(LocalPlayer player, String perm) {
+ return player.hasPermission(perm);
+ }
+
+ @Override
+ public void invokeMethod(Method parent, String[] args,
+ LocalPlayer player, Method method, Object instance,
+ Object[] methodArgs, int level) throws CommandException {
+ if (worldEdit.getConfiguration().logCommands) {
+ final Logging loggingAnnotation = method.getAnnotation(Logging.class);
+
+ final Logging.LogMode logMode;
+ if (loggingAnnotation == null) {
+ logMode = null;
+ } else {
+ logMode = loggingAnnotation.value();
+ }
+
+ String msg = "WorldEdit: " + player.getName();
+ if (player.isPlayer()) {
+ msg += " (in \"" + player.getWorld().getName() + "\")";
+ }
+ msg += ": " + StringUtil.joinString(args, " ");
+ if (logMode != null && player.isPlayer()) {
+ Vector position = player.getPosition();
+ final LocalSession session = worldEdit.getSessionManager().get(player);
+
+ switch (logMode) {
+ case PLACEMENT:
+ try {
+ position = session.getPlacementPosition(player);
+ } catch (IncompleteRegionException e) {
+ break;
+ }
+ /* FALL-THROUGH */
+
+ case POSITION:
+ msg += " - Position: " + position;
+ break;
+
+ case ALL:
+ msg += " - Position: " + position;
+ /* FALL-THROUGH */
+
+ case ORIENTATION_REGION:
+ msg += " - Orientation: " + player.getCardinalDirection().name();
+ /* FALL-THROUGH */
+
+ case REGION:
+ try {
+ msg += " - Region: " + session.getSelection(player.getWorld());
+ } catch (IncompleteRegionException e) {
+ break;
+ }
+ break;
+ }
+ }
+
+ getLogger().info(msg);
+ }
+ super.invokeMethod(parent, args, player, method, instance, methodArgs, level);
+ }
+ }
+
+ public static Logger getLogger() {
+ return logger;
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java b/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java
new file mode 100644
index 000000000..6e4f65945
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java
@@ -0,0 +1,89 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.extension.platform;
+
+import com.sk89q.minecraft.util.commands.Command;
+import com.sk89q.minecraft.util.commands.CommandsManager;
+import com.sk89q.worldedit.BiomeTypes;
+import com.sk89q.worldedit.LocalConfiguration;
+import com.sk89q.worldedit.LocalPlayer;
+import com.sk89q.worldedit.LocalWorld;
+
+import java.util.List;
+
+/**
+ * Represents a platform that WorldEdit has been implemented for.
+ */
+public interface Platform {
+
+ /**
+ * Resolves an item name to its ID.
+ *
+ * @param name The name to look up
+ * @return The id that corresponds to the name, or -1 if no such ID exists
+ */
+ int resolveItem(String name);
+
+ /**
+ * Checks if a mob type is valid.
+ *
+ * @param type The mob type name to check
+ * @return Whether the name is a valid mod bype
+ */
+ boolean isValidMobType(String type);
+
+ /**
+ * Reload WorldEdit configuration.
+ */
+ void reload();
+
+ /**
+ * Returns all available biomes.
+ *
+ * @return an object containing all the biomes
+ */
+ BiomeTypes getBiomes();
+
+ /**
+ * Schedules the given task
to be invoked once every period
ticks
+ * after an initial delay of delay
ticks.
+ *
+ * @param delay Delay in server ticks before executing first repeat
+ * @param period Period in server ticks of the task
+ * @param task Task to be executed
+ * @return Task id number (-1 if scheduling failed)
+ */
+ int schedule(long delay, long period, Runnable task);
+
+ List getWorlds();
+
+ @Deprecated
+ void onCommandRegistration(List commands);
+
+ void onCommandRegistration(List commands, CommandsManager manager);
+
+ /**
+ * Get the configuration from this platform.
+ *
+ * @return the configuration
+ */
+ LocalConfiguration getConfiguration();
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java
new file mode 100644
index 000000000..eb246fd05
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java
@@ -0,0 +1,162 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.extension.platform;
+
+import com.sk89q.worldedit.LocalConfiguration;
+import com.sk89q.worldedit.ServerInterface;
+import com.sk89q.worldedit.WorldEdit;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Manages registered {@link Platform}s for WorldEdit. Platforms are
+ * implementations of WorldEdit.
+ *
+ * This class is thread-safe.
+ */
+public class PlatformManager {
+
+ private static final Logger logger = Logger.getLogger(PlatformManager.class.getCanonicalName());
+
+ private final LocalConfiguration defaultConfig = new DefaultConfiguration();
+ private final List platforms = new ArrayList();
+ private final CommandManager commandManager;
+ private @Nullable Platform primary = null;
+
+ /**
+ * Create a new platform manager.
+ *
+ * @param worldEdit the WorldEdit instance
+ */
+ public PlatformManager(WorldEdit worldEdit) {
+ checkNotNull(worldEdit);
+ this.commandManager = new CommandManager(worldEdit);
+ }
+
+ /**
+ * Register a platform with WorldEdit.
+ *
+ * @param platform the platform
+ * @throws PlatformRejectionException thrown if the registration is rejected
+ */
+ public synchronized void register(Platform platform) throws PlatformRejectionException {
+ checkNotNull(platform);
+ logger.log(Level.FINE, "Got request to register " + platform.getClass().getCanonicalName() + " with WorldEdit");
+ platforms.add(platform);
+ if (this.primary == null) {
+ commandManager.register(platform);
+ this.primary = platform;
+ }
+ }
+
+ /**
+ * Unregister a platform from WorldEdit.
+ *
+ * @param platform the platform
+ */
+ public synchronized boolean unregister(Platform platform) {
+ checkNotNull(platform);
+ boolean removed = platforms.remove(platform);
+ if (removed) {
+ logger.log(Level.FINE, "Unregistering " + platform.getClass().getCanonicalName() + " from WorldEdit");
+
+ if (platform == primary) {
+ primary = null;
+ commandManager.unregister();
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * Get the command manager.
+ *
+ * @return the command manager
+ */
+ public CommandManager getCommandManager() {
+ return commandManager;
+ }
+
+ /**
+ * Get the current configuration.
+ *
+ * If no platform has been registered yet, then a default configuration
+ * will be returned.
+ *
+ * @return the configuration
+ */
+ public LocalConfiguration getConfiguration() {
+ Platform platform = primary;
+ if (platform != null) {
+ return platform.getConfiguration();
+ } else {
+ return defaultConfig;
+ }
+ }
+ /**
+ * Return a {@link Platform}.
+ *
+ * @return a {@link Platform}
+ * @throws IllegalStateException if no platform has been registered
+ */
+ public Platform getPlatform() throws IllegalStateException {
+ Platform platform = primary;
+ if (platform != null) {
+ return platform;
+ } else {
+ throw new IllegalStateException("No platform has been registered");
+ }
+ }
+
+ /**
+ * Return a legacy {@link ServerInterface}.
+ *
+ * @return a {@link ServerInterface}
+ * @throws IllegalStateException if no platform has been registered
+ */
+ public ServerInterface getServerInterface() throws IllegalStateException {
+ Platform platform = primary;
+ if (platform != null) {
+ if (platform instanceof ServerInterface) {
+ return (ServerInterface) platform;
+ } else {
+ return new ServerInterfaceAdapter(platform);
+ }
+ } else {
+ throw new IllegalStateException("No platform has been registered");
+ }
+ }
+
+ /**
+ * A default configuration for when none is set.
+ */
+ private static class DefaultConfiguration extends LocalConfiguration {
+ @Override
+ public void load() {
+ }
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/PlatformRejectionException.java b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformRejectionException.java
new file mode 100644
index 000000000..1810950eb
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformRejectionException.java
@@ -0,0 +1,49 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.extension.platform;
+
+import com.sk89q.worldedit.WorldEditException;
+
+/**
+ * Thrown when a platform registration request is rejected, which may
+ * be because another platform is already registered.
+ */
+public class PlatformRejectionException extends WorldEditException {
+
+ /**
+ * Create with a message.
+ *
+ * @param message the message
+ */
+ public PlatformRejectionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Create with a message and a cause.
+ *
+ * @param message the message
+ * @param cause the cause
+ */
+ public PlatformRejectionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/ServerInterfaceAdapter.java b/src/main/java/com/sk89q/worldedit/extension/platform/ServerInterfaceAdapter.java
new file mode 100644
index 000000000..d07ea2809
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/extension/platform/ServerInterfaceAdapter.java
@@ -0,0 +1,93 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.extension.platform;
+
+import com.sk89q.minecraft.util.commands.Command;
+import com.sk89q.minecraft.util.commands.CommandsManager;
+import com.sk89q.worldedit.*;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Adapts {@link Platform}s into the legacy {@link ServerInterface}.
+ */
+class ServerInterfaceAdapter extends ServerInterface {
+
+ private final Platform platform;
+
+ /**
+ * Create a new adapter.
+ *
+ * @param platform the platform
+ */
+ ServerInterfaceAdapter(Platform platform) {
+ checkNotNull(platform);
+ this.platform = platform;
+ }
+
+ @Override
+ public int resolveItem(String name) {
+ return platform.resolveItem(name);
+ }
+
+ @Override
+ public boolean isValidMobType(String type) {
+ return platform.isValidMobType(type);
+ }
+
+ @Override
+ public void reload() {
+ platform.reload();
+ }
+
+ @Override
+ public BiomeTypes getBiomes() {
+ return platform.getBiomes();
+ }
+
+ @Override
+ public int schedule(long delay, long period, Runnable task) {
+ return platform.schedule(delay, period, task);
+ }
+
+ @Override
+ public List getWorlds() {
+ return platform.getWorlds();
+ }
+
+ @Override
+ @Deprecated
+ public void onCommandRegistration(List commands) {
+ platform.onCommandRegistration(commands);
+ }
+
+ @Override
+ public void onCommandRegistration(List commands, CommandsManager manager) {
+ platform.onCommandRegistration(commands, manager);
+ }
+
+ @Override
+ public LocalConfiguration getConfiguration() {
+ return platform.getConfiguration();
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/util/logging/DynamicStreamHandler.java b/src/main/java/com/sk89q/worldedit/util/logging/DynamicStreamHandler.java
new file mode 100644
index 000000000..500b77aef
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/util/logging/DynamicStreamHandler.java
@@ -0,0 +1,179 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.util.logging;
+
+import javax.annotation.Nullable;
+import java.io.UnsupportedEncodingException;
+import java.util.logging.*;
+
+/**
+ * A {@link StreamHandler} delegate that allows for the swap and disable of
+ * another handler. When {@link #setHandler(StreamHandler)} is called with
+ * null, then records passed onto this handler will be dropped. Otherwise,
+ * the delegate handler will receive those records.
+ */
+public class DynamicStreamHandler extends StreamHandler {
+
+ private @Nullable StreamHandler handler;
+ private @Nullable Formatter formatter;
+ private @Nullable Filter filter;
+ private @Nullable String encoding;
+ private Level level = Level.ALL;
+
+ /**
+ * Get the delegate handler.
+ *
+ * @return the delegate handler (Which may be null)
+ */
+ public @Nullable synchronized StreamHandler getHandler() {
+ return handler;
+ }
+
+ /**
+ * Set the handler.
+ *
+ * @param handler the delegate handler (which can be null)
+ */
+ public synchronized void setHandler(@Nullable StreamHandler handler) {
+ if (this.handler != null) {
+ this.handler.close();
+ }
+
+ this.handler = handler;
+
+ if (handler != null) {
+ handler.setFormatter(formatter);
+ handler.setFilter(filter);
+ try {
+ handler.setEncoding(encoding);
+ } catch (UnsupportedEncodingException ignore) {
+ }
+ handler.setLevel(level);
+ }
+ }
+
+ @Override
+ public synchronized void publish(LogRecord record) {
+ if (handler != null) {
+ handler.publish(record);
+ }
+ }
+
+ @Override
+ public synchronized void close() throws SecurityException {
+ if (handler != null) {
+ handler.close();
+ }
+ }
+
+ @Override
+ public void setEncoding(@Nullable String encoding) throws SecurityException, UnsupportedEncodingException {
+ StreamHandler handler = this.handler;
+ this.encoding = encoding;
+ if (handler != null) {
+ handler.setEncoding(encoding);
+ }
+ }
+
+ @Override
+ public boolean isLoggable(LogRecord record) {
+ StreamHandler handler = this.handler;
+ return handler != null && handler.isLoggable(record);
+ }
+
+ @Override
+ public synchronized void flush() {
+ StreamHandler handler = this.handler;
+ if (handler != null) {
+ handler.flush();
+ }
+ }
+
+ @Override
+ public void setFormatter(@Nullable Formatter newFormatter) throws SecurityException {
+ StreamHandler handler = this.handler;
+ this.formatter = newFormatter;
+ if (handler != null) {
+ handler.setFormatter(newFormatter);
+ }
+ }
+
+ @Override
+ public Formatter getFormatter() {
+ StreamHandler handler = this.handler;
+ Formatter formatter = this.formatter;
+ if (handler != null) {
+ return handler.getFormatter();
+ } else if (formatter != null) {
+ return formatter;
+ } else {
+ return new SimpleFormatter();
+ }
+ }
+
+ @Override
+ public String getEncoding() {
+ StreamHandler handler = this.handler;
+ String encoding = this.encoding;
+ if (handler != null) {
+ return handler.getEncoding();
+ } else {
+ return encoding;
+ }
+ }
+
+ @Override
+ public void setFilter(@Nullable Filter newFilter) throws SecurityException {
+ StreamHandler handler = this.handler;
+ this.filter = newFilter;
+ if (handler != null) {
+ handler.setFilter(newFilter);
+ }
+ }
+
+ @Override
+ public Filter getFilter() {
+ StreamHandler handler = this.handler;
+ Filter filter = this.filter;
+ if (handler != null) {
+ return handler.getFilter();
+ } else {
+ return filter;
+ }
+ }
+
+ @Override
+ public synchronized void setLevel(Level newLevel) throws SecurityException {
+ if (handler != null) {
+ handler.setLevel(newLevel);
+ }
+ this.level = newLevel;
+ }
+
+ @Override
+ public synchronized Level getLevel() {
+ if (handler != null) {
+ return handler.getLevel();
+ } else {
+ return level;
+ }
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/util/LogFormat.java b/src/main/java/com/sk89q/worldedit/util/logging/LogFormat.java
similarity index 95%
rename from src/main/java/com/sk89q/worldedit/util/LogFormat.java
rename to src/main/java/com/sk89q/worldedit/util/logging/LogFormat.java
index a7be80c05..c605b6a3a 100644
--- a/src/main/java/com/sk89q/worldedit/util/LogFormat.java
+++ b/src/main/java/com/sk89q/worldedit/util/logging/LogFormat.java
@@ -17,7 +17,7 @@
* along with this program. If not, see .
*/
-package com.sk89q.worldedit.util;
+package com.sk89q.worldedit.util.logging;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
@@ -26,9 +26,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
/**
- * Used for formatting.
- *
- * @author sk89q
+ * A standard logging format for WorldEdit.
*/
public class LogFormat extends Formatter {
@Override
diff --git a/src/main/java/com/sk89q/worldedit/util/logging/WorldEditPrefixHandler.java b/src/main/java/com/sk89q/worldedit/util/logging/WorldEditPrefixHandler.java
new file mode 100644
index 000000000..f2c8a0754
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/util/logging/WorldEditPrefixHandler.java
@@ -0,0 +1,59 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.util.logging;
+
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * Adds a WorldEdit prefix to WorldEdit's logger messages using a handler.
+ */
+public final class WorldEditPrefixHandler extends Handler {
+
+ private WorldEditPrefixHandler() {
+ }
+
+ @Override
+ public void publish(LogRecord record) {
+ String message = record.getMessage();
+ if (!message.startsWith("WorldEdit: ") && !message.startsWith("[WorldEdit] ")) {
+ record.setMessage("[WorldEdit] " + message);
+ }
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ }
+
+ /**
+ * Add the handler to the following logger name.
+ *
+ * @param name the logger name
+ */
+ public static void register(String name) {
+ Logger.getLogger(name).addHandler(new WorldEditPrefixHandler());
+ }
+
+}
diff --git a/src/spout/java/com/sk89q/worldedit/spout/SpoutServerInterface.java b/src/spout/java/com/sk89q/worldedit/spout/SpoutServerInterface.java
index e2de37895..5bcf68cae 100644
--- a/src/spout/java/com/sk89q/worldedit/spout/SpoutServerInterface.java
+++ b/src/spout/java/com/sk89q/worldedit/spout/SpoutServerInterface.java
@@ -22,6 +22,7 @@ package com.sk89q.worldedit.spout;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.CommandsManager;
+import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.ServerInterface;
@@ -102,4 +103,9 @@ public class SpoutServerInterface extends ServerInterface {
spoutCommand.closeSubCommand();
}
}
+
+ @Override
+ public LocalConfiguration getConfiguration() {
+ return plugin.getLocalConfiguration();
+ }
}
diff --git a/src/spout/java/com/sk89q/worldedit/spout/WorldEditPlugin.java b/src/spout/java/com/sk89q/worldedit/spout/WorldEditPlugin.java
index 5f7454ded..0e9a7cae7 100644
--- a/src/spout/java/com/sk89q/worldedit/spout/WorldEditPlugin.java
+++ b/src/spout/java/com/sk89q/worldedit/spout/WorldEditPlugin.java
@@ -21,6 +21,7 @@ package com.sk89q.worldedit.spout;
import com.sk89q.util.yaml.YAMLProcessor;
import com.sk89q.worldedit.*;
+import com.sk89q.worldedit.extension.platform.PlatformRejectionException;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
@@ -99,7 +100,12 @@ public class WorldEditPlugin extends CommonPlugin {
// Setup interfaces
server = new SpoutServerInterface(this, getEngine());
- controller = new WorldEdit(server, config);
+ controller = WorldEdit.getInstance();
+ try {
+ controller.getPlatformManager().register(server);
+ } catch (PlatformRejectionException e) {
+ throw new RuntimeException("Failed to register with WorldEdit", e);
+ }
// Now we can register events!
registerEvents();