From c8c0c69f6d7e99baaf7f48fb07f546f500739259 Mon Sep 17 00:00:00 2001 From: zml2008 Date: Sat, 24 Dec 2011 22:34:53 -0800 Subject: [PATCH] Added support for dynamic command registration. --- .../bukkit/util/CommandRegistration.java | 96 ++++++ .../util/CommandsManagerRegistration.java | 42 +++ .../bukkit/util/DynamicPluginCommand.java | 47 +++ .../util/FallbackRegistrationListener.java | 18 + .../java/com/sk89q/util/ReflectionUtil.java | 40 +++ .../com/sk89q/worldedit/ServerInterface.java | 6 + .../java/com/sk89q/worldedit/WorldEdit.java | 73 ++-- .../worldedit/bukkit/BukkitCommandSender.java | 29 +- .../bukkit/BukkitServerInterface.java | 21 ++ .../bukkit/WorldEditPlayerListener.java | 10 +- .../worldedit/bukkit/WorldEditPlugin.java | 3 +- src/main/resources/plugin.yml | 322 ------------------ 12 files changed, 335 insertions(+), 372 deletions(-) create mode 100644 src/main/java/com/sk89q/bukkit/util/CommandRegistration.java create mode 100644 src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java create mode 100644 src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java create mode 100644 src/main/java/com/sk89q/util/ReflectionUtil.java diff --git a/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java b/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java new file mode 100644 index 000000000..869cf2450 --- /dev/null +++ b/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java @@ -0,0 +1,96 @@ +/* + * WorldEdit + * Copyright (C) 2011 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.bukkit.util; + +import com.sk89q.minecraft.util.commands.Command; +import com.sk89q.minecraft.util.commands.CommandsManager; +import com.sk89q.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.bukkit.event.Event; +import org.bukkit.plugin.Plugin; + +import java.util.*; + +/** + * @author zml2008 + */ +public class CommandRegistration { + private final Plugin plugin; + private CommandMap fallbackCommands; + + public CommandRegistration(Plugin plugin) { + this.plugin = plugin; + } + + public boolean registerAll(List registered) { + CommandMap commandMap = getCommandMap(); + if (registered == null || commandMap == null) { + return false; + } + for (Command command : registered) { + commandMap.register(plugin.getDescription().getName(), new DynamicPluginCommand(command, plugin)); + } + return true; + } + + private CommandMap getCommandMap() { + CommandMap commandMap = ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap"); + if (commandMap == null) { + if (fallbackCommands != null) { + commandMap = fallbackCommands; + } else { + Bukkit.getServer().getLogger().warning(plugin.getDescription().getName() + + ": Could not retrieve server CommandMap, using fallback instead! Please report to http://redmine.sk89q.com"); + fallbackCommands = commandMap = new SimpleCommandMap(Bukkit.getServer()); + Bukkit.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND_PREPROCESS, + new FallbackRegistrationListener(fallbackCommands), Event.Priority.Normal, plugin); + } + } + return commandMap; + } + + public boolean unregisterCommands() { + CommandMap commandMap = getCommandMap(); + List toRemove = new ArrayList(); + Map knownCommands = ReflectionUtil.getField(commandMap, "knownCommands"); + Set aliases = ReflectionUtil.getField(commandMap, "aliases"); + if (knownCommands == null || aliases == null) { + return false; + } + for (Iterator i = knownCommands.values().iterator(); i.hasNext();) { + org.bukkit.command.Command cmd = i.next(); + if (cmd instanceof DynamicPluginCommand && ((DynamicPluginCommand) cmd).getPlugin().equals(plugin)) { + i.remove(); + for (String alias : cmd.getAliases()) { + org.bukkit.command.Command aliasCmd = knownCommands.get(alias); + if (cmd.equals(aliasCmd)) { + aliases.remove(alias); + toRemove.add(alias); + } + } + } + } + for (String string : toRemove) { + knownCommands.remove(string); + } + return true; + } +} diff --git a/src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java b/src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java new file mode 100644 index 000000000..a74391e95 --- /dev/null +++ b/src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java @@ -0,0 +1,42 @@ +/* + * WorldEdit + * Copyright (C) 2011 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.bukkit.util; + +import com.sk89q.minecraft.util.commands.Command; +import com.sk89q.minecraft.util.commands.CommandsManager; +import org.bukkit.plugin.Plugin; + +import java.util.List; + +/** + * @author zml2008 + */ +public class CommandsManagerRegistration extends CommandRegistration { + protected CommandsManager commands; + + public CommandsManagerRegistration(Plugin plugin, CommandsManager commands) { + super(plugin); + this.commands = commands; + } + + public boolean register(Class clazz) { + List registered = commands.registerAndReturn(clazz); + return registerAll(registered); + } +} diff --git a/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java b/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java new file mode 100644 index 000000000..017e6a6e2 --- /dev/null +++ b/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java @@ -0,0 +1,47 @@ +/* + * WorldEdit + * Copyright (C) 2011 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.bukkit.util; + +import com.sk89q.minecraft.util.commands.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +import java.util.Arrays; + +/** +* @author zml2008 +*/ +public class DynamicPluginCommand extends org.bukkit.command.Command { + + protected final Plugin plugin; + + public DynamicPluginCommand(Command command, Plugin plugin) { + super(command.aliases()[0], command.desc(), command.usage(), Arrays.asList(command.aliases())); + this.plugin = plugin; + } + + @Override + public boolean execute(CommandSender sender, String label, String[] args) { + return plugin.onCommand(sender, this, label, args); + } + + public Plugin getPlugin() { + return plugin; + } +} diff --git a/src/main/java/com/sk89q/bukkit/util/FallbackRegistrationListener.java b/src/main/java/com/sk89q/bukkit/util/FallbackRegistrationListener.java index 4249162c7..14725b172 100644 --- a/src/main/java/com/sk89q/bukkit/util/FallbackRegistrationListener.java +++ b/src/main/java/com/sk89q/bukkit/util/FallbackRegistrationListener.java @@ -1,3 +1,21 @@ +/* + * WorldEdit + * Copyright (C) 2011 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.bukkit.util; import org.bukkit.command.CommandMap; diff --git a/src/main/java/com/sk89q/util/ReflectionUtil.java b/src/main/java/com/sk89q/util/ReflectionUtil.java new file mode 100644 index 000000000..6e1e4b021 --- /dev/null +++ b/src/main/java/com/sk89q/util/ReflectionUtil.java @@ -0,0 +1,40 @@ +/* + * WorldGuard + * Copyright (C) 2011 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.util; + +import java.lang.reflect.Field; + +/** + * @author zml2008 + */ +public class ReflectionUtil { + public static T getField(Object from, String name) { + Class checkClass = from.getClass(); + do { + try { + Field field = checkClass.getDeclaredField(name); + field.setAccessible(true); + return (T) field.get(from); + } catch (NoSuchFieldException e) { + } catch (IllegalAccessException e) { + } + } while (checkClass.getSuperclass() != Object.class && ((checkClass = checkClass.getSuperclass()) != null)); + return null; + } +} diff --git a/src/main/java/com/sk89q/worldedit/ServerInterface.java b/src/main/java/com/sk89q/worldedit/ServerInterface.java index a0dfade76..509dc63a0 100644 --- a/src/main/java/com/sk89q/worldedit/ServerInterface.java +++ b/src/main/java/com/sk89q/worldedit/ServerInterface.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit; +import com.sk89q.minecraft.util.commands.Command; + import java.util.Collections; import java.util.List; @@ -64,4 +66,8 @@ public abstract class ServerInterface { public List getWorlds() { return Collections.emptyList(); } + + public void onCommandRegistration(List commands) { + // Do nothing :) + } } diff --git a/src/main/java/com/sk89q/worldedit/WorldEdit.java b/src/main/java/com/sk89q/worldedit/WorldEdit.java index 174e6c499..696e875ed 100644 --- a/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -176,19 +176,19 @@ public class WorldEdit { commands.setInjector(new SimpleInjector(this)); - commands.register(ChunkCommands.class); - commands.register(ClipboardCommands.class); - commands.register(GeneralCommands.class); - commands.register(GenerationCommands.class); - commands.register(HistoryCommands.class); - commands.register(NavigationCommands.class); - commands.register(RegionCommands.class); - commands.register(ScriptingCommands.class); - commands.register(SelectionCommands.class); - commands.register(SnapshotUtilCommands.class); - commands.register(ToolUtilCommands.class); - commands.register(ToolCommands.class); - commands.register(UtilityCommands.class); + server.onCommandRegistration(commands.registerAndReturn(ChunkCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(ClipboardCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(GeneralCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(GenerationCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(HistoryCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(NavigationCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(RegionCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(ScriptingCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(SelectionCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(SnapshotUtilCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(ToolUtilCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(ToolCommands.class)); + server.onCommandRegistration(commands.registerAndReturn(UtilityCommands.class)); } /** @@ -1222,27 +1222,7 @@ public class WorldEdit { */ public boolean handleCommand(LocalPlayer player, String[] split) { try { - split[0] = split[0].substring(1); - - // Quick script shortcut - if (split[0].matches("^[^/].*\\.js$")) { - String[] newSplit = new String[split.length + 1]; - System.arraycopy(split, 0, newSplit, 1, split.length); - newSplit[0] = "cs"; - newSplit[1] = newSplit[1]; - split = newSplit; - } - - String searchCmd = split[0].toLowerCase(); - - // Try to detect the command - if (commands.hasCommand(searchCmd)) { - } else if (config.noDoubleSlash && commands.hasCommand("/" + searchCmd)) { - split[0] = "/" + split[0]; - } else if (split[0].length() >= 2 && split[0].charAt(0) == '/' - && commands.hasCommand(searchCmd.substring(1))) { - split[0] = split[0].substring(1); - } + split = commandDetection(split); // No command found! if (!commands.hasCommand(split[0])) { @@ -1337,6 +1317,31 @@ public class WorldEdit { return true; } + + public String[] commandDetection(String[] split) { + split[0] = split[0].substring(1); + + // Quick script shortcut + if (split[0].matches("^[^/].*\\.js$")) { + String[] newSplit = new String[split.length + 1]; + System.arraycopy(split, 0, newSplit, 1, split.length); + newSplit[0] = "cs"; + newSplit[1] = newSplit[1]; + split = newSplit; + } + + String searchCmd = split[0].toLowerCase(); + + // Try to detect the command + if (commands.hasCommand(searchCmd)) { + } else if (config.noDoubleSlash && commands.hasCommand("/" + searchCmd)) { + split[0] = "/" + split[0]; + } else if (split[0].length() >= 2 && split[0].charAt(0) == '/' + && commands.hasCommand(searchCmd.substring(1))) { + split[0] = split[0].substring(1); + } + return split; + } /** * Executes a WorldEdit script. diff --git a/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java b/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java index f6a27eaf8..6773bbe1c 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java @@ -1,8 +1,6 @@ package com.sk89q.worldedit.bukkit; -import java.util.logging.Level; - -import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -31,23 +29,30 @@ public class BukkitCommandSender extends LocalPlayer { @Override public void printRaw(String msg) { - System.out.println(msg); - } - - @Override - public void printDebug(String msg) { - Bukkit.getLogger().log(Level.WARNING, msg); - + for (String part : msg.split("\n")) { + sender.sendMessage(part); + } } @Override public void print(String msg) { - Bukkit.getLogger().info(msg); + for (String part : msg.split("\n")) { + sender.sendMessage("\u00A7d" + part); + } + } + + @Override + public void printDebug(String msg) { + for (String part : msg.split("\n")) { + sender.sendMessage("\u00A77" + part); + } } @Override public void printError(String msg) { - Bukkit.getLogger().log(Level.SEVERE, msg); + for (String part : msg.split("\n")) { + sender.sendMessage("\u00A7c" + part); + } } @Override diff --git a/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index ff1edf86f..a132294b4 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -22,18 +22,30 @@ package com.sk89q.worldedit.bukkit; import java.util.ArrayList; import java.util.List; +import com.sk89q.bukkit.util.CommandRegistration; +import com.sk89q.bukkit.util.DynamicPluginCommand; +import com.sk89q.bukkit.util.FallbackRegistrationListener; +import com.sk89q.util.ReflectionUtil; +import com.sk89q.minecraft.util.commands.Command; import org.bukkit.*; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; import org.bukkit.entity.CreatureType; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.ServerInterface; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerListener; public class BukkitServerInterface extends ServerInterface { public Server server; public WorldEditPlugin plugin; + private CommandRegistration dynamicCommands; public BukkitServerInterface(WorldEditPlugin plugin, Server server) { this.plugin = plugin; this.server = server; + dynamicCommands = new CommandRegistration(plugin); } @Override @@ -68,4 +80,13 @@ public class BukkitServerInterface extends ServerInterface { return ret; } + + @Override + public void onCommandRegistration(List commands) { + dynamicCommands.registerAll(commands); + } + + public void unregisterCommands() { + dynamicCommands.unregisterCommands(); + } } diff --git a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java index 3440d4920..9056528a9 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.bukkit; +import com.sk89q.util.StringUtil; import org.bukkit.Bukkit; import org.bukkit.block.Block; import org.bukkit.event.Event; @@ -57,7 +58,7 @@ public class WorldEditPlayerListener extends PlayerListener { plugin.registerEvent("PLAYER_QUIT", this); plugin.registerEvent("PLAYER_INTERACT", this); - plugin.registerEvent("PLAYER_COMMAND_PREPROCESS", this); + plugin.registerEvent("PLAYER_COMMAND_PREPROCESS", this, Event.Priority.Low); } /** @@ -83,9 +84,12 @@ public class WorldEditPlayerListener extends PlayerListener { String[] split = event.getMessage().split(" "); - if (plugin.getWorldEdit().handleCommand(plugin.wrapPlayer(event.getPlayer()), split)) { - event.setCancelled(true); + if (split.length > 0) { + split = plugin.getWorldEdit().commandDetection(split); + split[0] += "/"; } + + event.setMessage(StringUtil.joinString(split, " ")); } private boolean ignoreLeftClickAir = false; diff --git a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index 0e6c1e3a0..7278bdcd6 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -56,7 +56,7 @@ public class WorldEditPlugin extends JavaPlugin { /** * The server interface that all server-related API goes through. */ - private ServerInterface server; + private BukkitServerInterface server; /** * Main WorldEdit instance. */ @@ -121,6 +121,7 @@ public class WorldEditPlugin extends JavaPlugin { } controller.clearSessions(); config.unload(); + server.unregisterCommands(); this.getServer().getScheduler().cancelTasks(this); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index eb1776c50..fd757d4e2 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,328 +1,6 @@ name: WorldEdit main: com.sk89q.worldedit.bukkit.WorldEditPlugin version: ${project.version} -commands: - chunkinfo: - description: Get information about the chunk that you are inside - usage: / - listchunks: - description: List chunks that your selection includes - usage: / - delchunks: - description: Delete chunks that your selection includes - usage: / - /load: - description: Load a schematic into your clipboard - usage: / - /save: - description: Save a schematic into your clipboard - usage: / - /copy: - description: Copy the selection to the clipboard - usage: / - /flip: - description: Flip the contents of the clipboard. - usage: / [-p] [dir] - /rotate: - description: Rotate the contents of the clipboard - usage: / - /cut: - description: Cut the selection to the clipboard - usage: / [leave-id] - /paste: - description: Paste the clipboard's contents - usage: / [-ao] - clearclipboard: - description: Clear your clipboard - usage: / - /limit: - description: Modify block change limit - usage: / - /gmask: - description: Set the global mask - usage: / [mask] - aliases: ['gmask'] - we: - description: WorldEdit commands - usage: / - aliases: ['worldedit'] - /fast: - description: Toggle fast mode - usage: / - /toggleplace: - description: Switch between your position and pos1 for placement - usage: / - aliases: ['toggleplace'] - /searchitem: - description: Search for an item - usage: / [-bi] - aliases: ['/l', '/search', 'searchitem', 'search'] - /hcyl: - description: Generate a hollow cylinder - usage: / [height] - /cyl: - description: Generate a cylinder - usage: / [height] - /hsphere: - description: Generate a hollow sphere. - usage: / [-q] [,,] [raised?] - /sphere: - description: Generate a filled sphere. - usage: / [-q] [,,] [raised?] - forestgen: - description: Generate a forest - usage: / [size] [type] [density] - pumpkins: - description: Generate pumpkin patches - usage: / [size] - /pyramid: - description: Generate a filled pyramid - usage: / - /hpyramid: - description: Generate a hollow pyramid - usage: / - /undo: - description: Undoes the last action - usage: / [times] [player] - aliases: ['undo'] - /redo: - description: Redoes the last action (from history) - usage: / [times] [player] - aliases: ['redo'] - /clearhistory: - description: Clear your history - usage: / - aliases: ['clearhistory'] - unstuck: - description: Escape from being stuck inside a block - usage: / - aliases: ['!'] - ascend: - description: Go up a floor - usage: / [# of levels] - descend: - description: Go down a floor - usage: / [# of floors] - ceil: - description: Go to the celing - usage: / [clearance] - thru: - description: Passthrough walls - usage: / - jumpto: - description: Teleport to a location - usage: / - up: - description: Go upwards some distance - usage: / - /replace: - description: Replace all blocks in the selection with another - usage: / [-f] [from-block] - /stack: - description: Repeat the contents of the selection - usage: / [-sa] [count] [direction] - /set: - description: Set all the blocks inside the selection to a block - usage: / - /overlay: - description: Set a block on top of blocks in the region - usage: / - /naturalize: - description: 3 layers of dirt on top then rock below - usage: / - /walls: - description: Build the four sides of the selection - usage: / - /faces: - description: Build the walls, ceiling, and floor of a selection - usage: / - aliases: ['/outline'] - /smooth: - description: Smooth the elevation in the selection - usage: / [-n] [iterations] - /move: - description: Move the contents of the selection - usage: / [-s] [count] [direction] [leave-id] - /regen: - description: Regenerates the contents of the selection - usage: / - cs: - description: Execute a CraftScript - usage: / [args...] - .s: - description: Execute last CraftScript - usage: / [args...] - /count: - description: Counts the number of a certain type of block - usage: / - /size: - description: Get information about the selection - usage: / - /shift: - description: Shift the selection area - usage: / [direction] - /chunk: - description: Set the selection to your current chunk. - usage: / [-s] - /expand: - description: Expand the selection area - usage: / [reverse-amount] - /contract: - description: Contract the selection area - usage: / [reverse-amount] [direction] - /pos1: - description: Set position 1 - usage: / [coordinates] - /pos2: - description: Set position 2 - usage: / [coordinates] - /hpos1: - description: Set position 1 to targeted block - usage: / - /hpos2: - description: Set position 2 to targeted block - usage: / - /wand: - description: Get the wand object - usage: / - toggleeditwand: - description: Toggle functionality of the edit wand - usage: / - /outset: - description: Outset the selection area - usage: / [-hv] - /inset: - description: Inset the selection area - usage: / [-hv] - /distr: - description: Get the distribution of blocks in the selection - usage: / [-c] - /sel: - description: Choose a region selector - usage: / [type] - aliases: [';'] - snapshot: - description: Snapshot commands - usage: / - aliases: ['snap'] - restore: - description: Restore the selection from a snapshot - usage: / [snapshot] - aliases: ['/restore'] - size: - description: Set the brush size - usage: / [pattern] - mask: - description: Set the brush mask - usage: / [mask] - /: - description: Toggle the super pickaxe pickaxe function - usage: / [on|off] - aliases: [','] - 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'] - range: - description: Set the brush range - usage: / [pattern] - info: - description: Block information tool - usage: / - none: - description: Unbind all bound tools - usage: / - tree: - description: Tree generator tool - usage: / [type] - repl: - description: Block replacer tool - usage: / - cycler: - description: Block data cycler tool - usage: / - floodfill: - description: Flood fill tool - usage: / - aliases: ['flood'] - brush: - description: Brush tool - usage: / - aliases: ['br'] - deltree: - description: Floating tree remover tool - usage: / - farwand: - description: Wand at a distance tool - usage: / - lrbuild: - description: Long-range building tool - usage: / - aliases: ['/lrbuild'] - remove: - description: Remove all entities of a type - usage: / - aliases: ['rem', 'rement'] - /fill: - description: Fill a hole - usage: / [depth] - /fillr: - description: Fill a hole recursively - usage: / [depth] - /drain: - description: Drain a pool - usage: / - /fixlava: - description: Fix lava to be stationary - usage: / - aliases: ['fixlava'] - /fixwater: - description: Fix water to be stationary - usage: / - aliases: ['fixwater'] - /removeabove: - description: Remove blocks above your head. - usage: / [size] [height] - aliases: ['removeabove'] - /removebelow: - description: Remove blocks below you. - usage: / [size] [height] - aliases: ['removebelow'] - /removenear: - description: Remove blocks near you. - usage: / [size] - aliases: ['removenear'] - /replacenear: - description: Replace nearby blocks - usage: / [-f] - aliases: ['replacenear'] - /snow: - description: Simulates snow - usage: / [radius] - aliases: ['snow'] - /thaw: - description: Thaws the area - usage: / [radius] - aliases: ['thaw'] - /green: - description: Greens the area - usage: / [radius] - aliases: ['green'] - /ex: - description: Extinguish nearby fire - usage: / [radius] - aliases: ['/ext', '/extinguish', 'ex', 'ext', 'extinguish'] - butcher: - description: Kill all or nearby mobs - usage: / [-p] [radius] - # Permissions aren't here. Read http://wiki.sk89q.com/wiki/WEPIF/DinnerPerms # for how WorldEdit permissions actually work.