From d881c14e2d720d44813dea32ef9aebee5d0b9962 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 4 Jun 2011 10:30:45 -0700 Subject: [PATCH] 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. --- plugin.yml | 361 ++++++++++++++++++ .../java/com/sk89q/worldedit/EditSession.java | 43 ++- .../com/sk89q/worldedit/LocalSession.java | 39 ++ .../java/com/sk89q/worldedit/LocalWorld.java | 21 + .../java/com/sk89q/worldedit/WorldEdit.java | 11 +- .../sk89q/worldedit/bukkit/BukkitWorld.java | 24 +- .../worldedit/commands/GeneralCommands.java | 21 + .../sk89q/worldedit/tools/AreaPickaxe.java | 3 +- .../worldedit/tools/FloatingTreeRemover.java | 5 +- .../worldedit/tools/RecursivePickaxe.java | 5 +- .../sk89q/worldedit/tools/TreePlanter.java | 4 +- 11 files changed, 514 insertions(+), 23 deletions(-) create mode 100644 plugin.yml diff --git a/plugin.yml b/plugin.yml new file mode 100644 index 000000000..d8c8e9aa9 --- /dev/null +++ b/plugin.yml @@ -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: / + permissions: 'worldedit.chunkinfo' + listchunks: + description: List chunks that your selection includes + usage: / + permissions: 'worldedit.listchunks' + delchunks: + description: Delete chunks that your selection includes + usage: / + permissions: 'worldedit.delchunks' + clearclipboard: + description: Clear your clipboard + usage: / + permissions: 'worldedit.clipboard.clear' + /load: + description: Load a schematic into your clipboard + usage: / + permissions: 'worldedit.clipboard.load' + /save: + description: Save a schematic into your clipboard + usage: / + permissions: 'worldedit.clipboard.save' + /copy: + description: Copy the selection to the clipboard + usage: / + permissions: 'worldedit.clipboard.copy' + /flip: + description: Flip the contents of the clipboard + usage: / [dir] + permissions: 'worldedit.clipboard.flip' + /rotate: + description: Rotate the contents of the clipboard + usage: / + permissions: 'worldedit.clipboard.rotate' + /cut: + description: Cut the selection to the clipboard + usage: / [leave-id] + permissions: 'worldedit.clipboard.cut' + /paste: + description: Paste the clipboard's contents + usage: / [-ao] + permissions: 'worldedit.clipboard.paste' + we: + description: WorldEdit commands + usage: / + aliases: ['worldedit'] + /fast: + description: Toggle fast mode + usage: / + permissions: 'worldedit.fast' + toggleplace: + description: + usage: / + searchitem: + description: Search for an item + usage: / [-bi] + aliases: ['/l', 'search'] + /limit: + description: Modify block change limit + usage: / + permissions: 'worldedit.limit' + /hcyl: + description: Generate a hollow cylinder + usage: / [height] + permissions: 'worldedit.generation.cylinder' + /cyl: + description: Generate a cylinder + usage: / [height] + permissions: 'worldedit.generation.cylinder' + /hsphere: + description: Generate a hollow sphere + usage: / [raised?] + permissions: 'worldedit.generation.sphere' + /sphere: + description: Generate a filled sphere + usage: / [raised?] + permissions: 'worldedit.generation.sphere' + forestgen: + description: Generate a forest + usage: / [size] [type] [density] + permissions: 'worldedit.generation.forest' + pumpkins: + description: Generate pumpkin patches + usage: / [size] + permissions: 'worldedit.generation.pumpkins' + clearhistory: + description: Clear your history + usage: / + permissions: 'worldedit.history.clear' + /redo: + description: Redoes the last action (from history) + usage: / [times] + aliases: ['redo'] + permissions: 'worldedit.history.redo' + /undo: + description: Undoes the last action + usage: / [times] + aliases: ['undo'] + permissions: 'worldedit.history.undo' + unstuck: + description: Escape from being stuck inside a block + usage: / + permissions: 'worldedit.navigation.unstuck' + ascend: + description: Go up a floor + usage: / + permissions: 'worldedit.navigation.ascend' + descend: + description: Go down a floor + usage: / + permissions: 'worldedit.navigation.descend' + thru: + description: Passthrough walls + usage: / + permissions: 'worldedit.navigation.thru' + jumpto: + description: Teleport to a location + usage: / + permissions: 'worldedit.navigation.jumpto' + ceil: + description: Go to the celing + usage: / [clearance] + permissions: 'worldedit.navigation.ceiling' + up: + description: Go upwards some distance + usage: / + permissions: 'worldedit.navigation.up' + /overlay: + description: Set a block on top of blocks in the region + usage: / + permissions: 'worldedit.region.overlay' + /walls: + description: Build the four sides of the selection + usage: / + permissions: 'worldedit.region.walls' + /faces: + description: Build the walls, ceiling, and roof of a selection + usage: / + aliases: ['/outline'] + permissions: 'worldedit.region.faces' + /smooth: + description: Smooth the elevation in the selection + usage: / [iterations] + permissions: 'worldedit.region.smooth' + /regen: + description: Regenerates the contents of the selection + usage: / + permissions: 'worldedit.regen' + /replace: + description: Replace all blocks in the selection with another + usage: / [from-block] + permissions: 'worldedit.region.replace' + /stack: + description: Repeat the contents of the selection + usage: / [-sa] [count] [direction] + permissions: 'worldedit.region.stack' + /set: + description: Set all the blocks inside the selection to a block + usage: / + permissions: 'worldedit.region.set' + /move: + description: Move the contents of the selection + usage: / [-s] [count] [direction] [leave-id] + permissions: 'worldedit.region.move' + .s: + description: Execute last CraftScript + usage: / [args...] + permissions: 'worldedit.scripting.execute' + cs: + description: Execute a CraftScript + usage: / [args...] + permissions: 'worldedit.scripting.execute' + /chunk: + description: Set the selection to your current chunk + usage: / + permissions: 'worldedit.selection.chunk' + /contract: + description: Contract the selection area + usage: / [reverse-amount] [direction] + permissions: 'worldedit.selection.contract' + /pos1: + description: Set position 1 + usage: / + permissions: 'worldedit.selection.pos' + /pos2: + description: Set position 2 + usage: / + permissions: 'worldedit.selection.pos' + /hpos1: + description: Set position 1 to targeted block + usage: / + permissions: 'worldedit.selection.hpos' + /hpos2: + description: Set position 2 to targeted block + usage: / + permissions: 'worldedit.selection.hpos' + /wand: + description: Get the wand object + usage: / + permissions: 'worldedit.wand' + toggleeditwand: + description: Toggle functionality of the edit wand + usage: / + permissions: 'worldedit.wand.toggle' + /outset: + description: Outset the selection area + usage: / [-hv] + permissions: 'worldedit.selection.outset' + /distr: + description: Get the distribution of blocks in the selection + usage: / [-c] + permissions: 'worldedit.analysis.distr' + /count: + description: Counts the number of a certain type of block + usage: / + permissions: 'worldedit.analysis.count' + /size: + description: Get information about the selection + usage: / + permissions: 'worldedit.selection.size' + /shift: + description: Shift the selection area + usage: / [direction] + permissions: 'worldedit.selection.shift' + /expand: + description: Expand the selection area + usage: / [reverse-amount] + permissions: 'worldedit.selection.expand' + /sel: + description: Choose a region selector + usage: / [type] + aliases: [','] + /inset: + description: Inset the selection area + usage: / [-hv] + permissions: 'worldedit.selection.inset' + snapshot: + description: Snapshot commands + usage: / + aliases: ['snap'] + restore: + description: Restore the selection from a snapshot + usage: / [snapshot] + aliases: ['/restore'] + permissions: 'worldedit.snapshots.restore' + /: + description: Toggle the super pickaxe pickaxe function + usage: / + aliases: [','] + permissions: 'worldedit.superpickaxe' + superpickaxe: + description: Select super pickaxe mode + usage: / + aliases: ['pickaxe', 'sp'] + tool: + description: Select a tool to bind + usage: / + mat: + description: Set the brush material + usage: / [pattern] + aliases: ['material', 'fill'] + permissions: 'worldedit.brush.options.material' + size: + description: Set the brush size + usage: / [pattern] + permissions: 'worldedit.brush.options.size' + mask: + description: Set the brush mask + usage: / [mask] + permissions: 'worldedit.brush.options.mask' + none: + description: Turn off all superpickaxe alternate modes + usage: / + repl: + description: Block replacer tool + usage: / + permissions: 'worldedit.tool.replacer' + cycler: + description: Block data cycler tool + usage: / + permissions: 'worldedit.tool.data-cycler' + brush: + description: Brush tool + usage: / + aliases: ['br'] + deltree: + description: Floating tree remover tool + usage: / + permissions: 'worldedit.tool.deltree' + info: + description: Block information tool + usage: / + permissions: 'worldedit.tool.info' + tree: + description: Tree generator tool + usage: / [type] + permissions: 'worldedit.tool.tree' + /fillr: + description: Fill a hole recursively + usage: / [depth] + permissions: 'worldedit.fill.recursive' + fixlava: + description: Fix lava to be stationary + usage: / + permissions: 'worldedit.fixlava' + fixwater: + description: Fix water to be stationary + usage: / + permissions: 'worldedit.fixwater' + removeabove: + description: Remove blocks above your head. + usage: / [size] [height] + permissions: 'worldedit.removeabove' + removebelow: + description: Remove blocks below your head. + usage: / [size] [height] + permissions: 'worldedit.removebelow' + removenear: + description: Remove blocks near you. + usage: / [size] + permissions: 'worldedit.removenear' + replacenear: + description: Replace nearby blocks + usage: / + permissions: 'worldedit.replacenear' + snow: + description: Simulates snow + usage: / [radius] + permissions: 'worldedit.snow' + thaw: + description: Thaws the area + usage: / [radius] + permissions: 'worldedit.thaw' + ex: + description: Extinguish nearby fire + usage: / [radius] + aliases: ['ext', 'extinguish'] + permissions: 'worldedit.extinguish' + butcher: + description: Kill all or nearby mobs + usage: / [-p] [radius] + permissions: 'worldedit.butcher' + remove: + description: Remove all entities of a type + usage: / + aliases: ['rem', 'rement'] + permissions: 'worldedit.remove' + /fill: + description: Fill a hole + usage: / [depth] + permissions: 'worldedit.fill' + /drain: + description: Drain a pool + usage: / + permissions: 'worldedit.drain' diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index 8ef3a8c83..bdfb200b0 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -87,15 +87,23 @@ public class EditSession { * indicates no limit. */ private int maxBlocks = -1; + /** * Indicates whether some types of blocks should be queued for best * reproduction. */ 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. */ private BlockBag blockBag; + /** * List of missing blocks; */ @@ -185,11 +193,22 @@ public class EditSession { } } } + + boolean result; - boolean result = world.setBlockType(pt, id); + if (fastMode) { + result = world.setBlockTypeFast(pt, id); + } else { + result = world.setBlockType(pt, id); + } + if (id != 0) { - if (BlockType.usesData(id)) { - world.setBlockData(pt, block.getData()); + if (existing != type && block.getData() > 0 && BlockType.usesData(id)) { + if (fastMode) { + world.setBlockDataFast(pt, block.getData()); + } else { + world.setBlockData(pt, block.getData()); + } } // Signs @@ -488,6 +507,24 @@ public class EditSession { } 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. diff --git a/src/main/java/com/sk89q/worldedit/LocalSession.java b/src/main/java/com/sk89q/worldedit/LocalSession.java index 7316dbac9..3effd2c6f 100644 --- a/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -73,6 +73,7 @@ public class LocalSession { private String lastScript; private boolean beenToldVersion = false; private boolean hasCUISupport = false; + private boolean fastMode = false; private TimeZone timezone = TimeZone.getDefault(); /** @@ -144,6 +145,7 @@ public class LocalSession { EditSession newEditSession = new EditSession(editSession.getWorld(), -1, newBlockBag); newEditSession.enableQueue(); + newEditSession.setFastMode(fastMode); editSession.undo(newEditSession); return editSession; } else { @@ -164,6 +166,7 @@ public class LocalSession { EditSession newEditSession = new EditSession(editSession.getWorld(), -1, newBlockBag); newEditSession.enableQueue(); + newEditSession.setFastMode(fastMode); editSession.redo(newEditSession); historyPointer++; return editSession; @@ -642,4 +645,40 @@ public class LocalSession { public boolean hasExpired() { 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; + } } diff --git a/src/main/java/com/sk89q/worldedit/LocalWorld.java b/src/main/java/com/sk89q/worldedit/LocalWorld.java index 77a4a7043..277f18e8a 100644 --- a/src/main/java/com/sk89q/worldedit/LocalWorld.java +++ b/src/main/java/com/sk89q/worldedit/LocalWorld.java @@ -44,6 +44,17 @@ public abstract class LocalWorld { */ 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. * @@ -60,6 +71,16 @@ public abstract class LocalWorld { */ 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. * diff --git a/src/main/java/com/sk89q/worldedit/WorldEdit.java b/src/main/java/com/sk89q/worldedit/WorldEdit.java index 81fe35060..754a67d9f 100644 --- a/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -1010,16 +1010,11 @@ public class WorldEdit { } LocalSession session = getSession(player); - BlockBag blockBag = session.getBlockBag(player); - - session.tellVersion(player); - - // Create an edit session - EditSession editSession = - new EditSession(player.getWorld(), - session.getBlockChangeLimit(), blockBag); + EditSession editSession = session.createEditSession(player); editSession.enableQueue(); + session.tellVersion(player); + long start = System.currentTimeMillis(); try { diff --git a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 1c3700513..dce97468c 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -81,6 +81,18 @@ public class BukkitWorld extends LocalWorld { 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. * @@ -101,7 +113,17 @@ public class BukkitWorld extends LocalWorld { @Override public void setBlockData(Vector pt, int 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); } /** diff --git a/src/main/java/com/sk89q/worldedit/commands/GeneralCommands.java b/src/main/java/com/sk89q/worldedit/commands/GeneralCommands.java index e76742840..8f5ef4ae1 100644 --- a/src/main/java/com/sk89q/worldedit/commands/GeneralCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/GeneralCommands.java @@ -60,6 +60,27 @@ public class GeneralCommands { 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( aliases = {"toggleplace"}, usage = "", diff --git a/src/main/java/com/sk89q/worldedit/tools/AreaPickaxe.java b/src/main/java/com/sk89q/worldedit/tools/AreaPickaxe.java index d31910556..b7c9e0703 100644 --- a/src/main/java/com/sk89q/worldedit/tools/AreaPickaxe.java +++ b/src/main/java/com/sk89q/worldedit/tools/AreaPickaxe.java @@ -56,8 +56,7 @@ public class AreaPickaxe implements BlockTool { return true; } - EditSession editSession = - new EditSession(world, session.getBlockChangeLimit()); + EditSession editSession = session.createEditSession(player); try { for (int x = ox - range; x <= ox + range; x++) { diff --git a/src/main/java/com/sk89q/worldedit/tools/FloatingTreeRemover.java b/src/main/java/com/sk89q/worldedit/tools/FloatingTreeRemover.java index 1ee6fb648..93903f099 100755 --- a/src/main/java/com/sk89q/worldedit/tools/FloatingTreeRemover.java +++ b/src/main/java/com/sk89q/worldedit/tools/FloatingTreeRemover.java @@ -50,9 +50,8 @@ public class FloatingTreeRemover implements BlockTool { int initialType = world.getBlockType(clicked); int block; - - EditSession editSession = - new EditSession(world, session.getBlockChangeLimit()); + + EditSession editSession = session.createEditSession(player); if (initialType != BlockID.LEAVES && initialType != BlockID.LOG) { player.printError("That's not a floating tree."); diff --git a/src/main/java/com/sk89q/worldedit/tools/RecursivePickaxe.java b/src/main/java/com/sk89q/worldedit/tools/RecursivePickaxe.java index 145c80d2b..13c7cb008 100644 --- a/src/main/java/com/sk89q/worldedit/tools/RecursivePickaxe.java +++ b/src/main/java/com/sk89q/worldedit/tools/RecursivePickaxe.java @@ -56,9 +56,8 @@ public class RecursivePickaxe implements BlockTool { if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) { return true; } - - EditSession editSession = - new EditSession(world, session.getBlockChangeLimit()); + + EditSession editSession = session.createEditSession(player); try { recurse(server, editSession, world, clicked.toBlockVector(), diff --git a/src/main/java/com/sk89q/worldedit/tools/TreePlanter.java b/src/main/java/com/sk89q/worldedit/tools/TreePlanter.java index 613c68f0f..4c801aba2 100644 --- a/src/main/java/com/sk89q/worldedit/tools/TreePlanter.java +++ b/src/main/java/com/sk89q/worldedit/tools/TreePlanter.java @@ -41,9 +41,7 @@ public class TreePlanter implements BlockTool { public boolean actPrimary(ServerInterface server, LocalConfiguration config, LocalPlayer player, LocalSession session, WorldVector clicked) { - LocalWorld world = clicked.getWorld(); - EditSession editSession = - new EditSession(world, session.getBlockChangeLimit()); + EditSession editSession = session.createEditSession(player); try { if (!gen.generate(editSession, clicked.add(0, 1, 0))) {