Added //fast mode, which allows the server to skip the dirtying of chunks. This means that you have to rejoin to see changes though, but most operations are doubled in speed.

This commit is contained in:
sk89q 2011-06-04 10:30:45 -07:00
parent d397460026
commit d881c14e2d
11 changed files with 514 additions and 23 deletions

361
plugin.yml Normal file
View File

@ -0,0 +1,361 @@
name: WorldEdit
main: com.sk89q.worldedit.bukkit.WorldEditPlugin
version: ${project.version}
commands:
chunkinfo:
description: Get information about the chunk that you are inside
usage: /<command>
permissions: 'worldedit.chunkinfo'
listchunks:
description: List chunks that your selection includes
usage: /<command>
permissions: 'worldedit.listchunks'
delchunks:
description: Delete chunks that your selection includes
usage: /<command>
permissions: 'worldedit.delchunks'
clearclipboard:
description: Clear your clipboard
usage: /<command>
permissions: 'worldedit.clipboard.clear'
/load:
description: Load a schematic into your clipboard
usage: /<command> <filename>
permissions: 'worldedit.clipboard.load'
/save:
description: Save a schematic into your clipboard
usage: /<command> <filename>
permissions: 'worldedit.clipboard.save'
/copy:
description: Copy the selection to the clipboard
usage: /<command>
permissions: 'worldedit.clipboard.copy'
/flip:
description: Flip the contents of the clipboard
usage: /<command> [dir]
permissions: 'worldedit.clipboard.flip'
/rotate:
description: Rotate the contents of the clipboard
usage: /<command> <angle-in-degrees>
permissions: 'worldedit.clipboard.rotate'
/cut:
description: Cut the selection to the clipboard
usage: /<command> [leave-id]
permissions: 'worldedit.clipboard.cut'
/paste:
description: Paste the clipboard's contents
usage: /<command> [-ao]
permissions: 'worldedit.clipboard.paste'
we:
description: WorldEdit commands
usage: /<command>
aliases: ['worldedit']
/fast:
description: Toggle fast mode
usage: /<command>
permissions: 'worldedit.fast'
toggleplace:
description:
usage: /<command>
searchitem:
description: Search for an item
usage: /<command> [-bi] <query>
aliases: ['/l', 'search']
/limit:
description: Modify block change limit
usage: /<command> <limit>
permissions: 'worldedit.limit'
/hcyl:
description: Generate a hollow cylinder
usage: /<command> <block> <radius> [height]
permissions: 'worldedit.generation.cylinder'
/cyl:
description: Generate a cylinder
usage: /<command> <block> <radius> [height]
permissions: 'worldedit.generation.cylinder'
/hsphere:
description: Generate a hollow sphere
usage: /<command> <block> <radius> [raised?]
permissions: 'worldedit.generation.sphere'
/sphere:
description: Generate a filled sphere
usage: /<command> <block> <radius> [raised?]
permissions: 'worldedit.generation.sphere'
forestgen:
description: Generate a forest
usage: /<command> [size] [type] [density]
permissions: 'worldedit.generation.forest'
pumpkins:
description: Generate pumpkin patches
usage: /<command> [size]
permissions: 'worldedit.generation.pumpkins'
clearhistory:
description: Clear your history
usage: /<command>
permissions: 'worldedit.history.clear'
/redo:
description: Redoes the last action (from history)
usage: /<command> [times]
aliases: ['redo']
permissions: 'worldedit.history.redo'
/undo:
description: Undoes the last action
usage: /<command> [times]
aliases: ['undo']
permissions: 'worldedit.history.undo'
unstuck:
description: Escape from being stuck inside a block
usage: /<command>
permissions: 'worldedit.navigation.unstuck'
ascend:
description: Go up a floor
usage: /<command>
permissions: 'worldedit.navigation.ascend'
descend:
description: Go down a floor
usage: /<command>
permissions: 'worldedit.navigation.descend'
thru:
description: Passthrough walls
usage: /<command>
permissions: 'worldedit.navigation.thru'
jumpto:
description: Teleport to a location
usage: /<command>
permissions: 'worldedit.navigation.jumpto'
ceil:
description: Go to the celing
usage: /<command> [clearance]
permissions: 'worldedit.navigation.ceiling'
up:
description: Go upwards some distance
usage: /<command> <block>
permissions: 'worldedit.navigation.up'
/overlay:
description: Set a block on top of blocks in the region
usage: /<command> <block>
permissions: 'worldedit.region.overlay'
/walls:
description: Build the four sides of the selection
usage: /<command> <block>
permissions: 'worldedit.region.walls'
/faces:
description: Build the walls, ceiling, and roof of a selection
usage: /<command> <block>
aliases: ['/outline']
permissions: 'worldedit.region.faces'
/smooth:
description: Smooth the elevation in the selection
usage: /<command> [iterations]
permissions: 'worldedit.region.smooth'
/regen:
description: Regenerates the contents of the selection
usage: /<command>
permissions: 'worldedit.regen'
/replace:
description: Replace all blocks in the selection with another
usage: /<command> [from-block] <to-block>
permissions: 'worldedit.region.replace'
/stack:
description: Repeat the contents of the selection
usage: /<command> [-sa] [count] [direction]
permissions: 'worldedit.region.stack'
/set:
description: Set all the blocks inside the selection to a block
usage: /<command> <block>
permissions: 'worldedit.region.set'
/move:
description: Move the contents of the selection
usage: /<command> [-s] [count] [direction] [leave-id]
permissions: 'worldedit.region.move'
.s:
description: Execute last CraftScript
usage: /<command> [args...]
permissions: 'worldedit.scripting.execute'
cs:
description: Execute a CraftScript
usage: /<command> <filename> [args...]
permissions: 'worldedit.scripting.execute'
/chunk:
description: Set the selection to your current chunk
usage: /<command>
permissions: 'worldedit.selection.chunk'
/contract:
description: Contract the selection area
usage: /<command> <amount> [reverse-amount] [direction]
permissions: 'worldedit.selection.contract'
/pos1:
description: Set position 1
usage: /<command>
permissions: 'worldedit.selection.pos'
/pos2:
description: Set position 2
usage: /<command>
permissions: 'worldedit.selection.pos'
/hpos1:
description: Set position 1 to targeted block
usage: /<command>
permissions: 'worldedit.selection.hpos'
/hpos2:
description: Set position 2 to targeted block
usage: /<command>
permissions: 'worldedit.selection.hpos'
/wand:
description: Get the wand object
usage: /<command>
permissions: 'worldedit.wand'
toggleeditwand:
description: Toggle functionality of the edit wand
usage: /<command>
permissions: 'worldedit.wand.toggle'
/outset:
description: Outset the selection area
usage: /<command> [-hv] <amount>
permissions: 'worldedit.selection.outset'
/distr:
description: Get the distribution of blocks in the selection
usage: /<command> [-c]
permissions: 'worldedit.analysis.distr'
/count:
description: Counts the number of a certain type of block
usage: /<command> <block>
permissions: 'worldedit.analysis.count'
/size:
description: Get information about the selection
usage: /<command>
permissions: 'worldedit.selection.size'
/shift:
description: Shift the selection area
usage: /<command> <amount> [direction]
permissions: 'worldedit.selection.shift'
/expand:
description: Expand the selection area
usage: /<command> <amount> [reverse-amount] <direction>
permissions: 'worldedit.selection.expand'
/sel:
description: Choose a region selector
usage: /<command> [type]
aliases: [',']
/inset:
description: Inset the selection area
usage: /<command> [-hv] <amount>
permissions: 'worldedit.selection.inset'
snapshot:
description: Snapshot commands
usage: /<command>
aliases: ['snap']
restore:
description: Restore the selection from a snapshot
usage: /<command> [snapshot]
aliases: ['/restore']
permissions: 'worldedit.snapshots.restore'
/:
description: Toggle the super pickaxe pickaxe function
usage: /<command>
aliases: [',']
permissions: 'worldedit.superpickaxe'
superpickaxe:
description: Select super pickaxe mode
usage: /<command>
aliases: ['pickaxe', 'sp']
tool:
description: Select a tool to bind
usage: /<command>
mat:
description: Set the brush material
usage: /<command> [pattern]
aliases: ['material', 'fill']
permissions: 'worldedit.brush.options.material'
size:
description: Set the brush size
usage: /<command> [pattern]
permissions: 'worldedit.brush.options.size'
mask:
description: Set the brush mask
usage: /<command> [mask]
permissions: 'worldedit.brush.options.mask'
none:
description: Turn off all superpickaxe alternate modes
usage: /<command>
repl:
description: Block replacer tool
usage: /<command> <block>
permissions: 'worldedit.tool.replacer'
cycler:
description: Block data cycler tool
usage: /<command>
permissions: 'worldedit.tool.data-cycler'
brush:
description: Brush tool
usage: /<command>
aliases: ['br']
deltree:
description: Floating tree remover tool
usage: /<command>
permissions: 'worldedit.tool.deltree'
info:
description: Block information tool
usage: /<command>
permissions: 'worldedit.tool.info'
tree:
description: Tree generator tool
usage: /<command> [type]
permissions: 'worldedit.tool.tree'
/fillr:
description: Fill a hole recursively
usage: /<command> <block> <radius> [depth]
permissions: 'worldedit.fill.recursive'
fixlava:
description: Fix lava to be stationary
usage: /<command> <radius>
permissions: 'worldedit.fixlava'
fixwater:
description: Fix water to be stationary
usage: /<command> <radius>
permissions: 'worldedit.fixwater'
removeabove:
description: Remove blocks above your head.
usage: /<command> [size] [height]
permissions: 'worldedit.removeabove'
removebelow:
description: Remove blocks below your head.
usage: /<command> [size] [height]
permissions: 'worldedit.removebelow'
removenear:
description: Remove blocks near you.
usage: /<command> <block> [size]
permissions: 'worldedit.removenear'
replacenear:
description: Replace nearby blocks
usage: /<command> <size> <from-id> <to-id>
permissions: 'worldedit.replacenear'
snow:
description: Simulates snow
usage: /<command> [radius]
permissions: 'worldedit.snow'
thaw:
description: Thaws the area
usage: /<command> [radius]
permissions: 'worldedit.thaw'
ex:
description: Extinguish nearby fire
usage: /<command> [radius]
aliases: ['ext', 'extinguish']
permissions: 'worldedit.extinguish'
butcher:
description: Kill all or nearby mobs
usage: /<command> [-p] [radius]
permissions: 'worldedit.butcher'
remove:
description: Remove all entities of a type
usage: /<command> <type> <radius>
aliases: ['rem', 'rement']
permissions: 'worldedit.remove'
/fill:
description: Fill a hole
usage: /<command> <block> <radius> [depth]
permissions: 'worldedit.fill'
/drain:
description: Drain a pool
usage: /<command> <radius>
permissions: 'worldedit.drain'

View File

@ -87,15 +87,23 @@ public class EditSession {
* indicates no limit. * indicates no limit.
*/ */
private int maxBlocks = -1; private int maxBlocks = -1;
/** /**
* Indicates whether some types of blocks should be queued for best * Indicates whether some types of blocks should be queued for best
* reproduction. * reproduction.
*/ */
private boolean queued = false; private boolean queued = false;
/**
* Use the fast mode, which may leave chunks not flagged "dirty".
*/
private boolean fastMode = false;
/** /**
* Block bag to use for getting blocks. * Block bag to use for getting blocks.
*/ */
private BlockBag blockBag; private BlockBag blockBag;
/** /**
* List of missing blocks; * List of missing blocks;
*/ */
@ -186,11 +194,22 @@ public class EditSession {
} }
} }
boolean result = world.setBlockType(pt, id); boolean result;
if (fastMode) {
result = world.setBlockTypeFast(pt, id);
} else {
result = world.setBlockType(pt, id);
}
if (id != 0) { if (id != 0) {
if (BlockType.usesData(id)) { if (existing != type && block.getData() > 0 && BlockType.usesData(id)) {
if (fastMode) {
world.setBlockDataFast(pt, block.getData());
} else {
world.setBlockData(pt, block.getData()); world.setBlockData(pt, block.getData());
} }
}
// Signs // Signs
if (block instanceof SignBlock) { if (block instanceof SignBlock) {
@ -489,6 +508,24 @@ public class EditSession {
queued = false; queued = false;
} }
/**
* Set fast mode.
*
* @param fastMode
*/
public void setFastMode(boolean fastMode) {
this.fastMode = fastMode;
}
/**
* Return fast mode status.
*
* @return
*/
public boolean hasFastMode() {
return fastMode;
}
/** /**
* Finish off the queue. * Finish off the queue.
*/ */

View File

@ -73,6 +73,7 @@ public class LocalSession {
private String lastScript; private String lastScript;
private boolean beenToldVersion = false; private boolean beenToldVersion = false;
private boolean hasCUISupport = false; private boolean hasCUISupport = false;
private boolean fastMode = false;
private TimeZone timezone = TimeZone.getDefault(); private TimeZone timezone = TimeZone.getDefault();
/** /**
@ -144,6 +145,7 @@ public class LocalSession {
EditSession newEditSession = EditSession newEditSession =
new EditSession(editSession.getWorld(), -1, newBlockBag); new EditSession(editSession.getWorld(), -1, newBlockBag);
newEditSession.enableQueue(); newEditSession.enableQueue();
newEditSession.setFastMode(fastMode);
editSession.undo(newEditSession); editSession.undo(newEditSession);
return editSession; return editSession;
} else { } else {
@ -164,6 +166,7 @@ public class LocalSession {
EditSession newEditSession = EditSession newEditSession =
new EditSession(editSession.getWorld(), -1, newBlockBag); new EditSession(editSession.getWorld(), -1, newBlockBag);
newEditSession.enableQueue(); newEditSession.enableQueue();
newEditSession.setFastMode(fastMode);
editSession.redo(newEditSession); editSession.redo(newEditSession);
historyPointer++; historyPointer++;
return editSession; return editSession;
@ -642,4 +645,40 @@ public class LocalSession {
public boolean hasExpired() { public boolean hasExpired() {
return System.currentTimeMillis() - expirationTime > EXPIRATION_GRACE; return System.currentTimeMillis() - expirationTime > EXPIRATION_GRACE;
} }
/**
* Construct a new edit session.
*
* @param player
* @return
*/
public EditSession createEditSession(LocalPlayer player) {
BlockBag blockBag = getBlockBag(player);
// Create an edit session
EditSession editSession =
new EditSession(player.getWorld(),
getBlockChangeLimit(), blockBag);
editSession.setFastMode(fastMode);
return editSession;
}
/**
* Checks if the session has fast mode enabled.
*
* @return
*/
public boolean hasFastMode() {
return fastMode;
}
/**
* Set fast mode.
*
* @param fastMode
*/
public void setFastMode(boolean fastMode) {
this.fastMode = fastMode;
}
} }

View File

@ -44,6 +44,17 @@ public abstract class LocalWorld {
*/ */
public abstract boolean setBlockType(Vector pt, int type); public abstract boolean setBlockType(Vector pt, int type);
/**
* Set block type.
*
* @param pt
* @param type
* @return
*/
public boolean setBlockTypeFast(Vector pt, int type) {
return setBlockType(pt, type);
}
/** /**
* Get block type. * Get block type.
* *
@ -60,6 +71,16 @@ public abstract class LocalWorld {
*/ */
public abstract void setBlockData(Vector pt, int data); public abstract void setBlockData(Vector pt, int data);
/**
* Set block data.
*
* @param pt
* @param data
*/
public void setBlockDataFast(Vector pt, int data) {
setBlockData(pt, data);
}
/** /**
* Get block data. * Get block data.
* *

View File

@ -1010,16 +1010,11 @@ public class WorldEdit {
} }
LocalSession session = getSession(player); LocalSession session = getSession(player);
BlockBag blockBag = session.getBlockBag(player); EditSession editSession = session.createEditSession(player);
editSession.enableQueue();
session.tellVersion(player); session.tellVersion(player);
// Create an edit session
EditSession editSession =
new EditSession(player.getWorld(),
session.getBlockChangeLimit(), blockBag);
editSession.enableQueue();
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
try { try {

View File

@ -81,6 +81,18 @@ public class BukkitWorld extends LocalWorld {
return world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeId(type); return world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeId(type);
} }
/**
* Set block type.
*
* @param pt
* @param type
* @return
*/
@Override
public boolean setBlockTypeFast(Vector pt, int type) {
return world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeId(type, false);
}
/** /**
* Get block type. * Get block type.
* *
@ -101,7 +113,17 @@ public class BukkitWorld extends LocalWorld {
@Override @Override
public void setBlockData(Vector pt, int data) { public void setBlockData(Vector pt, int data) {
world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setData((byte)data); world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setData((byte)data);
}
/**
* Set block data.
*
* @param pt
* @param data
*/
@Override
public void setBlockDataFast(Vector pt, int data) {
world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setData((byte)data, false);
} }
/** /**

View File

@ -60,6 +60,27 @@ public class GeneralCommands {
player.print("Block change limit set to " + limit + "."); player.print("Block change limit set to " + limit + ".");
} }
@Command(
aliases = {"/fast"},
usage = "",
desc = "Toggle fast mode",
min = 0,
max = 0
)
@CommandPermissions({"worldedit.fast"})
public static void fast(CommandContext args, WorldEdit we,
LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException {
session.setFastMode(!session.hasFastMode());
if (session.hasFastMode()) {
player.print("Fast mode enabled. You may need to rejoin to see changes.");
} else {
player.print("Fast mode disabled.");
}
}
@Command( @Command(
aliases = {"toggleplace"}, aliases = {"toggleplace"},
usage = "", usage = "",

View File

@ -56,8 +56,7 @@ public class AreaPickaxe implements BlockTool {
return true; return true;
} }
EditSession editSession = EditSession editSession = session.createEditSession(player);
new EditSession(world, session.getBlockChangeLimit());
try { try {
for (int x = ox - range; x <= ox + range; x++) { for (int x = ox - range; x <= ox + range; x++) {

View File

@ -51,8 +51,7 @@ public class FloatingTreeRemover implements BlockTool {
int initialType = world.getBlockType(clicked); int initialType = world.getBlockType(clicked);
int block; int block;
EditSession editSession = EditSession editSession = session.createEditSession(player);
new EditSession(world, session.getBlockChangeLimit());
if (initialType != BlockID.LEAVES && initialType != BlockID.LOG) { if (initialType != BlockID.LEAVES && initialType != BlockID.LOG) {
player.printError("That's not a floating tree."); player.printError("That's not a floating tree.");

View File

@ -57,8 +57,7 @@ public class RecursivePickaxe implements BlockTool {
return true; return true;
} }
EditSession editSession = EditSession editSession = session.createEditSession(player);
new EditSession(world, session.getBlockChangeLimit());
try { try {
recurse(server, editSession, world, clicked.toBlockVector(), recurse(server, editSession, world, clicked.toBlockVector(),

View File

@ -41,9 +41,7 @@ public class TreePlanter implements BlockTool {
public boolean actPrimary(ServerInterface server, LocalConfiguration config, public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) { LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld(); EditSession editSession = session.createEditSession(player);
EditSession editSession =
new EditSession(world, session.getBlockChangeLimit());
try { try {
if (!gen.generate(editSession, clicked.add(0, 1, 0))) { if (!gen.generate(editSession, clicked.add(0, 1, 0))) {