This commit is contained in:
Jesse Boyd 2016-04-14 07:31:02 +10:00
parent 5b3e0973f2
commit fff311a99f
18 changed files with 2056 additions and 213 deletions

View File

@ -13,6 +13,7 @@ import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
@ -21,6 +22,8 @@ import org.bukkit.plugin.Plugin;
*/
public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
protected World bukkitWorld;
/**
* Map of chunks in the queue
*/
@ -47,6 +50,14 @@ public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
// return false;
};
@Override
public boolean regenerateChunk(int x, int z) {
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getServer().getWorld(world);
}
return bukkitWorld.regenerateChunk(x, z);
}
@Override
public void addTask(int x, int z, Runnable runnable) {
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;

View File

@ -132,16 +132,20 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
lcz = cz;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
if (Settings.CHUNK_WAIT > 0) {
synchronized (loadQueue) {
loadQueue.add(new IntegerPair(cx, cz));
try {
loadQueue.wait(Settings.CHUNK_WAIT);
} catch (InterruptedException e) {
e.printStackTrace();
if (Thread.currentThread() != Fawe.get().getMainThread()) {
synchronized (loadQueue) {
loadQueue.add(new IntegerPair(cx, cz));
try {
loadQueue.wait(Settings.CHUNK_WAIT);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
}
} else {
bukkitWorld.loadChunk(cx, cz, true);
}
} else {
return 0;
@ -316,7 +320,6 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
private int lcy = Integer.MIN_VALUE;
private Object lc;
private char[] ls;
private World bukkitWorld;
@Override
public boolean setComponents(final FaweChunk<Chunk> fc) {

View File

@ -128,16 +128,20 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
lcz = cz;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
if (Settings.CHUNK_WAIT > 0) {
synchronized (loadQueue) {
loadQueue.add(new IntegerPair(cx, cz));
try {
loadQueue.wait(Settings.CHUNK_WAIT);
} catch (InterruptedException e) {
e.printStackTrace();
if (Thread.currentThread() != Fawe.get().getMainThread()) {
synchronized (loadQueue) {
loadQueue.add(new IntegerPair(cx, cz));
try {
loadQueue.wait(Settings.CHUNK_WAIT);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
}
} else {
bukkitWorld.loadChunk(cx, cz, true);
}
} else {
return 0;

View File

@ -16,6 +16,7 @@ import com.boydti.fawe.util.WEManager;
import com.boydti.fawe.util.WESubscriber;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.command.ScriptingCommands;
@ -32,6 +33,7 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.history.change.EntityCreate;
import com.sk89q.worldedit.history.change.EntityRemove;
import com.sk89q.worldedit.regions.CuboidRegion;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
@ -154,9 +156,6 @@ public class Fawe {
this.IMP.startMetrics();
}
// // Delete old history
// MainUtil.deleteDirectory(new File(IMP.getDirectory(), "history"));
// Delayed setup
TaskManager.IMP.later(new Runnable() {
@Override
@ -229,6 +228,8 @@ public class Fawe {
EntityRemove.inject();
LocalSession.inject();
BlockArrayClipboard.inject();
CuboidRegion.inject();
Vector.inject();
try {
CommandManager.inject();
} catch (Throwable e) {

View File

@ -20,7 +20,6 @@ import java.util.Map;
import java.util.zip.GZIPInputStream;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
/**
* The FaweAPI class offers a few useful functions.<br>
@ -42,90 +41,14 @@ public class FaweAPI {
return (version[0] > major) || ((version[0] == major) && (version[1] > minor)) || ((version[0] == major) && (version[1] == minor) && (version[2] >= minor2));
}
/**
* Set a block at a location asynchronously
* @param loc
* @param m
*/
public static void setBlockAsync(final Location loc, final Material m) {
SetQueue.IMP.setBlock(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), (short) m.getId());
}
/**
* Set a block at a location asynchronously
* @param world
* @param x
* @param y
* @param z
* @param id
* @param data
*/
public static void setBlockAsync(final String world, final int x, final int y, final int z, final short id, final byte data) {
SetQueue.IMP.setBlock(world, x, y, z, id, data);
}
// /**
// * Set a biome at a location asynchronously
// * @param world
// * @param x
// * @param z
// * @param id
// * @param data
// */
// public static void setBiomeAsync(final String world, final int x, final int z, final BaseBiome biome) {
// SetQueue.IMP.setBiome(world, x, z, biome);
// }
//
// /**
// * Set a biome at a location asynchronously
// * @param loc
// * @param biome
// */
// public static void setBiomeAsync(final Location loc, final BaseBiome biome) {
// SetQueue.IMP.setBiome(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockZ(), biome);
// }
//
// /**
// * This will return a FaweChunk object that can be modified.<br>
// * - The FaweChunk object can be reused if you want identical changes across chunks<br>
// * - This is additive modification.<br>
// * - First use {@link FaweChunk#fill(int, byte)} (e.g. with air) for absolute modification<br>
// * When ready, use {@link #setChunk(FaweChunk, ChunkLoc)}
// * @return
// */
// public static FaweChunk<?> createChunk() {
// return SetQueue.IMP.queue.getChunk(new ChunkLoc(null, 0, 0));
// }
//
// /**
// * @see #createChunk()
// * @param data
// * @param location
// */
// public static void setChunkAsync(final FaweChunk<?> data, final ChunkLoc location) {
// data.setChunkLoc(location);
// data.addToQueue();
// }
//
// /**
// * @see #createChunk()
// * @param data
// * @param chunk
// */
// public static void setChunkAsync(final FaweChunk<?> data, final Chunk chunk) {
// final ChunkLoc loc = new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
// data.setChunkLoc(loc);
// data.addToQueue();
// }
//
public static void fixLighting(String world, int x, int z, final boolean fixAll) {
FaweQueue queue = SetQueue.IMP.getQueue(world);
FaweQueue queue = SetQueue.IMP.getNewQueue(world);
queue.fixLighting(queue.getChunk(x, z), fixAll);
}
public static void fixLighting(final Chunk chunk, final boolean fixAll) {
FaweQueue queue = SetQueue.IMP.getQueue(chunk.getWorld().getName());
FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName());
queue.fixLighting(queue.getChunk(chunk.getX(), chunk.getZ()), fixAll);
}
@ -218,6 +141,8 @@ public class FaweAPI {
tagMap = null;
tag = null;
FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world);
for (int y = 0; y < height; y++) {
final int yy = y_offset + y;
if (yy > 255) {
@ -298,10 +223,10 @@ public class FaweAPI {
case 190:
case 191:
case 192:
setBlockAsync(world, xx, yy, zz, id, (byte) 0);
queue.setBlock(xx, yy, zz, id, (byte) 0);
break;
default: {
setBlockAsync(world, xx, yy, zz, id, datas[i]);
queue.setBlock(xx, yy, zz, id, datas[i]);
break;
}
}
@ -309,6 +234,8 @@ public class FaweAPI {
}
}
queue.enqueue();
ids = null;
datas = null;
}

View File

@ -1,8 +1,7 @@
package com.boydti.fawe.object;
import com.boydti.fawe.util.SetQueue;
/**
/**
*/
public class FaweLocation {
@ -37,8 +36,4 @@ public class FaweLocation {
public int hashCode() {
return this.x << (8 + this.z) << (4 + this.y);
}
public void setBlockAsync(final short id, final byte data) {
SetQueue.IMP.setBlock(this.world, this.x, this.y, this.z, id, data);
}
}

View File

@ -224,9 +224,8 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
}
BlockVector position = new BlockVector(x, y, z);
return dir ? new BlockChange(position, to, from) : new BlockChange(position, from, to);
} catch (Exception e) {
return null;
}
} catch (Exception ignore) {}
return null;
}
@Override

View File

@ -25,6 +25,8 @@ public abstract class FaweQueue {
public abstract boolean isChunkLoaded(final int x, final int z);
public abstract boolean regenerateChunk(int x, int z);
/**
* Gets the FaweChunk and sets the requested blocks
* @return
@ -52,4 +54,8 @@ public abstract class FaweQueue {
public abstract void addTask(int x, int z, Runnable runnable);
public abstract int getCombinedId4Data(int x, int y, int z);
public void enqueue() {
SetQueue.IMP.enqueue(this);
}
}

View File

@ -3,12 +3,9 @@ package com.boydti.fawe.util;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class SetQueue {
@ -18,7 +15,7 @@ public class SetQueue {
*/
public static final SetQueue IMP = new SetQueue();
public final Map<String, FaweQueue> queues;
public final ArrayDeque<FaweQueue> queues;
/**
* Track the time in ticks
@ -39,7 +36,7 @@ public class SetQueue {
public SetQueue() {
queues = new ConcurrentHashMap<>();
queues = new ArrayDeque();
TaskManager.IMP.repeat(new Runnable() {
@Override
public void run() {
@ -79,34 +76,24 @@ public class SetQueue {
}, 1);
}
public List<FaweQueue> getQueues() {
List<FaweQueue> list = new ArrayList<>(queues.size());
try {
for (Map.Entry<String, FaweQueue> entry : queues.entrySet()) {
list.add(entry.getValue());
}
}
catch (Exception e) {
e.printStackTrace();
}
return list;
public void enqueue(FaweQueue queue) {
queues.add(queue);
}
public FaweQueue getQueue(String world) {
FaweQueue queue = queues.get(world);
if (queue != null) {
return queue;
}
queue = Fawe.imp().getNewQueue(world);
queues.put(world, queue);
return queue;
public List<FaweQueue> getQueues() {
return new ArrayList<>(queues);
}
public FaweQueue getNewQueue(String world) {
return Fawe.imp().getNewQueue(world);
}
public FaweChunk<?> next() {
for (Map.Entry<String, FaweQueue> entry : queues.entrySet()) {
FaweQueue queue = entry.getValue();
while (queues.size() > 0) {
FaweQueue queue = queues.poll();
final FaweChunk<?> set = queue.next();
if (set != null ) {
if (set != null) {
queues.add(queue);
return set;
}
}
@ -155,65 +142,4 @@ public class SetQueue {
}
return true;
}
/**
* @param world
* @param x
* @param y
* @param z
* @param id
* @param data
* @return
*/
@Deprecated
public boolean setBlock(final String world, final int x, final int y, final int z, final short id, final byte data) {
SetQueue.IMP.setWaiting();
return getQueue(world).setBlock(x, y, z, id, data);
}
/**
* @param world
* @param x
* @param y
* @param z
* @param id
* @return
*/
@Deprecated
public boolean setBlock(final String world, final int x, final int y, final int z, final short id) {
SetQueue.IMP.setWaiting();
return getQueue(world).setBlock(x, y, z, id, (byte) 0);
}
/**
* @param world
* @param x
* @param z
* @param biome
* @return
*/
@Deprecated
public boolean setBiome(final String world, final int x, final int z, final BaseBiome biome) {
SetQueue.IMP.setWaiting();
return getQueue(world).setBiome(x, z, biome);
}
@Deprecated
public boolean isChunkLoaded(final String world, final int x, final int z) {
return getQueue(world).isChunkLoaded(x, z);
}
/**
* Add a task to run when the chunk is set<br>
* @throws IllegalArgumentException if the chunk is not in the queue
* @param world
* @param x
* @param y
* @param z
* @param runnable
*/
@Deprecated
public void addTask(String world, int x, int y, int z, Runnable runnable) {
getQueue(world).addTask(x >> 4, z >> 4, runnable);
}
}

View File

@ -0,0 +1,289 @@
package com.boydti.fawe.wrappers;
import com.sk89q.worldedit.PlayerDirection;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.WorldVectorFace;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.session.SessionKey;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.World;
import java.io.File;
import java.util.UUID;
import javax.annotation.Nullable;
public class PlayerWrapper implements Player {
private final Player parent;
public PlayerWrapper(Player parent) {
this.parent = parent;
}
@Override
public World getWorld() {
return new WorldWrapper((AbstractWorld) parent.getWorld());
}
@Override
public boolean isHoldingPickAxe() {
return parent.isHoldingPickAxe();
}
@Override
public PlayerDirection getCardinalDirection(int yawOffset) {
return parent.getCardinalDirection(yawOffset);
}
@Override
public int getItemInHand() {
return parent.getItemInHand();
}
@Override
public BaseBlock getBlockInHand() throws WorldEditException {
return parent.getBlockInHand();
}
@Override
public void giveItem(int type, int amount) {
parent.giveItem(type, amount);
}
@Override
public BlockBag getInventoryBlockBag() {
return parent.getInventoryBlockBag();
}
@Override
public boolean hasCreativeMode() {
return parent.hasCreativeMode();
}
@Override
public void findFreePosition(WorldVector searchPos) {
parent.findFreePosition(searchPos);
}
@Override
public void setOnGround(WorldVector searchPos) {
parent.setOnGround(searchPos);
}
@Override
public void findFreePosition() {
parent.findFreePosition();
}
@Override
public boolean ascendLevel() {
return parent.ascendLevel();
}
@Override
public boolean descendLevel() {
return parent.descendLevel();
}
@Override
public boolean ascendToCeiling(int clearance) {
return parent.ascendToCeiling(clearance);
}
@Override
public boolean ascendToCeiling(int clearance, boolean alwaysGlass) {
return parent.ascendToCeiling(clearance, alwaysGlass);
}
@Override
public boolean ascendUpwards(int distance) {
return parent.ascendUpwards(distance);
}
@Override
public boolean ascendUpwards(int distance, boolean alwaysGlass) {
return parent.ascendUpwards(distance, alwaysGlass);
}
@Override
public void floatAt(int x, int y, int z, boolean alwaysGlass) {
parent.floatAt(x, y, z, alwaysGlass);
}
@Override
public WorldVector getBlockIn() {
return parent.getBlockIn();
}
@Override
public WorldVector getBlockOn() {
return parent.getBlockOn();
}
@Override
public WorldVector getBlockTrace(int range, boolean useLastBlock) {
return parent.getBlockTrace(range, useLastBlock);
}
@Override
public WorldVectorFace getBlockTraceFace(int range, boolean useLastBlock) {
return parent.getBlockTraceFace(range, useLastBlock);
}
@Override
public WorldVector getBlockTrace(int range) {
return parent.getBlockTrace(range);
}
@Override
public WorldVector getSolidBlockTrace(int range) {
return parent.getSolidBlockTrace(range);
}
@Override
public PlayerDirection getCardinalDirection() {
return parent.getCardinalDirection();
}
@Override
@Deprecated
public WorldVector getPosition() {
return parent.getPosition();
}
@Override
@Deprecated
public double getPitch() {
return parent.getPitch();
}
@Override
@Deprecated
public double getYaw() {
return parent.getYaw();
}
@Override
public boolean passThroughForwardWall(int range) {
return parent.passThroughForwardWall(range);
}
@Override
public void setPosition(Vector pos, float pitch, float yaw) {
parent.setPosition(pos, pitch, yaw);
}
@Override
public void setPosition(Vector pos) {
parent.setPosition(pos);
}
@Override
@Nullable
public BaseEntity getState() {
return parent.getState();
}
@Override
public Location getLocation() {
return parent.getLocation();
}
@Override
public Extent getExtent() {
return parent.getExtent();
}
@Override
public boolean remove() {
return parent.remove();
}
@Override
@Nullable
public <T> T getFacet(Class<? extends T> cls) {
return parent.getFacet(cls);
}
@Override
public String getName() {
return parent.getName();
}
@Override
public void printRaw(String msg) {
parent.printRaw(msg);
}
@Override
public void printDebug(String msg) {
parent.printDebug(msg);
}
@Override
public void print(String msg) {
parent.print(msg);
}
@Override
public void printError(String msg) {
parent.printError(msg);
}
@Override
public boolean canDestroyBedrock() {
return parent.canDestroyBedrock();
}
@Override
public boolean isPlayer() {
return parent.isPlayer();
}
@Override
public File openFileOpenDialog(String[] extensions) {
return parent.openFileOpenDialog(extensions);
}
@Override
public File openFileSaveDialog(String[] extensions) {
return parent.openFileSaveDialog(extensions);
}
@Override
public void dispatchCUIEvent(CUIEvent event) {
parent.dispatchCUIEvent(event);
}
@Override
public UUID getUniqueId() {
return parent.getUniqueId();
}
@Override
public SessionKey getSessionKey() {
return parent.getSessionKey();
}
@Override
public String[] getGroups() {
return parent.getGroups();
}
@Override
public void checkPermission(String permission) throws AuthorizationException {
parent.checkPermission(permission);
}
@Override
public boolean hasPermission(String permission) {
return parent.hasPermission(permission);
}
}

View File

@ -0,0 +1,336 @@
package com.boydti.fawe.wrappers;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.TaskManager;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.WorldData;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
public class WorldWrapper extends AbstractWorld {
private final AbstractWorld parent;
public WorldWrapper(AbstractWorld parent) {
this.parent = parent;
}
@Override
public boolean useItem(Vector position, BaseItem item, Direction face) {
return parent.useItem(position, item, face);
}
@Override
public int getMaxY() {
return parent.getMaxY();
}
@Override
public boolean isValidBlockType(int type) {
return parent.isValidBlockType(type);
}
@Override
public boolean usesBlockData(int type) {
return parent.usesBlockData(type);
}
@Override
public Mask createLiquidMask() {
return parent.createLiquidMask();
}
@Override
public int getBlockType(Vector pt) {
return parent.getBlockType(pt);
}
@Override
public int getBlockData(Vector pt) {
return parent.getBlockData(pt);
}
@Override
public void dropItem(Vector pt, BaseItemStack item, int times) {
parent.dropItem(pt, item, times);
}
@Override
public void simulateBlockMine(Vector pt) {
parent.simulateBlockMine(pt);
}
@Override
public boolean generateTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return parent.generateTree(editSession, pt);
}
@Override
public boolean generateBigTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return parent.generateBigTree(editSession, pt);
}
@Override
public boolean generateBirchTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return parent.generateBirchTree(editSession, pt);
}
@Override
public boolean generateRedwoodTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return parent.generateRedwoodTree(editSession, pt);
}
@Override
public boolean generateTallRedwoodTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return parent.generateTallRedwoodTree(editSession, pt);
}
@Override
public void checkLoadedChunk(Vector pt) {
parent.checkLoadedChunk(pt);
}
@Override
public void fixAfterFastMode(Iterable<BlockVector2D> chunks) {
parent.fixAfterFastMode(chunks);
}
@Override
public void fixLighting(Iterable<BlockVector2D> chunks) {
parent.fixLighting(chunks);
}
@Override
public boolean playEffect(Vector position, int type, int data) {
return parent.playEffect(position, type, data);
}
@Override
public boolean queueBlockBreakEffect(Platform server, Vector position, int blockId, double priority) {
return parent.queueBlockBreakEffect(server, position, blockId, priority);
}
@Override
public Vector getMinimumPoint() {
return parent.getMinimumPoint();
}
@Override
public Vector getMaximumPoint() {
return parent.getMaximumPoint();
}
@Override
@Nullable
public Operation commit() {
return parent.commit();
}
@Override
public String getName() {
return parent.getName();
}
@Override
public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException {
return parent.setBlock(position, block, notifyAndLight);
}
@Override
public int getBlockLightLevel(Vector position) {
return parent.getBlockLightLevel(position);
}
@Override
public boolean clearContainerBlockContents(Vector position) {
return parent.clearContainerBlockContents(position);
}
@Override
public void dropItem(Vector position, BaseItemStack item) {
parent.dropItem(position, item);
}
@Override
public boolean regenerate(final Region region, EditSession session) {
final FaweQueue queue = session.getQueue();
final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet();
session.setChangeSet(fcs);
final CuboidRegion cb = (CuboidRegion) region;
final boolean cuboid = region instanceof CuboidRegion;
Set<Vector2D> chunks = region.getChunks();
TaskManager.IMP.objectTask(chunks, new RunnableVal<Vector2D>() {
@Override
public void run(Vector2D chunk) {
int cx = chunk.getBlockX();
int cz = chunk.getBlockZ();
int bx = cx << 4;
int bz = cz << 4;
Vector cmin = new Vector(bx, 0, bz);
Vector cmax = cmin.add(15, getMaxY(), 15);
if (cuboid && region.contains(cmin) && region.contains(cmax)) {
if (fcs != null) {
for (int x = 0; x < 16; x++) {
int xx = x + bx;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
for (int y = 0; y < getMaxY() + 1; y++) {
int from = queue.getCombinedId4Data(xx, y, zz);
if (!FaweCache.hasNBT(from >> 4)) {
fcs.add(xx, y, zz, from, 0);
} else {
try {
Vector loc = new Vector(xx, y, zz);
BaseBlock block = getLazyBlock(loc);
fcs.add(loc, block, FaweCache.CACHE_BLOCK[0]);
} catch (Throwable e) {
fcs.add(xx, y, zz, from, 0);
}
}
}
}
}
}
} else {
for (int x = 0; x < 16; x++) {
int xx = x + bx;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
for (int y = 0; y < getMaxY() + 1; y++) {
final Vector loc = new Vector(xx, y, zz);
int from = queue.getCombinedId4Data(xx, y, zz);
if (region.contains(loc)) {
if (fcs != null) {
if (!FaweCache.hasNBT(from >> 4)) {
fcs.add(xx, y, zz, from, 0);
} else {
try {
BaseBlock block = getLazyBlock(loc);
fcs.add(loc, block, FaweCache.CACHE_BLOCK[0]);
} catch (Throwable e) {
fcs.add(xx, y, zz, from, 0);
}
}
}
} else {
short id = (short) (from >> 4);
byte data = (byte) (from & 0xf);
if (!FaweCache.hasNBT(id)) {
queue.setBlock(xx, y, zz, id, data);
} else {
try {
final BaseBlock block = getLazyBlock(loc);
queue.addTask(cx, cz, new Runnable() {
@Override
public void run() {
try {
setBlock(loc, block, false);
} catch (WorldEditException e) {
e.printStackTrace();
}
}
});
} catch (Throwable e) {
queue.setBlock(xx, y, zz, id, data);
}
}
}
}
}
}
}
queue.regenerateChunk(cx, cz);
}
}, new Runnable() {
@Override
public void run() {
queue.enqueue();
}
});
return false;
}
@Override
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector position) throws MaxChangedBlocksException {
return parent.generateTree(type, editSession, position);
}
@Override
public WorldData getWorldData() {
return parent.getWorldData();
}
@Override
public boolean equals(Object other) {
return parent.equals(other);
}
@Override
public int hashCode() {
return parent.hashCode();
}
@Override
public List<? extends Entity> getEntities(Region region) {
return parent.getEntities(region);
}
@Override
public List<? extends Entity> getEntities() {
return parent.getEntities();
}
@Override
@Nullable
public Entity createEntity(Location location, BaseEntity entity) {
return parent.createEntity(location, entity);
}
@Override
public BaseBlock getBlock(Vector position) {
return parent.getBlock(position);
}
@Override
public BaseBlock getLazyBlock(Vector position) {
return parent.getLazyBlock(position);
}
@Override
public BaseBiome getBiome(Vector2D position) {
return parent.getBiome(position);
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
return parent.setBiome(position, biome);
}
}

View File

@ -42,6 +42,7 @@ import com.boydti.fawe.util.Perm;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.WEManager;
import com.boydti.fawe.wrappers.WorldWrapper;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
@ -113,6 +114,7 @@ import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.collection.DoubleArrayList;
import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayDeque;
@ -155,7 +157,7 @@ public class EditSession implements Extent {
BEFORE_HISTORY, BEFORE_REORDER, BEFORE_CHANGE
}
protected final World world;
private World world;
private FaweChangeSet changeSet;
private final EditSessionWrapper wrapper;
private MaskingExtent maskingExtent;
@ -208,17 +210,13 @@ public class EditSession implements Extent {
* @param blockBag an optional {@link BlockBag} to use, otherwise null
* @param event the event to call with the extent
*/
public EditSession(final EventBus eventBus, final World world, final int maxBlocks, @Nullable final BlockBag blockBag, final EditSessionEvent event) {
public EditSession(final EventBus eventBus, World world, final int maxBlocks, @Nullable final BlockBag blockBag, final EditSessionEvent event) {
checkNotNull(eventBus);
checkArgument(maxBlocks >= -1, "maxBlocks >= -1 required");
checkNotNull(event);
// Wrap world
this.blockBag = blockBag;
this.maxBlocks = maxBlocks;
this.world = world;
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
// this.changeSet = new BlockOptimizedHistory();
// Invalid; return null extent
if (world == null) {
final Extent extent = new NullExtent();
@ -226,10 +224,13 @@ public class EditSession implements Extent {
this.bypassHistory = extent;
this.bypassNone = extent;
this.changeSet = new NullChangeSet();
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
return;
}
final Actor actor = event.getActor();
this.queue = SetQueue.IMP.getQueue(world.getName());
this.queue = SetQueue.IMP.getNewQueue(world.getName());
this.world = (world = new WorldWrapper((AbstractWorld) world));
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
// Not a player; bypass history
if ((actor == null) || !actor.isPlayer()) {
Extent extent = new FastWorldEditExtent(world, queue);
@ -339,6 +340,10 @@ public class EditSession implements Extent {
return;
}
public FaweQueue getQueue() {
return queue;
}
private Extent wrapExtent(final Extent extent, final EventBus eventBus, EditSessionEvent event, final Stage stage) {
event = event.clone(stage);
event.setExtent(extent);
@ -853,6 +858,9 @@ public class EditSession implements Extent {
@Override
public void run() {
Operations.completeBlindly(EditSession.this.commit());
if (queue != null) {
queue.enqueue();
}
}
});
}
@ -2069,10 +2077,15 @@ public class EditSession implements Extent {
break;
}
}
} catch (MaxChangedBlocksException ignore) {
}
catch (MaxChangedBlocksException ignore) {}
}
}, null);
}, new Runnable() {
@Override
public void run() {
queue.enqueue();
}
});
}
return this.changes = -1;
}

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.jchronic.Chronic;
import com.sk89q.jchronic.Options;
import com.sk89q.jchronic.utils.Span;
@ -191,6 +192,10 @@ public class LocalSession {
public void remember(EditSession editSession) {
checkNotNull(editSession);
if (editSession.getQueue() != null) {
SetQueue.IMP.enqueue(editSession.getQueue());
}
// Don't store anything if no changes were made
if (editSession.size() == 0) return;

View File

@ -0,0 +1,853 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit;
import com.sk89q.worldedit.math.transform.AffineTransform;
import javax.annotation.Nullable;
/**
* An immutable 3-dimensional vector.
*/
public class Vector implements Comparable<Vector> {
public static final Vector ZERO = new Vector(0, 0, 0);
public static final Vector UNIT_X = new Vector(1, 0, 0);
public static final Vector UNIT_Y = new Vector(0, 1, 0);
public static final Vector UNIT_Z = new Vector(0, 0, 1);
public static final Vector ONE = new Vector(1, 1, 1);
public double x, y, z;
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public Vector(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public Vector(int x, int y, int z) {
this.x = (double) x;
this.y = (double) y;
this.z = (double) z;
}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public Vector(float x, float y, float z) {
this.x = (double) x;
this.y = (double) y;
this.z = (double) z;
}
/**
* Copy another vector.
*
* @param other another vector to make a copy of
*/
public Vector(Vector other) {
this.x = other.x;
this.y = other.y;
this.z = other.z;
}
/**
* Construct a new instance with X, Y, and Z coordinates set to 0.
*
* <p>One can also refer to a static {@link #ZERO}.</p>
*/
public Vector() {
this.x = 0;
this.y = 0;
this.z = 0;
}
/**
* Get the X coordinate.
*
* @return the x coordinate
*/
public double getX() {
return x;
}
/**
* Get the X coordinate rounded.
*
* @return the x coordinate
*/
public int getBlockX() {
return (int) Math.round(x);
}
/**
* Set the X coordinate.
*
* @param x the new X
* @return a new vector
*/
public Vector setX(double x) {
return new Vector(x, y, z);
}
/**
* Set the X coordinate.
*
* @param x the X coordinate
* @return new vector
*/
public Vector setX(int x) {
return new Vector(x, y, z);
}
/**
* Get the Y coordinate.
*
* @return the y coordinate
*/
public double getY() {
return y;
}
/**
* Get the Y coordinate rounded.
*
* @return the y coordinate
*/
public int getBlockY() {
return (int) Math.round(y);
}
/**
* Set the Y coordinate.
*
* @param y the new Y
* @return a new vector
*/
public Vector setY(double y) {
return new Vector(x, y, z);
}
/**
* Set the Y coordinate.
*
* @param y the new Y
* @return a new vector
*/
public Vector setY(int y) {
return new Vector(x, y, z);
}
/**
* Get the Z coordinate.
*
* @return the z coordinate
*/
public double getZ() {
return z;
}
/**
* Get the Z coordinate rounded.
*
* @return the z coordinate
*/
public int getBlockZ() {
return (int) Math.round(z);
}
/**
* Set the Z coordinate.
*
* @param z the new Z
* @return a new vector
*/
public Vector setZ(double z) {
return new Vector(x, y, z);
}
/**
* Set the Z coordinate.
*
* @param z the new Z
* @return a new vector
*/
public Vector setZ(int z) {
return new Vector(x, y, z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param other the other vector
* @return a new vector
*/
public Vector add(Vector other) {
return new Vector(x + other.x, y + other.y, z + other.z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param x the value to add
* @param y the value to add
* @param z the value to add
* @return a new vector
*/
public Vector add(double x, double y, double z) {
return new Vector(this.x + x, this.y + y, this.z + z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param x the value to add
* @param y the value to add
* @param z the value to add
* @return a new vector
*/
public Vector add(int x, int y, int z) {
return new Vector(this.x + x, this.y + y, this.z + z);
}
/**
* Add a list of vectors to this vector and return the
* result as a new vector.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector add(Vector... others) {
double newX = x, newY = y, newZ = z;
for (Vector other : others) {
newX += other.x;
newY += other.y;
newZ += other.z;
}
return new Vector(newX, newY, newZ);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param other the other vector
* @return a new vector
*/
public Vector subtract(Vector other) {
return new Vector(x - other.x, y - other.y, z - other.z);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param x the value to subtract
* @param y the value to subtract
* @param z the value to subtract
* @return a new vector
*/
public Vector subtract(double x, double y, double z) {
return new Vector(this.x - x, this.y - y, this.z - z);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param x the value to subtract
* @param y the value to subtract
* @param z the value to subtract
* @return a new vector
*/
public Vector subtract(int x, int y, int z) {
return new Vector(this.x - x, this.y - y, this.z - z);
}
/**
* Subtract a list of vectors from this vector and return the result
* as a new vector.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector subtract(Vector... others) {
double newX = x, newY = y, newZ = z;
for (Vector other : others) {
newX -= other.x;
newY -= other.y;
newZ -= other.z;
}
return new Vector(newX, newY, newZ);
}
/**
* Multiply this vector by another vector on each component.
*
* @param other the other vector
* @return a new vector
*/
public Vector multiply(Vector other) {
return new Vector(x * other.x, y * other.y, z * other.z);
}
/**
* Multiply this vector by another vector on each component.
*
* @param x the value to multiply
* @param y the value to multiply
* @param z the value to multiply
* @return a new vector
*/
public Vector multiply(double x, double y, double z) {
return new Vector(this.x * x, this.y * y, this.z * z);
}
/**
* Multiply this vector by another vector on each component.
*
* @param x the value to multiply
* @param y the value to multiply
* @param z the value to multiply
* @return a new vector
*/
public Vector multiply(int x, int y, int z) {
return new Vector(this.x * x, this.y * y, this.z * z);
}
/**
* Multiply this vector by zero or more vectors on each component.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector multiply(Vector... others) {
double newX = x, newY = y, newZ = z;
for (Vector other : others) {
newX *= other.x;
newY *= other.y;
newZ *= other.z;
}
return new Vector(newX, newY, newZ);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector multiply(double n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector multiply(float n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector multiply(int n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Divide this vector by another vector on each component.
*
* @param other the other vector
* @return a new vector
*/
public Vector divide(Vector other) {
return new Vector(x / other.x, y / other.y, z / other.z);
}
/**
* Divide this vector by another vector on each component.
*
* @param x the value to divide by
* @param y the value to divide by
* @param z the value to divide by
* @return a new vector
*/
public Vector divide(double x, double y, double z) {
return new Vector(this.x / x, this.y / y, this.z / z);
}
/**
* Divide this vector by another vector on each component.
*
* @param x the value to divide by
* @param y the value to divide by
* @param z the value to divide by
* @return a new vector
*/
public Vector divide(int x, int y, int z) {
return new Vector(this.x / x, this.y / y, this.z / z);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector divide(int n) {
return new Vector(x / n, y / n, z / n);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector divide(double n) {
return new Vector(x / n, y / n, z / n);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector divide(float n) {
return new Vector(x / n, y / n, z / n);
}
/**
* Get the length of the vector.
*
* @return length
*/
public double length() {
return Math.sqrt(x * x + y * y + z * z);
}
/**
* Get the length, squared, of the vector.
*
* @return length, squared
*/
public double lengthSq() {
return x * x + y * y + z * z;
}
/**
* Get the distance between this vector and another vector.
*
* @param other the other vector
* @return distance
*/
public double distance(Vector other) {
return Math.sqrt(Math.pow(other.x - x, 2) +
Math.pow(other.y - y, 2) +
Math.pow(other.z - z, 2));
}
/**
* Get the distance between this vector and another vector, squared.
*
* @param other the other vector
* @return distance
*/
public double distanceSq(Vector other) {
return Math.pow(other.x - x, 2) +
Math.pow(other.y - y, 2) +
Math.pow(other.z - z, 2);
}
/**
* Get the normalized vector, which is the vector divided by its
* length, as a new vector.
*
* @return a new vector
*/
public Vector normalize() {
return divide(length());
}
/**
* Gets the dot product of this and another vector.
*
* @param other the other vector
* @return the dot product of this and the other vector
*/
public double dot(Vector other) {
return x * other.x + y * other.y + z * other.z;
}
/**
* Gets the cross product of this and another vector.
*
* @param other the other vector
* @return the cross product of this and the other vector
*/
public Vector cross(Vector other) {
return new Vector(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
);
}
/**
* Checks to see if a vector is contained with another.
*
* @param min the minimum point (X, Y, and Z are the lowest)
* @param max the maximum point (X, Y, and Z are the lowest)
* @return true if the vector is contained
*/
public boolean containedWithin(Vector min, Vector max) {
return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z;
}
/**
* Checks to see if a vector is contained with another, comparing
* using discrete comparisons, inclusively.
*
* @param min the minimum point (X, Y, and Z are the lowest)
* @param max the maximum point (X, Y, and Z are the lowest)
* @return true if the vector is contained
*/
public boolean containedWithinBlock(Vector min, Vector max) {
return getBlockX() >= min.getBlockX() && getBlockX() <= max.getBlockX()
&& getBlockY() >= min.getBlockY() && getBlockY() <= max.getBlockY()
&& getBlockZ() >= min.getBlockZ() && getBlockZ() <= max.getBlockZ();
}
/**
* Clamp the Y component.
*
* @param min the minimum value
* @param max the maximum value
* @return a new vector
*/
public Vector clampY(int min, int max) {
return new Vector(x, Math.max(min, Math.min(max, y)), z);
}
/**
* Floors the values of all components.
*
* @return a new vector
*/
public Vector floor() {
return new Vector(Math.floor(x), Math.floor(y), Math.floor(z));
}
/**
* Rounds all components up.
*
* @return a new vector
*/
public Vector ceil() {
return new Vector(Math.ceil(x), Math.ceil(y), Math.ceil(z));
}
/**
* Rounds all components to the closest integer.
*
* <p>Components &lt; 0.5 are rounded down, otherwise up.</p>
*
* @return a new vector
*/
public Vector round() {
return new Vector(Math.floor(x + 0.5), Math.floor(y + 0.5), Math.floor(z + 0.5));
}
/**
* Returns a vector with the absolute values of the components of
* this vector.
*
* @return a new vector
*/
public Vector positive() {
return new Vector(Math.abs(x), Math.abs(y), Math.abs(z));
}
/**
* Perform a 2D transformation on this vector and return a new one.
*
* @param angle in degrees
* @param aboutX about which x coordinate to rotate
* @param aboutZ about which z coordinate to rotate
* @param translateX what to add after rotation
* @param translateZ what to add after rotation
* @return a new vector
* @see AffineTransform another method to transform vectors
*/
public Vector transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) {
angle = Math.toRadians(angle);
double x = this.x - aboutX;
double z = this.z - aboutZ;
double x2 = x * Math.cos(angle) - z * Math.sin(angle);
double z2 = x * Math.sin(angle) + z * Math.cos(angle);
return new Vector(
x2 + aboutX + translateX,
y,
z2 + aboutZ + translateZ
);
}
/**
* Returns whether this vector is collinear with another vector.
*
* @param other the other vector
* @return true if collinear
*/
public boolean isCollinearWith(Vector other) {
if (x == 0 && y == 0 && z == 0) {
// this is a zero vector
return true;
}
final double otherX = other.x;
final double otherY = other.y;
final double otherZ = other.z;
if (otherX == 0 && otherY == 0 && otherZ == 0) {
// other is a zero vector
return true;
}
if ((x == 0) != (otherX == 0)) return false;
if ((y == 0) != (otherY == 0)) return false;
if ((z == 0) != (otherZ == 0)) return false;
final double quotientX = otherX / x;
if (!Double.isNaN(quotientX)) {
return other.equals(multiply(quotientX));
}
final double quotientY = otherY / y;
if (!Double.isNaN(quotientY)) {
return other.equals(multiply(quotientY));
}
final double quotientZ = otherZ / z;
if (!Double.isNaN(quotientZ)) {
return other.equals(multiply(quotientZ));
}
throw new RuntimeException("This should not happen");
}
/**
* Get this vector's pitch as used within the game.
*
* @return pitch in radians
*/
public float toPitch() {
double x = getX();
double z = getZ();
if (x == 0 && z == 0) {
return getY() > 0 ? -90 : 90;
} else {
double x2 = x * x;
double z2 = z * z;
double xz = Math.sqrt(x2 + z2);
return (float) Math.toDegrees(Math.atan(-getY() / xz));
}
}
/**
* Get this vector's yaw as used within the game.
*
* @return yaw in radians
*/
public float toYaw() {
double x = getX();
double z = getZ();
double t = Math.atan2(-x, z);
double _2pi = 2 * Math.PI;
return (float) Math.toDegrees(((t + _2pi) % _2pi));
}
/**
* Create a new {@code BlockVector} using the given components.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return a new {@code BlockVector}
*/
public static BlockVector toBlockPoint(double x, double y, double z) {
return new BlockVector(
Math.floor(x),
Math.floor(y),
Math.floor(z)
);
}
/**
* Create a new {@code BlockVector} from this vector.
*
* @return a new {@code BlockVector}
*/
public BlockVector toBlockPoint() {
return new BlockVector(
Math.floor(x),
Math.floor(y),
Math.floor(z)
);
}
/**
* Create a new {@code BlockVector} from this vector.
*
* @return a new {@code BlockVector}
*/
public BlockVector toBlockVector() {
return new BlockVector(this);
}
/**
* Creates a 2D vector by dropping the Y component from this vector.
*
* @return a new {@code Vector2D}
*/
public Vector2D toVector2D() {
return new Vector2D(x, z);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Vector)) {
return false;
}
Vector other = (Vector) obj;
return other.x == this.x && other.y == this.y && other.z == this.z;
}
@Override
public int compareTo(@Nullable Vector other) {
if (other == null) {
throw new IllegalArgumentException("null not supported");
}
if (y != other.y) return Double.compare(y, other.y);
if (z != other.z) return Double.compare(z, other.z);
if (x != other.x) return Double.compare(x, other.x);
return 0;
}
@Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32));
return hash;
}
@Override
public String toString() {
return "(" + x + ", " + y + ", " + z + ")";
}
/**
* Gets the minimum components of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return minimum
*/
public static Vector getMinimum(Vector v1, Vector v2) {
return new Vector(
Math.min(v1.x, v2.x),
Math.min(v1.y, v2.y),
Math.min(v1.z, v2.z)
);
}
/**
* Gets the maximum components of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return maximum
*/
public static Vector getMaximum(Vector v1, Vector v2) {
return new Vector(
Math.max(v1.x, v2.x),
Math.max(v1.y, v2.y),
Math.max(v1.z, v2.z)
);
}
/**
* Gets the midpoint of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return maximum
*/
public static Vector getMidpoint(Vector v1, Vector v2) {
return new Vector(
(v1.x + v2.x) / 2,
(v1.y + v2.y) / 2,
(v1.z + v2.z) / 2
);
}
public static Class<?> inject() {
return Vector.class;
}
}

View File

@ -24,6 +24,7 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.PlayerWrapper;
import com.google.common.base.Joiner;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
@ -59,6 +60,7 @@ import com.sk89q.worldedit.command.composition.DeformCommand;
import com.sk89q.worldedit.command.composition.PaintCommand;
import com.sk89q.worldedit.command.composition.SelectionCommand;
import com.sk89q.worldedit.command.composition.ShapedBrushCommand;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.function.factory.Deform;
@ -234,7 +236,11 @@ public final class CommandManager {
LocalConfiguration config = worldEdit.getConfiguration();
CommandLocals locals = new CommandLocals();
locals.put(Actor.class, actor);
if (actor != null && actor.isPlayer()) {
locals.put(Actor.class, new PlayerWrapper((Player) actor));
} else {
locals.put(Actor.class, actor);
}
locals.put("arguments", event.getArguments());
final long start = System.currentTimeMillis();

View File

@ -58,7 +58,6 @@ public class RegionVisitor implements Operation {
affected++;
}
}
return null;
}

View File

@ -0,0 +1,470 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* An axis-aligned cuboid. It can be defined using two corners of the cuboid.
*/
public class CuboidRegion extends AbstractRegion implements FlatRegion {
private Vector pos1;
private Vector pos2;
/**
* Construct a new instance of this cuboid using two corners of the cuboid.
*
* @param pos1 the first position
* @param pos2 the second position
*/
public CuboidRegion(Vector pos1, Vector pos2) {
this(null, pos1, pos2);
}
/**
* @deprecated cast {@code world} to {@link World}
*/
@Deprecated
public CuboidRegion(LocalWorld world, Vector pos1, Vector pos2) {
this((World) world, pos1, pos2);
}
/**
* Construct a new instance of this cuboid using two corners of the cuboid.
*
* @param world the world
* @param pos1 the first position
* @param pos2 the second position
*/
public CuboidRegion(World world, Vector pos1, Vector pos2) {
super(world);
checkNotNull(pos1);
checkNotNull(pos2);
this.pos1 = pos1;
this.pos2 = pos2;
recalculate();
}
/**
* Get the first cuboid-defining corner.
*
* @return a position
*/
public Vector getPos1() {
return pos1;
}
/**
* Set the first cuboid-defining corner.
*
* @param pos1 a position
*/
public void setPos1(Vector pos1) {
this.pos1 = pos1;
}
/**
* Get the second cuboid-defining corner.
*
* @return a position
*/
public Vector getPos2() {
return pos2;
}
/**
* Set the second cuboid-defining corner.
*
* @param pos2 a position
*/
public void setPos2(Vector pos2) {
this.pos2 = pos2;
}
/**
* Clamps the cuboid according to boundaries of the world.
*/
private void recalculate() {
pos1 = pos1.clampY(0, world == null ? 255 : world.getMaxY());
pos2 = pos2.clampY(0, world == null ? 255 : world.getMaxY());
}
/**
* Get a region that contains the faces of this cuboid.
*
* @return a new complex region
*/
public Region getFaces() {
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
return new RegionIntersection(
// Project to Z-Y plane
new CuboidRegion(pos1.setX(min.getX()), pos2.setX(min.getX())),
new CuboidRegion(pos1.setX(max.getX()), pos2.setX(max.getX())),
// Project to X-Y plane
new CuboidRegion(pos1.setZ(min.getZ()), pos2.setZ(min.getZ())),
new CuboidRegion(pos1.setZ(max.getZ()), pos2.setZ(max.getZ())),
// Project to the X-Z plane
new CuboidRegion(pos1.setY(min.getY()), pos2.setY(min.getY())),
new CuboidRegion(pos1.setY(max.getY()), pos2.setY(max.getY())));
}
/**
* Get a region that contains the walls (all faces but the ones parallel to
* the X-Z plane) of this cuboid.
*
* @return a new complex region
*/
public Region getWalls() {
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
return new RegionIntersection(
// Project to Z-Y plane
new CuboidRegion(pos1.setX(min.getX()), pos2.setX(min.getX())),
new CuboidRegion(pos1.setX(max.getX()), pos2.setX(max.getX())),
// Project to X-Y plane
new CuboidRegion(pos1.setZ(min.getZ()), pos2.setZ(min.getZ())),
new CuboidRegion(pos1.setZ(max.getZ()), pos2.setZ(max.getZ())));
}
@Override
public Vector getMinimumPoint() {
return new Vector(Math.min(pos1.getX(), pos2.getX()),
Math.min(pos1.getY(), pos2.getY()),
Math.min(pos1.getZ(), pos2.getZ()));
}
@Override
public Vector getMaximumPoint() {
return new Vector(Math.max(pos1.getX(), pos2.getX()),
Math.max(pos1.getY(), pos2.getY()),
Math.max(pos1.getZ(), pos2.getZ()));
}
@Override
public int getMinimumY() {
return Math.min(pos1.getBlockY(), pos2.getBlockY());
}
@Override
public int getMaximumY() {
return Math.max(pos1.getBlockY(), pos2.getBlockY());
}
@Override
public void expand(Vector... changes) {
checkNotNull(changes);
for (Vector change : changes) {
if (change.getX() > 0) {
if (Math.max(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
} else {
if (Math.min(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
}
if (change.getY() > 0) {
if (Math.max(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
} else {
if (Math.min(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
}
if (change.getZ() > 0) {
if (Math.max(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
} else {
if (Math.min(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
}
}
recalculate();
}
@Override
public void contract(Vector... changes) {
checkNotNull(changes);
for (Vector change : changes) {
if (change.getX() < 0) {
if (Math.max(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
} else {
if (Math.min(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
}
if (change.getY() < 0) {
if (Math.max(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
} else {
if (Math.min(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
}
if (change.getZ() < 0) {
if (Math.max(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
} else {
if (Math.min(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
}
}
recalculate();
}
@Override
public void shift(Vector change) throws RegionOperationException {
pos1 = pos1.add(change);
pos2 = pos2.add(change);
recalculate();
}
@Override
public Set<Vector2D> getChunks() {
Set<Vector2D> chunks = new HashSet<Vector2D>();
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
for (int x = min.getBlockX() >> ChunkStore.CHUNK_SHIFTS; x <= max.getBlockX() >> ChunkStore.CHUNK_SHIFTS; ++x) {
for (int z = min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; z <= max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; ++z) {
chunks.add(new BlockVector2D(x, z));
}
}
return chunks;
}
@Override
public Set<Vector> getChunkCubes() {
Set<Vector> chunks = new HashSet<Vector>();
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
for (int x = min.getBlockX() >> ChunkStore.CHUNK_SHIFTS; x <= max.getBlockX() >> ChunkStore.CHUNK_SHIFTS; ++x) {
for (int z = min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; z <= max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; ++z) {
for (int y = min.getBlockY() >> ChunkStore.CHUNK_SHIFTS; y <= max.getBlockY() >> ChunkStore.CHUNK_SHIFTS; ++y) {
chunks.add(new BlockVector(x, y, z));
}
}
}
return chunks;
}
@Override
public boolean contains(Vector position) {
double x = position.getX();
double y = position.getY();
double z = position.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();
}
@Override
public Iterator<BlockVector> iterator() {
final BlockVector v = new BlockVector(0,0,0);
return new Iterator<BlockVector>() {
private Vector min = getMinimumPoint();
private Vector max = getMaximumPoint();
int minX = min.getBlockX();
int minY = min.getBlockY();
int minZ = min.getBlockZ();
int maxX = max.getBlockX();
int maxY = max.getBlockY();
int maxZ = max.getBlockZ();
private int nextX = min.getBlockX();
private int nextY = min.getBlockY();
private int nextZ = min.getBlockZ();
@Override
public boolean hasNext() {
return (nextX != Integer.MIN_VALUE);
}
@Override
public BlockVector next() {
if (!hasNext()) throw new java.util.NoSuchElementException();
v.x = nextX;
v.y = nextY;
v.z = nextZ;
if (++nextX > maxX) {
nextX = minX;
if (++nextY > maxY) {
nextY = minY;
if (++nextZ > maxZ) {
nextX = Integer.MIN_VALUE;
}
}
}
return v;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public Iterable<Vector2D> asFlatRegion() {
return new Iterable<Vector2D>() {
@Override
public Iterator<Vector2D> iterator() {
return new Iterator<Vector2D>() {
private Vector min = getMinimumPoint();
private Vector max = getMaximumPoint();
private int nextX = min.getBlockX();
private int nextZ = min.getBlockZ();
@Override
public boolean hasNext() {
return (nextX != Integer.MIN_VALUE);
}
@Override
public Vector2D next() {
if (!hasNext()) throw new java.util.NoSuchElementException();
Vector2D answer = new Vector2D(nextX, nextZ);
if (++nextX > max.getBlockX()) {
nextX = min.getBlockX();
if (++nextZ > max.getBlockZ()) {
nextX = Integer.MIN_VALUE;
}
}
return answer;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
@Override
public String toString() {
return getMinimumPoint() + " - " + getMaximumPoint();
}
@Override
public CuboidRegion clone() {
return (CuboidRegion) super.clone();
}
/**
* Make a cuboid region out of the given region using the minimum and maximum
* bounds of the provided region.
*
* @param region the region
* @return a new cuboid region
*/
public static CuboidRegion makeCuboid(Region region) {
checkNotNull(region);
return new CuboidRegion(region.getMinimumPoint(), region.getMaximumPoint());
}
/**
* Make a cuboid from the center.
*
* @param origin the origin
* @param apothem the apothem, where 0 is the minimum value to make a 1x1 cuboid
* @return a cuboid region
*/
public static CuboidRegion fromCenter(Vector origin, int apothem) {
checkNotNull(origin);
checkArgument(apothem >= 0, "apothem => 0 required");
Vector size = new Vector(1, 1, 1).multiply(apothem);
return new CuboidRegion(origin.subtract(size), origin.add(size));
}
public static Class<?> inject() {
return CuboidRegion.class;
}
}

View File

@ -1,4 +1,4 @@
org.gradle.daemon=false
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.configureondemand=true
org.gradle.parallel=true