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.
*/
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>();
/**
* 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 @@ private boolean rawSetBlock(int x, int y, int z, int blockType) {
* @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<Integer> pt = new Point<Integer>(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 void redo() {
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;
}
}

View File

@ -100,8 +100,10 @@ public void copy(EditSession editSession) {
* @param editSession
* @param origin Position to paste it from
* @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 ys = getHeight();
int zs = getLength();

View File

@ -1,3 +1,6 @@
import com.sk89q.worldedit.MaxChangedBlocksException;
// $Id$
/*
* WorldEdit
@ -40,9 +43,11 @@ public ScriptMinecraftContext(EditSession editSession) {
* @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);
}

View File

@ -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 WorldEdit() {
commands.put("/editsave", "[Filename] - Save clipboard to .schematic");
commands.put("/editfill", "<ID> <Radius> <Depth> - Fill a hole");
commands.put("/editscript", "[Filename] <Args...> - Run a WorldEdit script");
commands.put("/setchangelimit", "<Num> - See documentation");
}
/**
@ -81,6 +83,7 @@ private WorldEditSession getSession(Player player) {
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 void enable() {
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 boolean onCommand(Player player, String[] split) {
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 boolean onCommand(Player player, String[] split) {
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 boolean onCommand(Player player, String[] split) {
* @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 @@ private boolean handleEditCommand(Player player, String[] split)
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 @@ private boolean handleEditCommand(Player player, String[] split)
(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 @@ private boolean handleEditCommand(Player player, String[] split)
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 @@ private boolean handleEditCommand(Player player, String[] split)
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 @@ private boolean handleEditCommand(Player player, String[] split)
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 @@ private boolean handleEditCommand(Player player, String[] split)
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 @@ private boolean handleEditCommand(Player player, String[] split)
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 @@ private boolean handleEditCommand(Player player, String[] split)
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 @@ private boolean handleEditCommand(Player player, String[] split)
* @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 @@ private int fill(EditSession editSession, int x, int z, int cx, int cy,
* @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 @@ private boolean runScript(Player player, WorldEditSession session,
player.sendMessage(Colors.Rose + filename + ": execution error: " + err.getMessage());
} finally {
Context.exit();
session.remember(editSession);
}
}

View File

@ -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 boolean hasToolBeenDoubleClicked() {
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;
}
}

View File

@ -23,6 +23,6 @@
*
* @author sk89q
*/
public class DisallowedItemException extends Exception {
public class DisallowedItemException extends WorldEditException {
}

View File

@ -24,6 +24,6 @@
*
* @author Albert
*/
public class IncompleteRegionException extends Exception {
public class IncompleteRegionException extends WorldEditException {
}

View File

@ -23,7 +23,7 @@
*
* @author sk89q
*/
public class InsufficientArgumentsException extends Exception {
public class InsufficientArgumentsException extends WorldEditException {
public InsufficientArgumentsException(String 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 @@
*
* @author Albert
*/
public class NoSuchScriptException extends Exception {
public class NoSuchScriptException extends WorldEditException {
}

View File

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

View File

@ -24,6 +24,6 @@
*
* @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);
}
}