(Breaking) Moved some packages around.

Most of the changes should not break *most* WorldEdit-using plugins,
but implementations of WorldEdit are broken by this change.
This commit is contained in:
sk89q
2014-04-02 19:08:50 -07:00
parent 6e70e8c862
commit 469cb8c8b3
185 changed files with 13303 additions and 13270 deletions

View File

@ -0,0 +1,190 @@
package com.sk89q.worldedit.command;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.masks.BiomeTypeMask;
import com.sk89q.worldedit.masks.InvertedMask;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region;
public class BiomeCommands {
private WorldEdit we;
public BiomeCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "biomelist", "biomels" },
usage = "[page]",
desc = "Gets all biomes available.",
max = 1
)
@CommandPermissions("worldedit.biome.list")
public void biomeList(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int page;
int offset;
int count = 0;
if (args.argsLength() == 0 || (page = args.getInteger(0)) < 2) {
page = 1;
offset = 0;
} else {
offset = (page - 1) * 19;
}
List<BiomeType> biomes = we.getServer().getBiomes().all();
int totalPages = biomes.size() / 19 + 1;
player.print("Available Biomes (page " + page + "/" + totalPages + ") :");
for (BiomeType biome : biomes) {
if (offset > 0) {
offset--;
} else {
player.print(" " + biome.getName());
if (++count == 19) {
break;
}
}
}
}
@Command(
aliases = { "biomeinfo" },
flags = "pt",
desc = "Get the biome of the targeted block.",
help =
"Get the biome of the block.\n" +
"By default use all the blocks contained in your selection.\n" +
"-t use the block you are looking at.\n" +
"-p use the block you are currently in",
max = 0
)
@CommandPermissions("worldedit.biome.info")
public void biomeInfo(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
if (args.hasFlag('t')) {
Vector blockPosition = player.getBlockTrace(300);
if (blockPosition == null) {
player.printError("No block in sight!");
return;
}
BiomeType biome = player.getWorld().getBiome(blockPosition.toVector2D());
player.print("Biome: " + biome.getName());
} else if (args.hasFlag('p')) {
BiomeType biome = player.getWorld().getBiome(player.getPosition().toVector2D());
player.print("Biome: " + biome.getName());
} else {
LocalWorld world = player.getWorld();
Region region = session.getSelection(world);
Set<BiomeType> biomes = new HashSet<BiomeType>();
if (region instanceof FlatRegion) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) {
biomes.add(world.getBiome(pt));
}
} else {
for (Vector pt : region) {
biomes.add(world.getBiome(pt.toVector2D()));
}
}
player.print("Biomes:");
for (BiomeType biome : biomes) {
player.print(" " + biome.getName());
}
}
}
@Command(
aliases = { "/setbiome" },
usage = "<biome>",
flags = "p",
desc = "Sets the biome of the player's current block or region.",
help =
"Set the biome of the region.\n" +
"By default use all the blocks contained in your selection.\n" +
"-p use the block you are currently in",
min = 1,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.biome.set")
public void setBiome(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final BiomeType target = we.getServer().getBiomes().get(args.getString(0));
if (target == null) {
player.printError("Biome '" + args.getString(0) + "' does not exist!");
return;
}
Mask mask = editSession.getMask();
BiomeTypeMask biomeMask = null;
boolean inverted = false;
if (mask instanceof BiomeTypeMask) {
biomeMask = (BiomeTypeMask) mask;
} else if (mask instanceof InvertedMask && ((InvertedMask) mask).getInvertedMask() instanceof BiomeTypeMask) {
inverted = true;
biomeMask = (BiomeTypeMask) ((InvertedMask) mask).getInvertedMask();
}
if (args.hasFlag('p')) {
Vector2D pos = player.getPosition().toVector2D();
if (biomeMask == null || (biomeMask.matches2D(editSession, pos) ^ inverted)) {
player.getWorld().setBiome(pos, target);
player.print("Biome changed to " + target.getName() + " at your current location.");
} else {
player.print("Your global mask doesn't match this biome. Type //gmask to disable it.");
}
} else {
int affected = 0;
LocalWorld world = player.getWorld();
Region region = session.getSelection(world);
if (region instanceof FlatRegion) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) {
if (biomeMask == null || (biomeMask.matches2D(editSession, pt) ^ inverted)) {
world.setBiome(pt, target);
++affected;
}
}
} else {
HashSet<Long> alreadyVisited = new HashSet<Long>();
for (Vector pt : region) {
if (!alreadyVisited.contains((long)pt.getBlockX() << 32 | pt.getBlockZ())) {
alreadyVisited.add(((long)pt.getBlockX() << 32 | pt.getBlockZ()));
if (biomeMask == null || (biomeMask.matches(editSession, pt) ^ inverted)) {
world.setBiome(pt.toVector2D(), target);
++affected;
}
}
}
}
player.print("Biome changed to " + target.getName() + ". " + affected + " columns affected.");
}
}
}

View File

@ -0,0 +1,293 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.command.UtilityCommands.FlagContainer;
import com.sk89q.worldedit.masks.BlockMask;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.brush.ButcherBrush;
import com.sk89q.worldedit.command.tool.brush.ClipboardBrush;
import com.sk89q.worldedit.command.tool.brush.CylinderBrush;
import com.sk89q.worldedit.command.tool.brush.GravityBrush;
import com.sk89q.worldedit.command.tool.brush.HollowCylinderBrush;
import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush;
import com.sk89q.worldedit.command.tool.brush.SmoothBrush;
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
/**
* Brush shape commands.
*
* @author sk89q
*/
public class BrushCommands {
private final WorldEdit we;
public BrushCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "sphere", "s" },
usage = "<block> [radius]",
flags = "h",
desc = "Choose the sphere brush",
help =
"Chooses the sphere brush.\n" +
"The -h flag creates hollow spheres instead.",
min = 1,
max = 2
)
@CommandPermissions("worldedit.brush.sphere")
public void sphereBrush(CommandContext args, LocalSession session,
LocalPlayer player, EditSession editSession) throws WorldEditException {
double radius = args.argsLength() > 1 ? args.getDouble(1) : 2;
we.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
Pattern fill = we.getBlockPattern(player, args.getString(0));
tool.setFill(fill);
tool.setSize(radius);
if (args.hasFlag('h')) {
tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere");
} else {
tool.setBrush(new SphereBrush(), "worldedit.brush.sphere");
}
player.print(String.format("Sphere brush shape equipped (%.0f).",
radius));
}
@Command(
aliases = { "cylinder", "cyl", "c" },
usage = "<block> [radius] [height]",
flags = "h",
desc = "Choose the cylinder brush",
help =
"Chooses the cylinder brush.\n" +
"The -h flag creates hollow cylinders instead.",
min = 1,
max = 3
)
@CommandPermissions("worldedit.brush.cylinder")
public void cylinderBrush(CommandContext args, LocalSession session,
LocalPlayer player, EditSession editSession) throws WorldEditException {
double radius = args.argsLength() > 1 ? args.getDouble(1) : 2;
we.checkMaxBrushRadius(radius);
int height = args.argsLength() > 2 ? args.getInteger(2) : 1;
we.checkMaxBrushRadius(height);
BrushTool tool = session.getBrushTool(player.getItemInHand());
Pattern fill = we.getBlockPattern(player, args.getString(0));
tool.setFill(fill);
tool.setSize(radius);
if (args.hasFlag('h')) {
tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder");
} else {
tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder");
}
player.print(String.format("Cylinder brush shape equipped (%.0f by %d).",
radius, height));
}
@Command(
aliases = { "clipboard", "copy" },
usage = "",
flags = "a",
desc = "Choose the clipboard brush",
help =
"Chooses the clipboard brush.\n" +
"The -a flag makes it not paste air.",
min = 0,
max = 0
)
@CommandPermissions("worldedit.brush.clipboard")
public void clipboardBrush(CommandContext args, LocalSession session,
LocalPlayer player, EditSession editSession) throws WorldEditException {
CuboidClipboard clipboard = session.getClipboard();
if (clipboard == null) {
player.printError("Copy something first.");
return;
}
Vector size = clipboard.getSize();
we.checkMaxBrushRadius(size.getBlockX());
we.checkMaxBrushRadius(size.getBlockY());
we.checkMaxBrushRadius(size.getBlockZ());
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setBrush(new ClipboardBrush(clipboard, args.hasFlag('a')), "worldedit.brush.clipboard");
player.print("Clipboard brush shape equipped.");
}
@Command(
aliases = { "smooth" },
usage = "[size] [iterations]",
flags = "n",
desc = "Choose the terrain softener brush",
help =
"Chooses the terrain softener brush.\n" +
"The -n flag makes it only consider naturally occuring blocks.",
min = 0,
max = 2
)
@CommandPermissions("worldedit.brush.smooth")
public void smoothBrush(CommandContext args, LocalSession session,
LocalPlayer player, EditSession editSession) throws WorldEditException {
double radius = args.argsLength() > 0 ? args.getDouble(0) : 2;
we.checkMaxBrushRadius(radius);
int iterations = args.argsLength() > 1 ? args.getInteger(1) : 4;
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new SmoothBrush(iterations, args.hasFlag('n')), "worldedit.brush.smooth");
player.print(String.format("Smooth brush equipped (%.0f x %dx, using " + (args.hasFlag('n') ? "natural blocks only" : "any block") + ").",
radius, iterations));
}
@Command(
aliases = { "ex", "extinguish" },
usage = "[radius]",
desc = "Shortcut fire extinguisher brush",
min = 0,
max = 1
)
@CommandPermissions("worldedit.brush.ex")
public void extinguishBrush(CommandContext args, LocalSession session,
LocalPlayer player, EditSession editSession) throws WorldEditException {
double radius = args.argsLength() > 1 ? args.getDouble(1) : 5;
we.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
Pattern fill = new SingleBlockPattern(new BaseBlock(0));
tool.setFill(fill);
tool.setSize(radius);
tool.setMask(new BlockMask(new BaseBlock(BlockID.FIRE)));
tool.setBrush(new SphereBrush(), "worldedit.brush.ex");
player.print(String.format("Extinguisher equipped (%.0f).",
radius));
}
@Command(
aliases = { "gravity", "grav" },
usage = "[radius]",
flags = "h",
desc = "Gravity brush",
help =
"This brush simulates the affect of gravity.\n" +
"The -h flag makes it affect blocks starting at the world's max y, " +
"instead of the clicked block's y + radius.",
min = 0,
max = 1
)
@CommandPermissions("worldedit.brush.gravity")
public void gravityBrush(CommandContext args, LocalSession session,
LocalPlayer player, EditSession editSession) throws WorldEditException {
double radius = args.argsLength() > 0 ? args.getDouble(0) : 5;
we.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new GravityBrush(args.hasFlag('h')), "worldedit.brush.gravity");
player.print(String.format("Gravity brush equipped (%.0f).",
radius));
}
@Command(
aliases = { "butcher", "kill" },
usage = "[radius] [command flags]",
desc = "Butcher brush",
help = "Kills nearby mobs within the specified radius.\n" +
"Any number of 'flags' that the //butcher command uses\n" +
"may be specified as an argument",
min = 0,
max = 2
)
@CommandPermissions("worldedit.brush.butcher")
public void butcherBrush(CommandContext args, LocalSession session,
LocalPlayer player, EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
double radius = args.argsLength() > 0 ? args.getDouble(0) : 5;
double maxRadius = config.maxBrushRadius;
// hmmmm not horribly worried about this because -1 is still rather efficient,
// the problem arises when butcherMaxRadius is some really high number but not infinite
// - original idea taken from https://github.com/sk89q/worldedit/pull/198#issuecomment-6463108
if (player.hasPermission("worldedit.butcher")) {
maxRadius = Math.max(config.maxBrushRadius, config.butcherMaxRadius);
}
if (radius > maxRadius) {
player.printError("Maximum allowed brush radius: " + maxRadius);
return;
}
FlagContainer flags = new FlagContainer(player);
if (args.argsLength() == 2) {
String flagString = args.getString(1);
// straight from the command, using contains instead of hasflag
flags.or(KillFlags.FRIENDLY , flagString.contains("f")); // No permission check here. Flags will instead be filtered by the subsequent calls.
flags.or(KillFlags.PETS , flagString.contains("p"), "worldedit.butcher.pets");
flags.or(KillFlags.NPCS , flagString.contains("n"), "worldedit.butcher.npcs");
flags.or(KillFlags.GOLEMS , flagString.contains("g"), "worldedit.butcher.golems");
flags.or(KillFlags.ANIMALS , flagString.contains("a"), "worldedit.butcher.animals");
flags.or(KillFlags.AMBIENT , flagString.contains("b"), "worldedit.butcher.ambient");
flags.or(KillFlags.WITH_LIGHTNING, flagString.contains("l"), "worldedit.butcher.lightning");
}
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new ButcherBrush(flags.flags), "worldedit.brush.butcher");
player.print(String.format("Butcher brush equipped (%.0f).",
radius));
}
}

View File

@ -0,0 +1,179 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Set;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.world.storage.LegacyChunkStore;
import com.sk89q.worldedit.world.storage.McRegionChunkStore;
/**
* Chunk tools.
*
* @author sk89q
*/
public class ChunkCommands {
private final WorldEdit we;
public ChunkCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "chunkinfo" },
usage = "",
desc = "Get information about the chunk that you are inside",
min = 0,
max = 0
)
@CommandPermissions("worldedit.chunkinfo")
public void chunkInfo(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Vector pos = player.getBlockIn();
int chunkX = (int) Math.floor(pos.getBlockX() / 16.0);
int chunkZ = (int) Math.floor(pos.getBlockZ() / 16.0);
String folder1 = Integer.toString(WorldEdit.divisorMod(chunkX, 64), 36);
String folder2 = Integer.toString(WorldEdit.divisorMod(chunkZ, 64), 36);
String filename = "c." + Integer.toString(chunkX, 36)
+ "." + Integer.toString(chunkZ, 36) + ".dat";
player.print("Chunk: " + chunkX + ", " + chunkZ);
player.print("Old format: " + folder1 + "/" + folder2 + "/" + filename);
player.print("McRegion: region/" + McRegionChunkStore.getFilename(
new Vector2D(chunkX, chunkZ)));
}
@Command(
aliases = { "listchunks" },
usage = "",
desc = "List chunks that your selection includes",
min = 0,
max = 0
)
@CommandPermissions("worldedit.listchunks")
public void listChunks(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
for (Vector2D chunk : chunks) {
player.print(LegacyChunkStore.getFilename(chunk));
}
}
@Command(
aliases = { "delchunks" },
usage = "",
desc = "Delete chunks that your selection includes",
min = 0,
max = 0
)
@CommandPermissions("worldedit.delchunks")
@Logging(REGION)
public void deleteChunks(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
player.print("Note that this command does not yet support the mcregion format.");
LocalConfiguration config = we.getConfiguration();
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
FileOutputStream out = null;
if (config.shellSaveType == null) {
player.printError("Shell script type must be configured: 'bat' or 'bash' expected.");
} else if (config.shellSaveType.equalsIgnoreCase("bat")) {
try {
out = new FileOutputStream("worldedit-delchunks.bat");
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
writer.write("@ECHO off\r\n");
writer.write("ECHO This batch file was generated by WorldEdit.\r\n");
writer.write("ECHO It contains a list of chunks that were in the selected region\r\n");
writer.write("ECHO at the time that the /delchunks command was used. Run this file\r\n");
writer.write("ECHO in order to delete the chunk files listed in this file.\r\n");
writer.write("ECHO.\r\n");
writer.write("PAUSE\r\n");
for (Vector2D chunk : chunks) {
String filename = LegacyChunkStore.getFilename(chunk);
writer.write("ECHO " + filename + "\r\n");
writer.write("DEL \"world/" + filename + "\"\r\n");
}
writer.write("ECHO Complete.\r\n");
writer.write("PAUSE\r\n");
writer.close();
player.print("worldedit-delchunks.bat written. Run it when no one is near the region.");
} catch (IOException e) {
player.printError("Error occurred: " + e.getMessage());
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ie) { }
}
}
} else if (config.shellSaveType.equalsIgnoreCase("bash")) {
try {
out = new FileOutputStream("worldedit-delchunks.sh");
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
writer.write("#!/bin/bash\n");
writer.write("echo This shell file was generated by WorldEdit.\n");
writer.write("echo It contains a list of chunks that were in the selected region\n");
writer.write("echo at the time that the /delchunks command was used. Run this file\n");
writer.write("echo in order to delete the chunk files listed in this file.\n");
writer.write("echo\n");
writer.write("read -p \"Press any key to continue...\"\n");
for (Vector2D chunk : chunks) {
String filename = LegacyChunkStore.getFilename(chunk);
writer.write("echo " + filename + "\n");
writer.write("rm \"world/" + filename + "\"\n");
}
writer.write("echo Complete.\n");
writer.write("read -p \"Press any key to continue...\"\n");
writer.close();
player.print("worldedit-delchunks.sh written. Run it when no one is near the region.");
player.print("You will have to chmod it to be executable.");
} catch (IOException e) {
player.printError("Error occurred: " + e.getMessage());
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ie) {
}
}
}
} else {
player.printError("Shell script type must be configured: 'bat' or 'bash' expected.");
}
}
}

View File

@ -0,0 +1,286 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CuboidRegionSelector;
import com.sk89q.worldedit.regions.Region;
/**
* Clipboard commands.
*
* @author sk89q
*/
public class ClipboardCommands {
private final WorldEdit we;
public ClipboardCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/copy" },
flags = "e",
desc = "Copy the selection to the clipboard",
help = "Copy the selection to the clipboard\n" +
"Flags:\n" +
" -e controls whether entities are copied\n" +
"WARNING: Pasting entities cannot yet be undone!",
min = 0,
max = 0
)
@CommandPermissions("worldedit.clipboard.copy")
public void copy(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
Vector pos = session.getPlacementPosition(player);
CuboidClipboard clipboard = new CuboidClipboard(
max.subtract(min).add(Vector.ONE),
min, min.subtract(pos));
if (region instanceof CuboidRegion) {
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
}
if (args.hasFlag('e')) {
for (LocalEntity entity : player.getWorld().getEntities(region)) {
clipboard.storeEntity(entity);
}
}
session.setClipboard(clipboard);
player.print("Block(s) copied.");
}
@Command(
aliases = { "/cut" },
usage = "[leave-id]",
desc = "Cut the selection to the clipboard",
help = "Copy the selection to the clipboard\n" +
"Flags:\n" +
" -e controls whether entities are copied\n" +
"WARNING: Cutting and pasting entities cannot yet be undone!",
flags = "e",
min = 0,
max = 1
)
@CommandPermissions("worldedit.clipboard.cut")
@Logging(REGION)
public void cut(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
BaseBlock block = new BaseBlock(BlockID.AIR);
LocalWorld world = player.getWorld();
if (args.argsLength() > 0) {
block = we.getBlock(player, args.getString(0));
}
Region region = session.getSelection(world);
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
Vector pos = session.getPlacementPosition(player);
CuboidClipboard clipboard = new CuboidClipboard(
max.subtract(min).add(Vector.ONE),
min, min.subtract(pos));
if (region instanceof CuboidRegion) {
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
}
if (args.hasFlag('e')) {
LocalEntity[] entities = world.getEntities(region);
for (LocalEntity entity : entities) {
clipboard.storeEntity(entity);
}
world.killEntities(entities);
}
session.setClipboard(clipboard);
editSession.setBlocks(region, block);
player.print("Block(s) cut.");
}
@Command(
aliases = { "/paste" },
usage = "",
flags = "sao",
desc = "Paste the clipboard's contents",
help =
"Pastes the clipboard's contents.\n" +
"Flags:\n" +
" -a skips air blocks\n" +
" -o pastes at the original position\n" +
" -s selects the region after pasting",
min = 0,
max = 0
)
@CommandPermissions("worldedit.clipboard.paste")
@Logging(PLACEMENT)
public void paste(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
boolean atOrigin = args.hasFlag('o');
boolean pasteNoAir = args.hasFlag('a');
CuboidClipboard clipboard = session.getClipboard();
Vector pos = atOrigin ? session.getClipboard().getOrigin()
: session.getPlacementPosition(player);
if (atOrigin) {
clipboard.place(editSession, pos, pasteNoAir);
clipboard.pasteEntities(pos);
player.findFreePosition();
player.print("Pasted to copy origin. Undo with //undo");
} else {
clipboard.paste(editSession, pos, pasteNoAir, true);
player.findFreePosition();
player.print("Pasted relative to you. Undo with //undo");
}
if (args.hasFlag('s')) {
LocalWorld world = player.getWorld();
Vector pos2 = pos.add(clipboard.getSize().subtract(1, 1, 1));
if (!atOrigin) {
pos2 = pos2.add(clipboard.getOffset());
pos = pos.add(clipboard.getOffset());
}
session.setRegionSelector(world, new CuboidRegionSelector(world, pos, pos2));
session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(player, session);
}
}
@Command(
aliases = { "/rotate" },
usage = "<angle-in-degrees>",
desc = "Rotate the contents of the clipboard",
min = 1,
max = 1
)
@CommandPermissions("worldedit.clipboard.rotate")
public void rotate(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int angle = args.getInteger(0);
if (angle % 90 == 0) {
CuboidClipboard clipboard = session.getClipboard();
clipboard.rotate2D(angle);
player.print("Clipboard rotated by " + angle + " degrees.");
} else {
player.printError("Angles must be divisible by 90 degrees.");
}
}
@Command(
aliases = { "/flip" },
usage = "[dir]",
flags = "p",
desc = "Flip the contents of the clipboard.",
help =
"Flips the contents of the clipboard.\n" +
"The -p flag flips the selection around the player,\n" +
"instead of the selections center.",
min = 0,
max = 1
)
@CommandPermissions("worldedit.clipboard.flip")
public void flip(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
CuboidClipboard.FlipDirection dir = we.getFlipDirection(player,
args.argsLength() > 0 ? args.getString(0).toLowerCase() : "me");
CuboidClipboard clipboard = session.getClipboard();
clipboard.flip(dir, args.hasFlag('p'));
player.print("Clipboard flipped.");
}
@Command(
aliases = { "/load" },
usage = "<filename>",
desc = "Load a schematic into your clipboard",
min = 0,
max = 1
)
@Deprecated
@CommandPermissions("worldedit.clipboard.load")
public void load(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
player.printError("This command is no longer used. See //schematic load.");
}
@Command(
aliases = { "/save" },
usage = "<filename>",
desc = "Save a schematic into your clipboard",
min = 0,
max = 1
)
@Deprecated
@CommandPermissions("worldedit.clipboard.save")
public void save(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
player.printError("This command is no longer used. See //schematic save.");
}
@Command(
aliases = { "/schematic", "/schem"},
desc = "Schematic-related commands"
)
@NestedCommand(SchematicCommands.class)
public void schematic() {}
@Command(
aliases = { "clearclipboard" },
usage = "",
desc = "Clear your clipboard",
min = 0,
max = 0
)
@CommandPermissions("worldedit.clipboard.clear")
public void clearClipboard(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setClipboard(null);
player.print("Clipboard cleared.");
}
}

View File

@ -0,0 +1,234 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Console;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldedit.masks.Mask;
/**
* General WorldEdit commands.
*
* @author sk89q
*/
public class GeneralCommands {
private final WorldEdit we;
public GeneralCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/limit" },
usage = "<limit>",
desc = "Modify block change limit",
min = 1,
max = 1
)
@CommandPermissions("worldedit.limit")
public void limit(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
int limit = Math.max(-1, args.getInteger(0));
if (!player.hasPermission("worldedit.limit.unrestricted")
&& config.maxChangeLimit > -1) {
if (limit > config.maxChangeLimit) {
player.printError("Your maximum allowable limit is "
+ config.maxChangeLimit + ".");
return;
}
}
session.setBlockChangeLimit(limit);
player.print("Block change limit set to " + limit + ".");
}
@Command(
aliases = { "/fast" },
usage = "[on|off]",
desc = "Toggle fast mode",
min = 0,
max = 1
)
@CommandPermissions("worldedit.fast")
public void fast(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
String newState = args.getString(0, null);
if (session.hasFastMode()) {
if ("on".equals(newState)) {
player.printError("Fast mode already enabled.");
return;
}
session.setFastMode(false);
player.print("Fast mode disabled.");
} else {
if ("off".equals(newState)) {
player.printError("Fast mode already disabled.");
return;
}
session.setFastMode(true);
player.print("Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.");
}
}
@Command(
aliases = { "/gmask", "gmask" },
usage = "[mask]",
desc = "Set the global mask",
min = 0,
max = -1
)
@CommandPermissions("worldedit.global-mask")
public void gmask(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
if (args.argsLength() == 0) {
session.setMask(null);
player.print("Global mask disabled.");
} else {
Mask mask = we.getBlockMask(player, session, args.getJoinedStrings(0));
session.setMask(mask);
player.print("Global mask set.");
}
}
@Command(
aliases = { "/toggleplace", "toggleplace" },
usage = "",
desc = "Switch between your position and pos1 for placement",
min = 0,
max = 0
)
public void togglePlace(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
if (session.togglePlacementPosition()) {
player.print("Now placing at pos #1.");
} else {
player.print("Now placing at the block you stand in.");
}
}
@Command(
aliases = { "/searchitem", "/l", "/search", "searchitem" },
usage = "<query>",
flags = "bi",
desc = "Search for an item",
help =
"Searches for an item.\n" +
"Flags:\n" +
" -b only search for blocks\n" +
" -i only search for items",
min = 1,
max = 1
)
@Console
public void searchItem(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
String query = args.getString(0).trim().toLowerCase();
boolean blocksOnly = args.hasFlag('b');
boolean itemsOnly = args.hasFlag('i');
try {
int id = Integer.parseInt(query);
ItemType type = ItemType.fromID(id);
if (type != null) {
player.print("#" + type.getID() + " (" + type.getName() + ")");
} else {
player.printError("No item found by ID " + id);
}
return;
} catch (NumberFormatException e) {
}
if (query.length() <= 2) {
player.printError("Enter a longer search string (len > 2).");
return;
}
if (!blocksOnly && !itemsOnly) {
player.print("Searching for: " + query);
} else if (blocksOnly && itemsOnly) {
player.printError("You cannot use both the 'b' and 'i' flags simultaneously.");
return;
} else if (blocksOnly) {
player.print("Searching for blocks: " + query);
} else {
player.print("Searching for items: " + query);
}
int found = 0;
for (ItemType type : ItemType.values()) {
if (found >= 15) {
player.print("Too many results!");
break;
}
if (blocksOnly && type.getID() > 255) {
continue;
}
if (itemsOnly && type.getID() <= 255) {
continue;
}
for (String alias : type.getAliases()) {
if (alias.contains(query)) {
player.print("#" + type.getID() + " (" + type.getName() + ")");
++found;
break;
}
}
}
if (found == 0) {
player.printError("No items found.");
}
}
@Command(
aliases = { "we", "worldedit" },
desc = "WorldEdit commands"
)
@NestedCommand(WorldEditCommands.class)
@Console
public void we(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
}

View File

@ -0,0 +1,486 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator;
/**
* Generation commands.
*
* @author sk89q
*/
public class GenerationCommands {
private final WorldEdit we;
public GenerationCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/hcyl" },
usage = "<block> <radius>[,<radius>] [height]",
desc = "Generates a hollow cylinder.",
help =
"Generates a hollow cylinder.\n" +
"By specifying 2 radii, separated by a comma,\n" +
"you can generate elliptical cylinders.\n" +
"The 1st radius is north/south, the 2nd radius is east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.cylinder")
@Logging(PLACEMENT)
public void hcyl(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0));
String[] radiuses = args.getString(1).split(",");
final double radiusX, radiusZ;
switch (radiuses.length) {
case 1:
radiusX = radiusZ = Math.max(1, Double.parseDouble(radiuses[0]));
break;
case 2:
radiusX = Math.max(1, Double.parseDouble(radiuses[0]));
radiusZ = Math.max(1, Double.parseDouble(radiuses[1]));
break;
default:
player.printError("You must either specify 1 or 2 radius values.");
return;
}
int height = args.argsLength() > 2 ? args.getInteger(2) : 1;
we.checkMaxRadius(radiusX);
we.checkMaxRadius(radiusZ);
we.checkMaxRadius(height);
Vector pos = session.getPlacementPosition(player);
int affected = editSession.makeCylinder(pos, block, radiusX, radiusZ, height, false);
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/cyl" },
usage = "<block> <radius>[,<radius>] [height]",
desc = "Generates a cylinder.",
help =
"Generates a cylinder.\n" +
"By specifying 2 radii, separated by a comma,\n" +
"you can generate elliptical cylinders.\n" +
"The 1st radius is north/south, the 2nd radius is east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.cylinder")
@Logging(PLACEMENT)
public void cyl(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0));
String[] radiuses = args.getString(1).split(",");
final double radiusX, radiusZ;
switch (radiuses.length) {
case 1:
radiusX = radiusZ = Math.max(1, Double.parseDouble(radiuses[0]));
break;
case 2:
radiusX = Math.max(1, Double.parseDouble(radiuses[0]));
radiusZ = Math.max(1, Double.parseDouble(radiuses[1]));
break;
default:
player.printError("You must either specify 1 or 2 radius values.");
return;
}
int height = args.argsLength() > 2 ? args.getInteger(2) : 1;
we.checkMaxRadius(radiusX);
we.checkMaxRadius(radiusZ);
we.checkMaxRadius(height);
Vector pos = session.getPlacementPosition(player);
int affected = editSession.makeCylinder(pos, block, radiusX, radiusZ, height, true);
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/hsphere" },
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
desc = "Generates a hollow sphere.",
help =
"Generates a hollow sphere.\n" +
"By specifying 3 radii, separated by commas,\n" +
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
"is north/south, up/down, east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.sphere")
@Logging(PLACEMENT)
public void hsphere(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final Pattern block = we.getBlockPattern(player, args.getString(0));
String[] radiuses = args.getString(1).split(",");
final double radiusX, radiusY, radiusZ;
switch (radiuses.length) {
case 1:
radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radiuses[0]));
break;
case 3:
radiusX = Math.max(1, Double.parseDouble(radiuses[0]));
radiusY = Math.max(1, Double.parseDouble(radiuses[1]));
radiusZ = Math.max(1, Double.parseDouble(radiuses[2]));
break;
default:
player.printError("You must either specify 1 or 3 radius values.");
return;
}
we.checkMaxRadius(radiusX);
we.checkMaxRadius(radiusY);
we.checkMaxRadius(radiusZ);
final boolean raised;
if (args.argsLength() > 2) {
raised = args.getString(2).equalsIgnoreCase("true") || args.getString(2).equalsIgnoreCase("yes");
} else {
raised = false;
}
Vector pos = session.getPlacementPosition(player);
if (raised) {
pos = pos.add(0, radiusY, 0);
}
int affected = editSession.makeSphere(pos, block, radiusX, radiusY, radiusZ, false);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/sphere" },
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
desc = "Generates a filled sphere.",
help =
"Generates a filled sphere.\n" +
"By specifying 3 radii, separated by commas,\n" +
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
"is north/south, up/down, east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.sphere")
@Logging(PLACEMENT)
public void sphere(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0));
String[] radiuses = args.getString(1).split(",");
final double radiusX, radiusY, radiusZ;
switch (radiuses.length) {
case 1:
radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radiuses[0]));
break;
case 3:
radiusX = Math.max(1, Double.parseDouble(radiuses[0]));
radiusY = Math.max(1, Double.parseDouble(radiuses[1]));
radiusZ = Math.max(1, Double.parseDouble(radiuses[2]));
break;
default:
player.printError("You must either specify 1 or 3 radius values.");
return;
}
we.checkMaxRadius(radiusX);
we.checkMaxRadius(radiusY);
we.checkMaxRadius(radiusZ);
final boolean raised;
if (args.argsLength() > 2) {
raised = args.getString(2).equalsIgnoreCase("true") || args.getString(2).equalsIgnoreCase("yes");
} else {
raised = false;
}
Vector pos = session.getPlacementPosition(player);
if (raised) {
pos = pos.add(0, radiusY, 0);
}
int affected = editSession.makeSphere(pos, block, radiusX, radiusY, radiusZ, true);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "forestgen" },
usage = "[size] [type] [density]",
desc = "Generate a forest",
min = 0,
max = 3
)
@CommandPermissions("worldedit.generation.forest")
@Logging(POSITION)
@SuppressWarnings("deprecation")
public void forestGen(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 10;
TreeGenerator.TreeType type = args.argsLength() > 1 ?
TreeGenerator.lookup(args.getString(1))
: TreeGenerator.TreeType.TREE;
double density = args.argsLength() > 2 ? args.getDouble(2) / 100 : 0.05;
if (type == null) {
player.printError("Tree type '" + args.getString(1) + "' is unknown.");
return;
}
int affected = editSession.makeForest(session.getPlacementPosition(player),
size, density, new TreeGenerator(type));
player.print(affected + " trees created.");
}
@Command(
aliases = { "pumpkins" },
usage = "[size]",
desc = "Generate pumpkin patches",
min = 0,
max = 1
)
@CommandPermissions("worldedit.generation.pumpkins")
@Logging(POSITION)
public void pumpkins(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 10;
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), size);
player.print(affected + " pumpkin patches created.");
}
@Command(
aliases = { "/pyramid" },
usage = "<block> <size>",
desc = "Generate a filled pyramid",
min = 2,
max = 2
)
@CommandPermissions("worldedit.generation.pyramid")
@Logging(PLACEMENT)
public void pyramid(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0));
int size = Math.max(1, args.getInteger(1));
Vector pos = session.getPlacementPosition(player);
we.checkMaxRadius(size);
int affected = editSession.makePyramid(pos, block, size, true);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/hpyramid" },
usage = "<block> <size>",
desc = "Generate a hollow pyramid",
min = 2,
max = 2
)
@CommandPermissions("worldedit.generation.pyramid")
@Logging(PLACEMENT)
public void hpyramid(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0));
int size = Math.max(1, args.getInteger(1));
Vector pos = session.getPlacementPosition(player);
we.checkMaxRadius(size);
int affected = editSession.makePyramid(pos, block, size, false);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/generate", "/gen", "/g" },
usage = "<block> <expression>",
desc = "Generates a shape according to a formula.",
help =
"Generates a shape according to a formula that is expected to\n" +
"return positive numbers (true) if the point is inside the shape\n" +
"Optionally set type/data to the desired block.\n" +
"Flags:\n" +
" -h to generate a hollow shape\n" +
" -r to use raw minecraft coordinates\n" +
" -o is like -r, except offset from placement.\n" +
" -c is like -r, except offset selection center.\n" +
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
"See also tinyurl.com/wesyntax.",
flags = "hroc",
min = 2,
max = -1
)
@CommandPermissions("worldedit.generation.shape")
@Logging(ALL)
public void generate(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final Pattern pattern = we.getBlockPattern(player, args.getString(0));
final Region region = session.getSelection(player.getWorld());
final boolean hollow = args.hasFlag('h');
final String expression = args.getJoinedStrings(1);
final Vector zero;
Vector unit;
if (args.hasFlag('r')) {
zero = Vector.ZERO;
unit = Vector.ONE;
} else if (args.hasFlag('o')) {
zero = session.getPlacementPosition(player);
unit = Vector.ONE;
} else if (args.hasFlag('c')) {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = Vector.ONE;
} else {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);
if (unit.getX() == 0) unit = unit.setX(1.0);
if (unit.getY() == 0) unit = unit.setY(1.0);
if (unit.getZ() == 0) unit = unit.setZ(1.0);
}
try {
final int affected = editSession.makeShape(region, zero, unit, pattern, expression, hollow);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
} catch (ExpressionException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/generatebiome", "/genbiome", "/gb" },
usage = "<block> <expression>",
desc = "Sets biome according to a formula.",
help =
"Generates a shape according to a formula that is expected to\n" +
"return positive numbers (true) if the point is inside the shape\n" +
"Optionally set type/data to the desired block.\n" +
"Flags:\n" +
" -h to generate a hollow shape\n" +
" -r to use raw minecraft coordinates\n" +
" -o is like -r, except offset from placement.\n" +
" -c is like -r, except offset selection center.\n" +
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
"See also tinyurl.com/wesyntax.",
flags = "hroc",
min = 2,
max = -1
)
@CommandPermissions({"worldedit.generation.shape", "worldedit.biome.set"})
@Logging(ALL)
public void generateBiome(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final BiomeType target = we.getServer().getBiomes().get(args.getString(0));
final Region region = session.getSelection(player.getWorld());
final boolean hollow = args.hasFlag('h');
final String expression = args.getJoinedStrings(1);
final Vector zero;
Vector unit;
if (args.hasFlag('r')) {
zero = Vector.ZERO;
unit = Vector.ONE;
} else if (args.hasFlag('o')) {
zero = session.getPlacementPosition(player);
unit = Vector.ONE;
} else if (args.hasFlag('c')) {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = Vector.ONE;
} else {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);
if (unit.getX() == 0) unit = unit.setX(1.0);
if (unit.getY() == 0) unit = unit.setY(1.0);
if (unit.getZ() == 0) unit = unit.setZ(1.0);
}
try {
final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow);
player.findFreePosition();
player.print("Biome changed to " + target.getName() + ". " + affected + " columns affected.");
} catch (ExpressionException e) {
player.printError(e.getMessage());
}
}
}

View File

@ -0,0 +1,123 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*;
/**
* History little commands.
*
* @author sk89q
*/
public class HistoryCommands {
private final WorldEdit we;
public HistoryCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/undo", "undo" },
usage = "[times] [player]",
desc = "Undoes the last action",
min = 0,
max = 2
)
@CommandPermissions("worldedit.history.undo")
public void undo(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int times = Math.max(1, args.getInteger(0, 1));
for (int i = 0; i < times; ++i) {
EditSession undone;
if (args.argsLength() < 2) {
undone = session.undo(session.getBlockBag(player), player);
} else {
player.checkPermission("worldedit.history.undo.other");
LocalSession sess = we.getSession(args.getString(1));
if (sess == null) {
player.printError("Unable to find session for " + args.getString(1));
break;
}
undone = sess.undo(session.getBlockBag(player), player);
}
if (undone != null) {
player.print("Undo successful.");
we.flushBlockBag(player, undone);
} else {
player.printError("Nothing left to undo.");
break;
}
}
}
@Command(
aliases = { "/redo", "redo" },
usage = "[times] [player]",
desc = "Redoes the last action (from history)",
min = 0,
max = 2
)
@CommandPermissions("worldedit.history.redo")
public void redo(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int times = Math.max(1, args.getInteger(0, 1));
for (int i = 0; i < times; ++i) {
EditSession redone;
if (args.argsLength() < 2) {
redone = session.redo(session.getBlockBag(player), player);
} else {
player.checkPermission("worldedit.history.redo.other");
LocalSession sess = we.getSession(args.getString(1));
if (sess == null) {
player.printError("Unable to find session for " + args.getString(1));
break;
}
redone = sess.redo(session.getBlockBag(player), player);
}
if (redone != null) {
player.print("Redo successful.");
we.flushBlockBag(player, redone);
} else {
player.printError("Nothing left to redo.");
}
}
}
@Command(
aliases = { "/clearhistory", "clearhistory" },
usage = "",
desc = "Clear your history",
min = 0,
max = 0
)
@CommandPermissions("worldedit.history.clear")
public void clearHistory(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.clearHistory();
player.print("History cleared.");
}
}

View File

@ -0,0 +1,34 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.worldedit.WorldEditException;
/**
*
* @author sk89q
*/
public class InsufficientArgumentsException extends WorldEditException {
private static final long serialVersionUID = 995264804658899764L;
public InsufficientArgumentsException(String error) {
super(error);
}
}

View File

@ -0,0 +1,216 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.WorldVector;
/**
* Navigation commands.
*
* @author sk89q
*/
public class NavigationCommands {
@SuppressWarnings("unused")
private final WorldEdit we;
public NavigationCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "unstuck", "!" },
usage = "",
desc = "Escape from being stuck inside a block",
min = 0,
max = 0
)
@CommandPermissions("worldedit.navigation.unstuck")
public void unstuck(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
player.print("There you go!");
player.findFreePosition();
}
@Command(
aliases = { "ascend", "asc" },
usage = "[# of levels]",
desc = "Go up a floor",
min = 0,
max = 1
)
@CommandPermissions("worldedit.navigation.ascend")
public void ascend(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int levelsToAscend = 0;
if (args.argsLength() == 0) {
levelsToAscend = 1;
} else {
levelsToAscend = args.getInteger(0);
}
int ascentLevels = 1;
while (player.ascendLevel() && levelsToAscend != ascentLevels) {
++ascentLevels;
}
if (ascentLevels == 0) {
player.printError("No free spot above you found.");
} else {
player.print((ascentLevels != 1) ? "Ascended " + Integer.toString(ascentLevels) + " levels." : "Ascended a level.");
}
}
@Command(
aliases = { "descend", "desc" },
usage = "[# of floors]",
desc = "Go down a floor",
min = 0,
max = 1
)
@CommandPermissions("worldedit.navigation.descend")
public void descend(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int levelsToDescend = 0;
if (args.argsLength() == 0) {
levelsToDescend = 1;
} else {
levelsToDescend = args.getInteger(0);
}
int descentLevels = 1;
while (player.descendLevel() && levelsToDescend != descentLevels) {
++descentLevels;
}
if (descentLevels == 0) {
player.printError("No free spot above you found.");
} else {
player.print((descentLevels != 1) ? "Descended " + Integer.toString(descentLevels) + " levels." : "Descended a level.");
}
}
@Command(
aliases = { "ceil" },
usage = "[clearance]",
desc = "Go to the celing",
flags = "fg",
min = 0,
max = 1
)
@CommandPermissions("worldedit.navigation.ceiling")
@Logging(POSITION)
public void ceiling(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final int clearance = args.argsLength() > 0 ?
Math.max(0, args.getInteger(0)) : 0;
final boolean alwaysGlass = getAlwaysGlass(args);
if (player.ascendToCeiling(clearance, alwaysGlass)) {
player.print("Whoosh!");
} else {
player.printError("No free spot above you found.");
}
}
@Command(
aliases = { "thru" },
usage = "",
desc = "Passthrough walls",
min = 0,
max = 0
)
@CommandPermissions("worldedit.navigation.thru.command")
public void thru(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
if (player.passThroughForwardWall(6)) {
player.print("Whoosh!");
} else {
player.printError("No free spot ahead of you found.");
}
}
@Command(
aliases = { "jumpto", "j" },
usage = "",
desc = "Teleport to a location",
min = 0,
max = 0
)
@CommandPermissions("worldedit.navigation.jumpto.command")
public void jumpTo(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
WorldVector pos = player.getSolidBlockTrace(300);
if (pos != null) {
player.findFreePosition(pos);
player.print("Poof!");
} else {
player.printError("No block in sight!");
}
}
@Command(
aliases = { "up" },
usage = "<block>",
desc = "Go upwards some distance",
flags = "fg",
min = 1,
max = 1
)
@CommandPermissions("worldedit.navigation.up")
@Logging(POSITION)
public void up(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final int distance = args.getInteger(0);
final boolean alwaysGlass = getAlwaysGlass(args);
if (player.ascendUpwards(distance, alwaysGlass)) {
player.print("Whoosh!");
} else {
player.printError("You would hit something above you.");
}
}
/**
* Helper function for /up and /ceil.
*
* @param args The {@link CommandContext} to extract the flags from.
* @return true, if glass should always be put under the player
*/
private boolean getAlwaysGlass(CommandContext args) {
final LocalConfiguration config = we.getConfiguration();
final boolean forceFlight = args.hasFlag('f');
final boolean forceGlass = args.hasFlag('g');
return forceGlass || (config.navigationUseGlass && !forceFlight);
}
}

View File

@ -0,0 +1,585 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.convolution.GaussianKernel;
import com.sk89q.worldedit.math.convolution.HeightMap;
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.generator.FloraGenerator;
import com.sk89q.worldedit.function.generator.ForestGenerator;
import com.sk89q.worldedit.function.visitor.LayerVisitor;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.function.mask.NoiseFilter2D;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.regions.ConvexPolyhedralRegion;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.math.noise.RandomNoise;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import static com.sk89q.worldedit.regions.Regions.*;
/**
* Region related commands.
*
* @author sk89q
*/
public class RegionCommands {
private final WorldEdit we;
public RegionCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/set" },
usage = "<block>",
desc = "Set all the blocks inside the selection to a block",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.set")
@Logging(REGION)
public void set(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern pattern = we.getBlockPattern(player, args.getString(0));
int affected;
if (pattern instanceof SingleBlockPattern) {
affected = editSession.setBlocks(session.getSelection(player.getWorld()),
((SingleBlockPattern) pattern).getBlock());
} else {
affected = editSession.setBlocks(session.getSelection(player.getWorld()), pattern);
}
player.print(affected + " block(s) have been changed.");
}
@Command(
aliases = { "/line" },
usage = "<block> [thickness]",
desc = "Draws a line segment between cuboid selection corners",
help =
"Draws a line segment between cuboid selection corners.\n" +
"Can only be used with cuboid selections.\n" +
"Flags:\n" +
" -h generates only a shell",
flags = "h",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.line")
@Logging(REGION)
public void line(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Region region = session.getSelection(session.getSelectionWorld());
if (!(region instanceof CuboidRegion)) {
player.printError("Invalid region type");
return;
}
if (args.argsLength() < 2 ? false : args.getDouble(1) < 0) {
player.printError("Invalid thickness. Must not be negative");
return;
}
Pattern pattern = we.getBlockPattern(player, args.getString(0));
CuboidRegion cuboidregion = (CuboidRegion) region;
Vector pos1 = cuboidregion.getPos1();
Vector pos2 = cuboidregion.getPos2();
int blocksChanged = editSession.drawLine(pattern, pos1, pos2, args.argsLength() < 2 ? 0 : args.getDouble(1), !args.hasFlag('h'));
player.print(blocksChanged + " block(s) have been changed.");
}
@Command(
aliases = { "/curve" },
usage = "<block> [thickness]",
desc = "Draws a spline through selected points",
help =
"Draws a spline through selected points.\n" +
"Can only be uesd with convex polyhedral selections.\n" +
"Flags:\n" +
" -h generates only a shell",
flags = "h",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.curve")
@Logging(REGION)
public void curve(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Region region = session.getSelection(session.getSelectionWorld());
if (!(region instanceof ConvexPolyhedralRegion)) {
player.printError("Invalid region type");
return;
}
if (args.argsLength() < 2 ? false : args.getDouble(1) < 0) {
player.printError("Invalid thickness. Must not be negative");
return;
}
Pattern pattern = we.getBlockPattern(player, args.getString(0));
ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region;
List<Vector> vectors = new ArrayList<Vector>(cpregion.getVertices());
int blocksChanged = editSession.drawSpline(pattern, vectors, 0, 0, 0, 10, args.argsLength() < 2 ? 0 : args.getDouble(1), !args.hasFlag('h'));
player.print(blocksChanged + " block(s) have been changed.");
}
@Command(
aliases = { "/replace", "/re", "/rep" },
usage = "[from-block] <to-block>",
desc = "Replace all blocks in the selection with another",
flags = "f",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.replace")
@Logging(REGION)
public void replace(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Set<BaseBlock> from;
Pattern to;
if (args.argsLength() == 1) {
from = null;
to = we.getBlockPattern(player, args.getString(0));
} else {
from = we.getBlocks(player, args.getString(0), true, !args.hasFlag('f'));
to = we.getBlockPattern(player, args.getString(1));
}
final int affected;
if (to instanceof SingleBlockPattern) {
affected = editSession.replaceBlocks(session.getSelection(player.getWorld()), from,
((SingleBlockPattern) to).getBlock());
} else {
affected = editSession.replaceBlocks(session.getSelection(player.getWorld()), from, to);
}
player.print(affected + " block(s) have been replaced.");
}
@Command(
aliases = { "/overlay" },
usage = "<block>",
desc = "Set a block on top of blocks in the region",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.overlay")
@Logging(REGION)
public void overlay(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern pat = we.getBlockPattern(player, args.getString(0));
Region region = session.getSelection(player.getWorld());
int affected = 0;
if (pat instanceof SingleBlockPattern) {
affected = editSession.overlayCuboidBlocks(region,
((SingleBlockPattern) pat).getBlock());
} else {
affected = editSession.overlayCuboidBlocks(region, pat);
}
player.print(affected + " block(s) have been overlayed.");
}
@Command(
aliases = { "/center", "/middle" },
usage = "<block>",
desc = "Set the center block(s)",
min = 1,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.region.center")
public void center(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern pattern = we.getBlockPattern(player, args.getString(0));
Region region = session.getSelection(player.getWorld());
int affected = editSession.center(region, pattern);
player.print("Center set ("+ affected + " blocks changed)");
}
@Command(
aliases = { "/naturalize" },
usage = "",
desc = "3 layers of dirt on top then rock below",
min = 0,
max = 0
)
@CommandPermissions("worldedit.region.naturalize")
@Logging(REGION)
public void naturalize(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
int affected = editSession.naturalizeCuboidBlocks(region);
player.print(affected + " block(s) have been naturalized.");
}
@Command(
aliases = { "/walls" },
usage = "<block>",
desc = "Build the four sides of the selection",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.walls")
@Logging(REGION)
public void walls(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final Pattern pattern = we.getBlockPattern(player, args.getString(0));
final int affected;
final Region region = session.getSelection(player.getWorld());
if (!(region instanceof CuboidRegion)) {
affected = editSession.makeWalls(region, pattern);
} else if (pattern instanceof SingleBlockPattern) {
affected = editSession.makeCuboidWalls(region, ((SingleBlockPattern) pattern).getBlock());
} else {
affected = editSession.makeCuboidWalls(region, pattern);
}
player.print(affected + " block(s) have been changed.");
}
@Command(
aliases = { "/faces", "/outline" },
usage = "<block>",
desc = "Build the walls, ceiling, and floor of a selection",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.faces")
@Logging(REGION)
public void faces(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final Pattern pattern = we.getBlockPattern(player, args.getString(0));
final int affected;
final Region region = session.getSelection(player.getWorld());
if (!(region instanceof CuboidRegion)) {
affected = editSession.makeFaces(region, pattern);
} else if (pattern instanceof SingleBlockPattern) {
affected = editSession.makeCuboidFaces(region, ((SingleBlockPattern) pattern).getBlock());
} else {
affected = editSession.makeCuboidFaces(region, pattern);
}
player.print(affected + " block(s) have been changed.");
}
@Command(
aliases = { "/smooth" },
usage = "[iterations]",
flags = "n",
desc = "Smooth the elevation in the selection",
help =
"Smooths the elevation in the selection.\n" +
"The -n flag makes it only consider naturally occuring blocks.",
min = 0,
max = 1
)
@CommandPermissions("worldedit.region.smooth")
@Logging(REGION)
public void smooth(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int iterations = 1;
if (args.argsLength() > 0) {
iterations = args.getInteger(0);
}
HeightMap heightMap = new HeightMap(editSession, session.getSelection(player.getWorld()), args.hasFlag('n'));
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
int affected = heightMap.applyFilter(filter, iterations);
player.print("Terrain's height map smoothed. " + affected + " block(s) changed.");
}
@Command(
aliases = { "/move" },
usage = "[count] [direction] [leave-id]",
flags = "s",
desc = "Move the contents of the selection",
help =
"Moves the contents of the selection.\n" +
"The -s flag shifts the selection to the target location.\n" +
"Optionally fills the old location with <leave-id>.",
min = 0,
max = 3
)
@CommandPermissions("worldedit.region.move")
@Logging(ORIENTATION_REGION)
public void move(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int count = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
Vector dir = we.getDirection(player,
args.argsLength() > 1 ? args.getString(1).toLowerCase() : "me");
BaseBlock replace;
// Replacement block argument
if (args.argsLength() > 2) {
replace = we.getBlock(player, args.getString(2));
} else {
replace = new BaseBlock(BlockID.AIR);
}
int affected = editSession.moveRegion(session.getSelection(player.getWorld()),
dir, count, true, replace);
if (args.hasFlag('s')) {
try {
Region region = session.getSelection(player.getWorld());
region.shift(dir.multiply(count));
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
player.print(affected + " blocks moved.");
}
@Command(
aliases = { "/stack" },
usage = "[count] [direction]",
flags = "sa",
desc = "Repeat the contents of the selection",
help =
"Repeats the contents of the selection.\n" +
"Flags:\n" +
" -s shifts the selection to the last stacked copy\n" +
" -a skips air blocks",
min = 0,
max = 2
)
@CommandPermissions("worldedit.region.stack")
@Logging(ORIENTATION_REGION)
public void stack(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int count = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
Vector dir = we.getDiagonalDirection(player,
args.argsLength() > 1 ? args.getString(1).toLowerCase() : "me");
int affected = editSession.stackCuboidRegion(session.getSelection(player.getWorld()),
dir, count, !args.hasFlag('a'));
if (args.hasFlag('s')) {
try {
final Region region = session.getSelection(player.getWorld());
final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
final Vector shiftVector = dir.multiply(count * (Math.abs(dir.dot(size)) + 1));
region.shift(shiftVector);
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
player.print(affected + " blocks changed. Undo with //undo");
}
@Command(
aliases = { "/regen" },
usage = "",
desc = "Regenerates the contents of the selection",
help =
"Regenerates the contents of the current selection.\n" +
"This command might affect things outside the selection,\n" +
"if they are within the same chunk.",
min = 0,
max = 0
)
@CommandPermissions("worldedit.regen")
@Logging(REGION)
public void regenerateChunk(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
Mask mask = session.getMask();
session.setMask(null);
player.getWorld().regenerate(region, editSession);
session.setMask(mask);
player.print("Region regenerated.");
}
@Command(
aliases = { "/deform" },
usage = "<expression>",
desc = "Deforms a selected region with an expression",
help =
"Deforms a selected region with an expression\n" +
"The expression is executed for each block and is expected\n" +
"to modify the variables x, y and z to point to a new block\n" +
"to fetch. See also tinyurl.com/wesyntax.",
flags = "ro",
min = 1,
max = -1
)
@CommandPermissions("worldedit.region.deform")
@Logging(ALL)
public void deform(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final Region region = session.getSelection(player.getWorld());
final String expression = args.getJoinedStrings(0);
final Vector zero;
Vector unit;
if (args.hasFlag('r')) {
zero = Vector.ZERO;
unit = Vector.ONE;
} else if (args.hasFlag('o')) {
zero = session.getPlacementPosition(player);
unit = Vector.ONE;
} else {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);
if (unit.getX() == 0) unit = unit.setX(1.0);
if (unit.getY() == 0) unit = unit.setY(1.0);
if (unit.getZ() == 0) unit = unit.setZ(1.0);
}
try {
final int affected = editSession.deformRegion(region, zero, unit, expression);
player.findFreePosition();
player.print(affected + " block(s) have been deformed.");
} catch (ExpressionException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/hollow" },
usage = "[<thickness>[ <block>]]",
desc = "Hollows out the object contained in this selection",
help =
"Hollows out the object contained in this selection.\n" +
"Optionally fills the hollowed out part with the given block.\n" +
"Thickness is measured in manhattan distance.",
min = 0,
max = 2
)
@CommandPermissions("worldedit.region.hollow")
@Logging(REGION)
public void hollow(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final int thickness = args.argsLength() >= 1 ? Math.max(1, args.getInteger(0)) : 1;
final Pattern pattern = args.argsLength() >= 2 ? we.getBlockPattern(player, args.getString(1)) : new SingleBlockPattern(new BaseBlock(BlockID.AIR));
final int affected = editSession.hollowOutRegion(session.getSelection(player.getWorld()), thickness, pattern);
player.print(affected + " block(s) have been changed.");
}
@Command(
aliases = { "/forest" },
usage = "[type] [density]",
desc = "Make a forest within the region",
min = 0,
max = 2
)
@CommandPermissions("worldedit.region.forest")
@Logging(REGION)
public void forest(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
TreeGenerator.TreeType type = args.argsLength() > 0 ? TreeGenerator.lookup(args.getString(0)) : TreeGenerator.TreeType.TREE;
double density = args.argsLength() > 1 ? args.getDouble(1) / 100 : 0.05;
if (type == null) {
player.printError("Tree type '" + args.getString(0) + "' is unknown.");
return;
}
Region region = session.getSelection(player.getWorld());
ForestGenerator generator = new ForestGenerator(editSession, new TreeGenerator(type));
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeLegacy(visitor);
player.print(ground.getAffected() + " trees created.");
}
@Command(
aliases = { "/flora" },
usage = "[density]",
desc = "Make flora within the region",
min = 0,
max = 1
)
@CommandPermissions("worldedit.region.flora")
@Logging(REGION)
public void flora(CommandContext args, LocalSession session, LocalPlayer player, EditSession editSession) throws WorldEditException {
double density = args.argsLength() > 0 ? args.getDouble(0) / 100 : 0.1;
Region region = session.getSelection(player.getWorld());
FloraGenerator generator = new FloraGenerator(editSession);
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeLegacy(visitor);
player.print(ground.getAffected() + " flora created.");
}
}

View File

@ -0,0 +1,253 @@
/*
* WorldEdit
* Copyright (C) 2012 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Console;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.FilenameResolutionException;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.schematic.SchematicFormat;
/**
* Commands related to schematics
*
* @see com.sk89q.worldedit.command.ClipboardCommands#schematic()
*/
public class SchematicCommands {
private final WorldEdit we;
public SchematicCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "load", "l" },
usage = "[format] <filename>",
desc = "Load a schematic into your clipboard",
help = "Load a schematic into your clipboard\n" +
"Format is a format from \"//schematic formats\"\n" +
"If the format is not provided, WorldEdit will\n" +
"attempt to automatically detect the format of the schematic",
flags = "f",
min = 1,
max = 2
)
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load"}) // TODO: Remove 'clipboard' perm
public void load(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
String fileName;
String formatName;
if (args.argsLength() == 1) {
formatName = null;
fileName = args.getString(0);
} else {
formatName = args.getString(0);
fileName = args.getString(1);
}
File dir = we.getWorkingDirectoryFile(config.saveDir);
File f = we.getSafeOpenFile(player, dir, fileName, "schematic", "schematic");
if (!f.exists()) {
player.printError("Schematic " + fileName + " does not exist!");
return;
}
SchematicFormat format = formatName == null ? null : SchematicFormat.getFormat(formatName);
if (format == null) {
format = SchematicFormat.getFormat(f);
}
if (format == null) {
player.printError("Unknown schematic format: " + formatName);
return;
}
if (!format.isOfFormat(f) && !args.hasFlag('f')) {
player.printError(fileName + " is not of the " + format.getName() + " schematic format!");
return;
}
try {
String filePath = f.getCanonicalPath();
String dirPath = dir.getCanonicalPath();
if (!filePath.substring(0, dirPath.length()).equals(dirPath)) {
player.printError("Schematic could not read or it does not exist.");
} else {
session.setClipboard(format.load(f));
WorldEdit.logger.info(player.getName() + " loaded " + filePath);
player.print(fileName + " loaded. Paste it with //paste");
}
} catch (DataException e) {
player.printError("Load error: " + e.getMessage());
} catch (IOException e) {
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
}
}
@Command(
aliases = { "save", "s" },
usage = "[format] <filename>",
desc = "Save a schematic into your clipboard",
help = "Save a schematic into your clipboard\n" +
"Format is a format from \"//schematic formats\"\n",
min = 1,
max = 2
)
@CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"}) // TODO: Remove 'clipboard' perm
public void save(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException, CommandException {
LocalConfiguration config = we.getConfiguration();
SchematicFormat format;
if (args.argsLength() == 1) {
if (SchematicFormat.getFormats().size() == 1) {
format = SchematicFormat.getFormats().iterator().next();
} else {
player.printError("More than one schematic format is available. Please provide the desired format");
return;
}
} else {
format = SchematicFormat.getFormat(args.getString(0));
if (format == null) {
player.printError("Unknown schematic format: " + args.getString(0));
return;
}
}
String filename = args.getString(args.argsLength() - 1);
File dir = we.getWorkingDirectoryFile(config.saveDir);
File f = we.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
if (!dir.exists()) {
if (!dir.mkdir()) {
player.printError("The storage folder could not be created.");
return;
}
}
try {
// Create parent directories
File parent = f.getParentFile();
if (parent != null && !parent.exists()) {
if (!parent.mkdirs()) {
throw new CommandException("Could not create folder for schematics!");
}
}
format.save(session.getClipboard(), f);
WorldEdit.logger.info(player.getName() + " saved " + f.getCanonicalPath());
player.print(filename + " saved.");
} catch (DataException se) {
player.printError("Save error: " + se.getMessage());
} catch (IOException e) {
player.printError("Schematic could not written: " + e.getMessage());
}
}
@Command(
aliases = {"formats", "listformats", "f"},
desc = "List available schematic formats",
max = 0
)
@Console
@CommandPermissions("worldedit.schematic.formats")
public void formats(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
player.print("Available schematic formats (Name: Lookup names)");
StringBuilder builder;
boolean first = true;
for (SchematicFormat format : SchematicFormat.getFormats()) {
builder = new StringBuilder();
builder.append(format.getName()).append(": ");
for (String lookupName : format.getLookupNames()) {
if (!first) {
builder.append(", ");
}
builder.append(lookupName);
first = false;
}
first = true;
player.print(builder.toString());
}
}
@Command(
aliases = {"list", "all", "ls"},
desc = "List available schematics",
max = 0,
flags = "dn",
help = "List all schematics in the schematics directory\n" +
" -d sorts by date, oldest first\n" +
" -n sorts by date, newest first\n"
)
@Console
@CommandPermissions("worldedit.schematic.list")
public void list(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
File dir = we.getWorkingDirectoryFile(we.getConfiguration().saveDir);
File[] files = dir.listFiles();
if (files == null) {
throw new FilenameResolutionException(dir.getPath(), "Schematics directory invalid or not found.");
}
StringBuilder build = new StringBuilder("Available schematics (Filename (Format)): ");
final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
// cleanup file list
Arrays.sort(files, new Comparator<File>(){
@Override
public int compare(File f1, File f2) {
if (!f1.isFile() || !f2.isFile()) return -1; // don't care, will get removed
// http://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified
int result = sortType == 0 ? f1.getName().compareToIgnoreCase(f2.getName()) : // use name by default
Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag
if (sortType == 1) result = -result; // flip date for newest first instead of oldest first
return result;
}
});
for (File file : files) {
if (!file.isFile()) {
continue;
}
build.append("\n\u00a79");
SchematicFormat format = SchematicFormat.getFormat(file);
build.append(file.getName()).append(": ").append(format == null ? "Unknown" : format.getName());
}
player.print(build.toString());
}
}

View File

@ -0,0 +1,101 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import java.io.File;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import com.sk89q.worldedit.*;
/**
* Scripting commands.
*
* @author sk89q
*/
public class ScriptingCommands {
private final WorldEdit we;
public ScriptingCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "cs" },
usage = "<filename> [args...]",
desc = "Execute a CraftScript",
min = 1,
max = -1
)
@CommandPermissions("worldedit.scripting.execute")
@Logging(ALL)
public void execute(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
String[] scriptArgs = args.getSlice(1);
String name = args.getString(0);
if (!player.hasPermission("worldedit.scripting.execute." + name)) {
player.printError("You don't have permission to use that script.");
return;
}
session.setLastScript(name);
File dir = we.getWorkingDirectoryFile(we.getConfiguration().scriptsDir);
File f = we.getSafeOpenFile(player, dir, name, "js", "js");
we.runScript(player, f, scriptArgs);
}
@Command(
aliases = { ".s" },
usage = "[args...]",
desc = "Execute last CraftScript",
min = 0,
max = -1
)
@CommandPermissions("worldedit.scripting.execute")
@Logging(ALL)
public void executeLast(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
String lastScript = session.getLastScript();
if (!player.hasPermission("worldedit.scripting.execute." + lastScript)) {
player.printError("You don't have permission to use that script.");
return;
}
if (lastScript == null) {
player.printError("Use /cs with a script name first.");
return;
}
String[] scriptArgs = args.getSlice(0);
File dir = we.getWorkingDirectoryFile(we.getConfiguration().scriptsDir);
File f = we.getSafeOpenFile(player, dir, lastScript, "js", "js");
we.runScript(player, f, scriptArgs);
}
}

View File

@ -0,0 +1,788 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandAlias;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.world.storage.ChunkStore;
import com.sk89q.worldedit.regions.ConvexPolyhedralRegionSelector;
import com.sk89q.worldedit.regions.CuboidRegionSelector;
import com.sk89q.worldedit.regions.CylinderRegionSelector;
import com.sk89q.worldedit.regions.EllipsoidRegionSelector;
import com.sk89q.worldedit.regions.ExtendingCuboidRegionSelector;
import com.sk89q.worldedit.regions.Polygonal2DRegionSelector;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.SphereRegionSelector;
/**
* Selection commands.
*
* @author sk89q
*/
public class SelectionCommands {
private final WorldEdit we;
public SelectionCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/pos1" },
usage = "[coordinates]",
desc = "Set position 1",
min = 0,
max = 1
)
@Logging(POSITION)
@CommandPermissions("worldedit.selection.pos")
public void pos1(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Vector pos;
if (args.argsLength() == 1) {
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
String[] coords = args.getString(0).split(",");
pos = new Vector(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(coords[2]));
} else {
player.printError("Invalid coordinates " + args.getString(0));
return;
}
} else {
pos = player.getBlockIn();
}
if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos)) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainPrimarySelection(player, session, pos);
}
@Command(
aliases = { "/pos2" },
usage = "[coordinates]",
desc = "Set position 2",
min = 0,
max = 1
)
@Logging(POSITION)
@CommandPermissions("worldedit.selection.pos")
public void pos2(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Vector pos;
if (args.argsLength() == 1) {
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
String[] coords = args.getString(0).split(",");
pos = new Vector(Integer.parseInt(coords[0]),
Integer.parseInt(coords[1]),
Integer.parseInt(coords[2]));
} else {
player.printError("Invalid coordinates " + args.getString(0));
return;
}
} else {
pos = player.getBlockIn();
}
if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos)) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainSecondarySelection(player, session, pos);
}
@Command(
aliases = { "/hpos1" },
usage = "",
desc = "Set position 1 to targeted block",
min = 0,
max = 0
)
@CommandPermissions("worldedit.selection.hpos")
public void hpos1(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Vector pos = player.getBlockTrace(300);
if (pos != null) {
if (!session.getRegionSelector(player.getWorld())
.selectPrimary(pos)) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainPrimarySelection(player, session, pos);
} else {
player.printError("No block in sight!");
}
}
@Command(
aliases = { "/hpos2" },
usage = "",
desc = "Set position 2 to targeted block",
min = 0,
max = 0
)
@CommandPermissions("worldedit.selection.hpos")
public void hpos2(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Vector pos = player.getBlockTrace(300);
if (pos != null) {
if (!session.getRegionSelector(player.getWorld())
.selectSecondary(pos)) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainSecondarySelection(player, session, pos);
} else {
player.printError("No block in sight!");
}
}
@Command(
aliases = { "/chunk" },
usage = "[x,z coordinates]",
flags = "sc",
desc = "Set the selection to your current chunk.",
help =
"Set the selection to the chunk you are currently in.\n" +
"With the -s flag, your current selection is expanded\n" +
"to encompass all chunks that are part of it.\n\n" +
"Specifying coordinates will use those instead of your\n"+
"current position. Use -c to specify chunk coordinates,\n" +
"otherwise full coordinates will be implied.\n" +
"(for example, the coordinates 5,5 are the same as -c 0,0)",
min = 0,
max = 1
)
@Logging(POSITION)
@CommandPermissions("worldedit.selection.chunk")
public void chunk(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final Vector min;
final Vector max;
final LocalWorld world = player.getWorld();
if (args.hasFlag('s')) {
Region region = session.getSelection(world);
final Vector2D min2D = ChunkStore.toChunk(region.getMinimumPoint());
final Vector2D max2D = ChunkStore.toChunk(region.getMaximumPoint());
min = new Vector(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
max = new Vector(max2D.getBlockX() * 16 + 15, world.getMaxY(), max2D.getBlockZ() * 16 + 15);
player.print("Chunks selected: ("
+ min2D.getBlockX() + ", " + min2D.getBlockZ() + ") - ("
+ max2D.getBlockX() + ", " + max2D.getBlockZ() + ")");
} else {
final Vector2D min2D;
if (args.argsLength() == 1) {
// coords specified
String[] coords = args.getString(0).split(",");
if (coords.length != 2) {
throw new InsufficientArgumentsException("Invalid coordinates specified.");
}
int x = Integer.parseInt(coords[0]);
int z = Integer.parseInt(coords[1]);
Vector2D pos = new Vector2D(x, z);
min2D = (args.hasFlag('c')) ? pos : ChunkStore.toChunk(pos.toVector());
} else {
// use player loc
min2D = ChunkStore.toChunk(player.getBlockIn());
}
min = new Vector(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
max = min.add(15, world.getMaxY(), 15);
player.print("Chunk selected: "
+ min2D.getBlockX() + ", " + min2D.getBlockZ());
}
final CuboidRegionSelector selector;
if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) {
selector = new ExtendingCuboidRegionSelector(world);
} else {
selector = new CuboidRegionSelector(world);
}
selector.selectPrimary(min);
selector.selectSecondary(max);
session.setRegionSelector(world, selector);
session.dispatchCUISelection(player);
}
@Command(
aliases = { "/wand" },
usage = "",
desc = "Get the wand object",
min = 0,
max = 0
)
@CommandPermissions("worldedit.wand")
public void wand(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
player.giveItem(we.getConfiguration().wandItem, 1);
player.print("Left click: select pos #1; Right click: select pos #2");
}
@Command(
aliases = { "toggleeditwand" },
usage = "",
desc = "Toggle functionality of the edit wand",
min = 0,
max = 0
)
@CommandPermissions("worldedit.wand.toggle")
public void toggleWand(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setToolControl(!session.isToolControlEnabled());
if (session.isToolControlEnabled()) {
player.print("Edit wand enabled.");
} else {
player.print("Edit wand disabled.");
}
}
@Command(
aliases = { "/expand" },
usage = "<amount> [reverse-amount] <direction>",
desc = "Expand the selection area",
min = 1,
max = 3
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.expand")
public void expand(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
// Special syntax (//expand vert) to expand the selection between
// sky and bedrock.
if (args.getString(0).equalsIgnoreCase("vert")
|| args.getString(0).equalsIgnoreCase("vertical")) {
Region region = session.getSelection(player.getWorld());
try {
int oldSize = region.getArea();
region.expand(
new Vector(0, (player.getWorld().getMaxY() + 1), 0),
new Vector(0, -(player.getWorld().getMaxY() + 1), 0));
session.getRegionSelector(player.getWorld()).learnChanges();
int newSize = region.getArea();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
player.print("Region expanded " + (newSize - oldSize)
+ " blocks [top-to-bottom].");
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
return;
}
List<Vector> dirs = new ArrayList<Vector>();
int change = args.getInteger(0);
int reverseChange = 0;
switch (args.argsLength()) {
case 2:
// Either a reverse amount or a direction
try {
reverseChange = args.getInteger(1);
dirs.add(we.getDirection(player, "me"));
} catch (NumberFormatException e) {
if (args.getString(1).contains(",")) {
String[] split = args.getString(1).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
}
}
break;
case 3:
// Both reverse amount and direction
reverseChange = args.getInteger(1);
if (args.getString(2).contains(",")) {
String[] split = args.getString(2).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
}
break;
default:
dirs.add(we.getDirection(player, "me"));
break;
}
Region region = session.getSelection(player.getWorld());
int oldSize = region.getArea();
if (reverseChange == 0) {
for (Vector dir : dirs) {
region.expand(dir.multiply(change));
}
} else {
for (Vector dir : dirs) {
region.expand(dir.multiply(change), dir.multiply(-reverseChange));
}
}
session.getRegionSelector(player.getWorld()).learnChanges();
int newSize = region.getArea();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
player.print("Region expanded " + (newSize - oldSize) + " blocks.");
}
@Command(
aliases = { "/contract" },
usage = "<amount> [reverse-amount] [direction]",
desc = "Contract the selection area",
min = 1,
max = 3
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.contract")
public void contract(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
List<Vector> dirs = new ArrayList<Vector>();
int change = args.getInteger(0);
int reverseChange = 0;
switch (args.argsLength()) {
case 2:
// Either a reverse amount or a direction
try {
reverseChange = args.getInteger(1);
dirs.add(we.getDirection(player, "me"));
} catch (NumberFormatException e) {
if (args.getString(1).contains(",")) {
String[] split = args.getString(1).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
}
}
break;
case 3:
// Both reverse amount and direction
reverseChange = args.getInteger(1);
if (args.getString(2).contains(",")) {
String[] split = args.getString(2).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
}
break;
default:
dirs.add(we.getDirection(player, "me"));
break;
}
try {
Region region = session.getSelection(player.getWorld());
int oldSize = region.getArea();
if (reverseChange == 0) {
for (Vector dir : dirs) {
region.contract(dir.multiply(change));
}
} else {
for (Vector dir : dirs) {
region.contract(dir.multiply(change), dir.multiply(-reverseChange));
}
}
session.getRegionSelector(player.getWorld()).learnChanges();
int newSize = region.getArea();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
player.print("Region contracted " + (oldSize - newSize) + " blocks.");
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/shift" },
usage = "<amount> [direction]",
desc = "Shift the selection area",
min = 1,
max = 2
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.shift")
public void shift(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
List<Vector> dirs = new ArrayList<Vector>();
int change = args.getInteger(0);
if (args.argsLength() == 2) {
if (args.getString(1).contains(",")) {
for (String s : args.getString(1).split(",")) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, "me"));
}
try {
Region region = session.getSelection(player.getWorld());
for (Vector dir : dirs) {
region.shift(dir.multiply(change));
}
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
player.print("Region shifted.");
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/outset" },
usage = "<amount>",
desc = "Outset the selection area",
help =
"Expands the selection by the given amount in all directions.\n" +
"Flags:\n" +
" -h only expand horizontally\n" +
" -v only expand vertically\n",
flags = "hv",
min = 1,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.outset")
public void outset(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
region.expand(getChangesForEachDir(args));
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
player.print("Region outset.");
}
@Command(
aliases = { "/inset" },
usage = "<amount>",
desc = "Inset the selection area",
help =
"Contracts the selection by the given amount in all directions.\n" +
"Flags:\n" +
" -h only contract horizontally\n" +
" -v only contract vertically\n",
flags = "hv",
min = 1,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.inset")
public void inset(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
region.contract(getChangesForEachDir(args));
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
player.print("Region inset.");
}
private Vector[] getChangesForEachDir(CommandContext args) {
List<Vector> changes = new ArrayList<Vector>(6);
int change = args.getInteger(0);
if (!args.hasFlag('h')) {
changes.add((new Vector(0, 1, 0)).multiply(change));
changes.add((new Vector(0, -1, 0)).multiply(change));
}
if (!args.hasFlag('v')) {
changes.add((new Vector(1, 0, 0)).multiply(change));
changes.add((new Vector(-1, 0, 0)).multiply(change));
changes.add((new Vector(0, 0, 1)).multiply(change));
changes.add((new Vector(0, 0, -1)).multiply(change));
}
return changes.toArray(new Vector[0]);
}
@Command(
aliases = { "/size" },
flags = "c",
usage = "",
desc = "Get information about the selection",
min = 0,
max = 0
)
@CommandPermissions("worldedit.selection.size")
public void size(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
if (args.hasFlag('c')) {
CuboidClipboard clipboard = session.getClipboard();
Vector size = clipboard.getSize();
Vector offset = clipboard.getOffset();
player.print("Size: " + size);
player.print("Offset: " + offset);
player.print("Cuboid distance: " + size.distance(Vector.ONE));
player.print("# of blocks: "
+ (int) (size.getX() * size.getY() * size.getZ()));
return;
}
Region region = session.getSelection(player.getWorld());
Vector size = region.getMaximumPoint()
.subtract(region.getMinimumPoint())
.add(1, 1, 1);
player.print("Type: " + session.getRegionSelector(player.getWorld())
.getTypeName());
for (String line : session.getRegionSelector(player.getWorld())
.getInformationLines()) {
player.print(line);
}
player.print("Size: " + size);
player.print("Cuboid distance: " + region.getMaximumPoint()
.distance(region.getMinimumPoint()));
player.print("# of blocks: " + region.getArea());
}
@Command(
aliases = { "/count" },
usage = "<block>",
desc = "Counts the number of a certain type of block",
flags = "d",
min = 1,
max = 1
)
@CommandPermissions("worldedit.analysis.count")
public void count(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
boolean useData = args.hasFlag('d');
if (args.getString(0).contains(":")) {
useData = true; //override d flag, if they specified data they want it
}
if (useData) {
Set<BaseBlock> searchBlocks = we.getBlocks(player, args.getString(0), true);
int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks);
player.print("Counted: " + count);
} else {
Set<Integer> searchIDs = we.getBlockIDs(player, args.getString(0), true);
int count = editSession.countBlock(session.getSelection(player.getWorld()), searchIDs);
player.print("Counted: " + count);
}
}
@Command(
aliases = { "/distr" },
usage = "",
desc = "Get the distribution of blocks in the selection",
help =
"Gets the distribution of blocks in the selection.\n" +
"The -c flag gets the distribution of your clipboard.\n" +
"The -d flag separates blocks by data",
flags = "cd",
min = 0,
max = 0
)
@CommandPermissions("worldedit.analysis.distr")
public void distr(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int size;
boolean useData = args.hasFlag('d');
List<Countable<Integer>> distribution = null;
List<Countable<BaseBlock>> distributionData = null;
if (args.hasFlag('c')) {
CuboidClipboard clip = session.getClipboard();
if (useData) {
distributionData = clip.getBlockDistributionWithData();
} else {
distribution = clip.getBlockDistribution();
}
size = clip.getHeight() * clip.getLength() * clip.getWidth();
} else {
if (useData) {
distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));
} else {
distribution = editSession.getBlockDistribution(session.getSelection(player.getWorld()));
}
size = session.getSelection(player.getWorld()).getArea();
}
if ((useData && distributionData.size() <= 0)
|| (!useData && distribution.size() <= 0)) { // *Should* always be false
player.printError("No blocks counted.");
return;
}
player.print("# total blocks: " + size);
if (useData) {
for (Countable<BaseBlock> c : distributionData) {
String name = BlockType.fromID(c.getID().getId()).getName();
String str = String.format("%-7s (%.3f%%) %s #%d:%d",
String.valueOf(c.getAmount()),
c.getAmount() / (double) size * 100,
name == null ? "Unknown" : name,
c.getID().getType(), c.getID().getData());
player.print(str);
}
} else {
for (Countable<Integer> c : distribution) {
BlockType block = BlockType.fromID(c.getID());
String str = String.format("%-7s (%.3f%%) %s #%d",
String.valueOf(c.getAmount()),
c.getAmount() / (double) size * 100,
block == null ? "Unknown" : block.getName(), c.getID());
player.print(str);
}
}
}
@Command(
aliases = { "/sel", ";" },
usage = "[cuboid|extend|poly|ellipsoid|sphere|cyl|convex]",
desc = "Choose a region selector",
min = 0,
max = 1
)
public void select(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final LocalWorld world = player.getWorld();
if (args.argsLength() == 0) {
session.getRegionSelector(world).clear();
session.dispatchCUISelection(player);
player.print("Selection cleared.");
return;
}
final String typeName = args.getString(0);
final RegionSelector oldSelector = session.getRegionSelector(world);
final RegionSelector selector;
if (typeName.equalsIgnoreCase("cuboid")) {
selector = new CuboidRegionSelector(oldSelector);
player.print("Cuboid: left click for point 1, right click for point 2");
} else if (typeName.equalsIgnoreCase("extend")) {
selector = new ExtendingCuboidRegionSelector(oldSelector);
player.print("Cuboid: left click for a starting point, right click to extend");
} else if (typeName.equalsIgnoreCase("poly")) {
int maxPoints = we.getMaximumPolygonalPoints(player);
selector = new Polygonal2DRegionSelector(oldSelector, maxPoints);
player.print("2D polygon selector: Left/right click to add a point.");
if (maxPoints > -1) {
player.print(maxPoints + " points maximum.");
}
} else if (typeName.equalsIgnoreCase("ellipsoid")) {
selector = new EllipsoidRegionSelector(oldSelector);
player.print("Ellipsoid selector: left click=center, right click to extend");
} else if (typeName.equalsIgnoreCase("sphere")) {
selector = new SphereRegionSelector(oldSelector);
player.print("Sphere selector: left click=center, right click to set radius");
} else if (typeName.equalsIgnoreCase("cyl")) {
selector = new CylinderRegionSelector(oldSelector);
player.print("Cylindrical selector: Left click=center, right click to extend.");
} else if (typeName.equalsIgnoreCase("convex") || typeName.equalsIgnoreCase("hull") || typeName.equalsIgnoreCase("polyhedron")) {
int maxVertices = we.getMaximumPolyhedronPoints(player);
selector = new ConvexPolyhedralRegionSelector(oldSelector, maxVertices);
player.print("Convex polyhedral selector: Left click=First vertex, right click to add more.");
} else {
player.printError("Only cuboid|extend|poly|ellipsoid|sphere|cyl|convex are accepted.");
return;
}
session.setRegionSelector(world, selector);
session.dispatchCUISelection(player);
}
@Command(aliases = {"/desel", "/deselect"}, desc = "Deselect the current selection")
@CommandAlias("/sel")
public void deselect() {
}
}

View File

@ -0,0 +1,272 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Logger;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.world.storage.MissingWorldException;
import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException;
import com.sk89q.worldedit.world.snapshot.Snapshot;
/**
* Snapshot commands.
*
* @author sk89q
*/
public class SnapshotCommands {
private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
private final WorldEdit we;
public SnapshotCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "list" },
usage = "[num]",
desc = "List snapshots",
min = 0,
max = 1
)
@CommandPermissions("worldedit.snapshots.list")
public void list(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
player.printError("Snapshot/backup restore is not configured.");
return;
}
try {
List<Snapshot> snapshots = config.snapshotRepo.getSnapshots(true, player.getWorld().getName());
if (snapshots.size() > 0) {
int num = args.argsLength() > 0 ? Math.min(40, Math.max(5, args.getInteger(0))) : 5;
player.print("Snapshots for world: '" + player.getWorld().getName() + "'");
for (byte i = 0; i < Math.min(num, snapshots.size()); i++) {
player.print((i + 1) + ". " + snapshots.get(i).getName());
}
player.print("Use /snap use [snapshot] or /snap use latest.");
} else {
player.printError("No snapshots are available. See console for details.");
// Okay, let's toss some debugging information!
File dir = config.snapshotRepo.getDirectory();
try {
logger.info("WorldEdit found no snapshots: looked in: "
+ dir.getCanonicalPath());
} catch (IOException e) {
logger.info("WorldEdit found no snapshots: looked in "
+ "(NON-RESOLVABLE PATH - does it exist?): "
+ dir.getPath());
}
}
} catch (MissingWorldException ex) {
player.printError("No snapshots were found for this world.");
}
}
@Command(
aliases = { "use" },
usage = "<snapshot>",
desc = "Choose a snapshot to use",
min = 1,
max = 1
)
@CommandPermissions("worldedit.snapshots.restore")
public void use(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
player.printError("Snapshot/backup restore is not configured.");
return;
}
String name = args.getString(0);
// Want the latest snapshot?
if (name.equalsIgnoreCase("latest")) {
try {
Snapshot snapshot = config.snapshotRepo.getDefaultSnapshot(player.getWorld().getName());
if (snapshot != null) {
session.setSnapshot(null);
player.print("Now using newest snapshot.");
} else {
player.printError("No snapshots were found.");
}
} catch (MissingWorldException ex) {
player.printError("No snapshots were found for this world.");
}
} else {
try {
session.setSnapshot(config.snapshotRepo.getSnapshot(name));
player.print("Snapshot set to: " + name);
} catch (InvalidSnapshotException e) {
player.printError("That snapshot does not exist or is not available.");
}
}
}
@Command(
aliases = { "sel" },
usage = "<index>",
desc = "Choose the snapshot based on the list id",
min = 1,
max = 1
)
@CommandPermissions("worldedit.snapshots.restore")
public void sel(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
player.printError("Snapshot/backup restore is not configured.");
return;
}
int index = -1;
try {
index = Integer.parseInt(args.getString(0));
} catch (NumberFormatException e) {
player.printError("Invalid index, " + args.getString(0) + " is not a valid integer.");
return;
}
if (index < 1) {
player.printError("Invalid index, must be equal or higher then 1.");
return;
}
try {
List<Snapshot> snapshots = config.snapshotRepo.getSnapshots(true, player.getWorld().getName());
if (snapshots.size() < index) {
player.printError("Invalid index, must be between 1 and " + snapshots.size() + ".");
return;
}
Snapshot snapshot = snapshots.get(index - 1);
if (snapshot == null) {
player.printError("That snapshot does not exist or is not available.");
return;
}
session.setSnapshot(snapshot);
player.print("Snapshot set to: " + snapshot.getName());
} catch (MissingWorldException e) {
player.printError("No snapshots were found for this world.");
}
}
@Command(
aliases = { "before" },
usage = "<date>",
desc = "Choose the nearest snapshot before a date",
min = 1,
max = -1
)
@CommandPermissions("worldedit.snapshots.restore")
public void before(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
player.printError("Snapshot/backup restore is not configured.");
return;
}
Calendar date = session.detectDate(args.getJoinedStrings(0));
if (date == null) {
player.printError("Could not detect the date inputted.");
} else {
try {
Snapshot snapshot = config.snapshotRepo.getSnapshotBefore(date, player.getWorld().getName());
if (snapshot == null) {
dateFormat.setTimeZone(session.getTimeZone());
player.printError("Couldn't find a snapshot before "
+ dateFormat.format(date.getTime()) + ".");
} else {
session.setSnapshot(snapshot);
player.print("Snapshot set to: " + snapshot.getName());
}
} catch (MissingWorldException ex) {
player.printError("No snapshots were found for this world.");
}
}
}
@Command(
aliases = { "after" },
usage = "<date>",
desc = "Choose the nearest snapshot after a date",
min = 1,
max = -1
)
@CommandPermissions("worldedit.snapshots.restore")
public void after(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
player.printError("Snapshot/backup restore is not configured.");
return;
}
Calendar date = session.detectDate(args.getJoinedStrings(0));
if (date == null) {
player.printError("Could not detect the date inputted.");
} else {
try {
Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName());
if (snapshot == null) {
dateFormat.setTimeZone(session.getTimeZone());
player.printError("Couldn't find a snapshot after "
+ dateFormat.format(date.getTime()) + ".");
} else {
session.setSnapshot(snapshot);
player.print("Snapshot set to: " + snapshot.getName());
}
} catch (MissingWorldException ex) {
player.printError("No snapshots were found for this world.");
}
}
}
}

View File

@ -0,0 +1,169 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.storage.ChunkStore;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.storage.MissingWorldException;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException;
import com.sk89q.worldedit.world.snapshot.Snapshot;
import com.sk89q.worldedit.world.snapshot.SnapshotRestore;
public class SnapshotUtilCommands {
private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
private final WorldEdit we;
public SnapshotUtilCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "snapshot", "snap" },
desc = "Snapshot commands"
)
@NestedCommand(SnapshotCommands.class)
public void snapshot(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command(
aliases = { "restore", "/restore" },
usage = "[snapshot]",
desc = "Restore the selection from a snapshot",
min = 0,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.snapshots.restore")
public void restore(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
player.printError("Snapshot/backup restore is not configured.");
return;
}
Region region = session.getSelection(player.getWorld());
Snapshot snapshot;
if (args.argsLength() > 0) {
try {
snapshot = config.snapshotRepo.getSnapshot(args.getString(0));
} catch (InvalidSnapshotException e) {
player.printError("That snapshot does not exist or is not available.");
return;
}
} else {
snapshot = session.getSnapshot();
}
// No snapshot set?
if (snapshot == null) {
try {
snapshot = config.snapshotRepo.getDefaultSnapshot(player.getWorld().getName());
if (snapshot == null) {
player.printError("No snapshots were found. See console for details.");
// Okay, let's toss some debugging information!
File dir = config.snapshotRepo.getDirectory();
try {
logger.info("WorldEdit found no snapshots: looked in: "
+ dir.getCanonicalPath());
} catch (IOException e) {
logger.info("WorldEdit found no snapshots: looked in "
+ "(NON-RESOLVABLE PATH - does it exist?): "
+ dir.getPath());
}
return;
}
} catch (MissingWorldException ex) {
player.printError("No snapshots were found for this world.");
return;
}
}
ChunkStore chunkStore = null;
// Load chunk store
try {
chunkStore = snapshot.getChunkStore();
player.print("Snapshot '" + snapshot.getName() + "' loaded; now restoring...");
} catch (DataException e) {
player.printError("Failed to load snapshot: " + e.getMessage());
return;
} catch (IOException e) {
player.printError("Failed to load snapshot: " + e.getMessage());
return;
}
try {
// Restore snapshot
SnapshotRestore restore = new SnapshotRestore(chunkStore, editSession, region);
//player.print(restore.getChunksAffected() + " chunk(s) will be loaded.");
restore.restore();
if (restore.hadTotalFailure()) {
String error = restore.getLastErrorMessage();
if (error != null) {
player.printError("Errors prevented any blocks from being restored.");
player.printError("Last error: " + error);
} else {
player.printError("No chunks could be loaded. (Bad archive?)");
}
} else {
player.print(String.format("Restored; %d "
+ "missing chunks and %d other errors.",
restore.getMissingChunks().size(),
restore.getErrorChunks().size()));
}
} finally {
try {
chunkStore.close();
} catch (IOException e) {
}
}
}
}

View File

@ -0,0 +1,105 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.tool.AreaPickaxe;
import com.sk89q.worldedit.command.tool.RecursivePickaxe;
import com.sk89q.worldedit.command.tool.SinglePickaxe;
public class SuperPickaxeCommands {
private final WorldEdit we;
public SuperPickaxeCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "single" },
usage = "",
desc = "Enable the single block super pickaxe mode",
min = 0,
max = 0
)
@CommandPermissions("worldedit.superpickaxe")
public void single(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setSuperPickaxe(new SinglePickaxe());
session.enableSuperPickAxe();
player.print("Mode changed. Left click with a pickaxe. // to disable.");
}
@Command(
aliases = { "area" },
usage = "<radius>",
desc = "Enable the area super pickaxe pickaxe mode",
min = 1,
max = 1
)
@CommandPermissions("worldedit.superpickaxe.area")
public void area(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
int range = args.getInteger(0);
if (range > config.maxSuperPickaxeSize) {
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
return;
}
session.setSuperPickaxe(new AreaPickaxe(range));
session.enableSuperPickAxe();
player.print("Mode changed. Left click with a pickaxe. // to disable.");
}
@Command(
aliases = { "recur", "recursive" },
usage = "<radius>",
desc = "Enable the recursive super pickaxe pickaxe mode",
min = 1,
max = 1
)
@CommandPermissions("worldedit.superpickaxe.recursive")
public void recursive(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
double range = args.getDouble(0);
if (range > config.maxSuperPickaxeSize) {
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
return;
}
session.setSuperPickaxe(new RecursivePickaxe(range));
session.enableSuperPickAxe();
player.print("Mode changed. Left click with a pickaxe. // to disable.");
}
}

View File

@ -0,0 +1,212 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.command.tool.*;
import com.sk89q.worldedit.util.TreeGenerator;
public class ToolCommands {
private final WorldEdit we;
public ToolCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "none" },
usage = "",
desc = "Unbind a bound tool from your current item",
min = 0,
max = 0
)
public void none(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setTool(player.getItemInHand(), null);
player.print("Tool unbound from your current item.");
}
@Command(
aliases = { "info" },
usage = "",
desc = "Block information tool",
min = 0,
max = 0
)
@CommandPermissions("worldedit.tool.info")
public void info(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setTool(player.getItemInHand(), new QueryTool());
player.print("Info tool bound to "
+ ItemType.toHeldName(player.getItemInHand()) + ".");
}
@Command(
aliases = { "tree" },
usage = "[type]",
desc = "Tree generator tool",
min = 0,
max = 1
)
@CommandPermissions("worldedit.tool.tree")
@SuppressWarnings("deprecation")
public void tree(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
TreeGenerator.TreeType type = args.argsLength() > 0 ?
type = TreeGenerator.lookup(args.getString(0))
: TreeGenerator.TreeType.TREE;
if (type == null) {
player.printError("Tree type '" + args.getString(0) + "' is unknown.");
return;
}
session.setTool(player.getItemInHand(), new TreePlanter(new TreeGenerator(type)));
player.print("Tree tool bound to "
+ ItemType.toHeldName(player.getItemInHand()) + ".");
}
@Command(
aliases = { "repl" },
usage = "<block>",
desc = "Block replacer tool",
min = 1,
max = 1
)
@CommandPermissions("worldedit.tool.replacer")
public void repl(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
BaseBlock targetBlock = we.getBlock(player, args.getString(0));
session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock));
player.print("Block replacer tool bound to "
+ ItemType.toHeldName(player.getItemInHand()) + ".");
}
@Command(
aliases = { "cycler" },
usage = "",
desc = "Block data cycler tool",
min = 0,
max = 0
)
@CommandPermissions("worldedit.tool.data-cycler")
public void cycler(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setTool(player.getItemInHand(), new BlockDataCyler());
player.print("Block data cycler tool bound to "
+ ItemType.toHeldName(player.getItemInHand()) + ".");
}
@Command(
aliases = { "floodfill", "flood" },
usage = "<pattern> <range>",
desc = "Flood fill tool",
min = 2,
max = 2
)
@CommandPermissions("worldedit.tool.flood-fill")
public void floodFill(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
int range = args.getInteger(1);
if (range > config.maxSuperPickaxeSize) {
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
return;
}
Pattern pattern = we.getBlockPattern(player, args.getString(0));
session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern));
player.print("Block flood fill tool bound to "
+ ItemType.toHeldName(player.getItemInHand()) + ".");
}
@Command(
aliases = { "brush", "br" },
desc = "Brush tool"
)
@NestedCommand(BrushCommands.class)
public void brush(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command(
aliases = { "deltree" },
usage = "",
desc = "Floating tree remover tool",
min = 0,
max = 0
)
@CommandPermissions("worldedit.tool.deltree")
public void deltree(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setTool(player.getItemInHand(), new FloatingTreeRemover());
player.print("Floating tree remover tool bound to "
+ ItemType.toHeldName(player.getItemInHand()) + ".");
}
@Command(
aliases = { "farwand" },
usage = "",
desc = "Wand at a distance tool",
min = 0,
max = 0
)
@CommandPermissions("worldedit.tool.farwand")
public void farwand(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setTool(player.getItemInHand(), new DistanceWand());
player.print("Far wand tool bound to " + ItemType.toHeldName(player.getItemInHand()) + ".");
}
@Command(
aliases = { "lrbuild", "/lrbuild" },
usage = "<leftclick block> <rightclick block>",
desc = "Long-range building tool",
min = 2,
max = 2
)
@CommandPermissions("worldedit.tool.lrbuild")
public void longrangebuildtool(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
BaseBlock secondary = we.getBlock(player, args.getString(0));
BaseBlock primary = we.getBlock(player, args.getString(1));
session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary));
player.print("Long-range building tool bound to " + ItemType.toHeldName(player.getItemInHand()) + ".");
player.print("Left-click set to " + ItemType.toName(secondary.getType()) + "; right-click set to "
+ ItemType.toName(primary.getType()) + ".");
}
}

View File

@ -0,0 +1,158 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.patterns.Pattern;
/**
* Tool commands.
*
* @author sk89q
*/
public class ToolUtilCommands {
private final WorldEdit we;
public ToolUtilCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/", "," },
usage = "[on|off]",
desc = "Toggle the super pickaxe pickaxe function",
min = 0,
max = 1
)
@CommandPermissions("worldedit.superpickaxe")
public void togglePickaxe(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
String newState = args.getString(0, null);
if (session.hasSuperPickAxe()) {
if ("on".equals(newState)) {
player.printError("Super pick axe already enabled.");
return;
}
session.disableSuperPickAxe();
player.print("Super pick axe disabled.");
} else {
if ("off".equals(newState)) {
player.printError("Super pick axe already disabled.");
return;
}
session.enableSuperPickAxe();
player.print("Super pick axe enabled.");
}
}
@Command(
aliases = { "superpickaxe", "pickaxe", "sp" },
desc = "Select super pickaxe mode"
)
@NestedCommand(SuperPickaxeCommands.class)
public void pickaxe(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command(
aliases = {"tool"},
desc = "Select a tool to bind"
)
@NestedCommand(ToolCommands.class)
public void tool(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command(
aliases = { "mask" },
usage = "[mask]",
desc = "Set the brush mask",
min = 0,
max = -1
)
@CommandPermissions("worldedit.brush.options.mask")
public void mask(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
if (args.argsLength() == 0) {
session.getBrushTool(player.getItemInHand()).setMask(null);
player.print("Brush mask disabled.");
} else {
Mask mask = we.getBlockMask(player, session, args.getJoinedStrings(0));
session.getBrushTool(player.getItemInHand()).setMask(mask);
player.print("Brush mask set.");
}
}
@Command(
aliases = { "mat", "material" },
usage = "[pattern]",
desc = "Set the brush material",
min = 1,
max = 1
)
@CommandPermissions("worldedit.brush.options.material")
public void material(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern pattern = we.getBlockPattern(player, args.getString(0));
session.getBrushTool(player.getItemInHand()).setFill(pattern);
player.print("Brush material set.");
}
@Command(
aliases = { "range" },
usage = "[pattern]",
desc = "Set the brush range",
min = 1,
max = 1
)
@CommandPermissions("worldedit.brush.options.range")
public void range(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int range = args.getInteger(0);
session.getBrushTool(player.getItemInHand()).setRange(range);
player.print("Brush range set.");
}
@Command(
aliases = { "size" },
usage = "[pattern]",
desc = "Set the brush size",
min = 1,
max = 1
)
@CommandPermissions("worldedit.brush.options.size")
public void size(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int radius = args.getInteger(0);
we.checkMaxBrushRadius(radius);
session.getBrushTool(player.getItemInHand()).setSize(radius);
player.print("Brush size set.");
}
}

View File

@ -0,0 +1,554 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import com.sk89q.minecraft.util.commands.*;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
/**
* Utility commands.
*
* @author sk89q
*/
public class UtilityCommands {
private final WorldEdit we;
public UtilityCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/fill" },
usage = "<block> <radius> [depth]",
desc = "Fill a hole",
min = 2,
max = 3
)
@CommandPermissions("worldedit.fill")
@Logging(PLACEMENT)
public void fill(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern pattern = we.getBlockPattern(player, args.getString(0));
double radius = Math.max(1, args.getDouble(1));
we.checkMaxRadius(radius);
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : 1;
Vector pos = session.getPlacementPosition(player);
int affected = 0;
if (pattern instanceof SingleBlockPattern) {
affected = editSession.fillXZ(pos,
((SingleBlockPattern) pattern).getBlock(),
radius, depth, false);
} else {
affected = editSession.fillXZ(pos, pattern, radius, depth, false);
}
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/fillr" },
usage = "<block> <radius> [depth]",
desc = "Fill a hole recursively",
min = 2,
max = 3
)
@CommandPermissions("worldedit.fill.recursive")
@Logging(PLACEMENT)
public void fillr(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
Pattern pattern = we.getBlockPattern(player, args.getString(0));
double radius = Math.max(1, args.getDouble(1));
we.checkMaxRadius(radius);
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : Integer.MAX_VALUE;
Vector pos = session.getPlacementPosition(player);
int affected = 0;
if (pattern instanceof SingleBlockPattern) {
affected = editSession.fillXZ(pos,
((SingleBlockPattern) pattern).getBlock(),
radius, depth, true);
} else {
affected = editSession.fillXZ(pos, pattern, radius, depth, true);
}
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/drain" },
usage = "<radius>",
desc = "Drain a pool",
min = 1,
max = 1
)
@CommandPermissions("worldedit.drain")
@Logging(PLACEMENT)
public void drain(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
double radius = Math.max(0, args.getDouble(0));
we.checkMaxRadius(radius);
int affected = editSession.drainArea(
session.getPlacementPosition(player), radius);
player.print(affected + " block(s) have been changed.");
}
@Command(
aliases = { "/fixlava", "fixlava" },
usage = "<radius>",
desc = "Fix lava to be stationary",
min = 1,
max = 1
)
@CommandPermissions("worldedit.fixlava")
@Logging(PLACEMENT)
public void fixLava(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
double radius = Math.max(0, args.getDouble(0));
we.checkMaxRadius(radius);
int affected = editSession.fixLiquid(
session.getPlacementPosition(player), radius, 10, 11);
player.print(affected + " block(s) have been changed.");
}
@Command(
aliases = { "/fixwater", "fixwater" },
usage = "<radius>",
desc = "Fix water to be stationary",
min = 1,
max = 1
)
@CommandPermissions("worldedit.fixwater")
@Logging(PLACEMENT)
public void fixWater(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
double radius = Math.max(0, args.getDouble(0));
we.checkMaxRadius(radius);
int affected = editSession.fixLiquid(
session.getPlacementPosition(player), radius, 8, 9);
player.print(affected + " block(s) have been changed.");
}
@Command(
aliases = { "/removeabove", "removeabove" },
usage = "[size] [height]",
desc = "Remove blocks above your head.",
min = 0,
max = 2
)
@CommandPermissions("worldedit.removeabove")
@Logging(PLACEMENT)
public void removeAbove(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
we.checkMaxRadius(size);
LocalWorld world = player.getWorld();
int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1);
int affected = editSession.removeAbove(
session.getPlacementPosition(player), size, height);
player.print(affected + " block(s) have been removed.");
}
@Command(
aliases = { "/removebelow", "removebelow" },
usage = "[size] [height]",
desc = "Remove blocks below you.",
min = 0,
max = 2
)
@CommandPermissions("worldedit.removebelow")
@Logging(PLACEMENT)
public void removeBelow(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
we.checkMaxRadius(size);
LocalWorld world = player.getWorld();
int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1);
int affected = editSession.removeBelow(session.getPlacementPosition(player), size, height);
player.print(affected + " block(s) have been removed.");
}
@Command(
aliases = { "/removenear", "removenear" },
usage = "<block> [size]",
desc = "Remove blocks near you.",
min = 1,
max = 2
)
@CommandPermissions("worldedit.removenear")
@Logging(PLACEMENT)
public void removeNear(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
BaseBlock block = we.getBlock(player, args.getString(0), true);
int size = Math.max(1, args.getInteger(1, 50));
we.checkMaxRadius(size);
int affected = editSession.removeNear(session.getPlacementPosition(player), block.getType(), size);
player.print(affected + " block(s) have been removed.");
}
@Command(
aliases = { "/replacenear", "replacenear" },
usage = "<size> <from-id> <to-id>",
desc = "Replace nearby blocks",
flags = "f",
min = 3,
max = 3
)
@CommandPermissions("worldedit.replacenear")
@Logging(PLACEMENT)
public void replaceNear(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
int size = Math.max(1, args.getInteger(0));
int affected;
Set<BaseBlock> from;
Pattern to;
if (args.argsLength() == 2) {
from = null;
to = we.getBlockPattern(player, args.getString(1));
} else {
from = we.getBlocks(player, args.getString(1), true, !args.hasFlag('f'));
to = we.getBlockPattern(player, args.getString(2));
}
Vector base = session.getPlacementPosition(player);
Vector min = base.subtract(size, size, size);
Vector max = base.add(size, size, size);
Region region = new CuboidRegion(player.getWorld(), min, max);
if (to instanceof SingleBlockPattern) {
affected = editSession.replaceBlocks(region, from, ((SingleBlockPattern) to).getBlock());
} else {
affected = editSession.replaceBlocks(region, from, to);
}
player.print(affected + " block(s) have been replaced.");
}
@Command(
aliases = { "/snow", "snow" },
usage = "[radius]",
desc = "Simulates snow",
min = 0,
max = 1
)
@CommandPermissions("worldedit.snow")
@Logging(PLACEMENT)
public void snow(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
int affected = editSession.simulateSnow(session.getPlacementPosition(player), size);
player.print(affected + " surfaces covered. Let it snow~");
}
@Command(
aliases = {"/thaw", "thaw"},
usage = "[radius]",
desc = "Thaws the area",
min = 0,
max = 1
)
@CommandPermissions("worldedit.thaw")
@Logging(PLACEMENT)
public void thaw(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
int affected = editSession.thaw(session.getPlacementPosition(player), size);
player.print(affected + " surfaces thawed.");
}
@Command(
aliases = { "/green", "green" },
usage = "[radius]",
desc = "Greens the area",
flags = "f",
min = 0,
max = 1
)
@CommandPermissions("worldedit.green")
@Logging(PLACEMENT)
public void green(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
final double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
final boolean onlyNormalDirt = !args.hasFlag('f');
final int affected = editSession.green(session.getPlacementPosition(player), size, onlyNormalDirt);
player.print(affected + " surfaces greened.");
}
@Command(
aliases = { "/ex", "/ext", "/extinguish", "ex", "ext", "extinguish" },
usage = "[radius]",
desc = "Extinguish nearby fire",
min = 0,
max = 1
)
@CommandPermissions("worldedit.extinguish")
@Logging(PLACEMENT)
public void extinguish(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40;
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0))
: defaultRadius;
we.checkMaxRadius(size);
int affected = editSession.removeNear(session.getPlacementPosition(player), 51, size);
player.print(affected + " block(s) have been removed.");
}
@Command(
aliases = { "butcher" },
usage = "[radius]",
flags = "plangbf",
desc = "Kill all or nearby mobs",
help =
"Kills nearby mobs, based on radius, if none is given uses default in configuration.\n" +
"Flags:" +
" -p also kills pets.\n" +
" -n also kills NPCs.\n" +
" -g also kills Golems.\n" +
" -a also kills animals.\n" +
" -b also kills ambient mobs.\n" +
" -f compounds all previous flags.\n" +
" -l strikes lightning on each killed mob.",
min = 0,
max = 1
)
@CommandPermissions("worldedit.butcher")
@Logging(PLACEMENT)
@Console
public void butcher(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
// technically the default can be larger than the max, but that's not my problem
int radius = config.butcherDefaultRadius;
// there might be a better way to do this but my brain is fried right now
if (args.argsLength() > 0) { // user inputted radius, override the default
radius = args.getInteger(0);
if (config.butcherMaxRadius != -1) { // clamp if there is a max
if (radius == -1) {
radius = config.butcherMaxRadius;
} else { // Math.min does not work if radius is -1 (actually highest possible value)
radius = Math.min(radius, config.butcherMaxRadius);
}
}
}
FlagContainer flags = new FlagContainer(player);
flags.or(KillFlags.FRIENDLY , args.hasFlag('f')); // No permission check here. Flags will instead be filtered by the subsequent calls.
flags.or(KillFlags.PETS , args.hasFlag('p'), "worldedit.butcher.pets");
flags.or(KillFlags.NPCS , args.hasFlag('n'), "worldedit.butcher.npcs");
flags.or(KillFlags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems");
flags.or(KillFlags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals");
flags.or(KillFlags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient");
flags.or(KillFlags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning");
// If you add flags here, please add them to com.sk89q.worldedit.commands.BrushCommands.butcherBrush() as well
int killed;
if (player.isPlayer()) {
killed = player.getWorld().killMobs(session.getPlacementPosition(player), radius, flags.flags);
} else {
killed = 0;
for (LocalWorld world : we.getServer().getWorlds()) {
killed += world.killMobs(new Vector(), radius, flags.flags);
}
}
if (radius < 0) {
player.print("Killed " + killed + " mobs.");
} else {
player.print("Killed " + killed + " mobs in a radius of " + radius + ".");
}
}
public static class FlagContainer {
private final LocalPlayer player;
public int flags = 0;
public FlagContainer(LocalPlayer player) {
this.player = player;
}
public void or(int flag, boolean on) {
if (on) flags |= flag;
}
public void or(int flag, boolean on, String permission) {
or(flag, on);
if ((flags & flag) != 0 && !player.hasPermission(permission)) {
flags &= ~flag;
}
}
}
@Command(
aliases = { "remove", "rem", "rement" },
usage = "<type> <radius>",
desc = "Remove all entities of a type",
min = 2,
max = 2
)
@CommandPermissions("worldedit.remove")
@Logging(PLACEMENT)
@Console
public void remove(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
String typeStr = args.getString(0);
int radius = args.getInteger(1);
if (radius < -1) {
player.printError("Use -1 to remove all entities in loaded chunks");
return;
}
EntityType type = null;
if (typeStr.matches("all")) {
type = EntityType.ALL;
} else if (typeStr.matches("projectiles?|arrows?")) {
type = EntityType.PROJECTILES;
} else if (typeStr.matches("items?")
|| typeStr.matches("drops?")) {
type = EntityType.ITEMS;
} else if (typeStr.matches("falling(blocks?|sand|gravel)")) {
type = EntityType.FALLING_BLOCKS;
} else if (typeStr.matches("paintings?")
|| typeStr.matches("art")) {
type = EntityType.PAINTINGS;
} else if (typeStr.matches("(item)frames?")) {
type = EntityType.ITEM_FRAMES;
} else if (typeStr.matches("boats?")) {
type = EntityType.BOATS;
} else if (typeStr.matches("minecarts?")
|| typeStr.matches("carts?")) {
type = EntityType.MINECARTS;
} else if (typeStr.matches("tnt")) {
type = EntityType.TNT;
} else if (typeStr.matches("xp")) {
type = EntityType.XP_ORBS;
} else {
player.printError("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all");
return;
}
int removed = 0;
if (player.isPlayer()) {
Vector origin = session.getPlacementPosition(player);
removed = player.getWorld().removeEntities(type, origin, radius);
} else {
for (LocalWorld world : we.getServer().getWorlds()) {
removed += world.removeEntities(type, new Vector(), radius);
}
}
player.print("Marked " + removed + " entit(ies) for removal.");
}
@Command(
aliases = { "/help" },
usage = "[<command>]",
desc = "Displays help for the given command or lists all commands.",
min = 0,
max = -1
)
@Console
@CommandPermissions("worldedit.help")
public void help(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
help(args, we, session, player, editSession);
}
public static void help(CommandContext args, WorldEdit we, LocalSession session, LocalPlayer player, EditSession editSession) {
final CommandsManager<LocalPlayer> commandsManager = we.getCommandsManager();
if (args.argsLength() == 0) {
SortedSet<String> commands = new TreeSet<String>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
final int ret = o1.replaceAll("/", "").compareToIgnoreCase(o2.replaceAll("/", ""));
if (ret == 0) {
return o1.compareToIgnoreCase(o2);
}
return ret;
}
});
commands.addAll(commandsManager.getCommands().keySet());
StringBuilder sb = new StringBuilder();
boolean first = true;
for (String command : commands) {
if (!first) {
sb.append(", ");
}
sb.append('/');
sb.append(command);
first = false;
}
player.print(sb.toString());
return;
}
String command = args.getJoinedStrings(0).toLowerCase().replaceAll("/", "");
String helpMessage = commandsManager.getHelpMessages().get(command);
if (helpMessage == null) {
player.printError("Unknown command '" + command + "'.");
return;
}
player.print(helpMessage);
}
}

View File

@ -0,0 +1,120 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Console;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
public class WorldEditCommands {
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
private final WorldEdit we;
public WorldEditCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "version", "ver" },
usage = "",
desc = "Get WorldEdit version",
min = 0,
max = 0
)
@Console
public void version(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
player.print("WorldEdit version " + WorldEdit.getVersion());
player.print("http://www.sk89q.com/projects/worldedit/");
}
@Command(
aliases = { "reload" },
usage = "",
desc = "Reload WorldEdit",
min = 0,
max = 0
)
@CommandPermissions("worldedit.reload")
@Console
public void reload(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
we.getServer().reload();
player.print("Configuration reloaded!");
}
@Command(
aliases = { "cui" },
usage = "",
desc = "Complete CUI handshake",
min = 0,
max = 0
)
public void cui(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
session.setCUISupport(true);
session.dispatchCUISetup(player);
}
@Command(
aliases = { "tz" },
usage = "[timezone]",
desc = "Set your timezone",
min = 1,
max = 1
)
@Console
public void tz(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
TimeZone tz = TimeZone.getTimeZone(args.getString(0));
session.setTimezone(tz);
player.print("Timezone set for this session to: " + tz.getDisplayName());
player.print("The current time in that timezone is: "
+ dateFormat.format(Calendar.getInstance(tz).getTime()));
}
@Command(
aliases = { "help" },
usage = "[<command>]",
desc = "Displays help for the given command or lists all commands.",
min = 0,
max = -1
)
@CommandPermissions("worldedit.help")
@Console
public void help(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
UtilityCommands.help(args, we, session, player, editSession);
}
}

View File

@ -0,0 +1,87 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
/**
* A super pickaxe mode that will remove blocks in an area.
*
* @author sk89q
*/
public class AreaPickaxe implements BlockTool {
private static final BaseBlock air = new BaseBlock(0);
private int range;
public AreaPickaxe(int range) {
this.range = range;
}
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.superpickaxe.area");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
int ox = clicked.getBlockX();
int oy = clicked.getBlockY();
int oz = clicked.getBlockZ();
int initialType = world.getBlockType(clicked);
if (initialType == 0) {
return true;
}
if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) {
return true;
}
EditSession editSession = session.createEditSession(player);
try {
for (int x = ox - range; x <= ox + range; ++x) {
for (int y = oy - range; y <= oy + range; ++y) {
for (int z = oz - range; z <= oz + range; ++z) {
Vector pos = new Vector(x, y, z);
if (world.getBlockType(pos) != initialType) {
continue;
}
if (config.superPickaxeManyDrop) {
world.simulateBlockMine(pos);
}
world.queueBlockBreakEffect(server, pos, initialType, clicked.distanceSq(pos));
editSession.setBlock(pos, air);
}
}
}
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
session.remember(editSession);
}
return true;
}
}

View File

@ -0,0 +1,74 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
/**
* A mode that cycles the data values of supported blocks.
*
* @author sk89q
*/
public class BlockDataCyler implements DoubleActionBlockTool {
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.tool.data-cycler");
}
private boolean handleCycle(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked, boolean forward) {
LocalWorld world = clicked.getWorld();
int type = world.getBlockType(clicked);
int data = world.getBlockData(clicked);
if (config.allowedDataCycleBlocks.size() > 0
&& !player.hasPermission("worldedit.override.data-cycler")
&& !config.allowedDataCycleBlocks.contains(type)) {
player.printError("You are not permitted to cycle the data value of that block.");
return true;
}
int increment = forward ? 1 : -1;
data = (new BaseBlock(type, data)).cycleData(increment);
if (data < 0) {
player.printError("That block's data cannot be cycled!");
} else {
world.setBlockData(clicked, data);
}
return true;
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
return handleCycle(server, config, player, session, clicked, true);
}
public boolean actSecondary(ServerInterface server,
LocalConfiguration config, LocalPlayer player,
LocalSession session, WorldVector clicked) {
return handleCycle(server, config, player, session, clicked, false);
}
}

View File

@ -0,0 +1,80 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
/**
* A mode that replaces one block.
*
* @author sk89q
*/
public class BlockReplacer implements DoubleActionBlockTool {
private BaseBlock targetBlock;
public BlockReplacer(BaseBlock targetBlock) {
this.targetBlock = targetBlock;
}
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.tool.replacer");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
BlockBag bag = session.getBlockBag(player);
LocalWorld world = clicked.getWorld();
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, bag, player);
try {
editSession.setBlock(clicked, targetBlock);
} catch (MaxChangedBlocksException e) {
} finally {
if (bag != null) {
bag.flushChanges();
}
session.remember(editSession);
}
return true;
}
public boolean actSecondary(ServerInterface server,
LocalConfiguration config, LocalPlayer player,
LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, player);
targetBlock = (editSession).getBlock(clicked);
BlockType type = BlockType.fromID(targetBlock.getType());
if (type != null) {
player.print("Replacer tool switched to: " + type.getName());
}
return true;
}
}

View File

@ -0,0 +1,43 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
/**
* Represents a tool that uses a block..
*
* @author sk89q
*/
public interface BlockTool extends Tool {
/**
* Perform the action. Should return true to deny the default
* action.
*
* @param server
* @param config
* @param player
* @param session
* @param clicked
* @return true to deny
*/
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked);
}

View File

@ -0,0 +1,208 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.masks.CombinedMask;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
/**
* Builds a shape at the place being looked at.
*
* @author sk89q
*/
public class BrushTool implements TraceTool {
protected static int MAX_RANGE = 500;
protected int range = -1;
private Mask mask = null;
private Brush brush = new SphereBrush();
private Pattern material = new SingleBlockPattern(new BaseBlock(BlockID.COBBLESTONE));
private double size = 1;
private String permission;
/**
* Construct the tool.
*
* @param permission
*/
public BrushTool(String permission) {
this.permission = permission;
}
/**
* Checks to see if the player can still be using this tool (considering
* permissions and such).
*
* @param player
* @return
*/
public boolean canUse(LocalPlayer player) {
return player.hasPermission(permission);
}
/**
* Get the filter.
*
* @return the filter
*/
public Mask getMask() {
return mask;
}
/**
* Set the block filter used for identifying blocks to replace.
*
* @param filter the filter to set
*/
public void setMask(Mask filter) {
this.mask = filter;
}
/**
* Set the brush.
*
* @param brush
* @param perm
*/
public void setBrush(Brush brush, String perm) {
this.brush = brush;
this.permission = perm;
}
/**
* Get the current brush.
*
* @return
*/
public Brush getBrush() {
return brush;
}
/**
* Set the material.
*
* @param material
*/
public void setFill(Pattern material) {
this.material = material;
}
/**
* Get the material.
*
* @return
*/
public Pattern getMaterial() {
return material;
}
/**
* Get the set brush size.
*
* @return
*/
public double getSize() {
return size;
}
/**
* Set the set brush size.
*
* @param radius
*/
public void setSize(double radius) {
this.size = radius;
}
/**
* Get the set brush range.
*
* @return
*/
public int getRange() {
return (range < 0) ? MAX_RANGE : Math.min(range, MAX_RANGE);
}
/**
* Set the set brush range.
*
* @param size
*/
public void setRange(int range) {
this.range = range;
}
/**
* Perform the action. Should return true to deny the default
* action.
*
* @param player
* @param session
* @return true to deny
*/
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session) {
WorldVector target = null;
target = player.getBlockTrace(getRange(), true);
if (target == null) {
player.printError("No block in sight!");
return true;
}
BlockBag bag = session.getBlockBag(player);
EditSession editSession = session.createEditSession(player);
if (mask != null) {
mask.prepare(session, player, target);
Mask existingMask = editSession.getMask();
if (existingMask == null) {
editSession.setMask(mask);
} else if (existingMask instanceof CombinedMask) {
((CombinedMask) existingMask).add(mask);
} else {
CombinedMask newMask = new CombinedMask(existingMask);
newMask.add(mask);
editSession.setMask(newMask);
}
}
try {
brush.build(editSession, target, material, size);
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
if (bag != null) {
bag.flushChanges();
}
session.remember(editSession);
}
return true;
}
}

View File

@ -0,0 +1,90 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.regions.RegionSelector;
/**
* A wand that can be used at a distance.
*
* @author wizjany
*/
public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
public DistanceWand() {
super("worldedit.wand");
}
@Override
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.wand");
}
public boolean actSecondary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session) {
if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) {
WorldVector target = getTarget(player);
if (target == null) return true;
RegionSelector selector = session.getRegionSelector(player.getWorld());
if (selector.selectPrimary(target)) {
selector.explainPrimarySelection(player, session, target);
}
return true;
}
return false;
}
@Override
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session) {
if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) {
WorldVector target = getTarget(player);
if (target == null) return true;
RegionSelector selector = session.getRegionSelector(player.getWorld());
if (selector.selectSecondary(target)) {
selector.explainSecondarySelection(player, session, target);
}
return true;
}
return false;
}
public WorldVector getTarget(LocalPlayer player) {
WorldVector target = null;
if (this.range > -1) {
target = player.getBlockTrace(getRange(), true);
} else {
target = player.getBlockTrace(MAX_RANGE);
}
if (target == null) {
player.printError("No block in sight!");
return null;
}
return target;
}
}

View File

@ -0,0 +1,47 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.WorldVector;
/**
* Represents a block tool that also has a secondary/primary function.
*
* @author sk89q
*/
public interface DoubleActionBlockTool extends BlockTool {
/**
* Perform the secondary action. Should return true to deny the default
* action.
*
* @param server
* @param config
* @param player
* @param session
* @param clicked
* @return true to deny
*/
public boolean actSecondary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked);
}

View File

@ -0,0 +1,43 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.ServerInterface;
/**
* Represents a trace tool that also has a secondary/primary function.
*/
public interface DoubleActionTraceTool extends TraceTool {
/**
* Perform the secondary action. Should return true to deny the default
* action.
*
* @param server
* @param config
* @param player
* @param session
* @return true to deny
*/
public boolean actSecondary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session);
}

View File

@ -0,0 +1,166 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
/**
* A pickaxe mode that removes floating treetops (logs and leaves not connected
* to anything else)
*
* @author Moo0
*/
public class FloatingTreeRemover implements BlockTool {
private static final BaseBlock AIR = new BaseBlock(BlockID.AIR);
private int rangeSq;
public FloatingTreeRemover() {
rangeSq = 100*100;
}
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.tool.deltree");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
final LocalWorld world = clicked.getWorld();
switch (world.getBlockType(clicked)) {
case BlockID.LOG:
case BlockID.LOG2:
case BlockID.LEAVES:
case BlockID.LEAVES2:
case BlockID.BROWN_MUSHROOM_CAP:
case BlockID.RED_MUSHROOM_CAP:
case BlockID.VINE:
break;
default:
player.printError("That's not a tree.");
return true;
}
final EditSession editSession = session.createEditSession(player);
try {
final Set<Vector> blockSet = bfs(world, clicked);
if (blockSet == null) {
player.printError("That's not a floating tree.");
return true;
}
for (Vector blockVector : blockSet) {
final int typeId = editSession.getBlock(blockVector).getType();
switch (typeId) {
case BlockID.LOG:
case BlockID.LOG2:
case BlockID.LEAVES:
case BlockID.LEAVES2:
case BlockID.BROWN_MUSHROOM_CAP:
case BlockID.RED_MUSHROOM_CAP:
case BlockID.VINE:
editSession.setBlock(blockVector, AIR);
}
}
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
session.remember(editSession);
}
return true;
}
Vector[] recurseDirections = {
PlayerDirection.NORTH.vector(),
PlayerDirection.EAST.vector(),
PlayerDirection.SOUTH.vector(),
PlayerDirection.WEST.vector(),
PlayerDirection.UP.vector(),
PlayerDirection.DOWN.vector(),
};
/**
* Helper method.
*
* @param world the world that contains the tree
* @param origin any point contained in the floating tree
* @return a set containing all blocks in the tree/shroom or null if this is not a floating tree/shroom.
*/
private Set<Vector> bfs(LocalWorld world, Vector origin) throws MaxChangedBlocksException {
final Set<Vector> visited = new HashSet<Vector>();
final LinkedList<Vector> queue = new LinkedList<Vector>();
queue.addLast(origin);
visited.add(origin);
while (!queue.isEmpty()) {
final Vector current = queue.removeFirst();
for (Vector recurseDirection : recurseDirections) {
final Vector next = current.add(recurseDirection);
if (origin.distanceSq(next) > rangeSq) {
// Maximum range exceeded => stop walking
continue;
}
if (visited.add(next)) {
switch (world.getBlockType(next)) {
case BlockID.AIR:
case BlockID.SNOW:
// we hit air or snow => stop walking this route
continue;
case BlockID.LOG:
case BlockID.LOG2:
case BlockID.LEAVES:
case BlockID.LEAVES2:
case BlockID.BROWN_MUSHROOM_CAP:
case BlockID.RED_MUSHROOM_CAP:
case BlockID.VINE:
// queue next point
queue.addLast(next);
break;
default:
// we hit something solid - evaluate where we came from
final int curId = world.getBlockType(current);
if (curId == BlockID.LEAVES || curId == BlockID.LEAVES2
|| curId == BlockID.VINE) {
// leaves touching a wall/the ground => stop walking this route
continue;
} else {
// log/shroom touching a wall/the ground => this is not a floating tree, bail out
return null;
}
} // switch
} // if
} // for
} // while
return visited;
} // bfs
}

View File

@ -0,0 +1,118 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import java.util.HashSet;
import java.util.Set;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.patterns.Pattern;
/**
* A tool that flood fills blocks.
*
* @author sk89q
*/
public class FloodFillTool implements BlockTool {
private int range;
private Pattern pattern;
public FloodFillTool(int range, Pattern pattern) {
this.range = range;
this.pattern = pattern;
}
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.tool.flood-fill");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
int initialType = world.getBlockType(clicked);
if (initialType == BlockID.AIR) {
return true;
}
if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) {
return true;
}
EditSession editSession = session.createEditSession(player);
try {
recurse(server, editSession, world, clicked.toBlockVector(),
clicked, range, initialType, new HashSet<BlockVector>());
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
session.remember(editSession);
}
return true;
}
/**
* Helper method.
*
* @param server
* @param superPickaxeManyDrop
* @param world
* @param pos
* @param origin
* @param size
* @param initialType
* @param visited
*/
private void recurse(ServerInterface server, EditSession editSession,
LocalWorld world, BlockVector pos,
Vector origin, int size, int initialType,
Set<BlockVector> visited)
throws MaxChangedBlocksException {
if (origin.distance(pos) > size || visited.contains(pos)) {
return;
}
visited.add(pos);
if (editSession.getBlock(pos).getType() == initialType) {
editSession.setBlock(pos, pattern.next(pos));
} else {
return;
}
recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(),
origin, size, initialType, visited);
}
}

View File

@ -0,0 +1,98 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
/**
* A tool that can place (or remove) blocks at a distance.
*
* @author wizjany
*/
public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTool {
BaseBlock primary;
BaseBlock secondary;
public LongRangeBuildTool(BaseBlock primary, BaseBlock secondary) {
super("worldedit.tool.lrbuild");
this.primary = primary;
this.secondary = secondary;
}
@Override
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.tool.lrbuild");
}
public boolean actSecondary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session) {
WorldVectorFace pos = getTargetFace(player);
if (pos == null) return false;
EditSession eS = session.createEditSession(player);
try {
if (secondary.getType() == BlockID.AIR) {
eS.setBlock(pos, secondary);
} else {
eS.setBlock(pos.getFaceVector(), secondary);
}
return true;
} catch (MaxChangedBlocksException e) {
// one block? eat it
}
return false;
}
@Override
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session) {
WorldVectorFace pos = getTargetFace(player);
if (pos == null) return false;
EditSession eS = session.createEditSession(player);
try {
if (primary.getType() == BlockID.AIR) {
eS.setBlock(pos, primary);
} else {
eS.setBlock(pos.getFaceVector(), primary);
}
return true;
} catch (MaxChangedBlocksException e) {
// one block? eat it
}
return false;
}
public WorldVectorFace getTargetFace(LocalPlayer player) {
WorldVectorFace target = null;
target = player.getBlockTraceFace(getRange(), true);
if (target == null) {
player.printError("No block in sight!");
return null;
}
return target;
}
}

View File

@ -0,0 +1,65 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.*;
/**
* Plants a tree.
*
* @author sk89q
*/
public class QueryTool implements BlockTool {
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.tool.info");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, 0, player);
BaseBlock block = (editSession).rawGetBlock(clicked);
BlockType type = BlockType.fromID(block.getType());
player.print("\u00A79@" + clicked + ": " + "\u00A7e"
+ "#" + block.getType() + "\u00A77" + " ("
+ (type == null ? "Unknown" : type.getName()) + ") "
+ "\u00A7f"
+ "[" + block.getData() + "]" + " (" + world.getBlockLightLevel(clicked) + "/" + world.getBlockLightLevel(clicked.add(0, 1, 0)) + ")");
if (block instanceof MobSpawnerBlock) {
player.printRaw("\u00A7e" + "Mob Type: "
+ ((MobSpawnerBlock) block).getMobType());
} else if (block instanceof NoteBlock) {
player.printRaw("\u00A7e" + "Note block: "
+ ((NoteBlock) block).getNote());
} else if (block.getType() == BlockID.CLOTH) {
// Should never be null
player.printRaw("\u00A7e" + "Color: "
+ ClothColor.fromID(block.getData()).getName());
}
return true;
}
}

View File

@ -0,0 +1,127 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import java.util.HashSet;
import java.util.Set;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
/**
* A pickaxe mode that recursively finds adjacent blocks within range of
* an initial block and of the same type.
*
* @author sk89q
*/
public class RecursivePickaxe implements BlockTool {
private static final BaseBlock air = new BaseBlock(0);
private double range;
public RecursivePickaxe(double range) {
this.range = range;
}
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.superpickaxe.recursive");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
int initialType = world.getBlockType(clicked);
if (initialType == BlockID.AIR) {
return true;
}
if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) {
return true;
}
EditSession editSession = session.createEditSession(player);
try {
recurse(server, editSession, world, clicked.toBlockVector(),
clicked, range, initialType, new HashSet<BlockVector>(),
config.superPickaxeManyDrop);
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
session.remember(editSession);
}
return true;
}
/**
* Helper method.
*
* @param server
* @param superPickaxeManyDrop
* @param world
* @param pos
* @param origin
* @param size
* @param initialType
* @param visited
*/
private static void recurse(ServerInterface server, EditSession editSession,
LocalWorld world, BlockVector pos,
Vector origin, double size, int initialType,
Set<BlockVector> visited, boolean drop)
throws MaxChangedBlocksException {
final double distanceSq = origin.distanceSq(pos);
if (distanceSq > size*size || visited.contains(pos)) {
return;
}
visited.add(pos);
if (editSession.getBlock(pos).getType() != initialType) {
return;
}
if (drop) {
world.simulateBlockMine(pos);
}
world.queueBlockBreakEffect(server, pos, initialType, distanceSq);
editSession.setBlock(pos, air);
recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(),
origin, size, initialType, visited, drop);
recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(),
origin, size, initialType, visited, drop);
recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(),
origin, size, initialType, visited, drop);
recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(),
origin, size, initialType, visited, drop);
recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(),
origin, size, initialType, visited, drop);
recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(),
origin, size, initialType, visited, drop);
}
}

View File

@ -0,0 +1,57 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BlockID;
/**
* A super pickaxe mode that removes one block.
*
* @author sk89q
*/
public class SinglePickaxe implements BlockTool {
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.superpickaxe");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
final int blockType = world.getBlockType(clicked);
if (blockType == BlockID.BEDROCK
&& !player.canDestroyBedrock()) {
return true;
}
if (config.superPickaxeDrop) {
world.simulateBlockMine(clicked);
}
world.setBlockType(clicked, BlockID.AIR);
world.playEffect(clicked, 2001, blockType);
return true;
}
}

View File

@ -0,0 +1,41 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.LocalPlayer;
/**
* Represents a tool. This interface alone defines nothing. A tool also
* has to implement <code>BlockTool</code> or <code>TraceTool</code>.
*
* @author sk89q
*/
public abstract interface Tool {
/**
* Checks to see if the player can still be using this tool (considering
* permissions and such).
*
* @param player
* @return
*/
public boolean canUse(LocalPlayer player);
}

View File

@ -0,0 +1,45 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.ServerInterface;
/**
* Represents a tool that does not require a block.
*
* @author sk89q
*/
public interface TraceTool extends Tool {
/**
* Perform the action. Should return true to deny the default
* action.
*
* @param server
* @param config
* @param player
* @param session
* @return true to deny
*/
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session);
}

View File

@ -0,0 +1,68 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.util.TreeGenerator;
/**
* Plants a tree.
*
* @author sk89q
*/
public class TreePlanter implements BlockTool {
private TreeGenerator gen;
public TreePlanter(TreeGenerator gen) {
this.gen = gen;
}
public boolean canUse(LocalPlayer player) {
return player.hasPermission("worldedit.tool.tree");
}
public boolean actPrimary(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
EditSession editSession = session.createEditSession(player);
try {
boolean successful = false;
for (int i = 0; i < 10; i++) {
if (gen.generate(editSession, clicked.add(0, 1, 0))) {
successful = true;
break;
}
}
if (!successful) {
player.printError("A tree can't go there.");
}
} catch (MaxChangedBlocksException e) {
player.printError("Max. blocks changed reached.");
} finally {
session.remember(editSession);
}
return true;
}
}

View File

@ -0,0 +1,44 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.patterns.Pattern;
/**
* Represents a brush.
*
* @author sk89q
*/
public interface Brush {
/**
* Build the object.
*
* @param editSession
* @param pos
* @param mat
* @param size
* @throws MaxChangedBlocksException
*/
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException;
}

View File

@ -0,0 +1,40 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.patterns.Pattern;
public class ButcherBrush implements Brush {
private int flags;
public ButcherBrush(int flags) {
this.flags = flags;
}
@Override
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException {
editSession.getWorld().killMobs(pos, size, flags);
}
}

View File

@ -0,0 +1,41 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.patterns.Pattern;
public class ClipboardBrush implements Brush {
private CuboidClipboard clipboard;
private boolean noAir;
public ClipboardBrush(CuboidClipboard clipboard, boolean noAir) {
this.clipboard = clipboard;
this.noAir = noAir;
}
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException {
clipboard.place(editSession, pos.subtract(clipboard.getSize().divide(2)), noAir);
}
}

View File

@ -0,0 +1,38 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.patterns.Pattern;
public class CylinderBrush implements Brush {
private int height;
public CylinderBrush(int height) {
this.height = height;
}
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException {
editSession.makeCylinder(pos, mat, size, size, height, true);
}
}

View File

@ -0,0 +1,68 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.patterns.Pattern;
import java.util.*;
/**
* @author zml2008
*/
public class GravityBrush implements Brush {
private final boolean fullHeight;
public GravityBrush(boolean fullHeight) {
this.fullHeight = fullHeight;
}
@Override
public void build(EditSession editSession, Vector pos, Pattern mat, double size) throws MaxChangedBlocksException {
final BaseBlock air = new BaseBlock(BlockID.AIR, 0);
final double startY = fullHeight ? editSession.getWorld().getMaxY() : pos.getBlockY() + size;
for (double x = pos.getBlockX() + size; x > pos.getBlockX() - size; --x) {
for (double z = pos.getBlockZ() + size; z > pos.getBlockZ() - size; --z) {
double y = startY;
final List<BaseBlock> blockTypes = new ArrayList<BaseBlock>();
for (; y > pos.getBlockY() - size; --y) {
final Vector pt = new Vector(x, y, z);
final BaseBlock block = editSession.getBlock(pt);
if (!block.isAir()) {
blockTypes.add(block);
editSession.setBlock(pt, air);
}
}
Vector pt = new Vector(x, y, z);
Collections.reverse(blockTypes);
for (int i = 0; i < blockTypes.size();) {
if (editSession.getBlock(pt).getType() == BlockID.AIR) {
editSession.setBlock(pt, blockTypes.get(i++));
}
pt = pt.add(0, 1, 0);
}
}
}
}
}

View File

@ -0,0 +1,38 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.patterns.Pattern;
public class HollowCylinderBrush implements Brush {
private int height;
public HollowCylinderBrush(int height) {
this.height = height;
}
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException {
editSession.makeCylinder(pos, mat, size, size, height, false);
}
}

View File

@ -0,0 +1,35 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.patterns.Pattern;
public class HollowSphereBrush implements Brush {
public HollowSphereBrush() {
}
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException {
editSession.makeSphere(pos, mat, size, size, size, false);
}
}

View File

@ -0,0 +1,56 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.math.convolution.HeightMap;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.math.convolution.GaussianKernel;
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
public class SmoothBrush implements Brush {
private int iterations;
private boolean naturalOnly;
public SmoothBrush(int iterations) {
this(iterations, false);
}
public SmoothBrush(int iterations, boolean naturalOnly) {
this.iterations = iterations;
this.naturalOnly = naturalOnly;
}
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException {
double rad = size;
WorldVector min = new WorldVector(editSession.getWorld(), pos.subtract(rad, rad, rad));
Vector max = pos.add(rad, rad + 10, rad);
Region region = new CuboidRegion(editSession.getWorld(), min, max);
HeightMap heightMap = new HeightMap(editSession, region, naturalOnly);
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
heightMap.applyFilter(filter, iterations);
}
}

View File

@ -0,0 +1,35 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com> and contributors
*
* 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.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.patterns.Pattern;
public class SphereBrush implements Brush {
public SphereBrush() {
}
public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException {
editSession.makeSphere(pos, mat, size, size, size, true);
}
}