Reorganized code, made exceptions inherit from WorldEditException, added /setchangelimit.

This commit is contained in:
sk89q 2010-10-04 16:39:35 -07:00
parent 1f7b39b8e3
commit 713f23d0de
13 changed files with 211 additions and 50 deletions

View File

@ -30,7 +30,32 @@ public class EditSession {
* Stores the original blocks before modification. * Stores the original blocks before modification.
*/ */
private HashMap<Point<Integer>,Integer> original = new HashMap<Point<Integer>,Integer>(); private HashMap<Point<Integer>,Integer> original = new HashMap<Point<Integer>,Integer>();
/**
* Stores the current blocks.
*/
private HashMap<Point<Integer>,Integer> current = new HashMap<Point<Integer>,Integer>(); private HashMap<Point<Integer>,Integer> current = new HashMap<Point<Integer>,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. * Sets a block without changing history.
@ -54,10 +79,15 @@ public class EditSession {
* @param blockType * @param blockType
* @return Whether the block changed * @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<Integer> pt = new Point<Integer>(x, y, z); Point<Integer> pt = new Point<Integer>(x, y, z);
if (!original.containsKey(pt)) { if (!original.containsKey(pt)) {
original.put(pt, getBlock(x, y, z)); original.put(pt, getBlock(x, y, z));
if (maxBlocks != -1 && original.size() > maxBlocks) {
throw new MaxChangedBlocksException(maxBlocks);
}
} }
current.put(pt, blockType); current.put(pt, blockType);
return rawSetBlock(x, y, z, blockType); return rawSetBlock(x, y, z, blockType);
@ -104,4 +134,26 @@ public class EditSession {
public int size() { public int size() {
return original.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;
}
} }

View File

@ -100,8 +100,10 @@ public class RegionClipboard {
* @param editSession * @param editSession
* @param origin Position to paste it from * @param origin Position to paste it from
* @param noAir True to not paste air * @param noAir True to not paste air
* @throws MaxChangedBlocksException
*/ */
public void paste(EditSession editSession, Point<Integer> newOrigin, boolean noAir) { public void paste(EditSession editSession, Point<Integer> newOrigin, boolean noAir)
throws MaxChangedBlocksException {
int xs = getWidth(); int xs = getWidth();
int ys = getHeight(); int ys = getHeight();
int zs = getLength(); int zs = getLength();

View File

@ -1,3 +1,6 @@
import com.sk89q.worldedit.MaxChangedBlocksException;
// $Id$ // $Id$
/* /*
* WorldEdit * WorldEdit
@ -40,9 +43,11 @@ public class ScriptMinecraftContext {
* @param y * @param y
* @param z * @param z
* @param blockType * @param blockType
* @throws MaxChangedBlocksException
* @return * @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); return editSession.setBlock(x, y, z, blockType);
} }

View File

@ -41,6 +41,7 @@ public class WorldEdit extends Plugin {
private PropertiesFile properties; private PropertiesFile properties;
private String[] allowedBlocks; private String[] allowedBlocks;
private int defaultMaxBlocksChanged;
private boolean mapScriptCommands = false; private boolean mapScriptCommands = false;
/** /**
@ -68,6 +69,7 @@ public class WorldEdit extends Plugin {
commands.put("/editsave", "[Filename] - Save clipboard to .schematic"); commands.put("/editsave", "[Filename] - Save clipboard to .schematic");
commands.put("/editfill", "<ID> <Radius> <Depth> - Fill a hole"); commands.put("/editfill", "<ID> <Radius> <Depth> - Fill a hole");
commands.put("/editscript", "[Filename] <Args...> - Run a WorldEdit script"); commands.put("/editscript", "[Filename] <Args...> - Run a WorldEdit script");
commands.put("/setchangelimit", "<Num> - See documentation");
} }
/** /**
@ -81,6 +83,7 @@ public class WorldEdit extends Plugin {
return sessions.get(player.getName()); return sessions.get(player.getName());
} else { } else {
WorldEditSession session = new WorldEditSession(); WorldEditSession session = new WorldEditSession();
session.setBlockChangeLimit(defaultMaxBlocksChanged);
sessions.put(player.getName(), session); sessions.put(player.getName(), session);
return session; return session;
} }
@ -169,6 +172,8 @@ public class WorldEdit extends Plugin {
allowedBlocks = properties.getString("allowed-blocks", DEFAULT_ALLOWED_BLOCKS).split(","); allowedBlocks = properties.getString("allowed-blocks", DEFAULT_ALLOWED_BLOCKS).split(",");
mapScriptCommands = properties.getBoolean("map-script-commands", true); mapScriptCommands = properties.getBoolean("map-script-commands", true);
defaultMaxBlocksChanged =
Math.max(-1, properties.getInt("max-blocks-changed", -1));
etc controller = etc.getInstance(); etc controller = etc.getInstance();
@ -255,21 +260,33 @@ public class WorldEdit extends Plugin {
try { try {
if (commands.containsKey(split[0])) { if (commands.containsKey(split[0])) {
if (player.canUseCommand(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 { } else {
// See if there is a script by the same name // See if there is a script by the same name
if (mapScriptCommands) { if (mapScriptCommands && player.canUseCommand("/editscript")) {
if (player.canUseCommand("/editscript")) { WorldEditSession session = getSession(player);
String filename = split[0].substring(1) + ".js"; EditSession editSession =
String[] args = new String[split.length - 1]; new EditSession(session.getBlockChangeLimit());
System.arraycopy(split, 1, args, 0, split.length - 1);
try { String filename = split[0].substring(1) + ".js";
return runScript(player, getSession(player), new EditSession(), String[] args = new String[split.length - 1];
filename, args); System.arraycopy(split, 1, args, 0, split.length - 1);
} catch (NoSuchScriptException nse) {
return false; 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; return false;
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
player.sendMessage(Colors.Rose + "Number expected; string given."); player.sendMessage(Colors.Rose + "Number expected; string given.");
return true;
} catch (IncompleteRegionException e2) { } catch (IncompleteRegionException e2) {
player.sendMessage(Colors.Rose + "The edit region has not been fully defined."); player.sendMessage(Colors.Rose + "The edit region has not been fully defined.");
return true;
} catch (UnknownItemException e3) { } catch (UnknownItemException e3) {
player.sendMessage(Colors.Rose + "Unknown item."); player.sendMessage(Colors.Rose + "Unknown item.");
return true;
} catch (DisallowedItemException e4) { } catch (DisallowedItemException e4) {
player.sendMessage(Colors.Rose + "Disallowed item."); player.sendMessage(Colors.Rose + "Disallowed item.");
return true; } catch (MaxChangedBlocksException e5) {
} catch (InsufficientArgumentsException e5) { player.sendMessage(Colors.Rose + "The maximum number of blocks changed ("
player.sendMessage(Colors.Rose + e5.getMessage()); + e5.getBlockLimit() + ") in an instance was reached.");
return true; } 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. * The main meat of command processing.
* *
* @param player * @param player
* @param session
* @param editSession
* @param split * @param split
* @return * @return
* @throws UnknownItemException * @throws UnknownItemException
@ -304,13 +325,10 @@ public class WorldEdit extends Plugin {
* @throws InsufficientArgumentsException * @throws InsufficientArgumentsException
* @throws DisallowedItemException * @throws DisallowedItemException
*/ */
private boolean handleEditCommand(Player player, String[] split) private boolean performCommand(Player player, WorldEditSession session,
throws UnknownItemException, IncompleteRegionException, EditSession editSession, String[] split)
InsufficientArgumentsException, DisallowedItemException throws WorldEditException
{ {
WorldEditSession session = getSession(player);
EditSession editSession = new EditSession();
// Set edit position #1 // Set edit position #1
if (split[0].equalsIgnoreCase("/editpos1")) { if (split[0].equalsIgnoreCase("/editpos1")) {
session.setPos1((int)Math.floor(player.getX()), session.setPos1((int)Math.floor(player.getX()),
@ -327,6 +345,14 @@ public class WorldEdit extends Plugin {
player.sendMessage(Colors.LightPurple + "Second edit position set."); player.sendMessage(Colors.LightPurple + "Second edit position set.");
return true; 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 // Undo
} else if (split[0].equalsIgnoreCase("/editundo")) { } else if (split[0].equalsIgnoreCase("/editundo")) {
if (session.undo()) { if (session.undo()) {
@ -368,7 +394,6 @@ public class WorldEdit extends Plugin {
(int)Math.floor(player.getZ())); (int)Math.floor(player.getZ()));
session.getClipboard().paste(editSession, pos, session.getClipboard().paste(editSession, pos,
split[0].equalsIgnoreCase("/editpaste")); split[0].equalsIgnoreCase("/editpaste"));
session.remember(editSession);
logger.log(Level.INFO, player.getName() + " used " + split[0]); logger.log(Level.INFO, player.getName() + " used " + split[0]);
player.sendMessage(Colors.LightPurple + "Pasted."); player.sendMessage(Colors.LightPurple + "Pasted.");
} }
@ -393,8 +418,6 @@ public class WorldEdit extends Plugin {
logger.log(Level.INFO, player.getName() + " used /editfill"); logger.log(Level.INFO, player.getName() + " used /editfill");
player.sendMessage(Colors.LightPurple + affected + " block(s) have been created."); player.sendMessage(Colors.LightPurple + affected + " block(s) have been created.");
session.remember(editSession);
return true; return true;
// Remove blocks above current position // Remove blocks above current position
@ -420,8 +443,6 @@ public class WorldEdit extends Plugin {
logger.log(Level.INFO, player.getName() + " used /removeabove"); logger.log(Level.INFO, player.getName() + " used /removeabove");
player.sendMessage(Colors.LightPurple + affected + " block(s) have been removed."); player.sendMessage(Colors.LightPurple + affected + " block(s) have been removed.");
session.remember(editSession);
return true; return true;
// Load .schematic to clipboard // Load .schematic to clipboard
@ -534,8 +555,6 @@ public class WorldEdit extends Plugin {
logger.log(Level.INFO, player.getName() + " used /editset"); logger.log(Level.INFO, player.getName() + " used /editset");
player.sendMessage(Colors.LightPurple + affected + " block(s) have been set."); player.sendMessage(Colors.LightPurple + affected + " block(s) have been set.");
session.remember(editSession);
return true; return true;
// Set the outline of a region // Set the outline of a region
@ -571,8 +590,6 @@ public class WorldEdit extends Plugin {
logger.log(Level.INFO, player.getName() + " used /editoutline"); logger.log(Level.INFO, player.getName() + " used /editoutline");
player.sendMessage(Colors.LightPurple + affected + " block(s) have been set."); player.sendMessage(Colors.LightPurple + affected + " block(s) have been set.");
session.remember(editSession);
return true; return true;
// Replace all blocks in the region // Replace all blocks in the region
@ -598,8 +615,6 @@ public class WorldEdit extends Plugin {
logger.log(Level.INFO, player.getName() + " used /editreplace"); logger.log(Level.INFO, player.getName() + " used /editreplace");
player.sendMessage(Colors.LightPurple + affected + " block(s) have been replaced."); player.sendMessage(Colors.LightPurple + affected + " block(s) have been replaced.");
session.remember(editSession);
return true; return true;
// Lay blocks over an area // Lay blocks over an area
@ -628,8 +643,6 @@ public class WorldEdit extends Plugin {
logger.log(Level.INFO, player.getName() + " used /editoverlay"); logger.log(Level.INFO, player.getName() + " used /editoverlay");
player.sendMessage(Colors.LightPurple + affected + " block(s) have been overlayed."); player.sendMessage(Colors.LightPurple + affected + " block(s) have been overlayed.");
session.remember(editSession);
return true; return true;
// Copy // Copy
@ -668,7 +681,8 @@ public class WorldEdit extends Plugin {
* @return * @return
*/ */
private int fill(EditSession editSession, int x, int z, int cx, int cy, 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)); double dist = Math.sqrt(Math.pow(cx - x, 2) + Math.pow(cz - z, 2));
int affected = 0; int affected = 0;
@ -699,10 +713,12 @@ public class WorldEdit extends Plugin {
* @param z * @param z
* @param blockType * @param blockType
* @param minY * @param minY
* @throws MaxChangedBlocksException
* @return * @return
*/ */
private int fillY(EditSession editSession, int x, int cy, 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; int affected = 0;
for (int y = cy; y > minY; y--) { 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()); player.sendMessage(Colors.Rose + filename + ": execution error: " + err.getMessage());
} finally { } finally {
Context.exit(); Context.exit();
session.remember(editSession);
} }
} }

View File

@ -36,6 +36,7 @@ public class WorldEditSession {
private boolean toolControl = true; private boolean toolControl = true;
private int[] lastToolPos1 = new int[3]; private int[] lastToolPos1 = new int[3];
private long lastToolClick = 0; private long lastToolClick = 0;
private int maxBlocksChanged = -1;
/** /**
* Clear history. * Clear history.
@ -337,4 +338,21 @@ public class WorldEditSession {
public void triggerToolClick() { public void triggerToolClick() {
lastToolClick = System.currentTimeMillis(); 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;
}
} }

View File

@ -23,6 +23,6 @@ package com.sk89q.worldedit;
* *
* @author sk89q * @author sk89q
*/ */
public class DisallowedItemException extends Exception { public class DisallowedItemException extends WorldEditException {
} }

View File

@ -24,6 +24,6 @@ package com.sk89q.worldedit;
* *
* @author Albert * @author Albert
*/ */
public class IncompleteRegionException extends Exception { public class IncompleteRegionException extends WorldEditException {
} }

View File

@ -23,7 +23,7 @@ package com.sk89q.worldedit;
* *
* @author sk89q * @author sk89q
*/ */
public class InsufficientArgumentsException extends Exception { public class InsufficientArgumentsException extends WorldEditException {
public InsufficientArgumentsException(String error) { public InsufficientArgumentsException(String error) {
super(error); super(error);
} }

View File

@ -0,0 +1,36 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -23,6 +23,6 @@ package com.sk89q.worldedit;
* *
* @author Albert * @author Albert
*/ */
public class NoSuchScriptException extends Exception { public class NoSuchScriptException extends WorldEditException {
} }

View File

@ -23,7 +23,7 @@ package com.sk89q.worldedit;
* *
* @author Albert * @author Albert
*/ */
public class SchematicLoadException extends Exception { public class SchematicLoadException extends WorldEditException {
public SchematicLoadException(String error) { public SchematicLoadException(String error) {
super(error); super(error);
} }

View File

@ -24,6 +24,6 @@ package com.sk89q.worldedit;
* *
* @author sk89q * @author sk89q
*/ */
public class UnknownItemException extends Exception { public class UnknownItemException extends WorldEditException {
} }

View File

@ -0,0 +1,33 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit;
/**
*
* @author Albert
*/
public abstract class WorldEditException extends Exception {
protected WorldEditException() {
}
protected WorldEditException(String msg) {
super(msg);
}
}