diff --git a/src/EditSession.java b/src/EditSession.java index 7a66f86b7..1a7693ae2 100644 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -30,7 +30,32 @@ public class EditSession { * Stores the original blocks before modification. */ private HashMap,Integer> original = new HashMap,Integer>(); + /** + * Stores the current blocks. + */ private HashMap,Integer> current = new HashMap,Integer>(); + /** + * The maximum number of blocks to change at a time. If this number is + * exceeded, a MaxChangedBlocksException exception will be + * raised. -1 indicates no limit. + */ + private int maxBlocks = -1; + + /** + * Default constructor. There is no maximum blocks limit. + */ + public EditSession() { + } + + /** + * Construct the object with a maximum number of blocks. + */ + public EditSession(int maxBlocks) { + if (maxBlocks < -1) { + throw new IllegalArgumentException("Max blocks must be >= -1"); + } + this.maxBlocks = maxBlocks; + } /** * Sets a block without changing history. @@ -54,10 +79,15 @@ public class EditSession { * @param blockType * @return Whether the block changed */ - public boolean setBlock(int x, int y, int z, int blockType) { + public boolean setBlock(int x, int y, int z, int blockType) + throws MaxChangedBlocksException { Point pt = new Point(x, y, z); if (!original.containsKey(pt)) { original.put(pt, getBlock(x, y, z)); + + if (maxBlocks != -1 && original.size() > maxBlocks) { + throw new MaxChangedBlocksException(maxBlocks); + } } current.put(pt, blockType); return rawSetBlock(x, y, z, blockType); @@ -104,4 +134,26 @@ public class EditSession { public int size() { return original.size(); } + + /** + * Get the maximum number of blocks that can be changed. -1 will be + * returned if disabled. + * + * @return + */ + public int getBlockChangeLimit() { + return maxBlocks; + } + + /** + * Set the maximum number of blocks that can be changed. + * + * @param maxBlocks -1 to disable + */ + public void setBlockChangeLimit(int maxBlocks) { + if (maxBlocks < -1) { + throw new IllegalArgumentException("Max blocks must be >= -1"); + } + this.maxBlocks = maxBlocks; + } } diff --git a/src/RegionClipboard.java b/src/RegionClipboard.java index 909620d2c..1cd4ad9a6 100644 --- a/src/RegionClipboard.java +++ b/src/RegionClipboard.java @@ -100,8 +100,10 @@ public class RegionClipboard { * @param editSession * @param origin Position to paste it from * @param noAir True to not paste air + * @throws MaxChangedBlocksException */ - public void paste(EditSession editSession, Point newOrigin, boolean noAir) { + public void paste(EditSession editSession, Point newOrigin, boolean noAir) + throws MaxChangedBlocksException { int xs = getWidth(); int ys = getHeight(); int zs = getLength(); diff --git a/src/ScriptMinecraftContext.java b/src/ScriptMinecraftContext.java index 778b96358..24300606c 100644 --- a/src/ScriptMinecraftContext.java +++ b/src/ScriptMinecraftContext.java @@ -1,3 +1,6 @@ + +import com.sk89q.worldedit.MaxChangedBlocksException; + // $Id$ /* * WorldEdit @@ -40,9 +43,11 @@ public class ScriptMinecraftContext { * @param y * @param z * @param blockType + * @throws MaxChangedBlocksException * @return */ - public boolean setBlock(int x, int y, int z, int blockType) { + public boolean setBlock(int x, int y, int z, int blockType) + throws MaxChangedBlocksException { return editSession.setBlock(x, y, z, blockType); } diff --git a/src/WorldEdit.java b/src/WorldEdit.java index 04f4d7ba3..25599d8ad 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -41,6 +41,7 @@ public class WorldEdit extends Plugin { private PropertiesFile properties; private String[] allowedBlocks; + private int defaultMaxBlocksChanged; private boolean mapScriptCommands = false; /** @@ -68,6 +69,7 @@ public class WorldEdit extends Plugin { commands.put("/editsave", "[Filename] - Save clipboard to .schematic"); commands.put("/editfill", " - Fill a hole"); commands.put("/editscript", "[Filename] - Run a WorldEdit script"); + commands.put("/setchangelimit", " - See documentation"); } /** @@ -81,6 +83,7 @@ public class WorldEdit extends Plugin { return sessions.get(player.getName()); } else { WorldEditSession session = new WorldEditSession(); + session.setBlockChangeLimit(defaultMaxBlocksChanged); sessions.put(player.getName(), session); return session; } @@ -169,6 +172,8 @@ public class WorldEdit extends Plugin { allowedBlocks = properties.getString("allowed-blocks", DEFAULT_ALLOWED_BLOCKS).split(","); mapScriptCommands = properties.getBoolean("map-script-commands", true); + defaultMaxBlocksChanged = + Math.max(-1, properties.getInt("max-blocks-changed", -1)); etc controller = etc.getInstance(); @@ -255,21 +260,33 @@ public class WorldEdit extends Plugin { try { if (commands.containsKey(split[0])) { if (player.canUseCommand(split[0])) { - return handleEditCommand(player, split); + WorldEditSession session = getSession(player); + EditSession editSession = + new EditSession(session.getBlockChangeLimit()); + + try { + return performCommand(player, session, editSession, split); + } finally { + session.remember(editSession); + } } } else { // See if there is a script by the same name - if (mapScriptCommands) { - if (player.canUseCommand("/editscript")) { - String filename = split[0].substring(1) + ".js"; - String[] args = new String[split.length - 1]; - System.arraycopy(split, 1, args, 0, split.length - 1); - try { - return runScript(player, getSession(player), new EditSession(), - filename, args); - } catch (NoSuchScriptException nse) { - return false; - } + if (mapScriptCommands && player.canUseCommand("/editscript")) { + WorldEditSession session = getSession(player); + EditSession editSession = + new EditSession(session.getBlockChangeLimit()); + + String filename = split[0].substring(1) + ".js"; + String[] args = new String[split.length - 1]; + System.arraycopy(split, 1, args, 0, split.length - 1); + + try { + return runScript(player, session, editSession, filename, args); + } catch (NoSuchScriptException nse) { + return false; + } finally { + session.remember(editSession); } } } @@ -277,26 +294,30 @@ public class WorldEdit extends Plugin { return false; } catch (NumberFormatException e) { player.sendMessage(Colors.Rose + "Number expected; string given."); - return true; } catch (IncompleteRegionException e2) { player.sendMessage(Colors.Rose + "The edit region has not been fully defined."); - return true; } catch (UnknownItemException e3) { player.sendMessage(Colors.Rose + "Unknown item."); - return true; } catch (DisallowedItemException e4) { player.sendMessage(Colors.Rose + "Disallowed item."); - return true; - } catch (InsufficientArgumentsException e5) { - player.sendMessage(Colors.Rose + e5.getMessage()); - return true; + } catch (MaxChangedBlocksException e5) { + player.sendMessage(Colors.Rose + "The maximum number of blocks changed (" + + e5.getBlockLimit() + ") in an instance was reached."); + } catch (InsufficientArgumentsException e6) { + player.sendMessage(Colors.Rose + e6.getMessage()); + } catch (WorldEditException e7) { + player.sendMessage(Colors.Rose + e7.getMessage()); } + + return true; } /** * The main meat of command processing. * * @param player + * @param session + * @param editSession * @param split * @return * @throws UnknownItemException @@ -304,13 +325,10 @@ public class WorldEdit extends Plugin { * @throws InsufficientArgumentsException * @throws DisallowedItemException */ - private boolean handleEditCommand(Player player, String[] split) - throws UnknownItemException, IncompleteRegionException, - InsufficientArgumentsException, DisallowedItemException + private boolean performCommand(Player player, WorldEditSession session, + EditSession editSession, String[] split) + throws WorldEditException { - WorldEditSession session = getSession(player); - EditSession editSession = new EditSession(); - // Set edit position #1 if (split[0].equalsIgnoreCase("/editpos1")) { session.setPos1((int)Math.floor(player.getX()), @@ -327,6 +345,14 @@ public class WorldEdit extends Plugin { player.sendMessage(Colors.LightPurple + "Second edit position set."); return true; + // Set edit position #2 + } else if (split[0].equalsIgnoreCase("/setchangelimit")) { + checkArgs(split, 1); + int limit = Math.max(-1, Integer.parseInt(split[1])); + session.setBlockChangeLimit(limit); + player.sendMessage(Colors.LightPurple + "Block change limit set."); + return true; + // Undo } else if (split[0].equalsIgnoreCase("/editundo")) { if (session.undo()) { @@ -368,7 +394,6 @@ public class WorldEdit extends Plugin { (int)Math.floor(player.getZ())); session.getClipboard().paste(editSession, pos, split[0].equalsIgnoreCase("/editpaste")); - session.remember(editSession); logger.log(Level.INFO, player.getName() + " used " + split[0]); player.sendMessage(Colors.LightPurple + "Pasted."); } @@ -393,8 +418,6 @@ public class WorldEdit extends Plugin { logger.log(Level.INFO, player.getName() + " used /editfill"); player.sendMessage(Colors.LightPurple + affected + " block(s) have been created."); - session.remember(editSession); - return true; // Remove blocks above current position @@ -420,8 +443,6 @@ public class WorldEdit extends Plugin { logger.log(Level.INFO, player.getName() + " used /removeabove"); player.sendMessage(Colors.LightPurple + affected + " block(s) have been removed."); - session.remember(editSession); - return true; // Load .schematic to clipboard @@ -534,8 +555,6 @@ public class WorldEdit extends Plugin { logger.log(Level.INFO, player.getName() + " used /editset"); player.sendMessage(Colors.LightPurple + affected + " block(s) have been set."); - session.remember(editSession); - return true; // Set the outline of a region @@ -571,8 +590,6 @@ public class WorldEdit extends Plugin { logger.log(Level.INFO, player.getName() + " used /editoutline"); player.sendMessage(Colors.LightPurple + affected + " block(s) have been set."); - session.remember(editSession); - return true; // Replace all blocks in the region @@ -598,8 +615,6 @@ public class WorldEdit extends Plugin { logger.log(Level.INFO, player.getName() + " used /editreplace"); player.sendMessage(Colors.LightPurple + affected + " block(s) have been replaced."); - session.remember(editSession); - return true; // Lay blocks over an area @@ -628,8 +643,6 @@ public class WorldEdit extends Plugin { logger.log(Level.INFO, player.getName() + " used /editoverlay"); player.sendMessage(Colors.LightPurple + affected + " block(s) have been overlayed."); - session.remember(editSession); - return true; // Copy @@ -668,7 +681,8 @@ public class WorldEdit extends Plugin { * @return */ private int fill(EditSession editSession, int x, int z, int cx, int cy, - int cz, int blockType, int radius, int minY) { + int cz, int blockType, int radius, int minY) + throws MaxChangedBlocksException { double dist = Math.sqrt(Math.pow(cx - x, 2) + Math.pow(cz - z, 2)); int affected = 0; @@ -699,10 +713,12 @@ public class WorldEdit extends Plugin { * @param z * @param blockType * @param minY + * @throws MaxChangedBlocksException * @return */ private int fillY(EditSession editSession, int x, int cy, - int z, int blockType, int minY) { + int z, int blockType, int minY) + throws MaxChangedBlocksException { int affected = 0; for (int y = cy; y > minY; y--) { @@ -787,7 +803,6 @@ public class WorldEdit extends Plugin { player.sendMessage(Colors.Rose + filename + ": execution error: " + err.getMessage()); } finally { Context.exit(); - session.remember(editSession); } } diff --git a/src/WorldEditSession.java b/src/WorldEditSession.java index 3fe0d973b..b7625f6ab 100644 --- a/src/WorldEditSession.java +++ b/src/WorldEditSession.java @@ -36,6 +36,7 @@ public class WorldEditSession { private boolean toolControl = true; private int[] lastToolPos1 = new int[3]; private long lastToolClick = 0; + private int maxBlocksChanged = -1; /** * Clear history. @@ -337,4 +338,21 @@ public class WorldEditSession { public void triggerToolClick() { lastToolClick = System.currentTimeMillis(); } + + /** + * Get the maximum number of blocks that can be changed in an edit session. + * @return + */ + public int getBlockChangeLimit() { + return maxBlocksChanged; + } + + /** + * Set the maximum number of blocks that can be changed. + * + * @param maxBlocksChanged + */ + public void setBlockChangeLimit(int maxBlocksChanged) { + this.maxBlocksChanged = maxBlocksChanged; + } } diff --git a/src/com/sk89q/worldedit/DisallowedItemException.java b/src/com/sk89q/worldedit/DisallowedItemException.java index f4fb945f3..132d6c147 100644 --- a/src/com/sk89q/worldedit/DisallowedItemException.java +++ b/src/com/sk89q/worldedit/DisallowedItemException.java @@ -23,6 +23,6 @@ package com.sk89q.worldedit; * * @author sk89q */ -public class DisallowedItemException extends Exception { +public class DisallowedItemException extends WorldEditException { } diff --git a/src/com/sk89q/worldedit/IncompleteRegionException.java b/src/com/sk89q/worldedit/IncompleteRegionException.java index 3b1ddea96..f726b25a7 100644 --- a/src/com/sk89q/worldedit/IncompleteRegionException.java +++ b/src/com/sk89q/worldedit/IncompleteRegionException.java @@ -24,6 +24,6 @@ package com.sk89q.worldedit; * * @author Albert */ -public class IncompleteRegionException extends Exception { +public class IncompleteRegionException extends WorldEditException { } diff --git a/src/com/sk89q/worldedit/InsufficientArgumentsException.java b/src/com/sk89q/worldedit/InsufficientArgumentsException.java index 61f2d3e83..56ea003b3 100644 --- a/src/com/sk89q/worldedit/InsufficientArgumentsException.java +++ b/src/com/sk89q/worldedit/InsufficientArgumentsException.java @@ -23,7 +23,7 @@ package com.sk89q.worldedit; * * @author sk89q */ -public class InsufficientArgumentsException extends Exception { +public class InsufficientArgumentsException extends WorldEditException { public InsufficientArgumentsException(String error) { super(error); } diff --git a/src/com/sk89q/worldedit/MaxChangedBlocksException.java b/src/com/sk89q/worldedit/MaxChangedBlocksException.java new file mode 100644 index 000000000..3a238034a --- /dev/null +++ b/src/com/sk89q/worldedit/MaxChangedBlocksException.java @@ -0,0 +1,36 @@ +// $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 . +*/ + +package com.sk89q.worldedit; + +/** + * + * @author sk89q + */ +public class MaxChangedBlocksException extends WorldEditException { + int maxBlocks; + + public MaxChangedBlocksException(int maxBlocks) { + this.maxBlocks = maxBlocks; + } + + public int getBlockLimit() { + return maxBlocks; + } +} diff --git a/src/com/sk89q/worldedit/NoSuchScriptException.java b/src/com/sk89q/worldedit/NoSuchScriptException.java index b39a8eb8a..a7f45329d 100644 --- a/src/com/sk89q/worldedit/NoSuchScriptException.java +++ b/src/com/sk89q/worldedit/NoSuchScriptException.java @@ -23,6 +23,6 @@ package com.sk89q.worldedit; * * @author Albert */ -public class NoSuchScriptException extends Exception { +public class NoSuchScriptException extends WorldEditException { } diff --git a/src/com/sk89q/worldedit/SchematicLoadException.java b/src/com/sk89q/worldedit/SchematicLoadException.java index bd1a63c79..b8a9266c7 100644 --- a/src/com/sk89q/worldedit/SchematicLoadException.java +++ b/src/com/sk89q/worldedit/SchematicLoadException.java @@ -23,7 +23,7 @@ package com.sk89q.worldedit; * * @author Albert */ -public class SchematicLoadException extends Exception { +public class SchematicLoadException extends WorldEditException { public SchematicLoadException(String error) { super(error); } diff --git a/src/com/sk89q/worldedit/UnknownItemException.java b/src/com/sk89q/worldedit/UnknownItemException.java index d36ff844a..ed0a5b167 100644 --- a/src/com/sk89q/worldedit/UnknownItemException.java +++ b/src/com/sk89q/worldedit/UnknownItemException.java @@ -24,6 +24,6 @@ package com.sk89q.worldedit; * * @author sk89q */ -public class UnknownItemException extends Exception { +public class UnknownItemException extends WorldEditException { } diff --git a/src/com/sk89q/worldedit/WorldEditException.java b/src/com/sk89q/worldedit/WorldEditException.java new file mode 100644 index 000000000..55c6bcd09 --- /dev/null +++ b/src/com/sk89q/worldedit/WorldEditException.java @@ -0,0 +1,33 @@ +// $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 . +*/ + +package com.sk89q.worldedit; + +/** + * + * @author Albert + */ +public abstract class WorldEditException extends Exception { + protected WorldEditException() { + } + + protected WorldEditException(String msg) { + super(msg); + } +}