From 28f76f869c5f1557bbde2f1cdb20d23ec3008e61 Mon Sep 17 00:00:00 2001 From: sk89q Date: Wed, 3 Nov 2010 16:46:47 -0700 Subject: [PATCH] Renamed SMWorldEdit to WorldEdit to prevent confusion. --- src/EditSession.java | 6 +- ...nterface.java => HmodServerInterface.java} | 2 +- ...stener.java => HmodWorldEditListener.java} | 24 +- ...itPlayer.java => HmodWorldEditPlayer.java} | 4 +- src/SMWorldEdit.java | 114 -- src/WorldEdit.java | 1255 +---------------- src/WorldEditLibrary.java | 1249 ++++++++++++++++ src/WorldEditPlayer.java | 8 +- 8 files changed, 1331 insertions(+), 1331 deletions(-) rename src/{SMServerInterface.java => HmodServerInterface.java} (98%) rename src/{SMWorldEditListener.java => HmodWorldEditListener.java} (89%) rename src/{SMWorldEditPlayer.java => HmodWorldEditPlayer.java} (98%) delete mode 100644 src/SMWorldEdit.java create mode 100644 src/WorldEditLibrary.java diff --git a/src/EditSession.java b/src/EditSession.java index 727e1dec7..2fc84f68d 100644 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -1,6 +1,6 @@ // $Id$ /* - * WorldEdit + * WorldEditLibrary * Copyright (C) 2010 sk89q * * This program is free software: you can redistribute it and/or modify @@ -96,7 +96,7 @@ public class EditSession { * Default constructor. There is no maximum blocks limit. */ public EditSession() { - server = WorldEdit.getServer(); + server = WorldEditLibrary.getServer(); } /** @@ -108,7 +108,7 @@ public class EditSession { } this.maxBlocks = maxBlocks; - server = WorldEdit.getServer(); + server = WorldEditLibrary.getServer(); } /** diff --git a/src/SMServerInterface.java b/src/HmodServerInterface.java similarity index 98% rename from src/SMServerInterface.java rename to src/HmodServerInterface.java index 24c024c1d..2b8af2cc2 100644 --- a/src/SMServerInterface.java +++ b/src/HmodServerInterface.java @@ -26,7 +26,7 @@ import java.util.HashMap; * * @author sk89q */ -public class SMServerInterface implements ServerInterface { +public class HmodServerInterface implements ServerInterface { /** * Set block type. * diff --git a/src/SMWorldEditListener.java b/src/HmodWorldEditListener.java similarity index 89% rename from src/SMWorldEditListener.java rename to src/HmodWorldEditListener.java index 583932a56..2a3ed2f3d 100644 --- a/src/SMWorldEditListener.java +++ b/src/HmodWorldEditListener.java @@ -1,6 +1,6 @@ // $Id$ /* - * WorldEdit + * WorldEditLibrary * Copyright (C) 2010 sk89q * * This program is free software: you can redistribute it and/or modify @@ -24,15 +24,15 @@ import com.sk89q.worldedit.*; * * @author sk89q */ -public class SMWorldEditListener extends PluginListener { +public class HmodWorldEditListener extends PluginListener { /** * * @param player */ @Override public void onDisconnect(Player player) { - WorldEdit worldEdit = WorldEdit.getInstance(); - worldEdit.removeSession(new SMWorldEditPlayer(player)); + WorldEditLibrary worldEdit = WorldEditLibrary.getInstance(); + worldEdit.removeSession(new HmodWorldEditPlayer(player)); } /** @@ -47,8 +47,8 @@ public class SMWorldEditListener extends PluginListener { @Override public boolean onBlockCreate(Player modPlayer, Block blockPlaced, Block blockClicked, int itemInHand) { - WorldEdit worldEdit = WorldEdit.getInstance(); - WorldEditPlayer player = new SMWorldEditPlayer(modPlayer); + WorldEditLibrary worldEdit = WorldEditLibrary.getInstance(); + WorldEditPlayer player = new HmodWorldEditPlayer(modPlayer); if (itemInHand != 271) { return false; } if (!canUseCommand(modPlayer, "//pos2")) { return false; } @@ -82,8 +82,8 @@ public class SMWorldEditListener extends PluginListener { if (!canUseCommand(modPlayer, "//pos1") && !canUseCommand(modPlayer, "//")) { return false; } - WorldEdit worldEdit = WorldEdit.getInstance(); - WorldEditPlayer player = new SMWorldEditPlayer(modPlayer); + WorldEditLibrary worldEdit = WorldEditLibrary.getInstance(); + WorldEditPlayer player = new HmodWorldEditPlayer(modPlayer); WorldEditSession session = worldEdit.getSession(player); if (player.getItemInHand() == 271) { @@ -114,12 +114,12 @@ public class SMWorldEditListener extends PluginListener { if (session.hasSuperPickAxe()) { Vector pos = new Vector(blockClicked.getX(), blockClicked.getY(), blockClicked.getZ()); - if (WorldEdit.getServer().getBlockType(pos) == 7 + if (WorldEditLibrary.getServer().getBlockType(pos) == 7 && !canUseCommand(modPlayer, "/worldeditbedrock")) { return true; } - WorldEdit.getServer().setBlockType(pos, 0); + WorldEditLibrary.getServer().setBlockType(pos, 0); return true; } @@ -136,7 +136,7 @@ public class SMWorldEditListener extends PluginListener { */ @Override public boolean onCommand(Player modPlayer, String[] split) { - WorldEdit worldEdit = WorldEdit.getInstance(); + WorldEditLibrary worldEdit = WorldEditLibrary.getInstance(); try { // Legacy /, command @@ -146,7 +146,7 @@ public class SMWorldEditListener extends PluginListener { if (worldEdit.getCommands().containsKey(split[0].toLowerCase())) { if (canUseCommand(modPlayer, split[0])) { - WorldEditPlayer player = new SMWorldEditPlayer(modPlayer); + WorldEditPlayer player = new HmodWorldEditPlayer(modPlayer); WorldEditSession session = worldEdit.getSession(player); EditSession editSession = new EditSession(session.getBlockChangeLimit()); diff --git a/src/SMWorldEditPlayer.java b/src/HmodWorldEditPlayer.java similarity index 98% rename from src/SMWorldEditPlayer.java rename to src/HmodWorldEditPlayer.java index 7c1c4f586..810ab46a1 100644 --- a/src/SMWorldEditPlayer.java +++ b/src/HmodWorldEditPlayer.java @@ -24,7 +24,7 @@ import com.sk89q.worldedit.ServerInterface; * * @author sk89q */ -public class SMWorldEditPlayer extends WorldEditPlayer { +public class HmodWorldEditPlayer extends WorldEditPlayer { private Player player; /** @@ -32,7 +32,7 @@ public class SMWorldEditPlayer extends WorldEditPlayer { * * @param player */ - public SMWorldEditPlayer(Player player) { + public HmodWorldEditPlayer(Player player) { super(); this.player = player; } diff --git a/src/SMWorldEdit.java b/src/SMWorldEdit.java deleted file mode 100644 index aee5489cf..000000000 --- a/src/SMWorldEdit.java +++ /dev/null @@ -1,114 +0,0 @@ -// $Id$ -/* - * WorldEdit - * Copyright (C) 2010 sk89q - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import com.sk89q.worldedit.snapshots.SnapshotRepository; -import java.util.Map; -import java.util.HashSet; -import com.sk89q.worldedit.ServerInterface; - -/** - * Entry point for the plugin for hey0's mod. - * - * @author sk89q - */ -public class SMWorldEdit extends Plugin { - /** - * WorldEdit's properties file. - */ - private PropertiesFile properties; - /** - * WorldEdit instance. - */ - private static final WorldEdit worldEdit = - WorldEdit.setup(new SMServerInterface()); - /** - * Listener for the plugin system. - */ - private static final SMWorldEditListener listener = - new SMWorldEditListener(); - - /** - * Initializes the plugin. - */ - @Override - public void initialize() { - PluginLoader loader = etc.getLoader(); - - loader.addListener(PluginLoader.Hook.BLOCK_CREATED, listener, this, - PluginListener.Priority.MEDIUM); - loader.addListener(PluginLoader.Hook.BLOCK_DESTROYED, listener, this, - PluginListener.Priority.MEDIUM); - loader.addListener(PluginLoader.Hook.COMMAND, listener, this, - PluginListener.Priority.MEDIUM); - loader.addListener(PluginLoader.Hook.DISCONNECT, listener, this, - PluginListener.Priority.MEDIUM); - loader.addListener(PluginLoader.Hook.LOGIN, listener, this, - PluginListener.Priority.MEDIUM); - } - - /** - * Enables the plugin. - */ - @Override - public void enable() { - if (properties == null) { - properties = new PropertiesFile("worldedit.properties"); - } else { - properties.load(); - } - - // Get allowed blocks - HashSet allowedBlocks = new HashSet(); - for (String b : properties.getString("allowed-blocks", - WorldEdit.getDefaultAllowedBlocks()).split(",")) { - try { - allowedBlocks.add(Integer.parseInt(b)); - } catch (NumberFormatException e) { - } - } - worldEdit.setAllowedBlocks(allowedBlocks); - - worldEdit.setDefaultChangeLimit( - Math.max(-1, properties.getInt("max-blocks-changed", -1))); - - String snapshotsDir = properties.getString("snapshots-dir", ""); - if (!snapshotsDir.trim().equals("")) { - worldEdit.setSnapshotRepository(new SnapshotRepository(snapshotsDir)); - } - - String shellSaveType = properties.getString("shell-save-type", "").trim(); - worldEdit.setShellSaveType(shellSaveType.equals("") ? null : shellSaveType); - - for (Map.Entry entry : worldEdit.getCommands().entrySet()) { - etc.getInstance().addCommand(entry.getKey(), entry.getValue()); - } - } - - /** - * Disables the plugin. - */ - @Override - public void disable() { - for (String key : worldEdit.getCommands().keySet()) { - etc.getInstance().removeCommand(key); - } - - worldEdit.clearSessions(); - } -} diff --git a/src/WorldEdit.java b/src/WorldEdit.java index 6ec5e6613..6dc7109c8 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -1,6 +1,6 @@ // $Id$ /* - * WorldEdit + * WorldEditLibrary * Copyright (C) 2010 sk89q * * This program is free software: you can redistribute it and/or modify @@ -18,1232 +18,97 @@ */ import com.sk89q.worldedit.snapshots.SnapshotRepository; -import com.sk89q.worldedit.snapshots.Snapshot; -import com.sk89q.worldedit.*; -import com.sk89q.worldedit.blocks.*; -import com.sk89q.worldedit.data.*; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.snapshots.InvalidSnapshotException; -import java.util.HashMap; -import java.util.Set; +import java.util.Map; import java.util.HashSet; -import java.util.Arrays; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.io.*; +import com.sk89q.worldedit.ServerInterface; /** - * Plugin base. - * + * Entry point for the plugin for hey0's mod. + * * @author sk89q */ -public class WorldEdit { +public class WorldEdit extends Plugin { /** - * WorldEdit instance. + * WorldEditLibrary's properties file. */ - private static WorldEdit instance; + private PropertiesFile properties; /** - * Server interface. + * WorldEditLibrary instance. */ - private ServerInterface server; - + private static final WorldEditLibrary worldEdit = + WorldEditLibrary.setup(new HmodServerInterface()); /** - * List of default allowed blocks. + * Listener for the plugin system. */ - private final static Integer[] DEFAULT_ALLOWED_BLOCKS = { - 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 35, 41, 42, 43, 44, 45, 47, 48, 49, 52, 53, 54, 56, 57, 58, 60, - 61, 62, 67, 73, 78, 79, 80, 82, 85, 86, 87, 88, 89, 91 - }; + private static final HmodWorldEditListener listener = + new HmodWorldEditListener(); /** - * Logger. + * Initializes the plugin. */ - private static final Logger logger = Logger.getLogger("Minecraft"); - /** - * Stores the WorldEdit sessions of players. - */ - private HashMap sessions = - new HashMap(); - /** - * Stores the commands. - */ - private HashMap commands = new HashMap(); + @Override + public void initialize() { + PluginLoader loader = etc.getLoader(); - /** - * List of the blocks that can be used. If null, all blocks can be used. - */ - private HashSet allowedBlocks; - /** - * Default block change limit. -1 for no limit. - */ - private int defaultChangeLimit = -1; - /** - * Shell script save type. - */ - private String shellSaveType; - /** - * Stores the snapshot repository. May be null; - */ - private SnapshotRepository snapshotRepo; - - /** - * Set up an instance. - * - * @param server - * @return - */ - public static WorldEdit setup(ServerInterface server) { - WorldEdit worldEdit = new WorldEdit(); - worldEdit.server = server; - instance = worldEdit; - return worldEdit; + loader.addListener(PluginLoader.Hook.BLOCK_CREATED, listener, this, + PluginListener.Priority.MEDIUM); + loader.addListener(PluginLoader.Hook.BLOCK_DESTROYED, listener, this, + PluginListener.Priority.MEDIUM); + loader.addListener(PluginLoader.Hook.COMMAND, listener, this, + PluginListener.Priority.MEDIUM); + loader.addListener(PluginLoader.Hook.DISCONNECT, listener, this, + PluginListener.Priority.MEDIUM); + loader.addListener(PluginLoader.Hook.LOGIN, listener, this, + PluginListener.Priority.MEDIUM); } /** - * Get WorldEdit instance. - * - * @return + * Enables the plugin. */ - public static WorldEdit getInstance() { - return instance; - } - - /** - * Get server interface. - * - * @return - */ - public static ServerInterface getServer() { - return instance.server; - } - - /** - * Construct an instance of the plugin. - */ - private WorldEdit() { - // Note: Commands should only have the phrase 'air' at the end - // for now (see SMWorldEditListener.canUseCommand) - commands.put("//pos1", "Set editing position #1"); - commands.put("//pos2", "Set editing position #2"); - commands.put("//hpos1", "Trace editing position #1"); - commands.put("//hpos2", "Trace editing position #2"); - commands.put("/toggleplace", "Toggle placing at pos #1"); - commands.put("//wand", "Gives you the \"edit wand\""); - commands.put("/toggleeditwand", "Toggles edit wand selection"); - commands.put("//", "Toggles super pick axe."); - commands.put("//undo", "Undo"); - commands.put("//redo", "Redo"); - commands.put("/clearhistory", "Clear history"); - commands.put("/clearclipboard", "Clear clipboard"); - commands.put("//size", "Get size of selected region"); - commands.put("//set", "[ID] - Set all blocks inside region"); - commands.put("//outline", "[ID] - Outline the region with blocks"); - commands.put("//walls", "[ID] - Build walls"); - commands.put("//replace", " [ToID] - Replace all existing blocks inside region"); - commands.put("//overlay", "[ID] - Overlay the area one layer"); - commands.put("/removeabove", " - Remove blocks above head"); - commands.put("/removebelow", " - Remove blocks below position"); - commands.put("/removenear", " - Remove blocks near you"); - commands.put("//copy", "Copies the currently selected region"); - commands.put("//cut", "Cuts the currently selected region"); - commands.put("//paste", "Pastes the clipboard"); - commands.put("//pasteair", "Pastes the clipboard (with air)"); - commands.put("//move", " - Move the selection"); - commands.put("//moveair", " - Move the selection (with air)"); - commands.put("//stack", " - Stacks the selection"); - commands.put("//stackair", " - Stacks the selection (with air)"); - commands.put("//load", "[Filename] - Load .schematic into clipboard"); - commands.put("//save", "[Filename] - Save clipboard to .schematic"); - commands.put("//fill", "[ID] [Radius] - Fill a hole"); - commands.put("//drain", "[Radius] - Drain nearby water/lava pools"); - commands.put("//limit", "[Num] - See documentation"); - commands.put("//expand", " [Num] - Expands the selection"); - commands.put("//contract", " [Num] - Contracts the selection"); - commands.put("//rotate", "[Angle] - Rotate the clipboard"); - commands.put("//hcyl", "[ID] [Radius] - Create a vertical hollow cylinder"); - commands.put("//cyl", "[ID] [Radius] - Create a vertical cylinder"); - commands.put("//sphere", "[ID] [Radius] - Create a sphere"); - commands.put("//hsphere", "[ID] [Radius] - Create a hollow sphere"); - commands.put("/fixwater", "[Radius] - Level nearby pools of water"); - commands.put("/forestgen", " - Make an ugly pine tree forest"); - commands.put("/pumpkins", " - Make a pumpkin forest"); - commands.put("/unstuck", "Go up to the first free spot"); - commands.put("/ascend", "Go up one level"); - commands.put("/descend", "Go down one level"); - commands.put("/jumpto", "Jump to the block that you are looking at"); - commands.put("/thru", "Go through the wall that you are looking at"); - commands.put("/ceil", " - Get to the ceiling"); - commands.put("/chunkinfo", "Get the filename of the chunk that you are in"); - commands.put("/listchunks", "Print a list of used chunks"); - commands.put("/delchunks", "Generate a shell script to delete chunks"); - commands.put("/listsnapshots", "List the 5 newest snapshots"); - commands.put("//use", "[SnapshotID] - Use a particular snapshot"); - commands.put("//restore", "Restore a particular snapshot"); - } - - /** - * Gets the WorldEdit session for a player. - * - * @param player - * @return - */ - public WorldEditSession getSession(WorldEditPlayer player) { - if (sessions.containsKey(player)) { - return sessions.get(player); + @Override + public void enable() { + if (properties == null) { + properties = new PropertiesFile("worldedit.properties"); } else { - WorldEditSession session = new WorldEditSession(); - session.setBlockChangeLimit(getDefaultChangeLimit()); - sessions.put(player, session); - return session; + properties.load(); } - } - /** - * Get an item ID from an item name or an item ID number. - * - * @param arg - * @return - * @throws UnknownItemException - * @throws DisallowedItemException - */ - public BaseBlock getBlock(String arg, boolean allAllowed) - throws UnknownItemException, DisallowedItemException { - BlockType blockType; - arg = arg.replace("_", " "); - String[] args0 = arg.split("\\|"); - String[] args1 = args0[0].split(":", 2); - String testID = args1[0]; + // Get allowed blocks + HashSet allowedBlocks = new HashSet(); + for (String b : properties.getString("allowed-blocks", + WorldEditLibrary.getDefaultAllowedBlocks()).split(",")) { + try { + allowedBlocks.add(Integer.parseInt(b)); + } catch (NumberFormatException e) { + } + } + worldEdit.setAllowedBlocks(allowedBlocks); - int data; - - try { - data = args1.length > 1 ? Integer.parseInt(args1[1]) : 0; - if (data > 15 || data < 0) { - data = 0; - } - } catch (NumberFormatException e) { - data = 0; + worldEdit.setDefaultChangeLimit( + Math.max(-1, properties.getInt("max-blocks-changed", -1))); + + String snapshotsDir = properties.getString("snapshots-dir", ""); + if (!snapshotsDir.trim().equals("")) { + worldEdit.setSnapshotRepository(new SnapshotRepository(snapshotsDir)); } - try { - blockType = BlockType.fromID(Integer.parseInt(testID)); - } catch (NumberFormatException e) { - blockType = BlockType.lookup(testID); - } + String shellSaveType = properties.getString("shell-save-type", "").trim(); + worldEdit.setShellSaveType(shellSaveType.equals("") ? null : shellSaveType); - if (blockType == null) { - throw new UnknownItemException(); - } - - // Check if the item is allowed - if (allAllowed || allowedBlocks.isEmpty() - || allowedBlocks.contains(blockType.getID())) { - if (blockType == BlockType.SIGN_POST - || blockType == BlockType.WALL_SIGN) { - String[] text = new String[4]; - text[0] = args0.length > 1 ? args0[1] : ""; - text[1] = args0.length > 2 ? args0[2] : ""; - text[2] = args0.length > 3 ? args0[3] : ""; - text[3] = args0.length > 4 ? args0[4] : ""; - return new SignBlock(blockType.getID(), data, text); - } - return new BaseBlock(blockType.getID(), data); - } - - throw new DisallowedItemException(); - } - - /** - * Get a block. - * - * @param id - * @return - * @throws UnknownItemException - * @throws DisallowedItemException - */ - public BaseBlock getBlock(String id) throws UnknownItemException, - DisallowedItemException { - return getBlock(id, false); - } - - /** - * Checks to make sure that there are enough but not too many arguments. - * - * @param args - * @param min - * @param max -1 for no maximum - * @param cmd command name - * @throws InsufficientArgumentsException - */ - private void checkArgs(String[] args, int min, int max, String cmd) - throws InsufficientArgumentsException { - if (args.length <= min || (max != -1 && args.length - 1 > max)) { - if (commands.containsKey(cmd)) { - throw new InsufficientArgumentsException(cmd + " usage: " + - commands.get(cmd)); - } else { - throw new InsufficientArgumentsException("Invalid number of arguments"); - } + for (Map.Entry entry : worldEdit.getCommands().entrySet()) { + etc.getInstance().addCommand(entry.getKey(), entry.getValue()); } } /** - * The main meat of command processing. - * - * @param player - * @param editPlayer - * @param session - * @param editSession - * @param split - * @return - * @throws UnknownItemException - * @throws IncompleteRegionException - * @throws InsufficientArgumentsException - * @throws DisallowedItemException + * Disables the plugin. */ - public boolean performCommand(WorldEditPlayer player, - WorldEditSession session, EditSession editSession, String[] split) - throws WorldEditException - { - // Jump to the first free position - if (split[0].equalsIgnoreCase("/unstuck")) { - checkArgs(split, 0, 0, split[0]); - player.print("There you go!"); - player.findFreePosition(); - return true; - - // Ascend a level - } else if(split[0].equalsIgnoreCase("/ascend")) { - checkArgs(split, 0, 0, split[0]); - if (player.ascendLevel()) { - player.print("Ascended a level."); - } else { - player.printError("No free spot above you found."); - } - return true; - - // Descend a level - } else if(split[0].equalsIgnoreCase("/descend")) { - checkArgs(split, 0, 0, split[0]); - if (player.descendLevel()) { - player.print("Descended a level."); - } else { - player.printError("No free spot below you found."); - } - return true; - - // Jump to the block in sight - } else if (split[0].equalsIgnoreCase("/jumpto")) { - checkArgs(split, 0, 0, split[0]); - Vector pos = player.getBlockTrace(300); - if (pos != null) { - player.findFreePosition(pos); - player.print("Poof!"); - } else { - player.printError("No block in sight!"); - } - return true; - - // Go through a wall - } else if (split[0].equalsIgnoreCase("/thru")) { - checkArgs(split, 0, 0, split[0]); - if (player.passThroughForwardWall(6)) { - player.print("Whoosh!"); - } else { - player.printError("No free spot ahead of you found."); - } - return true; - - // Go to the ceiling - } else if (split[0].equalsIgnoreCase("/ceil")) { - checkArgs(split, 0, 1, split[0]); - int clearence = split.length > 1 ? - Math.max(0, Integer.parseInt(split[1])) : 0; - - if (player.ascendToCeiling(clearence)) { - player.print("Whoosh!"); - } else { - player.printError("No free spot above you found."); - } - return true; - - // Set edit position #1 - } else if (split[0].equalsIgnoreCase("//pos1")) { - checkArgs(split, 0, 0, split[0]); - session.setPos1(player.getBlockIn()); - player.print("First edit position set."); - return true; - - // Set edit position #2 - } else if (split[0].equalsIgnoreCase("//pos2")) { - checkArgs(split, 0, 0, split[0]); - session.setPos2(player.getBlockIn()); - player.print("Second edit position set."); - return true; - - // Trace edit position #1 - } else if (split[0].equalsIgnoreCase("//hpos1")) { - checkArgs(split, 0, 0, split[0]); - Vector pos = player.getBlockTrace(300); - if (pos != null) { - session.setPos1(pos); - player.print("First edit position set."); - } else { - player.printError("No block in sight!"); - } - return true; - - // Trace edit position #2 - } else if (split[0].equalsIgnoreCase("//hpos2")) { - checkArgs(split, 0, 0, split[0]); - Vector pos = player.getBlockTrace(300); - if (pos != null) { - session.setPos2(pos); - player.print("Second edit position set."); - } else { - player.printError("No block in sight!"); - } - return true; - - // Edit wand - } else if (split[0].equalsIgnoreCase("//wand")) { - checkArgs(split, 0, 0, split[0]); - player.giveItem(271, 1); - player.print("Left click: select pos #1; Right click: select pos #2"); - return true; - - // Toggle placing at pos #1 - } else if (split[0].equalsIgnoreCase("/toggleplace")) { - checkArgs(split, 0, 0, split[0]); - if (session.togglePlacementPosition()) { - player.print("Now placing at pos #1."); - } else { - player.print("Now placing at the block you stand in."); - } - return true; - - // Toggle edit wand - } else if (split[0].equalsIgnoreCase("/toggleeditwand")) { - checkArgs(split, 0, 0, split[0]); - session.setToolControl(!session.isToolControlEnabled()); - if (session.isToolControlEnabled()) { - player.print("Edit wand enabled."); - } else { - player.print("Edit wand disabled."); - } - return true; - - // Toggle super pick axe - } else if (split[0].equalsIgnoreCase("//")) { - checkArgs(split, 0, 0, split[0]); - if (session.toggleSuperPickAxe()) { - player.print("Super pick axe enabled."); - } else { - player.print("Super pick axe disabled."); - } - return true; - - // Set max number of blocks to change at a time - } else if (split[0].equalsIgnoreCase("//limit")) { - checkArgs(split, 1, 1, split[0]); - int limit = Math.max(-1, Integer.parseInt(split[1])); - session.setBlockChangeLimit(limit); - player.print("Block change limit set to " + limit + "."); - return true; - - // Undo - } else if (split[0].equalsIgnoreCase("//undo")) { - checkArgs(split, 0, 0, split[0]); - if (session.undo()) { - player.print("Undo successful."); - } else { - player.printError("Nothing to undo."); - } - return true; - - // Redo - } else if (split[0].equalsIgnoreCase("//redo")) { - checkArgs(split, 0, 0, split[0]); - if (session.redo()) { - player.print("Redo successful."); - } else { - player.printError("Nothing to redo."); - } - return true; - - // Clear undo history - } else if (split[0].equalsIgnoreCase("/clearhistory")) { - checkArgs(split, 0, 0, split[0]); - session.clearHistory(); - player.print("History cleared."); - return true; - - // Clear clipboard - } else if (split[0].equalsIgnoreCase("/clearclipboard")) { - checkArgs(split, 0, 0, split[0]); - session.setClipboard(null); - player.print("Clipboard cleared."); - return true; - - // Paste - } else if (split[0].equalsIgnoreCase("//pasteair") || - split[0].equalsIgnoreCase("//paste")) { - Vector pos = session.getPlacementPosition(player); - session.getClipboard().paste(editSession, pos, - split[0].equalsIgnoreCase("//paste")); - player.findFreePosition(); - player.print("Pasted. Undo with //undo"); - - return true; - - // Draw a hollow cylinder - } else if (split[0].equalsIgnoreCase("//hcyl") - || split[0].equalsIgnoreCase("//cyl")) { - checkArgs(split, 2, 3, split[0]); - BaseBlock block = getBlock(split[1]); - int radius = Math.max(1, Integer.parseInt(split[2])); - int height = split.length > 3 ? Integer.parseInt(split[3]) : 1; - boolean filled = split[0].equalsIgnoreCase("//cyl"); - - Vector pos = session.getPlacementPosition(player); - int affected; - if (filled) { - affected = editSession.makeCylinder(pos, block, radius, height); - } else { - affected = editSession.makeHollowCylinder(pos, block, radius, height); - } - player.print(affected + " block(s) have been created."); - - return true; - - // Draw a sphere - } else if (split[0].equalsIgnoreCase("//sphere") - || split[0].equalsIgnoreCase("//hsphere")) { - checkArgs(split, 2, 3, split[0]); - BaseBlock block = getBlock(split[1]); - int radius = Math.max(1, Integer.parseInt(split[2])); - boolean raised = split.length > 3 - ? (split[3].equalsIgnoreCase("true") - || split[3].equalsIgnoreCase("yes")) - : false; - boolean filled = split[0].equalsIgnoreCase("//sphere"); - - Vector pos = session.getPlacementPosition(player); - if (raised) { - pos = pos.add(0, radius, 0); - } - - int affected = editSession.makeSphere(pos, block, radius, filled); - player.findFreePosition(); - player.print(affected + " block(s) have been created."); - - return true; - - // Fill a hole - } else if (split[0].equalsIgnoreCase("//fill")) { - checkArgs(split, 2, 3, split[0]); - BaseBlock block = getBlock(split[1]); - int radius = Math.max(1, Integer.parseInt(split[2])); - int depth = split.length > 3 ? Math.max(1, Integer.parseInt(split[3])) : 1; - - Vector pos = session.getPlacementPosition(player); - int affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(), - pos, block, radius, depth); - player.print(affected + " block(s) have been created."); - - return true; - - // Remove blocks above current position - } else if (split[0].equalsIgnoreCase("/removeabove")) { - checkArgs(split, 0, 2, split[0]); - int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; - int height = split.length > 2 ? Math.min(128, Integer.parseInt(split[2]) + 2) : 128; - - int affected = editSession.removeAbove( - session.getPlacementPosition(player), size, height); - player.print(affected + " block(s) have been removed."); - - return true; - - // Remove blocks below current position - } else if (split[0].equalsIgnoreCase("/removebelow")) { - checkArgs(split, 0, 2, split[0]); - int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; - int height = split.length > 2 ? Math.max(1, Integer.parseInt(split[2])) : 128; - - int affected = editSession.removeBelow( - session.getPlacementPosition(player), size, height); - player.print(affected + " block(s) have been removed."); - - return true; - - // Remove blocks near - } else if (split[0].equalsIgnoreCase("/removenear")) { - checkArgs(split, 2, 2, split[0]); - BaseBlock block = getBlock(split[1], true); - int size = Math.max(1, Integer.parseInt(split[2])); - - int affected = editSession.removeNear( - session.getPlacementPosition(player), block.getID(), size); - player.print(affected + " block(s) have been removed."); - - return true; - - // Load .schematic to clipboard - } else if (split[0].equalsIgnoreCase("//load")) { - checkArgs(split, 1, 1, split[0]); - String filename = split[1].replace("\0", "") + ".schematic"; - File dir = new File("schematics"); - File f = new File("schematics", filename); - - try { - String filePath = f.getCanonicalPath(); - String dirPath = dir.getCanonicalPath(); - - if (!filePath.substring(0, dirPath.length()).equals(dirPath)) { - player.printError("Schematic could not read or it does not exist."); - } else { - session.setClipboard(CuboidClipboard.loadSchematic(filePath)); - logger.log(Level.INFO, player.getName() + " loaded " + filePath); - player.print(filename + " loaded."); - } - } catch (DataException e) { - player.printError("Load error: " + e.getMessage()); - } catch (IOException e) { - player.printError("Schematic could not read or it does not exist."); - } - - return true; - - // Save clipboard to .schematic - } else if (split[0].equalsIgnoreCase("//save")) { - checkArgs(split, 1, 1, split[0]); - String filename = split[1].replace("\0", "") + ".schematic"; - File dir = new File("schematics"); - File f = new File("schematics", filename); - - if (!dir.exists()) { - if (!dir.mkdir()) { - player.printError("A schematics/ folder could not be created."); - return true; - } - } - - try { - String filePath = f.getCanonicalPath(); - String dirPath = dir.getCanonicalPath(); - - if (!filePath.substring(0, dirPath.length()).equals(dirPath)) { - player.printError("Invalid path for Schematic."); - } else { - // Create parent directories - File parent = f.getParentFile(); - if (parent != null && !parent.exists()) { - parent.mkdirs(); - } - - session.getClipboard().saveSchematic(filePath); - logger.log(Level.INFO, player.getName() + " saved " + filePath); - player.print(filename + " saved."); - } - } catch (DataException se) { - player.printError("Save error: " + se.getMessage()); - } catch (IOException e) { - player.printError("Schematic could not written."); - } - - return true; - - // Get size - } else if (split[0].equalsIgnoreCase("//size")) { - player.print("# of blocks: " + session.getRegion().getSize()); - return true; - - // Replace all blocks in the region - } else if(split[0].equalsIgnoreCase("//set")) { - checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); - int affected = editSession.setBlocks(session.getRegion(), block); - player.print(affected + " block(s) have been changed."); - - return true; - - // Set the outline of a region - } else if(split[0].equalsIgnoreCase("//outline")) { - checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); - int affected = editSession.makeCuboidFaces(session.getRegion(), block); - player.print(affected + " block(s) have been changed."); - - return true; - - // Set the walls of a region - } else if(split[0].equalsIgnoreCase("//walls")) { - checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); - int affected = editSession.makeCuboidWalls(session.getRegion(), block); - player.print(affected + " block(s) have been changed."); - - return true; - - // Drain pools - } else if(split[0].equalsIgnoreCase("//drain")) { - checkArgs(split, 1, 1, split[0]); - int radius = Math.max(0, Integer.parseInt(split[1])); - int affected = editSession.drainArea( - session.getPlacementPosition(player), radius); - player.print(affected + " block(s) have been changed."); - - return true; - - // Fix water - } else if(split[0].equalsIgnoreCase("/fixwater")) { - checkArgs(split, 1, 1, split[0]); - int radius = Math.max(0, Integer.parseInt(split[1])); - int affected = editSession.fixWater( - session.getPlacementPosition(player), radius); - player.print(affected + " block(s) have been changed."); - - return true; - - // Replace all blocks in the region - } else if(split[0].equalsIgnoreCase("//replace")) { - checkArgs(split, 1, 2, split[0]); - int from; - BaseBlock to; - if (split.length == 2) { - from = -1; - to = getBlock(split[1], true); - } else { - from = getBlock(split[1]).getID(); - to = getBlock(split[2]); - } - - int affected = editSession.replaceBlocks(session.getRegion(), from, to); - player.print(affected + " block(s) have been replaced."); - - return true; - - // Lay blocks over an area - } else if (split[0].equalsIgnoreCase("//overlay")) { - checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); - - Region region = session.getRegion(); - int affected = editSession.overlayCuboidBlocks(region, block); - player.print(affected + " block(s) have been overlayed."); - - return true; - - // Copy - } else if (split[0].equalsIgnoreCase("//copy") - || split[0].equalsIgnoreCase("//cut")) { - boolean cut = split[0].equalsIgnoreCase("//cut"); - BaseBlock block = new BaseBlock(0); - - if (cut) { - checkArgs(split, 0, 1, split[0]); - if (split.length > 1) { - getBlock(split[1]); - } - } else { - checkArgs(split, 0, 0, split[0]); - } - - Region region = session.getRegion(); - Vector min = region.getMinimumPoint(); - Vector max = region.getMaximumPoint(); - Vector pos = player.getBlockIn(); - - CuboidClipboard clipboard = new CuboidClipboard( - max.subtract(min).add(new Vector(1, 1, 1)), - min, min.subtract(pos)); - clipboard.copy(editSession); - session.setClipboard(clipboard); - - if (cut) { - editSession.setBlocks(session.getRegion(), block); - player.print("Block(s) cut."); - } else { - player.print("Block(s) copied."); - } - - return true; - - // Make pine tree forest - } else if (split[0].equalsIgnoreCase("/forestgen")) { - checkArgs(split, 0, 1, split[0]); - int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10; - - int affected = editSession.makePineTreeForest(player.getPosition(), size); - player.print(affected + " pine trees created."); - - return true; - - // Make pumpkin patches - } else if (split[0].equalsIgnoreCase("/pumpkins")) { - checkArgs(split, 0, 1, split[0]); - int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10; - - int affected = editSession.makePumpkinPatches(player.getPosition(), size); - player.print(affected + " pumpkin patches created."); - - return true; - - // Move - } else if (split[0].equalsIgnoreCase("//moveair") || - split[0].equalsIgnoreCase("//move")) { - checkArgs(split, 0, 3, split[0]); - int count = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; - Vector dir = getDirection(player, - split.length > 2 ? split[2].toLowerCase() : "me"); - BaseBlock replace; - - // Replacement block argument - if (split.length > 3) { - replace = getBlock(split[3]); - } else { - replace = new BaseBlock(0); - } - - boolean copyAir = split[0].equalsIgnoreCase("//moveair"); - - int affected = editSession.moveCuboidRegion(session.getRegion(), - dir, count, copyAir, replace); - player.print(affected + " blocks moved."); - - return true; - - // Stack - } else if (split[0].equalsIgnoreCase("//stackair") || - split[0].equalsIgnoreCase("//stack")) { - checkArgs(split, 0, 2, split[0]); - int count = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; - Vector dir = getDirection(player, - split.length > 2 ? split[2].toLowerCase() : "me"); - boolean copyAir = split[0].equalsIgnoreCase("//stackair"); - - int affected = editSession.stackCuboidRegion(session.getRegion(), - dir, count, copyAir); - player.print(affected + " blocks changed. Undo with //undo"); - - return true; - - // Expand - } else if (split[0].equalsIgnoreCase("//expand")) { - checkArgs(split, 1, 2, split[0]); - Vector dir; - int change; - if (split.length == 3) { - dir = getDirection(player, split[1].toLowerCase()); - change = Integer.parseInt(split[2]); - } else { - dir = getDirection(player, "me"); - change = Integer.parseInt(split[1]); - } - - Region region = session.getRegion(); - int oldSize = region.getSize(); - region.expand(dir.multiply(change)); - session.learnRegionChanges(); - int newSize = region.getSize(); - player.print("Region expanded " + (newSize - oldSize) + " blocks."); - - return true; - - // Contract - } else if (split[0].equalsIgnoreCase("//contract")) { - checkArgs(split, 1, 2, split[0]); - Vector dir; - int change; - if (split.length == 3) { - dir = getDirection(player, split[1].toLowerCase()); - change = Integer.parseInt(split[2]); - } else { - dir = getDirection(player, "me"); - change = Integer.parseInt(split[1]); - } - - Region region = session.getRegion(); - int oldSize = region.getSize(); - region.contract(dir.multiply(change)); - session.learnRegionChanges(); - int newSize = region.getSize(); - player.print("Region contracted " + (oldSize - newSize) + " blocks."); - - return true; - - // Rotate - } else if (split[0].equalsIgnoreCase("//rotate")) { - checkArgs(split, 1, 1, split[0]); - int angle = Integer.parseInt(split[1]); - if (angle % 90 == 0) { - CuboidClipboard clipboard = session.getClipboard(); - clipboard.rotate2D(angle); - player.print("Clipboard rotated by " + angle + " degrees."); - } else { - player.printError("Angles must be divisible by 90 degrees."); - } - - return true; - - // Get chunk filename - } else if (split[0].equalsIgnoreCase("/chunkinfo")) { - checkArgs(split, 0, 0, split[0]); - - Vector pos = player.getBlockIn(); - int chunkX = (int)Math.floor(pos.getBlockX() / 16.0); - int chunkZ = (int)Math.floor(pos.getBlockZ() / 16.0); - - String folder1 = Integer.toString(divisorMod(chunkX, 64), 36); - String folder2 = Integer.toString(divisorMod(chunkZ, 64), 36); - String filename = "c." + Integer.toString(chunkX, 36) - + "." + Integer.toString(chunkZ, 36) + ".dat"; - - player.print("Chunk: " + chunkX + ", " + chunkZ); - player.print(folder1 + "/" + folder2 + "/" + filename); - - return true; - - // Dump a list of involved chunks - } else if (split[0].equalsIgnoreCase("/listchunks")) { - checkArgs(split, 0, 0, split[0]); - - Set chunks = session.getRegion().getChunks(); - - for (Vector2D chunk : chunks) { - player.print(NestedFileChunkStore.getFilename(chunk)); - } - - return true; - - // Dump a list of involved chunks - } else if (split[0].equalsIgnoreCase("/delchunks")) { - checkArgs(split, 0, 0, split[0]); - - Set chunks = session.getRegion().getChunks(); - FileOutputStream out = null; - - if (shellSaveType == null) { - player.printError("shell-save-type has to be configured in worldedit.properties"); - } else if (shellSaveType.equalsIgnoreCase("bat")) { - try { - out = new FileOutputStream("worldedit-delchunks.bat"); - OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8"); - writer.write("@ECHO off\r\n"); - writer.write("ECHO This batch file was generated by WorldEdit.\r\n"); - writer.write("ECHO It contains a list of chunks that were in the selected region\r\n"); - writer.write("ECHO at the time that the /delchunks command was used. Run this file\r\n"); - writer.write("ECHO in order to delete the chunk files listed in this file.\r\n"); - writer.write("ECHO.\r\n"); - writer.write("PAUSE\r\n"); - - for (Vector2D chunk : chunks) { - String filename = NestedFileChunkStore.getFilename(chunk); - writer.write("ECHO " + filename + "\r\n"); - writer.write("DEL \"world/" + filename + "\"\r\n"); - } - - writer.write("ECHO Complete.\r\n"); - writer.write("PAUSE\r\n"); - writer.close(); - player.print("worldedit-delchunks.bat written. Run it when no one is near the region."); - } catch (IOException e) { - player.printError("Error occurred: " + e.getMessage()); - } finally { - if (out != null) { - try { out.close(); } catch (IOException ie) {} - } - } - } else if (shellSaveType.equalsIgnoreCase("bash")) { - try { - out = new FileOutputStream("worldedit-delchunks.sh"); - OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8"); - writer.write("#!/bin/bash\n"); - writer.write("echo This shell file was generated by WorldEdit.\n"); - writer.write("echo It contains a list of chunks that were in the selected region\n"); - writer.write("echo at the time that the /delchunks command was used. Run this file\n"); - writer.write("echo in order to delete the chunk files listed in this file.\n"); - writer.write("echo\n"); - writer.write("read -p \"Press any key to continue...\"\n"); - - for (Vector2D chunk : chunks) { - String filename = NestedFileChunkStore.getFilename(chunk); - writer.write("echo " + filename + "\n"); - writer.write("rm \"world/" + filename + "\"\n"); - } - - writer.write("echo Complete.\n"); - writer.write("read -p \"Press any key to continue...\"\n"); - writer.close(); - player.print("worldedit-delchunks.sh written. Run it when no one is near the region."); - player.print("You will have to chmod it to be executable."); - } catch (IOException e) { - player.printError("Error occurred: " + e.getMessage()); - } finally { - if (out != null) { - try { out.close(); } catch (IOException ie) {} - } - } - } else { - player.printError("Unknown shell script save type. 'bat' or 'bash' expected."); - } - - return true; - - // List snapshots - } else if (split[0].equalsIgnoreCase("/listsnapshots")) { - checkArgs(split, 0, 0, split[0]); - - if (snapshotRepo != null) { - Snapshot[] snapshots = snapshotRepo.getSnapshots(); - - if (snapshots.length > 0) { - for (byte i = 0; i < Math.min(5, snapshots.length); i++) { - player.print((i + 1) + ". " + snapshots[i].getName()); - } - - player.print("Use //use [snapshot] or //use latest to set the snapshot."); - } else { - player.printError("No snapshots are available."); - } - } else { - player.printError("Snapshot/backup restore is not configured."); - } - - return true; - - // Use a certain snapshot - } else if (split[0].equalsIgnoreCase("//use")) { - checkArgs(split, 1, 1, split[0]); - - if (snapshotRepo == null) { - player.printError("Snapshot/backup restore is not configured."); - return true; - } - - String name = split[1]; - - // Want the latest snapshot? - if (name.equalsIgnoreCase("latest")) { - Snapshot snapshot = snapshotRepo.getDefaultSnapshot(); - - if (snapshot != null) { - session.setSnapshot(null); - player.print("Now using newest snapshot."); - } else { - player.printError("No snapshots were found."); - } - } else { - try { - session.setSnapshot(snapshotRepo.getSnapshot(name)); - player.print("Snapshot set to: " + name); - } catch (InvalidSnapshotException e) { - player.printError("That snapshot does not exist or is not available."); - } - } - - return true; - - // Restore - } else if (split[0].equalsIgnoreCase("//restore")) { - checkArgs(split, 0, 0, split[0]); - - if (snapshotRepo == null) { - player.printError("Snapshot/backup restore is not configured."); - return true; - } - - Region region = session.getRegion(); - Snapshot snapshot = session.getSnapshot(); - ChunkStore chunkStore = null; - - // No snapshot set? - if (snapshot == null) { - snapshot = snapshotRepo.getDefaultSnapshot(); - - if (snapshot == null) { - player.printError("No snapshots were found."); - return true; - } - } - - // Load chunk store - try { - chunkStore = snapshot.getChunkStore(); - player.print("Snapshot '" + snapshot.getName() + "' loaded; now restoring..."); - } catch (IOException e) { - player.printError("Failed to load snapshot: " + e.getMessage()); - return true; - } - - try { - // Restore snapshot - SnapshotRestore restore = new SnapshotRestore(chunkStore, region); - //player.print(restore.getChunksAffected() + " chunk(s) will be loaded."); - - restore.restore(editSession); - - if (restore.hadTotalFailure()) { - player.printError("No blocks could be restored. (Bad backup?)"); - } else { - player.print(String.format("Restored; %d " - + "missing chunks and %d other errors.", - restore.getMissingChunks().size(), - restore.getErrorChunks().size())); - } - } finally { - try { - chunkStore.close(); - } catch (IOException e) { - } - } - - return true; + @Override + public void disable() { + for (String key : worldEdit.getCommands().keySet()) { + etc.getInstance().removeCommand(key); } - return false; - } - - /** - * Modulus, divisor-style. - * - * @param a - * @param n - * @return - */ - private static int divisorMod(int a, int n) { - return (int)(a - n * Math.floor(Math.floor(a) / (double)n)); - } - - /** - * Get the direction vector for a player's direction. May return - * null if a direction could not be found. - * - * @param player - * @param dir - * @return - */ - public Vector getDirection(WorldEditPlayer player, String dir) - throws UnknownDirectionException { - int xm = 0; - int ym = 0; - int zm = 0; - - if (dir.equals("me")) { - dir = player.getCardinalDirection(); - } - - if (dir.charAt(0) == 'w') { - zm += 1; - } else if (dir.charAt(0) == 'e') { - zm -= 1; - } else if (dir.charAt(0) == 's') { - xm += 1; - } else if (dir.charAt(0) == 'n') { - xm -= 1; - } else if (dir.charAt(0) == 'u') { - ym += 1; - } else if (dir.charAt(0) == 'd') { - ym -= 1; - } else { - throw new UnknownDirectionException(dir); - } - - return new Vector(xm, ym, zm); - } - - /** - * Remove a session. - * - * @param player - */ - public void removeSession(WorldEditPlayer player) { - sessions.remove(player); - } - - /** - * Remove all sessions. - */ - public void clearSessions() { - sessions.clear(); - } - - /** - * Get the list of commands. - * - * @return List - */ - public HashMap getCommands() { - return commands; - } - - /** - * Set the list of allowed blocks. Provided null to use the default list. - * - * @param allowedBlocks - */ - public void setAllowedBlocks(HashSet allowedBlocks) { - this.allowedBlocks = allowedBlocks != null ? allowedBlocks - : new HashSet(Arrays.asList(DEFAULT_ALLOWED_BLOCKS)); - } - - /** - * Get a comma-delimited list of the default allowed blocks. - * - * @return comma-delimited list - */ - public static String getDefaultAllowedBlocks() { - StringBuilder b = new StringBuilder(); - for (Integer id : DEFAULT_ALLOWED_BLOCKS) { - b.append(id).append(","); - } - return b.substring(0, b.length() - 1); - } - - /** - * @return the defaultChangeLimit - */ - public int getDefaultChangeLimit() { - return defaultChangeLimit; - } - - /** - * Set the default limit on the number of blocks that can be changed - * in one operation. - * - * @param defaultChangeLimit the defaultChangeLimit to set - */ - public void setDefaultChangeLimit(int defaultChangeLimit) { - this.defaultChangeLimit = defaultChangeLimit; - } - - /** - * @return the snapshotRepo - */ - public SnapshotRepository getSnapshotRepo() { - return snapshotRepo; - } - - /** - * @param snapshotRepo the snapshotRepo to set - */ - public void setSnapshotRepository(SnapshotRepository snapshotRepo) { - this.snapshotRepo = snapshotRepo; - } - - /** - * @return the shellSaveType - */ - public String getShellSaveType() { - return shellSaveType; - } - - /** - * @param shellSaveType the shellSaveType to set - */ - public void setShellSaveType(String shellSaveType) { - this.shellSaveType = shellSaveType; + worldEdit.clearSessions(); } } diff --git a/src/WorldEditLibrary.java b/src/WorldEditLibrary.java new file mode 100644 index 000000000..342630ebe --- /dev/null +++ b/src/WorldEditLibrary.java @@ -0,0 +1,1249 @@ +// $Id$ +/* + * WorldEditLibrary + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import com.sk89q.worldedit.snapshots.SnapshotRepository; +import com.sk89q.worldedit.snapshots.Snapshot; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.*; +import com.sk89q.worldedit.data.*; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.snapshots.InvalidSnapshotException; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.io.*; + +/** + * Plugin base. + * + * @author sk89q + */ +public class WorldEditLibrary { + /** + * WorldEditLibrary instance. + */ + private static WorldEditLibrary instance; + /** + * Server interface. + */ + private ServerInterface server; + + /** + * List of default allowed blocks. + */ + private final static Integer[] DEFAULT_ALLOWED_BLOCKS = { + 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 35, 41, 42, 43, 44, 45, 47, 48, 49, 52, 53, 54, 56, 57, 58, 60, + 61, 62, 67, 73, 78, 79, 80, 82, 85, 86, 87, 88, 89, 91 + }; + + /** + * Logger. + */ + private static final Logger logger = Logger.getLogger("Minecraft"); + /** + * Stores the WorldEditLibrary sessions of players. + */ + private HashMap sessions = + new HashMap(); + /** + * Stores the commands. + */ + private HashMap commands = new HashMap(); + + /** + * List of the blocks that can be used. If null, all blocks can be used. + */ + private HashSet allowedBlocks; + /** + * Default block change limit. -1 for no limit. + */ + private int defaultChangeLimit = -1; + /** + * Shell script save type. + */ + private String shellSaveType; + /** + * Stores the snapshot repository. May be null; + */ + private SnapshotRepository snapshotRepo; + + /** + * Set up an instance. + * + * @param server + * @return + */ + public static WorldEditLibrary setup(ServerInterface server) { + WorldEditLibrary worldEdit = new WorldEditLibrary(); + worldEdit.server = server; + instance = worldEdit; + return worldEdit; + } + + /** + * Get WorldEditLibrary instance. + * + * @return + */ + public static WorldEditLibrary getInstance() { + return instance; + } + + /** + * Get server interface. + * + * @return + */ + public static ServerInterface getServer() { + return instance.server; + } + + /** + * Construct an instance of the plugin. + */ + private WorldEditLibrary() { + // Note: Commands should only have the phrase 'air' at the end + // for now (see SMWorldEditListener.canUseCommand) + commands.put("//pos1", "Set editing position #1"); + commands.put("//pos2", "Set editing position #2"); + commands.put("//hpos1", "Trace editing position #1"); + commands.put("//hpos2", "Trace editing position #2"); + commands.put("/toggleplace", "Toggle placing at pos #1"); + commands.put("//wand", "Gives you the \"edit wand\""); + commands.put("/toggleeditwand", "Toggles edit wand selection"); + commands.put("//", "Toggles super pick axe."); + commands.put("//undo", "Undo"); + commands.put("//redo", "Redo"); + commands.put("/clearhistory", "Clear history"); + commands.put("/clearclipboard", "Clear clipboard"); + commands.put("//size", "Get size of selected region"); + commands.put("//set", "[ID] - Set all blocks inside region"); + commands.put("//outline", "[ID] - Outline the region with blocks"); + commands.put("//walls", "[ID] - Build walls"); + commands.put("//replace", " [ToID] - Replace all existing blocks inside region"); + commands.put("//overlay", "[ID] - Overlay the area one layer"); + commands.put("/removeabove", " - Remove blocks above head"); + commands.put("/removebelow", " - Remove blocks below position"); + commands.put("/removenear", " - Remove blocks near you"); + commands.put("//copy", "Copies the currently selected region"); + commands.put("//cut", "Cuts the currently selected region"); + commands.put("//paste", "Pastes the clipboard"); + commands.put("//pasteair", "Pastes the clipboard (with air)"); + commands.put("//move", " - Move the selection"); + commands.put("//moveair", " - Move the selection (with air)"); + commands.put("//stack", " - Stacks the selection"); + commands.put("//stackair", " - Stacks the selection (with air)"); + commands.put("//load", "[Filename] - Load .schematic into clipboard"); + commands.put("//save", "[Filename] - Save clipboard to .schematic"); + commands.put("//fill", "[ID] [Radius] - Fill a hole"); + commands.put("//drain", "[Radius] - Drain nearby water/lava pools"); + commands.put("//limit", "[Num] - See documentation"); + commands.put("//expand", " [Num] - Expands the selection"); + commands.put("//contract", " [Num] - Contracts the selection"); + commands.put("//rotate", "[Angle] - Rotate the clipboard"); + commands.put("//hcyl", "[ID] [Radius] - Create a vertical hollow cylinder"); + commands.put("//cyl", "[ID] [Radius] - Create a vertical cylinder"); + commands.put("//sphere", "[ID] [Radius] - Create a sphere"); + commands.put("//hsphere", "[ID] [Radius] - Create a hollow sphere"); + commands.put("/fixwater", "[Radius] - Level nearby pools of water"); + commands.put("/forestgen", " - Make an ugly pine tree forest"); + commands.put("/pumpkins", " - Make a pumpkin forest"); + commands.put("/unstuck", "Go up to the first free spot"); + commands.put("/ascend", "Go up one level"); + commands.put("/descend", "Go down one level"); + commands.put("/jumpto", "Jump to the block that you are looking at"); + commands.put("/thru", "Go through the wall that you are looking at"); + commands.put("/ceil", " - Get to the ceiling"); + commands.put("/chunkinfo", "Get the filename of the chunk that you are in"); + commands.put("/listchunks", "Print a list of used chunks"); + commands.put("/delchunks", "Generate a shell script to delete chunks"); + commands.put("/listsnapshots", "List the 5 newest snapshots"); + commands.put("//use", "[SnapshotID] - Use a particular snapshot"); + commands.put("//restore", "Restore a particular snapshot"); + } + + /** + * Gets the WorldEditLibrary session for a player. + * + * @param player + * @return + */ + public WorldEditSession getSession(WorldEditPlayer player) { + if (sessions.containsKey(player)) { + return sessions.get(player); + } else { + WorldEditSession session = new WorldEditSession(); + session.setBlockChangeLimit(getDefaultChangeLimit()); + sessions.put(player, session); + return session; + } + } + + /** + * Get an item ID from an item name or an item ID number. + * + * @param arg + * @return + * @throws UnknownItemException + * @throws DisallowedItemException + */ + public BaseBlock getBlock(String arg, boolean allAllowed) + throws UnknownItemException, DisallowedItemException { + BlockType blockType; + arg = arg.replace("_", " "); + String[] args0 = arg.split("\\|"); + String[] args1 = args0[0].split(":", 2); + String testID = args1[0]; + + int data; + + try { + data = args1.length > 1 ? Integer.parseInt(args1[1]) : 0; + if (data > 15 || data < 0) { + data = 0; + } + } catch (NumberFormatException e) { + data = 0; + } + + try { + blockType = BlockType.fromID(Integer.parseInt(testID)); + } catch (NumberFormatException e) { + blockType = BlockType.lookup(testID); + } + + if (blockType == null) { + throw new UnknownItemException(); + } + + // Check if the item is allowed + if (allAllowed || allowedBlocks.isEmpty() + || allowedBlocks.contains(blockType.getID())) { + if (blockType == BlockType.SIGN_POST + || blockType == BlockType.WALL_SIGN) { + String[] text = new String[4]; + text[0] = args0.length > 1 ? args0[1] : ""; + text[1] = args0.length > 2 ? args0[2] : ""; + text[2] = args0.length > 3 ? args0[3] : ""; + text[3] = args0.length > 4 ? args0[4] : ""; + return new SignBlock(blockType.getID(), data, text); + } + return new BaseBlock(blockType.getID(), data); + } + + throw new DisallowedItemException(); + } + + /** + * Get a block. + * + * @param id + * @return + * @throws UnknownItemException + * @throws DisallowedItemException + */ + public BaseBlock getBlock(String id) throws UnknownItemException, + DisallowedItemException { + return getBlock(id, false); + } + + /** + * Checks to make sure that there are enough but not too many arguments. + * + * @param args + * @param min + * @param max -1 for no maximum + * @param cmd command name + * @throws InsufficientArgumentsException + */ + private void checkArgs(String[] args, int min, int max, String cmd) + throws InsufficientArgumentsException { + if (args.length <= min || (max != -1 && args.length - 1 > max)) { + if (commands.containsKey(cmd)) { + throw new InsufficientArgumentsException(cmd + " usage: " + + commands.get(cmd)); + } else { + throw new InsufficientArgumentsException("Invalid number of arguments"); + } + } + } + + /** + * The main meat of command processing. + * + * @param player + * @param editPlayer + * @param session + * @param editSession + * @param split + * @return + * @throws UnknownItemException + * @throws IncompleteRegionException + * @throws InsufficientArgumentsException + * @throws DisallowedItemException + */ + public boolean performCommand(WorldEditPlayer player, + WorldEditSession session, EditSession editSession, String[] split) + throws WorldEditException + { + // Jump to the first free position + if (split[0].equalsIgnoreCase("/unstuck")) { + checkArgs(split, 0, 0, split[0]); + player.print("There you go!"); + player.findFreePosition(); + return true; + + // Ascend a level + } else if(split[0].equalsIgnoreCase("/ascend")) { + checkArgs(split, 0, 0, split[0]); + if (player.ascendLevel()) { + player.print("Ascended a level."); + } else { + player.printError("No free spot above you found."); + } + return true; + + // Descend a level + } else if(split[0].equalsIgnoreCase("/descend")) { + checkArgs(split, 0, 0, split[0]); + if (player.descendLevel()) { + player.print("Descended a level."); + } else { + player.printError("No free spot below you found."); + } + return true; + + // Jump to the block in sight + } else if (split[0].equalsIgnoreCase("/jumpto")) { + checkArgs(split, 0, 0, split[0]); + Vector pos = player.getBlockTrace(300); + if (pos != null) { + player.findFreePosition(pos); + player.print("Poof!"); + } else { + player.printError("No block in sight!"); + } + return true; + + // Go through a wall + } else if (split[0].equalsIgnoreCase("/thru")) { + checkArgs(split, 0, 0, split[0]); + if (player.passThroughForwardWall(6)) { + player.print("Whoosh!"); + } else { + player.printError("No free spot ahead of you found."); + } + return true; + + // Go to the ceiling + } else if (split[0].equalsIgnoreCase("/ceil")) { + checkArgs(split, 0, 1, split[0]); + int clearence = split.length > 1 ? + Math.max(0, Integer.parseInt(split[1])) : 0; + + if (player.ascendToCeiling(clearence)) { + player.print("Whoosh!"); + } else { + player.printError("No free spot above you found."); + } + return true; + + // Set edit position #1 + } else if (split[0].equalsIgnoreCase("//pos1")) { + checkArgs(split, 0, 0, split[0]); + session.setPos1(player.getBlockIn()); + player.print("First edit position set."); + return true; + + // Set edit position #2 + } else if (split[0].equalsIgnoreCase("//pos2")) { + checkArgs(split, 0, 0, split[0]); + session.setPos2(player.getBlockIn()); + player.print("Second edit position set."); + return true; + + // Trace edit position #1 + } else if (split[0].equalsIgnoreCase("//hpos1")) { + checkArgs(split, 0, 0, split[0]); + Vector pos = player.getBlockTrace(300); + if (pos != null) { + session.setPos1(pos); + player.print("First edit position set."); + } else { + player.printError("No block in sight!"); + } + return true; + + // Trace edit position #2 + } else if (split[0].equalsIgnoreCase("//hpos2")) { + checkArgs(split, 0, 0, split[0]); + Vector pos = player.getBlockTrace(300); + if (pos != null) { + session.setPos2(pos); + player.print("Second edit position set."); + } else { + player.printError("No block in sight!"); + } + return true; + + // Edit wand + } else if (split[0].equalsIgnoreCase("//wand")) { + checkArgs(split, 0, 0, split[0]); + player.giveItem(271, 1); + player.print("Left click: select pos #1; Right click: select pos #2"); + return true; + + // Toggle placing at pos #1 + } else if (split[0].equalsIgnoreCase("/toggleplace")) { + checkArgs(split, 0, 0, split[0]); + if (session.togglePlacementPosition()) { + player.print("Now placing at pos #1."); + } else { + player.print("Now placing at the block you stand in."); + } + return true; + + // Toggle edit wand + } else if (split[0].equalsIgnoreCase("/toggleeditwand")) { + checkArgs(split, 0, 0, split[0]); + session.setToolControl(!session.isToolControlEnabled()); + if (session.isToolControlEnabled()) { + player.print("Edit wand enabled."); + } else { + player.print("Edit wand disabled."); + } + return true; + + // Toggle super pick axe + } else if (split[0].equalsIgnoreCase("//")) { + checkArgs(split, 0, 0, split[0]); + if (session.toggleSuperPickAxe()) { + player.print("Super pick axe enabled."); + } else { + player.print("Super pick axe disabled."); + } + return true; + + // Set max number of blocks to change at a time + } else if (split[0].equalsIgnoreCase("//limit")) { + checkArgs(split, 1, 1, split[0]); + int limit = Math.max(-1, Integer.parseInt(split[1])); + session.setBlockChangeLimit(limit); + player.print("Block change limit set to " + limit + "."); + return true; + + // Undo + } else if (split[0].equalsIgnoreCase("//undo")) { + checkArgs(split, 0, 0, split[0]); + if (session.undo()) { + player.print("Undo successful."); + } else { + player.printError("Nothing to undo."); + } + return true; + + // Redo + } else if (split[0].equalsIgnoreCase("//redo")) { + checkArgs(split, 0, 0, split[0]); + if (session.redo()) { + player.print("Redo successful."); + } else { + player.printError("Nothing to redo."); + } + return true; + + // Clear undo history + } else if (split[0].equalsIgnoreCase("/clearhistory")) { + checkArgs(split, 0, 0, split[0]); + session.clearHistory(); + player.print("History cleared."); + return true; + + // Clear clipboard + } else if (split[0].equalsIgnoreCase("/clearclipboard")) { + checkArgs(split, 0, 0, split[0]); + session.setClipboard(null); + player.print("Clipboard cleared."); + return true; + + // Paste + } else if (split[0].equalsIgnoreCase("//pasteair") || + split[0].equalsIgnoreCase("//paste")) { + Vector pos = session.getPlacementPosition(player); + session.getClipboard().paste(editSession, pos, + split[0].equalsIgnoreCase("//paste")); + player.findFreePosition(); + player.print("Pasted. Undo with //undo"); + + return true; + + // Draw a hollow cylinder + } else if (split[0].equalsIgnoreCase("//hcyl") + || split[0].equalsIgnoreCase("//cyl")) { + checkArgs(split, 2, 3, split[0]); + BaseBlock block = getBlock(split[1]); + int radius = Math.max(1, Integer.parseInt(split[2])); + int height = split.length > 3 ? Integer.parseInt(split[3]) : 1; + boolean filled = split[0].equalsIgnoreCase("//cyl"); + + Vector pos = session.getPlacementPosition(player); + int affected; + if (filled) { + affected = editSession.makeCylinder(pos, block, radius, height); + } else { + affected = editSession.makeHollowCylinder(pos, block, radius, height); + } + player.print(affected + " block(s) have been created."); + + return true; + + // Draw a sphere + } else if (split[0].equalsIgnoreCase("//sphere") + || split[0].equalsIgnoreCase("//hsphere")) { + checkArgs(split, 2, 3, split[0]); + BaseBlock block = getBlock(split[1]); + int radius = Math.max(1, Integer.parseInt(split[2])); + boolean raised = split.length > 3 + ? (split[3].equalsIgnoreCase("true") + || split[3].equalsIgnoreCase("yes")) + : false; + boolean filled = split[0].equalsIgnoreCase("//sphere"); + + Vector pos = session.getPlacementPosition(player); + if (raised) { + pos = pos.add(0, radius, 0); + } + + int affected = editSession.makeSphere(pos, block, radius, filled); + player.findFreePosition(); + player.print(affected + " block(s) have been created."); + + return true; + + // Fill a hole + } else if (split[0].equalsIgnoreCase("//fill")) { + checkArgs(split, 2, 3, split[0]); + BaseBlock block = getBlock(split[1]); + int radius = Math.max(1, Integer.parseInt(split[2])); + int depth = split.length > 3 ? Math.max(1, Integer.parseInt(split[3])) : 1; + + Vector pos = session.getPlacementPosition(player); + int affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(), + pos, block, radius, depth); + player.print(affected + " block(s) have been created."); + + return true; + + // Remove blocks above current position + } else if (split[0].equalsIgnoreCase("/removeabove")) { + checkArgs(split, 0, 2, split[0]); + int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; + int height = split.length > 2 ? Math.min(128, Integer.parseInt(split[2]) + 2) : 128; + + int affected = editSession.removeAbove( + session.getPlacementPosition(player), size, height); + player.print(affected + " block(s) have been removed."); + + return true; + + // Remove blocks below current position + } else if (split[0].equalsIgnoreCase("/removebelow")) { + checkArgs(split, 0, 2, split[0]); + int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; + int height = split.length > 2 ? Math.max(1, Integer.parseInt(split[2])) : 128; + + int affected = editSession.removeBelow( + session.getPlacementPosition(player), size, height); + player.print(affected + " block(s) have been removed."); + + return true; + + // Remove blocks near + } else if (split[0].equalsIgnoreCase("/removenear")) { + checkArgs(split, 2, 2, split[0]); + BaseBlock block = getBlock(split[1], true); + int size = Math.max(1, Integer.parseInt(split[2])); + + int affected = editSession.removeNear( + session.getPlacementPosition(player), block.getID(), size); + player.print(affected + " block(s) have been removed."); + + return true; + + // Load .schematic to clipboard + } else if (split[0].equalsIgnoreCase("//load")) { + checkArgs(split, 1, 1, split[0]); + String filename = split[1].replace("\0", "") + ".schematic"; + File dir = new File("schematics"); + File f = new File("schematics", filename); + + try { + String filePath = f.getCanonicalPath(); + String dirPath = dir.getCanonicalPath(); + + if (!filePath.substring(0, dirPath.length()).equals(dirPath)) { + player.printError("Schematic could not read or it does not exist."); + } else { + session.setClipboard(CuboidClipboard.loadSchematic(filePath)); + logger.log(Level.INFO, player.getName() + " loaded " + filePath); + player.print(filename + " loaded."); + } + } catch (DataException e) { + player.printError("Load error: " + e.getMessage()); + } catch (IOException e) { + player.printError("Schematic could not read or it does not exist."); + } + + return true; + + // Save clipboard to .schematic + } else if (split[0].equalsIgnoreCase("//save")) { + checkArgs(split, 1, 1, split[0]); + String filename = split[1].replace("\0", "") + ".schematic"; + File dir = new File("schematics"); + File f = new File("schematics", filename); + + if (!dir.exists()) { + if (!dir.mkdir()) { + player.printError("A schematics/ folder could not be created."); + return true; + } + } + + try { + String filePath = f.getCanonicalPath(); + String dirPath = dir.getCanonicalPath(); + + if (!filePath.substring(0, dirPath.length()).equals(dirPath)) { + player.printError("Invalid path for Schematic."); + } else { + // Create parent directories + File parent = f.getParentFile(); + if (parent != null && !parent.exists()) { + parent.mkdirs(); + } + + session.getClipboard().saveSchematic(filePath); + logger.log(Level.INFO, player.getName() + " saved " + filePath); + player.print(filename + " saved."); + } + } catch (DataException se) { + player.printError("Save error: " + se.getMessage()); + } catch (IOException e) { + player.printError("Schematic could not written."); + } + + return true; + + // Get size + } else if (split[0].equalsIgnoreCase("//size")) { + player.print("# of blocks: " + session.getRegion().getSize()); + return true; + + // Replace all blocks in the region + } else if(split[0].equalsIgnoreCase("//set")) { + checkArgs(split, 1, 1, split[0]); + BaseBlock block = getBlock(split[1]); + int affected = editSession.setBlocks(session.getRegion(), block); + player.print(affected + " block(s) have been changed."); + + return true; + + // Set the outline of a region + } else if(split[0].equalsIgnoreCase("//outline")) { + checkArgs(split, 1, 1, split[0]); + BaseBlock block = getBlock(split[1]); + int affected = editSession.makeCuboidFaces(session.getRegion(), block); + player.print(affected + " block(s) have been changed."); + + return true; + + // Set the walls of a region + } else if(split[0].equalsIgnoreCase("//walls")) { + checkArgs(split, 1, 1, split[0]); + BaseBlock block = getBlock(split[1]); + int affected = editSession.makeCuboidWalls(session.getRegion(), block); + player.print(affected + " block(s) have been changed."); + + return true; + + // Drain pools + } else if(split[0].equalsIgnoreCase("//drain")) { + checkArgs(split, 1, 1, split[0]); + int radius = Math.max(0, Integer.parseInt(split[1])); + int affected = editSession.drainArea( + session.getPlacementPosition(player), radius); + player.print(affected + " block(s) have been changed."); + + return true; + + // Fix water + } else if(split[0].equalsIgnoreCase("/fixwater")) { + checkArgs(split, 1, 1, split[0]); + int radius = Math.max(0, Integer.parseInt(split[1])); + int affected = editSession.fixWater( + session.getPlacementPosition(player), radius); + player.print(affected + " block(s) have been changed."); + + return true; + + // Replace all blocks in the region + } else if(split[0].equalsIgnoreCase("//replace")) { + checkArgs(split, 1, 2, split[0]); + int from; + BaseBlock to; + if (split.length == 2) { + from = -1; + to = getBlock(split[1], true); + } else { + from = getBlock(split[1]).getID(); + to = getBlock(split[2]); + } + + int affected = editSession.replaceBlocks(session.getRegion(), from, to); + player.print(affected + " block(s) have been replaced."); + + return true; + + // Lay blocks over an area + } else if (split[0].equalsIgnoreCase("//overlay")) { + checkArgs(split, 1, 1, split[0]); + BaseBlock block = getBlock(split[1]); + + Region region = session.getRegion(); + int affected = editSession.overlayCuboidBlocks(region, block); + player.print(affected + " block(s) have been overlayed."); + + return true; + + // Copy + } else if (split[0].equalsIgnoreCase("//copy") + || split[0].equalsIgnoreCase("//cut")) { + boolean cut = split[0].equalsIgnoreCase("//cut"); + BaseBlock block = new BaseBlock(0); + + if (cut) { + checkArgs(split, 0, 1, split[0]); + if (split.length > 1) { + getBlock(split[1]); + } + } else { + checkArgs(split, 0, 0, split[0]); + } + + Region region = session.getRegion(); + Vector min = region.getMinimumPoint(); + Vector max = region.getMaximumPoint(); + Vector pos = player.getBlockIn(); + + CuboidClipboard clipboard = new CuboidClipboard( + max.subtract(min).add(new Vector(1, 1, 1)), + min, min.subtract(pos)); + clipboard.copy(editSession); + session.setClipboard(clipboard); + + if (cut) { + editSession.setBlocks(session.getRegion(), block); + player.print("Block(s) cut."); + } else { + player.print("Block(s) copied."); + } + + return true; + + // Make pine tree forest + } else if (split[0].equalsIgnoreCase("/forestgen")) { + checkArgs(split, 0, 1, split[0]); + int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10; + + int affected = editSession.makePineTreeForest(player.getPosition(), size); + player.print(affected + " pine trees created."); + + return true; + + // Make pumpkin patches + } else if (split[0].equalsIgnoreCase("/pumpkins")) { + checkArgs(split, 0, 1, split[0]); + int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10; + + int affected = editSession.makePumpkinPatches(player.getPosition(), size); + player.print(affected + " pumpkin patches created."); + + return true; + + // Move + } else if (split[0].equalsIgnoreCase("//moveair") || + split[0].equalsIgnoreCase("//move")) { + checkArgs(split, 0, 3, split[0]); + int count = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; + Vector dir = getDirection(player, + split.length > 2 ? split[2].toLowerCase() : "me"); + BaseBlock replace; + + // Replacement block argument + if (split.length > 3) { + replace = getBlock(split[3]); + } else { + replace = new BaseBlock(0); + } + + boolean copyAir = split[0].equalsIgnoreCase("//moveair"); + + int affected = editSession.moveCuboidRegion(session.getRegion(), + dir, count, copyAir, replace); + player.print(affected + " blocks moved."); + + return true; + + // Stack + } else if (split[0].equalsIgnoreCase("//stackair") || + split[0].equalsIgnoreCase("//stack")) { + checkArgs(split, 0, 2, split[0]); + int count = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; + Vector dir = getDirection(player, + split.length > 2 ? split[2].toLowerCase() : "me"); + boolean copyAir = split[0].equalsIgnoreCase("//stackair"); + + int affected = editSession.stackCuboidRegion(session.getRegion(), + dir, count, copyAir); + player.print(affected + " blocks changed. Undo with //undo"); + + return true; + + // Expand + } else if (split[0].equalsIgnoreCase("//expand")) { + checkArgs(split, 1, 2, split[0]); + Vector dir; + int change; + if (split.length == 3) { + dir = getDirection(player, split[1].toLowerCase()); + change = Integer.parseInt(split[2]); + } else { + dir = getDirection(player, "me"); + change = Integer.parseInt(split[1]); + } + + Region region = session.getRegion(); + int oldSize = region.getSize(); + region.expand(dir.multiply(change)); + session.learnRegionChanges(); + int newSize = region.getSize(); + player.print("Region expanded " + (newSize - oldSize) + " blocks."); + + return true; + + // Contract + } else if (split[0].equalsIgnoreCase("//contract")) { + checkArgs(split, 1, 2, split[0]); + Vector dir; + int change; + if (split.length == 3) { + dir = getDirection(player, split[1].toLowerCase()); + change = Integer.parseInt(split[2]); + } else { + dir = getDirection(player, "me"); + change = Integer.parseInt(split[1]); + } + + Region region = session.getRegion(); + int oldSize = region.getSize(); + region.contract(dir.multiply(change)); + session.learnRegionChanges(); + int newSize = region.getSize(); + player.print("Region contracted " + (oldSize - newSize) + " blocks."); + + return true; + + // Rotate + } else if (split[0].equalsIgnoreCase("//rotate")) { + checkArgs(split, 1, 1, split[0]); + int angle = Integer.parseInt(split[1]); + if (angle % 90 == 0) { + CuboidClipboard clipboard = session.getClipboard(); + clipboard.rotate2D(angle); + player.print("Clipboard rotated by " + angle + " degrees."); + } else { + player.printError("Angles must be divisible by 90 degrees."); + } + + return true; + + // Get chunk filename + } else if (split[0].equalsIgnoreCase("/chunkinfo")) { + checkArgs(split, 0, 0, split[0]); + + Vector pos = player.getBlockIn(); + int chunkX = (int)Math.floor(pos.getBlockX() / 16.0); + int chunkZ = (int)Math.floor(pos.getBlockZ() / 16.0); + + String folder1 = Integer.toString(divisorMod(chunkX, 64), 36); + String folder2 = Integer.toString(divisorMod(chunkZ, 64), 36); + String filename = "c." + Integer.toString(chunkX, 36) + + "." + Integer.toString(chunkZ, 36) + ".dat"; + + player.print("Chunk: " + chunkX + ", " + chunkZ); + player.print(folder1 + "/" + folder2 + "/" + filename); + + return true; + + // Dump a list of involved chunks + } else if (split[0].equalsIgnoreCase("/listchunks")) { + checkArgs(split, 0, 0, split[0]); + + Set chunks = session.getRegion().getChunks(); + + for (Vector2D chunk : chunks) { + player.print(NestedFileChunkStore.getFilename(chunk)); + } + + return true; + + // Dump a list of involved chunks + } else if (split[0].equalsIgnoreCase("/delchunks")) { + checkArgs(split, 0, 0, split[0]); + + Set chunks = session.getRegion().getChunks(); + FileOutputStream out = null; + + if (shellSaveType == null) { + player.printError("shell-save-type has to be configured in worldedit.properties"); + } else if (shellSaveType.equalsIgnoreCase("bat")) { + try { + out = new FileOutputStream("worldedit-delchunks.bat"); + OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8"); + writer.write("@ECHO off\r\n"); + writer.write("ECHO This batch file was generated by WorldEdit.\r\n"); + writer.write("ECHO It contains a list of chunks that were in the selected region\r\n"); + writer.write("ECHO at the time that the /delchunks command was used. Run this file\r\n"); + writer.write("ECHO in order to delete the chunk files listed in this file.\r\n"); + writer.write("ECHO.\r\n"); + writer.write("PAUSE\r\n"); + + for (Vector2D chunk : chunks) { + String filename = NestedFileChunkStore.getFilename(chunk); + writer.write("ECHO " + filename + "\r\n"); + writer.write("DEL \"world/" + filename + "\"\r\n"); + } + + writer.write("ECHO Complete.\r\n"); + writer.write("PAUSE\r\n"); + writer.close(); + player.print("worldedit-delchunks.bat written. Run it when no one is near the region."); + } catch (IOException e) { + player.printError("Error occurred: " + e.getMessage()); + } finally { + if (out != null) { + try { out.close(); } catch (IOException ie) {} + } + } + } else if (shellSaveType.equalsIgnoreCase("bash")) { + try { + out = new FileOutputStream("worldedit-delchunks.sh"); + OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8"); + writer.write("#!/bin/bash\n"); + writer.write("echo This shell file was generated by WorldEdit.\n"); + writer.write("echo It contains a list of chunks that were in the selected region\n"); + writer.write("echo at the time that the /delchunks command was used. Run this file\n"); + writer.write("echo in order to delete the chunk files listed in this file.\n"); + writer.write("echo\n"); + writer.write("read -p \"Press any key to continue...\"\n"); + + for (Vector2D chunk : chunks) { + String filename = NestedFileChunkStore.getFilename(chunk); + writer.write("echo " + filename + "\n"); + writer.write("rm \"world/" + filename + "\"\n"); + } + + writer.write("echo Complete.\n"); + writer.write("read -p \"Press any key to continue...\"\n"); + writer.close(); + player.print("worldedit-delchunks.sh written. Run it when no one is near the region."); + player.print("You will have to chmod it to be executable."); + } catch (IOException e) { + player.printError("Error occurred: " + e.getMessage()); + } finally { + if (out != null) { + try { out.close(); } catch (IOException ie) {} + } + } + } else { + player.printError("Unknown shell script save type. 'bat' or 'bash' expected."); + } + + return true; + + // List snapshots + } else if (split[0].equalsIgnoreCase("/listsnapshots")) { + checkArgs(split, 0, 0, split[0]); + + if (snapshotRepo != null) { + Snapshot[] snapshots = snapshotRepo.getSnapshots(); + + if (snapshots.length > 0) { + for (byte i = 0; i < Math.min(5, snapshots.length); i++) { + player.print((i + 1) + ". " + snapshots[i].getName()); + } + + player.print("Use //use [snapshot] or //use latest to set the snapshot."); + } else { + player.printError("No snapshots are available."); + } + } else { + player.printError("Snapshot/backup restore is not configured."); + } + + return true; + + // Use a certain snapshot + } else if (split[0].equalsIgnoreCase("//use")) { + checkArgs(split, 1, 1, split[0]); + + if (snapshotRepo == null) { + player.printError("Snapshot/backup restore is not configured."); + return true; + } + + String name = split[1]; + + // Want the latest snapshot? + if (name.equalsIgnoreCase("latest")) { + Snapshot snapshot = snapshotRepo.getDefaultSnapshot(); + + if (snapshot != null) { + session.setSnapshot(null); + player.print("Now using newest snapshot."); + } else { + player.printError("No snapshots were found."); + } + } else { + try { + session.setSnapshot(snapshotRepo.getSnapshot(name)); + player.print("Snapshot set to: " + name); + } catch (InvalidSnapshotException e) { + player.printError("That snapshot does not exist or is not available."); + } + } + + return true; + + // Restore + } else if (split[0].equalsIgnoreCase("//restore")) { + checkArgs(split, 0, 0, split[0]); + + if (snapshotRepo == null) { + player.printError("Snapshot/backup restore is not configured."); + return true; + } + + Region region = session.getRegion(); + Snapshot snapshot = session.getSnapshot(); + ChunkStore chunkStore = null; + + // No snapshot set? + if (snapshot == null) { + snapshot = snapshotRepo.getDefaultSnapshot(); + + if (snapshot == null) { + player.printError("No snapshots were found."); + return true; + } + } + + // Load chunk store + try { + chunkStore = snapshot.getChunkStore(); + player.print("Snapshot '" + snapshot.getName() + "' loaded; now restoring..."); + } catch (IOException e) { + player.printError("Failed to load snapshot: " + e.getMessage()); + return true; + } + + try { + // Restore snapshot + SnapshotRestore restore = new SnapshotRestore(chunkStore, region); + //player.print(restore.getChunksAffected() + " chunk(s) will be loaded."); + + restore.restore(editSession); + + if (restore.hadTotalFailure()) { + player.printError("No blocks could be restored. (Bad backup?)"); + } else { + player.print(String.format("Restored; %d " + + "missing chunks and %d other errors.", + restore.getMissingChunks().size(), + restore.getErrorChunks().size())); + } + } finally { + try { + chunkStore.close(); + } catch (IOException e) { + } + } + + return true; + } + + return false; + } + + /** + * Modulus, divisor-style. + * + * @param a + * @param n + * @return + */ + private static int divisorMod(int a, int n) { + return (int)(a - n * Math.floor(Math.floor(a) / (double)n)); + } + + /** + * Get the direction vector for a player's direction. May return + * null if a direction could not be found. + * + * @param player + * @param dir + * @return + */ + public Vector getDirection(WorldEditPlayer player, String dir) + throws UnknownDirectionException { + int xm = 0; + int ym = 0; + int zm = 0; + + if (dir.equals("me")) { + dir = player.getCardinalDirection(); + } + + if (dir.charAt(0) == 'w') { + zm += 1; + } else if (dir.charAt(0) == 'e') { + zm -= 1; + } else if (dir.charAt(0) == 's') { + xm += 1; + } else if (dir.charAt(0) == 'n') { + xm -= 1; + } else if (dir.charAt(0) == 'u') { + ym += 1; + } else if (dir.charAt(0) == 'd') { + ym -= 1; + } else { + throw new UnknownDirectionException(dir); + } + + return new Vector(xm, ym, zm); + } + + /** + * Remove a session. + * + * @param player + */ + public void removeSession(WorldEditPlayer player) { + sessions.remove(player); + } + + /** + * Remove all sessions. + */ + public void clearSessions() { + sessions.clear(); + } + + /** + * Get the list of commands. + * + * @return List + */ + public HashMap getCommands() { + return commands; + } + + /** + * Set the list of allowed blocks. Provided null to use the default list. + * + * @param allowedBlocks + */ + public void setAllowedBlocks(HashSet allowedBlocks) { + this.allowedBlocks = allowedBlocks != null ? allowedBlocks + : new HashSet(Arrays.asList(DEFAULT_ALLOWED_BLOCKS)); + } + + /** + * Get a comma-delimited list of the default allowed blocks. + * + * @return comma-delimited list + */ + public static String getDefaultAllowedBlocks() { + StringBuilder b = new StringBuilder(); + for (Integer id : DEFAULT_ALLOWED_BLOCKS) { + b.append(id).append(","); + } + return b.substring(0, b.length() - 1); + } + + /** + * @return the defaultChangeLimit + */ + public int getDefaultChangeLimit() { + return defaultChangeLimit; + } + + /** + * Set the default limit on the number of blocks that can be changed + * in one operation. + * + * @param defaultChangeLimit the defaultChangeLimit to set + */ + public void setDefaultChangeLimit(int defaultChangeLimit) { + this.defaultChangeLimit = defaultChangeLimit; + } + + /** + * @return the snapshotRepo + */ + public SnapshotRepository getSnapshotRepo() { + return snapshotRepo; + } + + /** + * @param snapshotRepo the snapshotRepo to set + */ + public void setSnapshotRepository(SnapshotRepository snapshotRepo) { + this.snapshotRepo = snapshotRepo; + } + + /** + * @return the shellSaveType + */ + public String getShellSaveType() { + return shellSaveType; + } + + /** + * @param shellSaveType the shellSaveType to set + */ + public void setShellSaveType(String shellSaveType) { + this.shellSaveType = shellSaveType; + } +} diff --git a/src/WorldEditPlayer.java b/src/WorldEditPlayer.java index 6cbd0b3ef..170778ca1 100644 --- a/src/WorldEditPlayer.java +++ b/src/WorldEditPlayer.java @@ -1,6 +1,6 @@ // $Id$ /* - * WorldEdit + * WorldEditLibrary * Copyright (C) 2010 sk89q * * This program is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ public abstract class WorldEditPlayer { * Construct the player. */ public WorldEditPlayer() { - server = WorldEdit.getServer(); + server = WorldEditLibrary.getServer(); } /** @@ -107,14 +107,14 @@ public abstract class WorldEditPlayer { public abstract String getCardinalDirection(); /** - * Print a WorldEdit message. + * Print a WorldEditLibrary message. * * @param msg */ public abstract void print(String msg); /** - * Print a WorldEdit error. + * Print a WorldEditLibrary error. * * @param msg */