mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 17:57:38 +00:00
Added polygonal regions.
This commit is contained in:
parent
9667e92d66
commit
97529abaca
13
plugin.yml
13
plugin.yml
@ -178,15 +178,20 @@ commands:
|
||||
//count:
|
||||
description: Counts the number of a certain type of block
|
||||
usage: /<command> <block>
|
||||
/size:
|
||||
/m:
|
||||
description: Get information about the selection
|
||||
usage: /<command>
|
||||
aliases: ['//size']
|
||||
/shift:
|
||||
description: Shift the selection area
|
||||
usage: /<command> <amount> [direction]
|
||||
/expand:
|
||||
description: Expand the selection area
|
||||
usage: /<command> <amount> [reverse-amount] <direction>
|
||||
/sel:
|
||||
description: Choose a region selector
|
||||
usage: /<command> [type]
|
||||
aliases: [',']
|
||||
/inset:
|
||||
description: Inset the selection area
|
||||
usage: /<command> [-hv] <amount>
|
||||
@ -299,6 +304,10 @@ commands:
|
||||
/drain:
|
||||
description: Drain a pool
|
||||
usage: /<command> <radius>
|
||||
/version:
|
||||
version:
|
||||
description: Get WorldEdit version
|
||||
usage: /<command>
|
||||
aliases: ['ver']
|
||||
reload:
|
||||
description: Reload WorldEdit
|
||||
usage: /<command>
|
||||
|
@ -28,8 +28,9 @@ import com.sk89q.worldedit.tools.SinglePickaxe;
|
||||
import com.sk89q.worldedit.tools.BlockTool;
|
||||
import com.sk89q.worldedit.tools.Tool;
|
||||
import com.sk89q.worldedit.bags.BlockBag;
|
||||
import com.sk89q.worldedit.regions.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
|
||||
/**
|
||||
* An instance of this represents the WorldEdit session of a user. A session
|
||||
@ -51,9 +52,9 @@ public class LocalSession {
|
||||
|
||||
private LocalConfiguration config;
|
||||
|
||||
private LocalWorld selectionWorld;
|
||||
private RegionSelector regionSelector = new CuboidRegionSelector();
|
||||
private boolean placeAtPos1 = false;
|
||||
private Vector pos1, pos2;
|
||||
private Region region;
|
||||
private LinkedList<EditSession> history = new LinkedList<EditSession>();
|
||||
private int historyPointer = 0;
|
||||
private CuboidClipboard clipboard;
|
||||
@ -147,25 +148,41 @@ public class LocalSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to make sure that position 1 is defined.
|
||||
* Get the region selector for defining the selection. If the selection
|
||||
* was defined for a different world, the old selection will be discarded.
|
||||
*
|
||||
* @throws IncompleteRegionException
|
||||
* @param world
|
||||
* @return position
|
||||
*/
|
||||
private void checkPos1() throws IncompleteRegionException {
|
||||
if (pos1 == null) {
|
||||
throw new IncompleteRegionException();
|
||||
public RegionSelector getRegionSelector(LocalWorld world) {
|
||||
if (selectionWorld == null) {
|
||||
selectionWorld = world;
|
||||
} else if (!selectionWorld.equals(world)) {
|
||||
selectionWorld = world;
|
||||
regionSelector.clear();
|
||||
}
|
||||
return regionSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to make sure that position 2 is defined.
|
||||
* Get the region selector. This won't check worlds so make sure that
|
||||
* this region selector isn't used blindly.
|
||||
*
|
||||
* @throws IncompleteRegionException
|
||||
* @return position
|
||||
*/
|
||||
private void checkPos2() throws IncompleteRegionException {
|
||||
if (pos2 == null) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
public RegionSelector getRegionSelector() {
|
||||
return regionSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the region selector.
|
||||
*
|
||||
* @param world
|
||||
* @param selector
|
||||
*/
|
||||
public void setRegionSelector(LocalWorld world, RegionSelector selector) {
|
||||
selectionWorld = world;
|
||||
regionSelector = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -173,80 +190,50 @@ public class LocalSession {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isRegionDefined() {
|
||||
return pos1 != null && pos2 != null;
|
||||
return regionSelector.isDefined();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets defined position 1.
|
||||
* Returns true if the region is fully defined for the specified world.
|
||||
*
|
||||
* @return position 1
|
||||
* @throws IncompleteRegionException
|
||||
* @param world
|
||||
* @return
|
||||
*/
|
||||
public Vector getPos1() throws IncompleteRegionException {
|
||||
checkPos1();
|
||||
return pos1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets position 1.
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public void setPos1(Vector pt) {
|
||||
pos1 = pt;
|
||||
if (pos1 != null && pos2 != null) {
|
||||
region = new CuboidRegion(pos1, pos2);
|
||||
public boolean isSelectionDefined(LocalWorld world) {
|
||||
if (selectionWorld == null || !selectionWorld.equals(world)) {
|
||||
return false;
|
||||
}
|
||||
return regionSelector.isDefined();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets position 2.
|
||||
*
|
||||
* @return position 2
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
public Vector getPos2() throws IncompleteRegionException {
|
||||
checkPos2();
|
||||
return pos2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets position 2.
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public void setPos2(Vector pt) {
|
||||
pos2 = pt;
|
||||
if (pos1 != null && pos2 != null) {
|
||||
region = new CuboidRegion(pos1, pos2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update session position 1/2 based on the currently set region,
|
||||
* provided that the region is of a cuboid.
|
||||
*/
|
||||
public void learnRegionChanges() {
|
||||
if (region instanceof CuboidRegion) {
|
||||
CuboidRegion cuboidRegion = (CuboidRegion)region;
|
||||
pos1 = cuboidRegion.getPos1();
|
||||
pos2 = cuboidRegion.getPos2();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the region. If you change the region, you should
|
||||
* call learnRegionChanges().
|
||||
* Use <code>getSelection()</code>.
|
||||
*
|
||||
* @return region
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
@Deprecated
|
||||
public Region getRegion() throws IncompleteRegionException {
|
||||
if (region == null) {
|
||||
return regionSelector.getRegion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selection region. If you change the region, you should
|
||||
* call learnRegionChanges(). If the selection is defined in
|
||||
* a different world, the <code>IncompleteRegionException</code>
|
||||
* exception will be thrown.
|
||||
*
|
||||
* @param world
|
||||
* @return region
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
public Region getSelection(LocalWorld world) throws IncompleteRegionException {
|
||||
if (selectionWorld == null || !selectionWorld.equals(world)) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
return region;
|
||||
return regionSelector.getRegion();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -353,8 +340,7 @@ public class LocalSession {
|
||||
return player.getBlockIn();
|
||||
}
|
||||
|
||||
checkPos1();
|
||||
return pos1;
|
||||
return regionSelector.getPrimaryPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -145,6 +145,15 @@ public class Vector2D {
|
||||
return new Vector2D(x, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a BlockVector version.
|
||||
*
|
||||
* @return BlockVector
|
||||
*/
|
||||
public BlockVector2D toBlockVector2D() {
|
||||
return new BlockVector2D(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if another object is equivalent.
|
||||
*
|
||||
|
@ -35,6 +35,7 @@ import com.sk89q.worldedit.LocalSession.CompassMode;
|
||||
import com.sk89q.worldedit.bags.BlockBag;
|
||||
import com.sk89q.worldedit.blocks.*;
|
||||
import com.sk89q.worldedit.commands.*;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.scripting.*;
|
||||
import com.sk89q.worldedit.tools.BlockTool;
|
||||
import com.sk89q.worldedit.tools.Tool;
|
||||
@ -782,13 +783,9 @@ public class WorldEdit {
|
||||
|
||||
if (itemInHand == config.wandItem && session.isToolControlEnabled()
|
||||
&& player.hasPermission("worldedit.selection.pos")) {
|
||||
session.setPos2(clicked);
|
||||
|
||||
try {
|
||||
player.print("Second position set to " + clicked
|
||||
+ " (" + session.getRegion().getSize() + ").");
|
||||
} catch (IncompleteRegionException e) {
|
||||
player.print("Second position set to " + clicked + ".");
|
||||
RegionSelector selector = session.getRegionSelector(player.getWorld());
|
||||
if (selector.selectSecondary(clicked)) {
|
||||
selector.explainSecondarySelection(player, clicked);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -823,19 +820,9 @@ public class WorldEdit {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (session.getPos1().equals(clicked)) {
|
||||
return false;
|
||||
}
|
||||
} catch (IncompleteRegionException e) {
|
||||
}
|
||||
|
||||
session.setPos1(clicked);
|
||||
try {
|
||||
player.print("First position set to " + clicked
|
||||
+ " (" + session.getRegion().getSize() + ").");
|
||||
} catch (IncompleteRegionException e) {
|
||||
player.print("First position set to " + clicked + ".");
|
||||
RegionSelector selector = session.getRegionSelector(player.getWorld());
|
||||
if (selector.selectPrimary(clicked)) {
|
||||
selector.explainPrimarySelection(player, clicked);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -208,7 +208,8 @@ public class WorldEditPlugin extends JavaPlugin {
|
||||
*/
|
||||
public Region getPlayerSelection(Player player)
|
||||
throws IncompleteRegionException {
|
||||
return controller.getSession(wrapPlayer(player)).getRegion();
|
||||
return controller.getSession(wrapPlayer(player))
|
||||
.getSelection(new BukkitWorld(player.getWorld()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,7 +70,7 @@ public class ChunkCommands {
|
||||
LocalSession session, LocalPlayer player, EditSession editSession)
|
||||
throws WorldEditException {
|
||||
|
||||
Set<Vector2D> chunks = session.getRegion().getChunks();
|
||||
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
|
||||
|
||||
for (Vector2D chunk : chunks) {
|
||||
player.print(NestedFileChunkStore.getFilename(chunk));
|
||||
@ -91,7 +91,7 @@ public class ChunkCommands {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
Set<Vector2D> chunks = session.getRegion().getChunks();
|
||||
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
|
||||
FileOutputStream out = null;
|
||||
|
||||
if (config.shellSaveType == null) {
|
||||
|
@ -47,7 +47,7 @@ public class ClipboardCommands {
|
||||
LocalSession session, LocalPlayer player, EditSession editSession)
|
||||
throws WorldEditException {
|
||||
|
||||
Region region = session.getRegion();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
Vector min = region.getMinimumPoint();
|
||||
Vector max = region.getMaximumPoint();
|
||||
Vector pos = player.getBlockIn();
|
||||
@ -79,7 +79,7 @@ public class ClipboardCommands {
|
||||
block = we.getBlock(player, args.getString(0));
|
||||
}
|
||||
|
||||
Region region = session.getRegion();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
Vector min = region.getMinimumPoint();
|
||||
Vector max = region.getMaximumPoint();
|
||||
Vector pos = player.getBlockIn();
|
||||
@ -90,7 +90,7 @@ public class ClipboardCommands {
|
||||
clipboard.copy(editSession);
|
||||
session.setClipboard(clipboard);
|
||||
|
||||
editSession.setBlocks(session.getRegion(), block);
|
||||
editSession.setBlocks(session.getSelection(player.getWorld()), block);
|
||||
player.print("Block(s) cut.");
|
||||
}
|
||||
|
||||
|
@ -53,10 +53,10 @@ public class RegionCommands {
|
||||
int affected;
|
||||
|
||||
if (pattern instanceof SingleBlockPattern) {
|
||||
affected = editSession.setBlocks(session.getRegion(),
|
||||
affected = editSession.setBlocks(session.getSelection(player.getWorld()),
|
||||
((SingleBlockPattern)pattern).getBlock());
|
||||
} else {
|
||||
affected = editSession.setBlocks(session.getRegion(), pattern);
|
||||
affected = editSession.setBlocks(session.getSelection(player.getWorld()), pattern);
|
||||
}
|
||||
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
@ -86,10 +86,10 @@ public class RegionCommands {
|
||||
|
||||
int affected = 0;
|
||||
if (to instanceof SingleBlockPattern) {
|
||||
affected = editSession.replaceBlocks(session.getRegion(), from,
|
||||
affected = editSession.replaceBlocks(session.getSelection(player.getWorld()), from,
|
||||
((SingleBlockPattern)to).getBlock());
|
||||
} else {
|
||||
affected = editSession.replaceBlocks(session.getRegion(), from, to);
|
||||
affected = editSession.replaceBlocks(session.getSelection(player.getWorld()), from, to);
|
||||
}
|
||||
|
||||
player.print(affected + " block(s) have been replaced.");
|
||||
@ -109,7 +109,7 @@ public class RegionCommands {
|
||||
|
||||
Pattern pat = we.getBlockPattern(player, args.getString(0));
|
||||
|
||||
Region region = session.getRegion();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
int affected = 0;
|
||||
if (pat instanceof SingleBlockPattern) {
|
||||
affected = editSession.overlayCuboidBlocks(region,
|
||||
@ -133,7 +133,7 @@ public class RegionCommands {
|
||||
throws WorldEditException {
|
||||
|
||||
BaseBlock block = we.getBlock(player, args.getString(0));
|
||||
int affected = editSession.makeCuboidWalls(session.getRegion(), block);
|
||||
int affected = editSession.makeCuboidWalls(session.getSelection(player.getWorld()), block);
|
||||
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
@ -151,7 +151,7 @@ public class RegionCommands {
|
||||
throws WorldEditException {
|
||||
|
||||
BaseBlock block = we.getBlock(player, args.getString(0));
|
||||
int affected = editSession.makeCuboidFaces(session.getRegion(), block);
|
||||
int affected = editSession.makeCuboidFaces(session.getSelection(player.getWorld()), block);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ public class RegionCommands {
|
||||
iterations = args.getInteger(0);
|
||||
}
|
||||
|
||||
HeightMap heightMap = new HeightMap(editSession, session.getRegion());
|
||||
HeightMap heightMap = new HeightMap(editSession, session.getSelection(player.getWorld()));
|
||||
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.");
|
||||
@ -203,7 +203,7 @@ public class RegionCommands {
|
||||
replace = new BaseBlock(0);
|
||||
}
|
||||
|
||||
int affected = editSession.moveCuboidRegion(session.getRegion(),
|
||||
int affected = editSession.moveCuboidRegion(session.getSelection(player.getWorld()),
|
||||
dir, count, true, replace);
|
||||
player.print(affected + " blocks moved.");
|
||||
}
|
||||
@ -226,7 +226,7 @@ public class RegionCommands {
|
||||
Vector dir = we.getDirection(player,
|
||||
args.argsLength() > 1 ? args.getString(1).toLowerCase() : "me");
|
||||
|
||||
int affected = editSession.stackCuboidRegion(session.getRegion(),
|
||||
int affected = editSession.stackCuboidRegion(session.getSelection(player.getWorld()),
|
||||
dir, count, !args.hasFlag('a'));
|
||||
player.print(affected + " blocks changed. Undo with //undo");
|
||||
}
|
||||
|
@ -27,7 +27,10 @@ import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.data.ChunkStore;
|
||||
import com.sk89q.worldedit.regions.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.regions.Polygonal2DRegionSelector;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.blocks.*;
|
||||
|
||||
/**
|
||||
@ -48,14 +51,14 @@ public class SelectionCommands {
|
||||
LocalSession session, LocalPlayer player, EditSession editSession)
|
||||
throws WorldEditException {
|
||||
|
||||
session.setPos1(player.getBlockIn());
|
||||
|
||||
if (session.isRegionDefined()) {
|
||||
player.print("First position set to " + player.getBlockIn()
|
||||
+ " (" + session.getRegion().getSize() + ").");
|
||||
} else {
|
||||
player.print("First position set to " + player.getBlockIn() + ".");
|
||||
if (!session.getRegionSelector(player.getWorld())
|
||||
.selectPrimary(player.getBlockIn())) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainPrimarySelection(player, player.getBlockIn());
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -70,14 +73,15 @@ public class SelectionCommands {
|
||||
LocalSession session, LocalPlayer player, EditSession editSession)
|
||||
throws WorldEditException {
|
||||
|
||||
session.setPos2(player.getBlockIn());
|
||||
|
||||
if (session.isRegionDefined()) {
|
||||
player.print("Second position set to " + player.getBlockIn()
|
||||
+ " (" + session.getRegion().getSize() + ").");
|
||||
} else {
|
||||
player.print("Second position set to " + player.getBlockIn() + ".");
|
||||
if (!session.getRegionSelector(player.getWorld())
|
||||
.selectSecondary(player.getBlockIn())) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainSecondarySelection(player, player.getBlockIn());
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -95,13 +99,14 @@ public class SelectionCommands {
|
||||
Vector pos = player.getBlockTrace(300);
|
||||
|
||||
if (pos != null) {
|
||||
session.setPos1(pos);
|
||||
if (session.isRegionDefined()) {
|
||||
player.print("First position set to " + pos
|
||||
+ " (" + session.getRegion().getSize() + ").");
|
||||
} else {
|
||||
player.print("First position set to " + pos.toString() + " .");
|
||||
if (!session.getRegionSelector(player.getWorld())
|
||||
.selectPrimary(pos)) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainPrimarySelection(player, pos);
|
||||
} else {
|
||||
player.printError("No block in sight!");
|
||||
}
|
||||
@ -122,14 +127,14 @@ public class SelectionCommands {
|
||||
Vector pos = player.getBlockTrace(300);
|
||||
|
||||
if (pos != null) {
|
||||
session.setPos2(pos);
|
||||
|
||||
if (session.isRegionDefined()) {
|
||||
player.print("Second position set to " + pos
|
||||
+ " (" + session.getRegion().getSize() + ").");
|
||||
} else {
|
||||
player.print("Second position set to " + pos.toString() + " .");
|
||||
if (!session.getRegionSelector(player.getWorld())
|
||||
.selectSecondary(pos)) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainSecondarySelection(player, pos);
|
||||
} else {
|
||||
player.printError("No block in sight!");
|
||||
}
|
||||
@ -151,8 +156,10 @@ public class SelectionCommands {
|
||||
Vector min = new Vector(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
|
||||
Vector max = min.add(15, 127, 15);
|
||||
|
||||
session.setPos1(min);
|
||||
session.setPos2(max);
|
||||
CuboidRegionSelector selector = new CuboidRegionSelector();
|
||||
selector.selectPrimary(min);
|
||||
selector.selectSecondary(max);
|
||||
session.setRegionSelector(player.getWorld(), selector);
|
||||
|
||||
player.print("Chunk selected: "
|
||||
+ min2D.getBlockX() + ", " + min2D.getBlockZ());
|
||||
@ -213,14 +220,18 @@ public class SelectionCommands {
|
||||
// sky and bedrock.
|
||||
if (args.getString(0).equalsIgnoreCase("vert")
|
||||
|| args.getString(0).equalsIgnoreCase("vertical")) {
|
||||
Region region = session.getRegion();
|
||||
int oldSize = region.getSize();
|
||||
region.expand(new Vector(0, 128, 0));
|
||||
region.expand(new Vector(0, -128, 0));
|
||||
session.learnRegionChanges();
|
||||
int newSize = region.getSize();
|
||||
player.print("Region expanded " + (newSize - oldSize)
|
||||
+ " blocks [top-to-bottom].");
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
try {
|
||||
int oldSize = region.getArea();
|
||||
region.expand(new Vector(0, 128, 0));
|
||||
region.expand(new Vector(0, -128, 0));
|
||||
session.getRegionSelector().learnChanges();
|
||||
int newSize = region.getArea();
|
||||
player.print("Region expanded " + (newSize - oldSize)
|
||||
+ " blocks [top-to-bottom].");
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -246,16 +257,16 @@ public class SelectionCommands {
|
||||
dir = we.getDirection(player, "me");
|
||||
}
|
||||
|
||||
Region region = session.getRegion();
|
||||
int oldSize = region.getSize();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
int oldSize = region.getArea();
|
||||
region.expand(dir.multiply(change));
|
||||
|
||||
if (reverseChange != 0) {
|
||||
region.expand(dir.multiply(reverseChange));
|
||||
}
|
||||
|
||||
session.learnRegionChanges();
|
||||
int newSize = region.getSize();
|
||||
session.getRegionSelector().learnChanges();
|
||||
int newSize = region.getArea();
|
||||
|
||||
player.print("Region expanded " + (newSize - oldSize) + " blocks.");
|
||||
}
|
||||
@ -294,16 +305,20 @@ public class SelectionCommands {
|
||||
dir = we.getDirection(player, "me");
|
||||
}
|
||||
|
||||
Region region = session.getRegion();
|
||||
int oldSize = region.getSize();
|
||||
region.contract(dir.multiply(change));
|
||||
if (reverseChange != 0) {
|
||||
region.contract(dir.multiply(reverseChange));
|
||||
}
|
||||
session.learnRegionChanges();
|
||||
int newSize = region.getSize();
|
||||
try {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
int oldSize = region.getArea();
|
||||
region.contract(dir.multiply(change));
|
||||
if (reverseChange != 0) {
|
||||
region.contract(dir.multiply(reverseChange));
|
||||
}
|
||||
session.getRegionSelector().learnChanges();
|
||||
int newSize = region.getArea();
|
||||
|
||||
player.print("Region contracted " + (oldSize - newSize) + " blocks.");
|
||||
player.print("Region contracted " + (oldSize - newSize) + " blocks.");
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -327,12 +342,16 @@ public class SelectionCommands {
|
||||
dir = we.getDirection(player, "me");
|
||||
}
|
||||
|
||||
Region region = session.getRegion();
|
||||
region.expand(dir.multiply(change));
|
||||
region.contract(dir.multiply(change));
|
||||
session.learnRegionChanges();
|
||||
try {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
region.expand(dir.multiply(change));
|
||||
region.contract(dir.multiply(change));
|
||||
session.getRegionSelector().learnChanges();
|
||||
|
||||
player.print("Region shifted.");
|
||||
player.print("Region shifted.");
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -349,23 +368,27 @@ public class SelectionCommands {
|
||||
throws WorldEditException {
|
||||
int change = args.getInteger(0);
|
||||
|
||||
Region region = session.getRegion();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
|
||||
if (!args.hasFlag('h')) {
|
||||
region.expand((new Vector(0, 1, 0)).multiply(change));
|
||||
region.expand((new Vector(0, -1, 0)).multiply(change));
|
||||
try {
|
||||
if (!args.hasFlag('h')) {
|
||||
region.expand((new Vector(0, 1, 0)).multiply(change));
|
||||
region.expand((new Vector(0, -1, 0)).multiply(change));
|
||||
}
|
||||
|
||||
if (!args.hasFlag('v')) {
|
||||
region.expand((new Vector(1, 0, 0)).multiply(change));
|
||||
region.expand((new Vector(-1, 0, 0)).multiply(change));
|
||||
region.expand((new Vector(0, 0, 1)).multiply(change));
|
||||
region.expand((new Vector(0, 0, -1)).multiply(change));
|
||||
}
|
||||
|
||||
session.getRegionSelector().learnChanges();
|
||||
|
||||
player.print("Region outset.");
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
|
||||
if (!args.hasFlag('v')) {
|
||||
region.expand((new Vector(1, 0, 0)).multiply(change));
|
||||
region.expand((new Vector(-1, 0, 0)).multiply(change));
|
||||
region.expand((new Vector(0, 0, 1)).multiply(change));
|
||||
region.expand((new Vector(0, 0, -1)).multiply(change));
|
||||
}
|
||||
|
||||
session.learnRegionChanges();
|
||||
|
||||
player.print("Region outset.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -382,7 +405,7 @@ public class SelectionCommands {
|
||||
throws WorldEditException {
|
||||
int change = args.getInteger(0);
|
||||
|
||||
Region region = session.getRegion();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
|
||||
if (!args.hasFlag('h')) {
|
||||
region.contract((new Vector(0, 1, 0)).multiply(change));
|
||||
@ -396,13 +419,13 @@ public class SelectionCommands {
|
||||
region.contract((new Vector(0, 0, -1)).multiply(change));
|
||||
}
|
||||
|
||||
session.learnRegionChanges();
|
||||
session.getRegionSelector().learnChanges();
|
||||
|
||||
player.print("Region inset.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"/size"},
|
||||
aliases = {"/m", "//size"},
|
||||
usage = "",
|
||||
desc = "Get information about the selection",
|
||||
min = 0,
|
||||
@ -413,16 +436,20 @@ public class SelectionCommands {
|
||||
LocalSession session, LocalPlayer player, EditSession editSession)
|
||||
throws WorldEditException {
|
||||
|
||||
Region region = session.getRegion();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
Vector size = region.getMaximumPoint()
|
||||
.subtract(region.getMinimumPoint())
|
||||
.add(1, 1, 1);
|
||||
|
||||
player.print("First position: " + session.getPos1());
|
||||
player.print("Second position: " + session.getPos2());
|
||||
player.print("Type: " + session.getRegionSelector().getTypeName());
|
||||
|
||||
for (String line : session.getRegionSelector().getInformationLines()) {
|
||||
player.print(line);
|
||||
}
|
||||
|
||||
player.print("Size: " + size);
|
||||
player.print("Distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
|
||||
player.print("# of blocks: " + region.getSize());
|
||||
player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
|
||||
player.print("# of blocks: " + region.getArea());
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -440,7 +467,7 @@ public class SelectionCommands {
|
||||
Set<Integer> searchIDs = we.getBlockIDs(player,
|
||||
args.getString(0), true);
|
||||
player.print("Counted: " +
|
||||
editSession.countBlocks(session.getRegion(), searchIDs));
|
||||
editSession.countBlocks(session.getSelection(player.getWorld()), searchIDs));
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -457,12 +484,12 @@ public class SelectionCommands {
|
||||
throws WorldEditException {
|
||||
|
||||
List<Countable<Integer>> distribution =
|
||||
editSession.getBlockDistribution(session.getRegion());
|
||||
editSession.getBlockDistribution(session.getSelection(player.getWorld()));
|
||||
|
||||
Logger logger = Logger.getLogger("Minecraft.WorldEdit");
|
||||
|
||||
if (distribution.size() > 0) { // *Should* always be true
|
||||
int size = session.getRegion().getSize();
|
||||
int size = session.getSelection(player.getWorld()).getArea();
|
||||
|
||||
player.print("# total blocks: " + size);
|
||||
|
||||
@ -486,4 +513,27 @@ public class SelectionCommands {
|
||||
player.printError("No blocks counted.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"/sel", ","},
|
||||
usage = "[type]",
|
||||
desc = "Choose a region selector",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
public static void select(CommandContext args, WorldEdit we,
|
||||
LocalSession session, LocalPlayer player, EditSession editSession)
|
||||
throws WorldEditException {
|
||||
|
||||
String typeName = args.getString(0);
|
||||
if (typeName.equalsIgnoreCase("cuboid")) {
|
||||
session.setRegionSelector(player.getWorld(), new CuboidRegionSelector());
|
||||
player.print("Cuboid: left click for point 1, right click for point 2");
|
||||
} else if (typeName.equalsIgnoreCase("poly")) {
|
||||
session.setRegionSelector(player.getWorld(), new Polygonal2DRegionSelector());
|
||||
player.print("2D polygon selector: Left/right click to add a point.");
|
||||
} else {
|
||||
player.printError("Only 'cuboid' and 'poly' are accepted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public class SnapshotUtilCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
Region region = session.getRegion();
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
Snapshot snapshot;
|
||||
|
||||
if (args.argsLength() > 0) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.data.ChunkStore;
|
||||
@ -28,7 +29,7 @@ import java.util.HashSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Albert
|
||||
* @author sk89q
|
||||
*/
|
||||
public class CuboidRegion implements Region {
|
||||
/**
|
||||
@ -80,7 +81,7 @@ public class CuboidRegion implements Region {
|
||||
*
|
||||
* @return number of blocks
|
||||
*/
|
||||
public int getSize() {
|
||||
public int getArea() {
|
||||
Vector min = getMinimumPoint();
|
||||
Vector max = getMaximumPoint();
|
||||
|
||||
@ -288,12 +289,30 @@ public class CuboidRegion implements Region {
|
||||
return chunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true based on whether the region contains the point,
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public boolean contains(Vector pt) {
|
||||
double x = pt.getX();
|
||||
double y = pt.getY();
|
||||
double z = pt.getZ();
|
||||
|
||||
Vector min = getMinimumPoint();
|
||||
Vector max = getMaximumPoint();
|
||||
|
||||
return x >= min.getBlockX() && x <= max.getBlockX()
|
||||
&& y >= min.getBlockY() && y <= max.getBlockY()
|
||||
&& z >= min.getBlockZ() && z <= max.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the iterator.
|
||||
*
|
||||
* @return iterator of Points
|
||||
* @return iterator of points inside the region
|
||||
*/
|
||||
public Iterator<Vector> iterator() {
|
||||
public Iterator<BlockVector> iterator() {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
}
|
||||
|
122
src/com/sk89q/worldedit/regions/CuboidRegionSelector.java
Normal file
122
src/com/sk89q/worldedit/regions/CuboidRegionSelector.java
Normal file
@ -0,0 +1,122 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalPlayer;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
|
||||
/**
|
||||
* Selector for cuboids.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class CuboidRegionSelector implements RegionSelector {
|
||||
protected BlockVector pos1;
|
||||
protected BlockVector pos2;
|
||||
protected CuboidRegion region = new CuboidRegion(new Vector(), new Vector());
|
||||
|
||||
public boolean selectPrimary(Vector pos) {
|
||||
if (pos1 != null && pos1.equals(pos)) {
|
||||
return false;
|
||||
}
|
||||
pos1 = pos.toBlockVector();
|
||||
region.setPos1(pos1);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean selectSecondary(Vector pos) {
|
||||
if (pos2 != null && pos2.equals(pos)) {
|
||||
return false;
|
||||
}
|
||||
pos2 = pos.toBlockVector();
|
||||
region.setPos2(pos2);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void explainPrimarySelection(LocalPlayer player, Vector pos) {
|
||||
if (pos1 != null && pos2 != null) {
|
||||
player.print("First position set to " + pos1
|
||||
+ " (" + region.getArea() + ").");
|
||||
} else {
|
||||
player.print("First position set to " + pos1 + ".");
|
||||
}
|
||||
}
|
||||
|
||||
public void explainSecondarySelection(LocalPlayer player, Vector pos) {
|
||||
if (pos1 != null && pos2 != null) {
|
||||
player.print("Second position set to " + pos1
|
||||
+ " (" + region.getArea() + ").");
|
||||
} else {
|
||||
player.print("Second position set to " + pos1 + ".");
|
||||
}
|
||||
}
|
||||
|
||||
public BlockVector getPrimaryPosition() throws IncompleteRegionException {
|
||||
if (pos1 == null) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
|
||||
return pos1;
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return pos1 != null && pos2 != null;
|
||||
}
|
||||
|
||||
public Region getRegion() throws IncompleteRegionException {
|
||||
if (pos1 == null || pos2 == null) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
public void learnChanges() {
|
||||
pos1 = region.getPos1().toBlockVector();
|
||||
pos2 = region.getPos2().toBlockVector();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
pos1 = null;
|
||||
pos2 = null;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return "cuboid";
|
||||
}
|
||||
|
||||
public List<String> getInformationLines() {
|
||||
List<String> lines = new ArrayList<String>();
|
||||
|
||||
if (pos1 != null) {
|
||||
lines.add("Position 1: " + pos1);
|
||||
}
|
||||
|
||||
if (pos2 != null) {
|
||||
lines.add("Position 2: " + pos2);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
527
src/com/sk89q/worldedit/regions/Polygonal2DRegion.java
Normal file
527
src/com/sk89q/worldedit/regions/Polygonal2DRegion.java
Normal file
@ -0,0 +1,527 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.data.ChunkStore;
|
||||
|
||||
/**
|
||||
* Represents a 2D polygonal region.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class Polygonal2DRegion implements Region {
|
||||
protected List<BlockVector2D> points;
|
||||
protected BlockVector min;
|
||||
protected BlockVector max;
|
||||
protected int minY;
|
||||
protected int maxY;
|
||||
protected boolean hasY = false;
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*/
|
||||
public Polygonal2DRegion() {
|
||||
points = new ArrayList<BlockVector2D>();
|
||||
minY = 0;
|
||||
maxY = 0;
|
||||
hasY = false;
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*
|
||||
* @param points
|
||||
* @param minY
|
||||
* @param maxY
|
||||
*/
|
||||
public Polygonal2DRegion(List<BlockVector2D> points, int minY, int maxY) {
|
||||
this.points = points;
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
hasY = true;
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of points.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<BlockVector2D> getPoints() {
|
||||
return Collections.unmodifiableList(points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate the bounding box of this polygonal region. This should be
|
||||
* called after points have been changed.
|
||||
*/
|
||||
protected void recalculate() {
|
||||
if (points.size() == 0) {
|
||||
min = new BlockVector(0, 0, 0);
|
||||
max = new BlockVector(0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int minX = points.get(0).getBlockX();
|
||||
int minZ = points.get(0).getBlockZ();
|
||||
int maxX = points.get(0).getBlockX();
|
||||
int maxZ = points.get(0).getBlockZ();
|
||||
|
||||
for (BlockVector2D v : points) {
|
||||
int x = v.getBlockX();
|
||||
int z = v.getBlockZ();
|
||||
if (x < minX) minX = x;
|
||||
if (z < minZ) minZ = z;
|
||||
if (x > maxX) maxX = x;
|
||||
if (z > maxZ) maxZ = z;
|
||||
}
|
||||
|
||||
int oldMinY = minY;
|
||||
int oldMaxY = maxY;
|
||||
minY = Math.min(oldMinY, oldMaxY);
|
||||
maxY = Math.max(oldMinY, oldMaxY);
|
||||
|
||||
min = new BlockVector(minX, minY, minZ);
|
||||
max = new BlockVector(maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a point to the list.
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public void addPoint(Vector2D pt) {
|
||||
points.add(pt.toBlockVector2D());
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a point to the list.
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public void addPoint(BlockVector2D pt) {
|
||||
points.add(pt);
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a point to the list.
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public void addPoint(Vector pt) {
|
||||
points.add(new BlockVector2D(pt.getBlockX(), pt.getBlockZ()));
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lower point of a region.
|
||||
*
|
||||
* @return min. point
|
||||
*/
|
||||
public Vector getMinimumPoint() {
|
||||
return min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the upper point of a region.
|
||||
*
|
||||
* @return max. point
|
||||
*/
|
||||
public Vector getMaximumPoint() {
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of blocks in the region.
|
||||
*
|
||||
* @return number of blocks
|
||||
*/
|
||||
public int getArea() {
|
||||
double area = 0;
|
||||
int i, j = points.size() - 1;
|
||||
|
||||
for (i = 0; i < points.size(); i++) {
|
||||
area += (points.get(j).getBlockX() + points.get(i).getBlockX())
|
||||
* (points.get(j).getBlockZ() - points.get(i).getBlockZ());
|
||||
j = i;
|
||||
}
|
||||
|
||||
return (int)Math.floor(Math.abs(area * 0.5)
|
||||
* (maxY - minY + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X-size.
|
||||
*
|
||||
* @return width
|
||||
*/
|
||||
public int getWidth() {
|
||||
return max.getBlockX() - min.getBlockX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Y-size.
|
||||
*
|
||||
* @return height
|
||||
*/
|
||||
public int getHeight() {
|
||||
return max.getBlockY() - min.getBlockY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Z-size.
|
||||
*
|
||||
* @return length
|
||||
*/
|
||||
public int getLength() {
|
||||
return max.getBlockZ() - min.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the region.
|
||||
*
|
||||
* @param change
|
||||
*/
|
||||
public void expand(Vector change) throws RegionOperationException {
|
||||
if (change.getBlockX() != 0 || change.getBlockZ() != 0) {
|
||||
throw new RegionOperationException("Polygons can only be expanded vertically.");
|
||||
}
|
||||
|
||||
int changeY = change.getBlockY();
|
||||
if (changeY > 0) {
|
||||
maxY += changeY;
|
||||
} else {
|
||||
minY += changeY;
|
||||
}
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract the region.
|
||||
*
|
||||
* @param change
|
||||
*/
|
||||
public void contract(Vector change) throws RegionOperationException {
|
||||
if (change.getBlockX() != 0 || change.getBlockZ() != 0) {
|
||||
throw new RegionOperationException("Polygons can only be contracted vertically.");
|
||||
}
|
||||
|
||||
int changeY = change.getBlockY();
|
||||
if (changeY > 0) {
|
||||
minY += changeY;
|
||||
} else {
|
||||
maxY += changeY;
|
||||
}
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a point is inside this region.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(Vector pt) {
|
||||
return contains(points, minY, maxY, pt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a point is inside a region.
|
||||
*
|
||||
* @param points
|
||||
* @param minY
|
||||
* @param maxY
|
||||
* @param pt
|
||||
* @return
|
||||
*/
|
||||
public static boolean contains(List<BlockVector2D> points, int minY,
|
||||
int maxY, Vector pt) {
|
||||
if (points.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int targetX = pt.getBlockX();
|
||||
int targetY = pt.getBlockY();
|
||||
int targetZ = pt.getBlockZ();
|
||||
|
||||
if (targetY < minY || targetY > maxY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean inside = false;
|
||||
int npoints = points.size();
|
||||
int xNew, zNew;
|
||||
int xOld, zOld;
|
||||
int x1, z1;
|
||||
int x2, z2;
|
||||
int i;
|
||||
|
||||
xOld = points.get(npoints - 1).getBlockX();
|
||||
zOld = points.get(npoints - 1).getBlockZ();
|
||||
|
||||
for (i = 0; i < npoints; i++) {
|
||||
xNew = points.get(i).getBlockX();
|
||||
zNew = points.get(i).getBlockZ();
|
||||
|
||||
if (xNew > xOld) {
|
||||
x1 = xOld - 1;
|
||||
x2 = xNew;
|
||||
z1 = zOld;
|
||||
z2 = zNew + 1;
|
||||
} else {
|
||||
x1 = xNew - 1;
|
||||
x2 = xOld;
|
||||
z1 = zNew;
|
||||
z2 = zOld + 1;
|
||||
}
|
||||
|
||||
if (xNew < targetX == targetX <= xOld) {
|
||||
long v1 = ((long) targetZ - (long) z1) * (long) (x2 - x1);
|
||||
long v2 = ((long) z2 - (long) z1) * (long) (targetX - x1);
|
||||
|
||||
if (v1 < v2) {
|
||||
inside = !inside;
|
||||
}
|
||||
}
|
||||
|
||||
xOld = xNew;
|
||||
zOld = zNew;
|
||||
}
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of chunks.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Vector2D> getChunks() {
|
||||
Set<Vector2D> chunks = new HashSet<Vector2D>();
|
||||
|
||||
Vector min = getMinimumPoint();
|
||||
Vector max = getMaximumPoint();
|
||||
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
Vector pt = new Vector(x, y, z);
|
||||
if (contains(pt)) { // Not the best
|
||||
chunks.add(ChunkStore.toChunk(pt));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of points.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int size() {
|
||||
return points.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the height of the polygon to fit the specified Y.
|
||||
*
|
||||
* @param y
|
||||
* @return true if the area was expanded
|
||||
*/
|
||||
public boolean expandY(int y) {
|
||||
if (!hasY) {
|
||||
minY = y;
|
||||
maxY = y;
|
||||
hasY = true;
|
||||
return true;
|
||||
} else if (y < minY) {
|
||||
minY = y;
|
||||
return true;
|
||||
} else if (y > maxY) {
|
||||
maxY = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the iterator.
|
||||
*
|
||||
* @return iterator of points inside the region
|
||||
*/
|
||||
public Iterator<BlockVector> iterator() {
|
||||
return new Polygonal2DRegionIterator(this);
|
||||
|
||||
/*
|
||||
Incomplete iterator. Where's my yield?!
|
||||
|
||||
ArrayList<BlockVector> items = new ArrayList<BlockVector>();
|
||||
|
||||
int nodes, pixelZ, i, j, swap;
|
||||
int n = points.size();
|
||||
int[] nodeX = new int[n];
|
||||
|
||||
int minZ = getMinimumPoint().getBlockZ();
|
||||
int maxZ = getMaximumPoint().getBlockZ();
|
||||
|
||||
for (pixelZ = minZ; pixelZ < maxZ; pixelZ++) {
|
||||
// Build a list of nodes
|
||||
nodes = 0;
|
||||
j = n - 1;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (points.get(i).getBlockZ() < (double) pixelZ
|
||||
&& points.get(j).getBlockZ() >= (double) pixelZ
|
||||
|| points.get(j).getBlockZ() < (double) pixelZ
|
||||
&& points.get(i).getBlockZ() >= (double) pixelZ) {
|
||||
nodeX[nodes++] = (int) (points.get(i).getBlockX()
|
||||
+ (pixelZ - points.get(i).getBlockZ())
|
||||
/ (points.get(j).getBlockZ() - points.get(i)
|
||||
.getBlockZ())
|
||||
* (points.get(j).getBlockX() - points.get(i)
|
||||
.getBlockX()));
|
||||
}
|
||||
j = i;
|
||||
}
|
||||
|
||||
// Sort the nodes, via a simple bubble sort
|
||||
i = 0;
|
||||
while (i < nodes - 1) {
|
||||
if (nodeX[i] > nodeX[i + 1]) {
|
||||
swap = nodeX[i];
|
||||
nodeX[i] = nodeX[i + 1];
|
||||
nodeX[i + 1] = swap;
|
||||
if (i > 0)
|
||||
i--;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the pixels between node pairs
|
||||
for (i = 0; i < nodes; i += 2) {
|
||||
for (j = nodeX[i]; j < nodeX[i + 1]; j++) {
|
||||
for (int y = minY; y >= maxY; y++) {
|
||||
items.add(new BlockVector(j, y, pixelZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items.iterator();*/
|
||||
}
|
||||
|
||||
/**
|
||||
* A terrible polygonal region iterator.
|
||||
*/
|
||||
public class Polygonal2DRegionIterator implements Iterator<BlockVector> {
|
||||
protected List<BlockVector2D> points = new ArrayList<BlockVector2D>();
|
||||
protected int minX;
|
||||
protected int minY;
|
||||
protected int minZ;
|
||||
protected int maxX;
|
||||
protected int maxY;
|
||||
protected int maxZ;
|
||||
protected int n;
|
||||
protected int i;
|
||||
protected int curX;
|
||||
protected int curZ;
|
||||
protected int curY;
|
||||
protected BlockVector next;
|
||||
|
||||
public Polygonal2DRegionIterator(Polygonal2DRegion region) {
|
||||
points = new ArrayList<BlockVector2D>(region.points);
|
||||
Vector min = region.getMinimumPoint();
|
||||
Vector max = region.getMaximumPoint();
|
||||
minX = min.getBlockX();
|
||||
minY = min.getBlockY();
|
||||
minZ = min.getBlockZ();
|
||||
maxX = max.getBlockX();
|
||||
maxY = max.getBlockY();
|
||||
maxZ = max.getBlockZ();
|
||||
n = (maxX - minX + 1) * (maxZ - minZ + 1);
|
||||
i = 0;
|
||||
curX = 0;
|
||||
curZ = 0;
|
||||
curY = minY;
|
||||
next = null;
|
||||
findNext();
|
||||
}
|
||||
|
||||
private void findNext() {
|
||||
if (i >= n) {
|
||||
next = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (next != null && curY <= maxY) {
|
||||
curY++;
|
||||
next = new BlockVector(curX, curY, curZ);
|
||||
if (curY > maxY) {
|
||||
i++;
|
||||
curY = minY;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (i < n) {
|
||||
curZ = i / (maxX - minX + 1) + minZ;
|
||||
curX = (i % (maxX - minX + 1)) + minX;
|
||||
BlockVector pt = new BlockVector(curX, minY, curZ);
|
||||
if (contains(points, minY, maxY, pt)) {
|
||||
next = pt;
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
next = null;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
public BlockVector next() {
|
||||
BlockVector next = this.next;
|
||||
findNext();
|
||||
return next;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
}
|
||||
}
|
114
src/com/sk89q/worldedit/regions/Polygonal2DRegionSelector.java
Normal file
114
src/com/sk89q/worldedit/regions/Polygonal2DRegionSelector.java
Normal file
@ -0,0 +1,114 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalPlayer;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
|
||||
/**
|
||||
* Selector for polygonal regions.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class Polygonal2DRegionSelector implements RegionSelector {
|
||||
protected BlockVector pos1;
|
||||
protected Polygonal2DRegion region = new Polygonal2DRegion();
|
||||
|
||||
public boolean selectPrimary(Vector pos) {
|
||||
if (pos1 != null && pos1.equals(pos)) {
|
||||
return false;
|
||||
}
|
||||
pos1 = pos.toBlockVector();
|
||||
region = new Polygonal2DRegion();
|
||||
region.addPoint(pos);
|
||||
region.expandY(pos.getBlockY());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean selectSecondary(Vector pos) {
|
||||
if (region.size() > 0) {
|
||||
List<BlockVector2D> points = region.getPoints();
|
||||
BlockVector2D lastPoint = points.get(region.size() - 1);
|
||||
if (lastPoint.getBlockX() == pos.getBlockX()
|
||||
&& lastPoint.getBlockZ() == pos.getBlockZ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (points.size() >= 20) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
region.addPoint(pos);
|
||||
region.expandY(pos.getBlockY());
|
||||
return true;
|
||||
}
|
||||
|
||||
public void explainPrimarySelection(LocalPlayer player, Vector pos) {
|
||||
player.print("Starting a new polygon at " + pos + ".");
|
||||
}
|
||||
|
||||
public void explainSecondarySelection(LocalPlayer player, Vector pos) {
|
||||
player.print("Added point #" + region.size() + " at " + pos + ".");
|
||||
}
|
||||
|
||||
public BlockVector getPrimaryPosition() throws IncompleteRegionException {
|
||||
if (pos1 == null) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
return pos1;
|
||||
}
|
||||
|
||||
public Region getRegion() throws IncompleteRegionException {
|
||||
if (!isDefined()) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return region.size() > 2;
|
||||
}
|
||||
|
||||
public void learnChanges() {
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
pos1 = null;
|
||||
region = new Polygonal2DRegion();
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return "2Dx1D polygon";
|
||||
}
|
||||
|
||||
public List<String> getInformationLines() {
|
||||
List<String> lines = new ArrayList<String>();
|
||||
lines.add("# points: " + region.size());
|
||||
return lines;
|
||||
}
|
||||
|
||||
}
|
@ -19,15 +19,16 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Albert
|
||||
* @author sk89q
|
||||
*/
|
||||
public interface Region extends Iterable<Vector> {
|
||||
public interface Region extends Iterable<BlockVector> {
|
||||
/**
|
||||
* Get the lower point of a region.
|
||||
*
|
||||
@ -45,7 +46,7 @@ public interface Region extends Iterable<Vector> {
|
||||
*
|
||||
* @return number of blocks
|
||||
*/
|
||||
public int getSize();
|
||||
public int getArea();
|
||||
/**
|
||||
* Get X-size.
|
||||
*
|
||||
@ -68,14 +69,23 @@ public interface Region extends Iterable<Vector> {
|
||||
* Expand the region.
|
||||
*
|
||||
* @param change
|
||||
* @throws RegionOperationException
|
||||
*/
|
||||
public void expand(Vector change);
|
||||
public void expand(Vector change) throws RegionOperationException;
|
||||
/**
|
||||
* Contract the region.
|
||||
*
|
||||
* @param change
|
||||
* @throws RegionOperationException
|
||||
*/
|
||||
public void contract(Vector change);
|
||||
public void contract(Vector change) throws RegionOperationException;
|
||||
/**
|
||||
* Returns true based on whether the region contains the point,
|
||||
*
|
||||
* @param pt
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(Vector pt);
|
||||
/**
|
||||
* Get a list of chunks.
|
||||
*
|
||||
|
@ -0,0 +1,30 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
public class RegionOperationException extends WorldEditException {
|
||||
private static final long serialVersionUID = -6180325009115242142L;
|
||||
|
||||
public RegionOperationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
112
src/com/sk89q/worldedit/regions/RegionSelector.java
Normal file
112
src/com/sk89q/worldedit/regions/RegionSelector.java
Normal file
@ -0,0 +1,112 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import java.util.List;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalPlayer;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
|
||||
/**
|
||||
* Region selection factory.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public interface RegionSelector {
|
||||
/**
|
||||
* Called when the first point is selected.
|
||||
*
|
||||
* @param pos
|
||||
* @return true if something changed
|
||||
*/
|
||||
public boolean selectPrimary(Vector pos);
|
||||
|
||||
/**
|
||||
* Called when the second point is selected.
|
||||
*
|
||||
* @param pos
|
||||
* @return true if something changed
|
||||
*/
|
||||
public boolean selectSecondary(Vector pos);
|
||||
|
||||
/**
|
||||
* Tell the player information about his/her primary selection.
|
||||
*
|
||||
* @param player
|
||||
* @param pos
|
||||
*/
|
||||
public void explainPrimarySelection(LocalPlayer player, Vector pos);
|
||||
|
||||
/**
|
||||
* Tell the player information about his/her secondary selection.
|
||||
*
|
||||
* @param player
|
||||
* @param pos
|
||||
*/
|
||||
public void explainSecondarySelection(LocalPlayer player, Vector pos);
|
||||
|
||||
/**
|
||||
* Get the primary position.
|
||||
*
|
||||
* @return
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
public BlockVector getPrimaryPosition() throws IncompleteRegionException;
|
||||
|
||||
/**
|
||||
* Get the selection.
|
||||
*
|
||||
* @return
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
public Region getRegion() throws IncompleteRegionException;
|
||||
|
||||
/**
|
||||
* Returns whether the region has been fully defined.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isDefined();
|
||||
|
||||
/**
|
||||
* Update the selector with changes to the region.
|
||||
*/
|
||||
public void learnChanges();
|
||||
|
||||
/**
|
||||
* Clear the selection.
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Get a lowercase name of this region selector type.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getTypeName();
|
||||
|
||||
/**
|
||||
* Get lines of information about the selection.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> getInformationLines();
|
||||
}
|
Loading…
Reference in New Issue
Block a user