mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-06-27 09:56:41 +00:00
Initial abstraction.
This commit is contained in:
528
src/com/sk89q/worldedit/CuboidClipboard.java
Normal file
528
src/com/sk89q/worldedit/CuboidClipboard.java
Normal file
@ -0,0 +1,528 @@
|
||||
package com.sk89q.worldedit;
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.*;
|
||||
import com.sk89q.worldedit.data.*;
|
||||
import org.jnbt.*;
|
||||
import java.io.*;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The clipboard remembers the state of a cuboid region.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class CuboidClipboard {
|
||||
/**
|
||||
* Flip direction.
|
||||
*/
|
||||
public enum FlipDirection {
|
||||
NORTH_SOUTH,
|
||||
WEST_EAST,
|
||||
UP_DOWN
|
||||
}
|
||||
|
||||
private BaseBlock[][][] data;
|
||||
private Vector offset;
|
||||
private Vector origin;
|
||||
private Vector size;
|
||||
|
||||
/**
|
||||
* Constructs the clipboard.
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public CuboidClipboard(Vector size) {
|
||||
this.size = size;
|
||||
data = new BaseBlock[size.getBlockX()][size.getBlockY()][size.getBlockZ()];
|
||||
origin = new Vector();
|
||||
offset = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the clipboard.
|
||||
*
|
||||
* @param size
|
||||
* @param origin
|
||||
*/
|
||||
public CuboidClipboard(Vector size, Vector origin) {
|
||||
this.size = size;
|
||||
data = new BaseBlock[size.getBlockX()][size.getBlockY()][size.getBlockZ()];
|
||||
this.origin = origin;
|
||||
offset = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the clipboard.
|
||||
*
|
||||
* @param size
|
||||
* @param origin
|
||||
*/
|
||||
public CuboidClipboard(Vector size, Vector origin, Vector offset) {
|
||||
this.size = size;
|
||||
data = new BaseBlock[size.getBlockX()][size.getBlockY()][size.getBlockZ()];
|
||||
this.origin = origin;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width (X-direction) of the clipboard.
|
||||
*
|
||||
* @return width
|
||||
*/
|
||||
public int getWidth() {
|
||||
return size.getBlockX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length (Z-direction) of the clipboard.
|
||||
*
|
||||
* @return length
|
||||
*/
|
||||
public int getLength() {
|
||||
return size.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height (Y-direction) of the clipboard.
|
||||
*
|
||||
* @return height
|
||||
*/
|
||||
public int getHeight() {
|
||||
return size.getBlockY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the clipboard in 2D. It can only rotate by angles divisible by 90.
|
||||
*
|
||||
* @param angle in degrees
|
||||
*/
|
||||
public void rotate2D(int angle) {
|
||||
angle = angle % 360;
|
||||
if (angle % 90 != 0) { // Can only rotate 90 degrees at the moment
|
||||
return;
|
||||
}
|
||||
|
||||
int width = getWidth();
|
||||
int length = getLength();
|
||||
int height = getHeight();
|
||||
Vector sizeRotated = size.transform2D(angle, 0, 0, 0, 0);
|
||||
int shiftX = sizeRotated.getX() < 0 ? -sizeRotated.getBlockX() - 1 : 0;
|
||||
int shiftZ = sizeRotated.getZ() < 0 ? -sizeRotated.getBlockZ() - 1 : 0;
|
||||
|
||||
BaseBlock newData[][][] = new BaseBlock
|
||||
[Math.abs(sizeRotated.getBlockX())]
|
||||
[Math.abs(sizeRotated.getBlockY())]
|
||||
[Math.abs(sizeRotated.getBlockZ())];
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
Vector v = (new Vector(x, 0, z)).transform2D(angle, 0, 0, 0, 0);
|
||||
int newX = v.getBlockX();
|
||||
int newZ = v.getBlockZ();
|
||||
for (int y = 0; y < height; y++) {
|
||||
newData[shiftX + newX][y][shiftZ + newZ] = data[x][y][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = newData;
|
||||
size = new Vector(Math.abs(sizeRotated.getBlockX()),
|
||||
Math.abs(sizeRotated.getBlockY()),
|
||||
Math.abs(sizeRotated.getBlockZ()));
|
||||
offset = offset.transform2D(angle, 0, 0, 0, 0)
|
||||
.subtract(shiftX, 0, shiftZ);;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the clipboard.
|
||||
*
|
||||
* @param dir
|
||||
*/
|
||||
public void flip(FlipDirection dir) {
|
||||
int width = getWidth();
|
||||
int length = getLength();
|
||||
int height = getHeight();
|
||||
|
||||
if (dir == FlipDirection.NORTH_SOUTH) {
|
||||
int len = (int)Math.floor(width / 2);
|
||||
for (int xs = 0; xs < len; xs++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
BaseBlock old = data[xs][y][z];
|
||||
data[xs][y][z] = data[width - xs - 1][y][z];
|
||||
data[width - xs - 1][y][z] = old;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (dir == FlipDirection.WEST_EAST) {
|
||||
int len = (int)Math.floor(length / 2);
|
||||
for (int zs = 0; zs < len; zs++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
BaseBlock old = data[x][y][zs];
|
||||
data[x][y][zs] = data[x][y][length - zs - 1];
|
||||
data[x][y][length - zs - 1] = old;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (dir == FlipDirection.UP_DOWN) {
|
||||
int len = (int)Math.floor(height / 2);
|
||||
for (int ys = 0; ys < len; ys++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
BaseBlock old = data[x][ys][z];
|
||||
data[x][ys][z] = data[x][height - ys - 1][z];
|
||||
data[x][height - ys - 1][z] = old;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy to the clipboard.
|
||||
*
|
||||
* @param editSession
|
||||
*/
|
||||
public void copy(EditSession editSession) {
|
||||
for (int x = 0; x < size.getBlockX(); x++) {
|
||||
for (int y = 0; y < size.getBlockY(); y++) {
|
||||
for (int z = 0; z < size.getBlockZ(); z++) {
|
||||
data[x][y][z] =
|
||||
editSession.getBlock(new Vector(x, y, z).add(getOrigin()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paste from the clipboard.
|
||||
*
|
||||
* @param editSession
|
||||
* @param newOrigin Position to paste it from
|
||||
* @param noAir True to not paste air
|
||||
* @throws MaxChangedBlocksException
|
||||
*/
|
||||
public void paste(EditSession editSession, Vector newOrigin, boolean noAir)
|
||||
throws MaxChangedBlocksException {
|
||||
place(editSession, newOrigin.add(offset), noAir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places the blocks in a position from the minimum corner.
|
||||
*
|
||||
* @param editSession
|
||||
* @param pos
|
||||
* @param noAir
|
||||
* @throws MaxChangedBlocksException
|
||||
*/
|
||||
public void place(EditSession editSession, Vector pos, boolean noAir)
|
||||
throws MaxChangedBlocksException {
|
||||
for (int x = 0; x < size.getBlockX(); x++) {
|
||||
for (int y = 0; y < size.getBlockY(); y++) {
|
||||
for (int z = 0; z < size.getBlockZ(); z++) {
|
||||
if (noAir && data[x][y][z].isAir())
|
||||
continue;
|
||||
|
||||
editSession.setBlock(new Vector(x, y, z).add(pos),
|
||||
data[x][y][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the clipboard data to a .schematic-format file.
|
||||
*
|
||||
* @param path
|
||||
* @throws IOException
|
||||
* @throws DataException
|
||||
*/
|
||||
public void saveSchematic(String path) throws IOException, DataException {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
int length = getLength();
|
||||
|
||||
if (width > 65535) {
|
||||
throw new DataException("Width of region too large for a .schematic");
|
||||
}
|
||||
if (height > 65535) {
|
||||
throw new DataException("Height of region too large for a .schematic");
|
||||
}
|
||||
if (length > 65535) {
|
||||
throw new DataException("Length of region too large for a .schematic");
|
||||
}
|
||||
|
||||
HashMap<String,Tag> schematic = new HashMap<String,Tag>();
|
||||
schematic.put("Width", new ShortTag("Width", (short)width));
|
||||
schematic.put("Length", new ShortTag("Length", (short)length));
|
||||
schematic.put("Height", new ShortTag("Height", (short)height));
|
||||
schematic.put("Materials", new StringTag("Materials", "Alpha"));
|
||||
schematic.put("WEOriginX", new IntTag("WEOriginX", getOrigin().getBlockX()));
|
||||
schematic.put("WEOriginY", new IntTag("WEOriginY", getOrigin().getBlockY()));
|
||||
schematic.put("WEOriginZ", new IntTag("WEOriginZ", getOrigin().getBlockZ()));
|
||||
schematic.put("WEOffsetX", new IntTag("WEOffsetX", getOffset().getBlockX()));
|
||||
schematic.put("WEOffsetY", new IntTag("WEOffsetY", getOffset().getBlockY()));
|
||||
schematic.put("WEOffsetZ", new IntTag("WEOffsetZ", getOffset().getBlockZ()));
|
||||
|
||||
// Copy
|
||||
byte[] blocks = new byte[width * height * length];
|
||||
byte[] blockData = new byte[width * height * length];
|
||||
ArrayList<Tag> tileEntities = new ArrayList<Tag>();
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
int index = y * width * length + z * width + x;
|
||||
blocks[index] = (byte)data[x][y][z].getID();
|
||||
blockData[index] = (byte)data[x][y][z].getData();
|
||||
|
||||
// Store TileEntity data
|
||||
if (data[x][y][z] instanceof TileEntityBlock) {
|
||||
TileEntityBlock tileEntityBlock =
|
||||
(TileEntityBlock)data[x][y][z];
|
||||
|
||||
// Get the list of key/values from the block
|
||||
Map<String,Tag> values = tileEntityBlock.toTileEntityNBT();
|
||||
if (values != null) {
|
||||
values.put("id", new StringTag("id",
|
||||
tileEntityBlock.getTileEntityID()));
|
||||
values.put("x", new IntTag("x", x));
|
||||
values.put("y", new IntTag("y", y));
|
||||
values.put("z", new IntTag("z", z));
|
||||
CompoundTag tileEntityTag =
|
||||
new CompoundTag("TileEntity", values);
|
||||
tileEntities.add(tileEntityTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
schematic.put("Blocks", new ByteArrayTag("Blocks", blocks));
|
||||
schematic.put("Data", new ByteArrayTag("Data", blockData));
|
||||
schematic.put("Entities", new ListTag("Entities", CompoundTag.class, new ArrayList<Tag>()));
|
||||
schematic.put("TileEntities", new ListTag("TileEntities", CompoundTag.class, tileEntities));
|
||||
|
||||
// Build and output
|
||||
CompoundTag schematicTag = new CompoundTag("Schematic", schematic);
|
||||
NBTOutputStream stream = new NBTOutputStream(new FileOutputStream(path));
|
||||
stream.writeTag(schematicTag);
|
||||
stream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a .schematic file into a clipboard.
|
||||
*
|
||||
* @param path
|
||||
* @param origin
|
||||
* @return clipboard
|
||||
* @throws DataException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static CuboidClipboard loadSchematic(String path)
|
||||
throws DataException, IOException {
|
||||
FileInputStream stream = new FileInputStream(path);
|
||||
NBTInputStream nbtStream = new NBTInputStream(stream);
|
||||
|
||||
Vector origin = new Vector();
|
||||
Vector offset = new Vector();
|
||||
|
||||
// Schematic tag
|
||||
CompoundTag schematicTag = (CompoundTag)nbtStream.readTag();
|
||||
if (!schematicTag.getName().equals("Schematic")) {
|
||||
throw new DataException("Tag \"Schematic\" does not exist or is not first");
|
||||
}
|
||||
|
||||
// Check
|
||||
Map<String,Tag> schematic = schematicTag.getValue();
|
||||
if (!schematic.containsKey("Blocks")) {
|
||||
throw new DataException("Schematic file is missing a \"Blocks\" tag");
|
||||
}
|
||||
|
||||
// Get information
|
||||
short width = (Short)getChildTag(schematic, "Width", ShortTag.class).getValue();
|
||||
short length = (Short)getChildTag(schematic, "Length", ShortTag.class).getValue();
|
||||
short height = (Short)getChildTag(schematic, "Height", ShortTag.class).getValue();
|
||||
|
||||
try {
|
||||
int originX = (Integer)getChildTag(schematic, "WEOriginX", IntTag.class).getValue();
|
||||
int originY = (Integer)getChildTag(schematic, "WEOriginY", IntTag.class).getValue();
|
||||
int originZ = (Integer)getChildTag(schematic, "WEOriginZ", IntTag.class).getValue();
|
||||
origin = new Vector(originX, originY, originZ);
|
||||
} catch (DataException e) {
|
||||
// No origin data
|
||||
}
|
||||
|
||||
try {
|
||||
int offsetX = (Integer)getChildTag(schematic, "WEOffsetX", IntTag.class).getValue();
|
||||
int offsetY = (Integer)getChildTag(schematic, "WEOffsetY", IntTag.class).getValue();
|
||||
int offsetZ = (Integer)getChildTag(schematic, "WEOffsetZ", IntTag.class).getValue();
|
||||
offset = new Vector(offsetX, offsetY, offsetZ);
|
||||
} catch (DataException e) {
|
||||
// No offset data
|
||||
}
|
||||
|
||||
// Check type of Schematic
|
||||
String materials = (String)getChildTag(schematic, "Materials", StringTag.class).getValue();
|
||||
if (!materials.equals("Alpha")) {
|
||||
throw new DataException("Schematic file is not an Alpha schematic");
|
||||
}
|
||||
|
||||
// Get blocks
|
||||
byte[] blocks = (byte[])getChildTag(schematic, "Blocks", ByteArrayTag.class).getValue();
|
||||
byte[] blockData = (byte[])getChildTag(schematic, "Data", ByteArrayTag.class).getValue();
|
||||
|
||||
// Need to pull out tile entities
|
||||
List<Tag> tileEntities = (List<Tag>)((ListTag)getChildTag(schematic, "TileEntities", ListTag.class))
|
||||
.getValue();
|
||||
Map<BlockVector,Map<String,Tag>> tileEntitiesMap =
|
||||
new HashMap<BlockVector,Map<String,Tag>>();
|
||||
|
||||
for (Tag tag : tileEntities) {
|
||||
if (!(tag instanceof CompoundTag)) continue;
|
||||
CompoundTag t = (CompoundTag)tag;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
|
||||
Map<String,Tag> values = new HashMap<String,Tag>();
|
||||
|
||||
for (Map.Entry<String,Tag> entry : t.getValue().entrySet()) {
|
||||
if (entry.getKey().equals("x")) {
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
x = ((IntTag)entry.getValue()).getValue();
|
||||
}
|
||||
} else if (entry.getKey().equals("y")) {
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
y = ((IntTag)entry.getValue()).getValue();
|
||||
}
|
||||
} else if (entry.getKey().equals("z")) {
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
z = ((IntTag)entry.getValue()).getValue();
|
||||
}
|
||||
}
|
||||
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
BlockVector vec = new BlockVector(x, y, z);
|
||||
tileEntitiesMap.put(vec, values);
|
||||
}
|
||||
|
||||
Vector size = new Vector(width, height, length);
|
||||
CuboidClipboard clipboard = new CuboidClipboard(size);
|
||||
clipboard.setOrigin(origin);
|
||||
clipboard.setOffset(offset);
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
int index = y * width * length + z * width + x;
|
||||
BlockVector pt = new BlockVector(x, y, z);
|
||||
BaseBlock block;
|
||||
|
||||
if (blocks[index] == 63 || blocks[index] == 68) { // Signs
|
||||
block = new SignBlock(blocks[index], blockData[index]);
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
((TileEntityBlock)block).fromTileEntityNBT(
|
||||
tileEntitiesMap.get(pt));
|
||||
}
|
||||
} else if(blocks[index] == 54) { // Chest
|
||||
block = new ChestBlock();
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
((TileEntityBlock)block).fromTileEntityNBT(
|
||||
tileEntitiesMap.get(pt));
|
||||
}
|
||||
} else if(blocks[index] == 52) { // Mob spawner
|
||||
block = new MobSpawnerBlock();
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
((TileEntityBlock)block).fromTileEntityNBT(
|
||||
tileEntitiesMap.get(pt));
|
||||
}
|
||||
} else {
|
||||
block = new BaseBlock(blocks[index], blockData[index]);
|
||||
}
|
||||
|
||||
clipboard.data[x][y][z] = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child tag of a NBT structure.
|
||||
*
|
||||
* @param items
|
||||
* @param key
|
||||
* @param expected
|
||||
* @return child tag
|
||||
* @throws DataException
|
||||
*/
|
||||
private static Tag getChildTag(Map<String,Tag> items, String key,
|
||||
Class<? extends Tag> expected) throws DataException {
|
||||
|
||||
if (!items.containsKey(key)) {
|
||||
throw new DataException("Schematic file is missing a \"" + key + "\" tag");
|
||||
}
|
||||
Tag tag = items.get(key);
|
||||
if (!expected.isInstance(tag)) {
|
||||
throw new DataException(
|
||||
key + " tag is not of tag type " + expected.getName());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the origin
|
||||
*/
|
||||
public Vector getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param origin the origin to set
|
||||
*/
|
||||
public void setOrigin(Vector origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the offset
|
||||
*/
|
||||
public Vector getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param origin the offset to set
|
||||
*/
|
||||
public void setOffset(Vector offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
1982
src/com/sk89q/worldedit/EditSession.java
Executable file
1982
src/com/sk89q/worldedit/EditSession.java
Executable file
File diff suppressed because it is too large
Load Diff
194
src/com/sk89q/worldedit/ServerInterface.java
Normal file
194
src/com/sk89q/worldedit/ServerInterface.java
Normal file
@ -0,0 +1,194 @@
|
||||
package com.sk89q.worldedit;
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
|
||||
import com.sk89q.worldedit.bags.BlockBag;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public abstract class ServerInterface {
|
||||
/**
|
||||
* Instance.
|
||||
*/
|
||||
private static ServerInterface instance;
|
||||
|
||||
/**
|
||||
* Get the current instance.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ServerInterface getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up an instance.
|
||||
* @param instance
|
||||
*/
|
||||
public static void setup(ServerInterface instance) {
|
||||
ServerInterface.instance = instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set block type.
|
||||
*
|
||||
* @param pt
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean setBlockType(Vector pt, int type);
|
||||
|
||||
/**
|
||||
* Get block type.
|
||||
*
|
||||
* @param pt
|
||||
* @return
|
||||
*/
|
||||
public abstract int getBlockType(Vector pt);
|
||||
|
||||
/**
|
||||
* Set block data.
|
||||
*
|
||||
* @param pt
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public abstract void setBlockData(Vector pt, int data);
|
||||
|
||||
/**
|
||||
* Get block data.
|
||||
*
|
||||
* @param pt
|
||||
* @return
|
||||
*/
|
||||
public abstract int getBlockData(Vector pt);
|
||||
|
||||
/**
|
||||
* Set sign text.
|
||||
*
|
||||
* @param pt
|
||||
* @param text
|
||||
*/
|
||||
public abstract void setSignText(Vector pt, String[] text);
|
||||
|
||||
/**
|
||||
* Get sign text.
|
||||
*
|
||||
* @param pt
|
||||
* @return
|
||||
*/
|
||||
public abstract String[] getSignText(Vector pt);
|
||||
|
||||
/**
|
||||
* Gets the contents of chests. Will return null if the chest does not
|
||||
* really exist or it is the second block for a double chest.
|
||||
*
|
||||
* @param pt
|
||||
* @return
|
||||
*/
|
||||
public abstract BaseItemStack[] getChestContents(Vector pt);
|
||||
|
||||
/**
|
||||
* Sets a chest slot.
|
||||
*
|
||||
* @param pt
|
||||
* @param contents
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean setChestContents(Vector pt, BaseItemStack[] contents);
|
||||
|
||||
/**
|
||||
* Clear a chest's contents.
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public abstract boolean clearChest(Vector pt);
|
||||
|
||||
/**
|
||||
* Checks if a mob type is valid.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean isValidMobType(String type);
|
||||
|
||||
/**
|
||||
* Set mob spawner mob type.
|
||||
*
|
||||
* @param pt
|
||||
* @param mobType
|
||||
*/
|
||||
public abstract void setMobSpawnerType(Vector pt, String mobType);
|
||||
|
||||
/**
|
||||
* Get mob spawner mob type. May return an empty string.
|
||||
*
|
||||
* @param pt
|
||||
* @param mobType
|
||||
*/
|
||||
public abstract String getMobSpawnerType(Vector pt);
|
||||
|
||||
/**
|
||||
* Generate a tree at a location.
|
||||
*
|
||||
* @param pt
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean generateTree(EditSession editSession, Vector pt);
|
||||
|
||||
/**
|
||||
* Drop an item.
|
||||
*
|
||||
* @param pt
|
||||
* @param type
|
||||
* @param count
|
||||
* @param times
|
||||
*/
|
||||
public abstract void dropItem(Vector pt, int type, int count, int times);
|
||||
|
||||
/**
|
||||
* Drop an item.
|
||||
*
|
||||
* @param pt
|
||||
* @param type
|
||||
* @param count
|
||||
* @param times
|
||||
*/
|
||||
public abstract void dropItem(Vector pt, int type, int count);
|
||||
|
||||
/**
|
||||
* Drop an item.
|
||||
*
|
||||
* @param pt
|
||||
* @param type
|
||||
* @param count
|
||||
* @param times
|
||||
*/
|
||||
public abstract void dropItem(Vector pt, int type);
|
||||
|
||||
/**
|
||||
* Simulate a block being mined.
|
||||
*
|
||||
* @param pt
|
||||
*/
|
||||
public abstract void simulateBlockMine(Vector pt);
|
||||
}
|
490
src/com/sk89q/worldedit/WorldEditPlayer.java
Normal file
490
src/com/sk89q/worldedit/WorldEditPlayer.java
Normal file
@ -0,0 +1,490 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
import com.sk89q.worldedit.bags.BlockBag;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public abstract class WorldEditPlayer {
|
||||
/**
|
||||
* Directions.
|
||||
*/
|
||||
public enum DIRECTION {
|
||||
NORTH,
|
||||
NORTH_EAST,
|
||||
EAST,
|
||||
SOUTH_EAST,
|
||||
SOUTH,
|
||||
SOUTH_WEST,
|
||||
WEST,
|
||||
NORTH_WEST
|
||||
};
|
||||
|
||||
/**
|
||||
* Server.
|
||||
*/
|
||||
protected ServerInterface server;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*/
|
||||
protected WorldEditPlayer() {
|
||||
server = ServerInterface.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the player is holding a pick axe.
|
||||
*
|
||||
* @return whether a pick axe is held
|
||||
*/
|
||||
public boolean isHoldingPickAxe() {
|
||||
int item = getItemInHand();
|
||||
return item == 257 || item == 270 || item == 274 || item == 278
|
||||
|| item == 285;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a position for the player to stand that is not inside a block.
|
||||
* Blocks above the player will be iteratively tested until there is
|
||||
* a series of two free blocks. The player will be teleported to
|
||||
* that free position.
|
||||
*
|
||||
* @param searchPos search position
|
||||
*/
|
||||
public void findFreePosition(Vector searchPos) {
|
||||
int x = searchPos.getBlockX();
|
||||
int y = Math.max(0, searchPos.getBlockY());
|
||||
int origY = y;
|
||||
int z = searchPos.getBlockZ();
|
||||
|
||||
byte free = 0;
|
||||
|
||||
while (y <= 129) {
|
||||
if (BlockType.canPassThrough(server.getBlockType(new Vector(x, y, z)))) {
|
||||
free++;
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
|
||||
if (free == 2) {
|
||||
if (y - 1 != origY) {
|
||||
setPosition(new Vector(x + 0.5, y - 1, z + 0.5));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a position for the player to stand that is not inside a block.
|
||||
* Blocks above the player will be iteratively tested until there is
|
||||
* a series of two free blocks. The player will be teleported to
|
||||
* that free position.
|
||||
*/
|
||||
public void findFreePosition() {
|
||||
findFreePosition(getBlockIn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Go up one level to the next free space above.
|
||||
*
|
||||
* @return true if a spot was found
|
||||
*/
|
||||
public boolean ascendLevel() {
|
||||
Vector pos = getBlockIn();
|
||||
int x = pos.getBlockX();
|
||||
int y = Math.max(0, pos.getBlockY());
|
||||
int z = pos.getBlockZ();
|
||||
|
||||
byte free = 0;
|
||||
byte spots = 0;
|
||||
|
||||
while (y <= 129) {
|
||||
if (BlockType.canPassThrough(server.getBlockType(new Vector(x, y, z)))) {
|
||||
free++;
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
|
||||
if (free == 2) {
|
||||
spots++;
|
||||
if (spots == 2) {
|
||||
int type = server.getBlockType(new Vector(x, y - 2, z));
|
||||
|
||||
// Don't get put in lava!
|
||||
if (type == 10 || type == 11) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setPosition(new Vector(x + 0.5, y - 1, z + 0.5));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go up one level to the next free space above.
|
||||
*
|
||||
* @return true if a spot was found
|
||||
*/
|
||||
public boolean descendLevel() {
|
||||
Vector pos = getBlockIn();
|
||||
int x = pos.getBlockX();
|
||||
int y = Math.max(0, pos.getBlockY() - 1);
|
||||
int z = pos.getBlockZ();
|
||||
|
||||
byte free = 0;
|
||||
|
||||
while (y >= 1) {
|
||||
if (BlockType.canPassThrough(server.getBlockType(new Vector(x, y, z)))) {
|
||||
free++;
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
|
||||
if (free == 2) {
|
||||
// So we've found a spot, but we have to drop the player
|
||||
// lightly and also check to see if there's something to
|
||||
// stand upon
|
||||
while (y >= 0) {
|
||||
int type = server.getBlockType(new Vector(x, y, z));
|
||||
|
||||
// Don't want to end up in lava
|
||||
if (type != 0 && type != 10 && type != 11) {
|
||||
// Found a block!
|
||||
setPosition(new Vector(x + 0.5, y + 1, z + 0.5));
|
||||
return true;
|
||||
}
|
||||
|
||||
y--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
y--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ascend to the ceiling above.
|
||||
*
|
||||
* @param clearance
|
||||
* @return whether the player was moved
|
||||
*/
|
||||
public boolean ascendToCeiling(int clearance) {
|
||||
Vector pos = getBlockIn();
|
||||
int x = pos.getBlockX();
|
||||
int initialY = Math.max(0, pos.getBlockY());
|
||||
int y = Math.max(0, pos.getBlockY() + 2);
|
||||
int z = pos.getBlockZ();
|
||||
|
||||
// No free space above
|
||||
if (server.getBlockType(new Vector(x, y, z)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (y <= 127) {
|
||||
// Found a ceiling!
|
||||
if (!BlockType.canPassThrough(server.getBlockType(new Vector(x, y, z)))) {
|
||||
int platformY = Math.max(initialY, y - 3 - clearance);
|
||||
server.setBlockType(new Vector(x, platformY, z),
|
||||
BlockType.GLASS.getID());
|
||||
setPosition(new Vector(x + 0.5, platformY + 1, z + 0.5));
|
||||
return true;
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just go up.
|
||||
*
|
||||
* @param distance
|
||||
* @return whether the player was moved
|
||||
*/
|
||||
public boolean ascendUpwards(int distance) {
|
||||
Vector pos = getBlockIn();
|
||||
int x = pos.getBlockX();
|
||||
int initialY = Math.max(0, pos.getBlockY());
|
||||
int y = Math.max(0, pos.getBlockY() + 1);
|
||||
int z = pos.getBlockZ();
|
||||
int maxY = Math.min(128, initialY + distance);
|
||||
|
||||
while (y <= 129) {
|
||||
if (!BlockType.canPassThrough(server.getBlockType(new Vector(x, y, z)))) {
|
||||
break; // Hit something
|
||||
} else if (y > maxY + 1) {
|
||||
break;
|
||||
} else if (y == maxY + 1) {
|
||||
server.setBlockType(new Vector(x, y - 2, z),
|
||||
BlockType.GLASS.getID());
|
||||
setPosition(new Vector(x + 0.5, y - 1, z + 0.5));
|
||||
return true;
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the point of the block that is being stood in.
|
||||
*
|
||||
* @return point
|
||||
*/
|
||||
public Vector getBlockIn() {
|
||||
return getPosition().toBlockVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the point of the block that is being stood upon.
|
||||
*
|
||||
* @return point
|
||||
*/
|
||||
public Vector getBlockOn() {
|
||||
return getPosition().subtract(0, 1, 0).toBlockVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the point of the block being looked at. May return null.
|
||||
*
|
||||
* @param range
|
||||
* @return point
|
||||
*/
|
||||
public abstract Vector getBlockTrace(int range);
|
||||
|
||||
/**
|
||||
* Get the point of the block being looked at. May return null.
|
||||
*
|
||||
* @param range
|
||||
* @return point
|
||||
*/
|
||||
public abstract Vector getSolidBlockTrace(int range);
|
||||
|
||||
/**
|
||||
* Get the player's cardinal direction (N, W, NW, etc.). May return null.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WorldEditPlayer.DIRECTION getCardinalDirection() {
|
||||
// From hey0's code
|
||||
double rot = (getYaw() - 90) % 360;
|
||||
if (rot < 0) {
|
||||
rot += 360.0;
|
||||
}
|
||||
return getDirection(rot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns direction according to rotation. May return null.
|
||||
*
|
||||
* @param rot
|
||||
* @return
|
||||
*/
|
||||
private static WorldEditPlayer.DIRECTION getDirection(double rot) {
|
||||
if (0 <= rot && rot < 22.5) {
|
||||
return WorldEditPlayer.DIRECTION.NORTH;
|
||||
} else if (22.5 <= rot && rot < 67.5) {
|
||||
return WorldEditPlayer.DIRECTION.NORTH_EAST;
|
||||
} else if (67.5 <= rot && rot < 112.5) {
|
||||
return WorldEditPlayer.DIRECTION.EAST;
|
||||
} else if (112.5 <= rot && rot < 157.5) {
|
||||
return WorldEditPlayer.DIRECTION.SOUTH_EAST;
|
||||
} else if (157.5 <= rot && rot < 202.5) {
|
||||
return WorldEditPlayer.DIRECTION.SOUTH;
|
||||
} else if (202.5 <= rot && rot < 247.5) {
|
||||
return WorldEditPlayer.DIRECTION.SOUTH_WEST;
|
||||
} else if (247.5 <= rot && rot < 292.5) {
|
||||
return WorldEditPlayer.DIRECTION.WEST;
|
||||
} else if (292.5 <= rot && rot < 337.5) {
|
||||
return WorldEditPlayer.DIRECTION.NORTH_WEST;
|
||||
} else if (337.5 <= rot && rot < 360.0) {
|
||||
return WorldEditPlayer.DIRECTION.NORTH;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the item that the player is holding.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract int getItemInHand();
|
||||
|
||||
/**
|
||||
* Get the name of the player.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/**
|
||||
* Get the player's position.
|
||||
*
|
||||
* @return point
|
||||
*/
|
||||
public abstract Vector getPosition();
|
||||
|
||||
/**
|
||||
* Get the player's view pitch.
|
||||
*
|
||||
* @return pitch
|
||||
*/
|
||||
/**
|
||||
* Get the player's view pitch.
|
||||
*
|
||||
* @return pitch
|
||||
*/
|
||||
public abstract double getPitch();
|
||||
|
||||
/**
|
||||
* Get the player's view yaw.
|
||||
*
|
||||
* @return yaw
|
||||
*/
|
||||
/**
|
||||
* Get the player's view yaw.
|
||||
*
|
||||
* @return yaw
|
||||
*/
|
||||
public abstract double getYaw();
|
||||
|
||||
/**
|
||||
* Gives the player an item.
|
||||
*
|
||||
* @param type
|
||||
* @param amt
|
||||
*/
|
||||
public abstract void giveItem(int type, int amt);
|
||||
|
||||
/**
|
||||
* Pass through the wall that you are looking at.
|
||||
*
|
||||
* @param range
|
||||
* @return whether the player was pass through
|
||||
*/
|
||||
public abstract boolean passThroughForwardWall(int range);
|
||||
|
||||
/**
|
||||
* Print a message.
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public abstract void printRaw(String msg);
|
||||
|
||||
/**
|
||||
* Print a WorldEdit message.
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public abstract void print(String msg);
|
||||
|
||||
/**
|
||||
* Print a WorldEdit error.
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public abstract void printError(String msg);
|
||||
|
||||
/**
|
||||
* Move the player.
|
||||
*
|
||||
* @param pos
|
||||
* @param pitch
|
||||
* @param yaw
|
||||
*/
|
||||
public abstract void setPosition(Vector pos, float pitch, float yaw);
|
||||
|
||||
/**
|
||||
* Move the player.
|
||||
*
|
||||
* @param pos
|
||||
*/
|
||||
public void setPosition(Vector pos) {
|
||||
setPosition(pos, (float)getPitch(), (float)getYaw());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player's list of groups.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract String[] getGroups();
|
||||
|
||||
/**
|
||||
* Get this player's block bag.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract BlockBag getInventoryBlockBag();
|
||||
|
||||
/**
|
||||
* Checks if a player has permission.
|
||||
*
|
||||
* @param perm
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean hasPermission(String perm);
|
||||
|
||||
/**
|
||||
* Returns true if equal.
|
||||
*
|
||||
* @param other
|
||||
* @return whether the other object is equivalent
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof WorldEditPlayer)) {
|
||||
return false;
|
||||
}
|
||||
WorldEditPlayer other2 = (WorldEditPlayer)other;
|
||||
return other2.getName().equals(getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hash code.
|
||||
*
|
||||
* @return hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getName().hashCode();
|
||||
}
|
||||
}
|
430
src/com/sk89q/worldedit/WorldEditSession.java
Normal file
430
src/com/sk89q/worldedit/WorldEditSession.java
Normal file
@ -0,0 +1,430 @@
|
||||
package com.sk89q.worldedit;
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
|
||||
import com.sk89q.worldedit.snapshots.Snapshot;
|
||||
import com.sk89q.worldedit.bags.BlockBag;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.*;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class WorldEditSession {
|
||||
/**
|
||||
* List of super pick axe modes.
|
||||
*/
|
||||
public static enum SuperPickaxeMode {
|
||||
SINGLE,
|
||||
SAME_TYPE_RECURSIVE,
|
||||
SAME_TYPE_AREA
|
||||
};
|
||||
/**
|
||||
* List of tools.
|
||||
*/
|
||||
public static enum Tool {
|
||||
NONE,
|
||||
INFO,
|
||||
TREE,
|
||||
}
|
||||
|
||||
public static final int MAX_HISTORY_SIZE = 15;
|
||||
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;
|
||||
private boolean toolControl = true;
|
||||
private boolean superPickAxe = false;
|
||||
private SuperPickaxeMode superPickaxeMode = SuperPickaxeMode.SINGLE;
|
||||
private Tool tool = Tool.NONE;
|
||||
private int superPickaxeRange = 3;
|
||||
private int maxBlocksChanged = -1;
|
||||
private boolean useInventory;
|
||||
private Snapshot snapshot;
|
||||
|
||||
/**
|
||||
* Clear history.
|
||||
*/
|
||||
public void clearHistory() {
|
||||
history.clear();
|
||||
historyPointer = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the edit session.
|
||||
*/
|
||||
public void remember(EditSession editSession) {
|
||||
// Don't store anything if no changes were made
|
||||
if (editSession.size() == 0) { return; }
|
||||
|
||||
// Destroy any sessions after this undo point
|
||||
while (historyPointer < history.size()) {
|
||||
history.remove(historyPointer);
|
||||
}
|
||||
history.add(editSession);
|
||||
while (history.size() > MAX_HISTORY_SIZE) {
|
||||
history.remove(0);
|
||||
}
|
||||
historyPointer = history.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo.
|
||||
*
|
||||
* @return whether anything was undone
|
||||
*/
|
||||
public EditSession undo(BlockBag newBlockBag) {
|
||||
historyPointer--;
|
||||
if (historyPointer >= 0) {
|
||||
EditSession editSession = history.get(historyPointer);
|
||||
editSession.setBlockBag(newBlockBag);
|
||||
editSession.undo();
|
||||
return editSession;
|
||||
} else {
|
||||
historyPointer = 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redo.
|
||||
*
|
||||
* @return whether anything was redone
|
||||
*/
|
||||
public EditSession redo(BlockBag newBlockBag) {
|
||||
if (historyPointer < history.size()) {
|
||||
EditSession editSession = history.get(historyPointer);
|
||||
editSession.setBlockBag(newBlockBag);
|
||||
editSession.redo();
|
||||
historyPointer++;
|
||||
return editSession;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to make sure that position 1 is defined.
|
||||
*
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
private void checkPos1() throws IncompleteRegionException {
|
||||
if (pos1 == null) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to make sure that position 2 is defined.
|
||||
*
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
private void checkPos2() throws IncompleteRegionException {
|
||||
if (pos2 == null) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the region is fully defined.
|
||||
*
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
public boolean isRegionDefined() {
|
||||
return pos1 != null && pos2 != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets defined position 1.
|
||||
*
|
||||
* @return position 1
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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().
|
||||
*
|
||||
* @return region
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
public Region getRegion() throws IncompleteRegionException {
|
||||
if (region == null) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clipboard.
|
||||
*
|
||||
* @return clipboard, may be null
|
||||
* @throws EmptyClipboardException
|
||||
*/
|
||||
public CuboidClipboard getClipboard() throws EmptyClipboardException {
|
||||
if (clipboard == null) {
|
||||
throw new EmptyClipboardException();
|
||||
}
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clipboard.
|
||||
*
|
||||
* @param clipboard
|
||||
*/
|
||||
public void setClipboard(CuboidClipboard clipboard) {
|
||||
this.clipboard = clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if tool control is enabled.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
public boolean isToolControlEnabled() {
|
||||
return toolControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change tool control setting.
|
||||
*
|
||||
* @param toolControl
|
||||
*/
|
||||
public void setToolControl(boolean toolControl) {
|
||||
this.toolControl = toolControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of blocks that can be changed in an edit session.
|
||||
*
|
||||
* @return block change limit
|
||||
*/
|
||||
public int getBlockChangeLimit() {
|
||||
return maxBlocksChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of blocks that can be changed.
|
||||
*
|
||||
* @param maxBlocksChanged
|
||||
*/
|
||||
public void setBlockChangeLimit(int maxBlocksChanged) {
|
||||
this.maxBlocksChanged = maxBlocksChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the super pick axe is enabled.
|
||||
*
|
||||
* @return status
|
||||
*/
|
||||
public boolean hasSuperPickAxe() {
|
||||
return superPickAxe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable super pick axe.
|
||||
*
|
||||
* @param superPickAxe
|
||||
*/
|
||||
public void enableSuperPickAxe() {
|
||||
superPickAxe = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable super pick axe.
|
||||
*
|
||||
* @param superPickAxe
|
||||
*/
|
||||
public void disableSuperPickAxe() {
|
||||
superPickAxe = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the super pick axe.
|
||||
*
|
||||
* @return status
|
||||
*/
|
||||
public boolean toggleSuperPickAxe() {
|
||||
superPickAxe = !superPickAxe;
|
||||
return superPickAxe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return position
|
||||
* @throws IncompleteRegionException
|
||||
*/
|
||||
public Vector getPlacementPosition(WorldEditPlayer player)
|
||||
throws IncompleteRegionException {
|
||||
if (!placeAtPos1) {
|
||||
return player.getBlockIn();
|
||||
}
|
||||
|
||||
checkPos1();
|
||||
return pos1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle placement position;
|
||||
*/
|
||||
public boolean togglePlacementPosition() {
|
||||
placeAtPos1 = !placeAtPos1;
|
||||
return placeAtPos1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a block bag for a player.
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
*/
|
||||
public BlockBag getBlockBag(WorldEditPlayer player) {
|
||||
if (!useInventory) {
|
||||
return null;
|
||||
}
|
||||
return player.getInventoryBlockBag();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the snapshotName
|
||||
*/
|
||||
public Snapshot getSnapshot() {
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param snapshot
|
||||
*/
|
||||
public void setSnapshot(Snapshot snapshot) {
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the superPickaxeMode
|
||||
*/
|
||||
public SuperPickaxeMode getSuperPickaxeMode() {
|
||||
return superPickaxeMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param superPickaxeMode the superPickaxeMode to set
|
||||
*/
|
||||
public void setSuperPickaxeMode(SuperPickaxeMode superPickaxeMode) {
|
||||
this.superPickaxeMode = superPickaxeMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the superPickaxeRange
|
||||
*/
|
||||
public int getSuperPickaxeRange() {
|
||||
return superPickaxeRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param superPickaxeRange the superPickaxeRange to set
|
||||
*/
|
||||
public void setSuperPickaxeRange(int superPickaxeRange) {
|
||||
this.superPickaxeRange = superPickaxeRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tool
|
||||
*/
|
||||
public Tool getTool() {
|
||||
return tool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tool the tool to set
|
||||
*/
|
||||
public void setTool(Tool tool) {
|
||||
this.tool = tool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the useInventory
|
||||
*/
|
||||
public boolean isUsingInventory() {
|
||||
return useInventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useInventory the useInventory to set
|
||||
*/
|
||||
public void setUseInventory(boolean useInventory) {
|
||||
this.useInventory = useInventory;
|
||||
}
|
||||
}
|
205
src/com/sk89q/worldedit/snapshots/SnapshotRestore.java
Normal file
205
src/com/sk89q/worldedit/snapshots/SnapshotRestore.java
Normal file
@ -0,0 +1,205 @@
|
||||
package com.sk89q.worldedit.snapshots;
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.regions.*;
|
||||
import com.sk89q.worldedit.blocks.*;
|
||||
import com.sk89q.worldedit.data.*;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class SnapshotRestore {
|
||||
/**
|
||||
* Store a list of chunks that are needed and the points in them.
|
||||
*/
|
||||
private Map<BlockVector2D,ArrayList<Vector>> neededChunks =
|
||||
new LinkedHashMap<BlockVector2D,ArrayList<Vector>>();
|
||||
/**
|
||||
* Chunk store.
|
||||
*/
|
||||
private ChunkStore chunkStore;
|
||||
/**
|
||||
* Count of the number of missing chunks.
|
||||
*/
|
||||
private ArrayList<Vector2D> missingChunks;
|
||||
/**
|
||||
* Count of the number of chunks that could be loaded for other reasons.
|
||||
*/
|
||||
private ArrayList<Vector2D> errorChunks;
|
||||
/**
|
||||
* Last error message.
|
||||
*/
|
||||
private String lastErrorMessage;
|
||||
|
||||
/**
|
||||
* Construct the snapshot restore operation.
|
||||
*
|
||||
* @param region
|
||||
*/
|
||||
public SnapshotRestore(ChunkStore chunkStore, Region region) {
|
||||
this.chunkStore = chunkStore;
|
||||
|
||||
if (region instanceof CuboidRegion) {
|
||||
findNeededCuboidChunks(region);
|
||||
} else {
|
||||
findNeededChunks(region);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find needed chunks in the cuboid of the region.
|
||||
*
|
||||
* @param region
|
||||
*/
|
||||
private void findNeededCuboidChunks(Region region) {
|
||||
Vector min = region.getMinimumPoint();
|
||||
Vector max = region.getMaximumPoint();
|
||||
|
||||
// First, we need to group points by chunk so that we only need
|
||||
// to keep one chunk in memory at any given moment
|
||||
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 pos = new Vector(x, y, z);
|
||||
BlockVector2D chunkPos = ChunkStore.toChunk(pos);
|
||||
|
||||
// Unidentified chunk
|
||||
if (!neededChunks.containsKey(chunkPos)) {
|
||||
neededChunks.put(chunkPos, new ArrayList<Vector>());
|
||||
}
|
||||
|
||||
neededChunks.get(chunkPos).add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find needed chunks in the region.
|
||||
*
|
||||
* @param region
|
||||
*/
|
||||
private void findNeededChunks(Region region) {
|
||||
// First, we need to group points by chunk so that we only need
|
||||
// to keep one chunk in memory at any given moment
|
||||
for (Vector pos : region) {
|
||||
BlockVector2D chunkPos = ChunkStore.toChunk(pos);
|
||||
|
||||
// Unidentified chunk
|
||||
if (!neededChunks.containsKey(chunkPos)) {
|
||||
neededChunks.put(chunkPos, new ArrayList<Vector>());
|
||||
}
|
||||
|
||||
neededChunks.get(chunkPos).add(pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of chunks that are needed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getChunksAffected() {
|
||||
return neededChunks.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores to world.
|
||||
*
|
||||
* @param editSession
|
||||
* @param region
|
||||
*/
|
||||
public void restore(EditSession editSession)
|
||||
throws MaxChangedBlocksException {
|
||||
|
||||
missingChunks = new ArrayList<Vector2D>();
|
||||
errorChunks = new ArrayList<Vector2D>();
|
||||
|
||||
// Now let's start restoring!
|
||||
for (Map.Entry<BlockVector2D,ArrayList<Vector>> entry :
|
||||
neededChunks.entrySet()) {
|
||||
BlockVector2D chunkPos = entry.getKey();
|
||||
Chunk chunk;
|
||||
|
||||
try {
|
||||
chunk = chunkStore.getChunk(chunkPos);
|
||||
// Good, the chunk could be at least loaded
|
||||
|
||||
// Now just copy blocks!
|
||||
for (Vector pos : entry.getValue()) {
|
||||
BaseBlock block = chunk.getBlock(pos);
|
||||
editSession.setBlock(pos, block);
|
||||
}
|
||||
} catch (MissingChunkException me) {
|
||||
missingChunks.add(chunkPos);
|
||||
} catch (DataException de) {
|
||||
errorChunks.add(chunkPos);
|
||||
lastErrorMessage = de.getMessage();
|
||||
} catch (IOException ioe) {
|
||||
errorChunks.add(chunkPos);
|
||||
lastErrorMessage = ioe.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the missing chunks. restore() must have been called
|
||||
* already.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Vector2D> getMissingChunks() {
|
||||
return missingChunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the chunks that could not have been loaded for other
|
||||
* reasons. restore() must have been called already.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Vector2D> getErrorChunks() {
|
||||
return errorChunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see where the backup succeeded in any capacity. False will
|
||||
* be returned if no chunk could be successfully loaded.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean hadTotalFailure() {
|
||||
return missingChunks.size() + errorChunks.size() == getChunksAffected();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastErrorMessage
|
||||
*/
|
||||
public String getLastErrorMessage() {
|
||||
return lastErrorMessage;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user