diff --git a/build.gradle b/build.gradle
index f81729b5..3ec1aaf5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,7 +37,7 @@ subprojects {
exclude(module: 'bukkit-classloader-check')
}
compile 'com.sk89q:worldguard:6.0.0-SNAPSHOT'
- compile 'com.intellectualcrafters.plot:plotsquared:3.3.1'
+ compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT'
}
repositories {
diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java
index b277fd53..104dc54c 100644
--- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java
+++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java
@@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
+import com.boydti.fawe.wrappers.PlayerWrapper;
import java.lang.reflect.Method;
import java.util.UUID;
import org.bukkit.Bukkit;
@@ -92,7 +93,7 @@ public class BukkitPlayer extends FawePlayer {
@Override
public com.sk89q.worldedit.entity.Player getPlayer() {
- return Fawe. imp().getWorldEditPlugin().wrapPlayer(this.parent);
+ return PlayerWrapper.wrap(Fawe. imp().getWorldEditPlugin().wrapPlayer(this.parent));
}
}
diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java
index a819bf0c..a33dd646 100644
--- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java
+++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java
@@ -8,6 +8,7 @@ import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
+import com.sk89q.worldedit.bukkit.entity.BukkitEntity;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.File;
import java.lang.reflect.Field;
diff --git a/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java b/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java
index 95343d3d..c50d535a 100644
--- a/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java
+++ b/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java
@@ -399,7 +399,7 @@ public class Sniper {
FawePlayer
*/
public class EditSession implements Extent {
-
- private final Logger log = Logger.getLogger(EditSession.class.getCanonicalName());
-
/**
* Used by {@link #setBlock(Vector, BaseBlock, Stage)} to
* determine which {@link Extent}s should be bypassed.
@@ -165,25 +155,113 @@ public class EditSession implements Extent {
}
private World world;
- private Actor actor;
- private FaweChangeSet changeSet;
- private EditSessionWrapper wrapper;
- private MaskingExtent maskingExtent;
- private FaweRegionExtent regionExtent;
- private Extent primaryExtent;
- private HistoryExtent history;
- private Extent bypassReorderHistory;
- private Extent bypassHistory;
- private Extent bypassNone;
- private SurvivalModeExtent lazySurvivalExtent;
- private boolean fastmode;
- private Mask oldMask;
- private FaweLimit limit = FaweLimit.MAX.copy();
private FaweQueue queue;
+ private Extent bypassNone;
+ private HistoryExtent history;
+ private Extent bypassHistory;
+ private Extent bypassAll;
+ private FaweLimit limit;
+ private FawePlayer player;
+ private FaweChangeSet changeTask;
+
+ private int changes = 0;
+ private BlockBag blockBag;
public static final UUID CONSOLE = UUID.fromString("1-1-3-3-7");
public static final BaseBiome nullBiome = new BaseBiome(0);
public static final BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0];
+ private static final Vector[] recurseDirections = {
+ PlayerDirection.NORTH.vector(),
+ PlayerDirection.EAST.vector(),
+ PlayerDirection.SOUTH.vector(),
+ PlayerDirection.WEST.vector(),
+ PlayerDirection.UP.vector(),
+ PlayerDirection.DOWN.vector(), };
+
+ public EditSession(@Nonnull World world, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) {
+ checkNotNull(world);
+ this.world = world = WorldWrapper.wrap((AbstractWorld) world);
+ if (bus == null) {
+ bus = WorldEdit.getInstance().getEventBus();
+ }
+ if (event == null) {
+ event = new EditSessionEvent(world, player == null ? null : (player.getPlayer()), -1, null);
+ }
+ event.setEditSession(this);
+ if (player == null) {
+ player = FawePlayer.wrap(event.getActor());
+ }
+ this.player = player;
+ if (changeSet == null) {
+ if (Settings.STORE_HISTORY_ON_DISK) {
+ UUID uuid = player == null ? CONSOLE : player.getUUID();
+ changeSet = new DiskStorageHistory(world, uuid);
+ } else if (Settings.COMBINE_HISTORY_STAGE && Settings.COMPRESSION_LEVEL == 0) {
+ changeSet = new CPUOptimizedChangeSet(world);
+ } else {
+ changeSet = new MemoryOptimizedHistory(world);
+ }
+ }
+ if (limit == null) {
+ if (player == null) {
+ limit = FaweLimit.MAX.copy();
+ } else {
+ limit = player.getLimit();
+ }
+ }
+ if (allowedRegions == null) {
+ if (player != null && !player.hasWorldEditBypass()) {
+ allowedRegions = player.getCurrentRegions();
+ if (allowedRegions.length == 1 && allowedRegions[0].isGlobal()) {
+ allowedRegions = null;
+ }
+ }
+ }
+ if (autoQueue == null) {
+ autoQueue = true;
+ }
+ if (fastmode == null) {
+ if (player == null) {
+ fastmode = Settings.CONSOLE_HISTORY;
+ } else {
+ fastmode = player.getSession().hasFastMode();
+ }
+ }
+ if (checkMemory == null) {
+ checkMemory = player != null && !fastmode;
+ }
+ if (combineStages == null) {
+ combineStages = Settings.COMBINE_HISTORY_STAGE;
+ }
+ if (checkMemory) {
+ if (MemUtil.isMemoryLimitedSlow()) {
+ if (Perm.hasPermission(player, "worldedit.fast")) {
+ BBC.WORLDEDIT_OOM_ADMIN.send(player);
+ }
+ throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY);
+ }
+ }
+ if (allowedRegions != null && allowedRegions.length == 0) {
+ throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_NO_REGION);
+ }
+ this.blockBag = blockBag;
+ this.limit = limit;
+ this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), fastmode, autoQueue);
+ this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), bus, event, Stage.BEFORE_CHANGE);
+ this.bypassHistory = (bypassNone = wrapExtent(bypassAll, bus, event, Stage.BEFORE_REORDER));
+ if (!fastmode && !(changeSet instanceof NullChangeSet)) {
+ if (combineStages) {
+ changeTask = changeSet;
+ changeSet.addChangeTask(queue);
+ } else {
+ this.bypassNone = (history = new HistoryExtent(this, bypassHistory, changeSet, queue));
+ }
+ }
+ if (allowedRegions != null) {
+ this.bypassNone = new ProcessedWEExtent(bypassNone, allowedRegions, limit);
+ }
+ bypassNone = wrapExtent(bypassNone, bus, event, Stage.BEFORE_HISTORY);
+ }
/**
* Create a new instance.
@@ -210,9 +288,6 @@ public class EditSession implements Extent {
this(WorldEdit.getInstance().getEventBus(), world, maxBlocks, blockBag, new EditSessionEvent(world, null, maxBlocks, null));
}
- private int changes = 0;
- private BlockBag blockBag;
-
/**
* Construct the object with a maximum number of blocks and a block bag.
*
@@ -223,167 +298,12 @@ public class EditSession implements Extent {
* @param event the event to call with the extent
*/
public EditSession(final EventBus eventBus, World world, final int maxBlocks, @Nullable final BlockBag blockBag, EditSessionEvent event) {
- checkNotNull(eventBus);
- checkArgument(maxBlocks >= -1, "maxBlocks >= -1 required");
- checkNotNull(event);
- event.setEditSession(this);
-
- this.actor = event.getActor();
- // TODO block bag
- this.blockBag = blockBag;
-
- // Invalid world: return null extent
- if (world == null) {
- Extent extent = this.regionExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
- this.bypassReorderHistory = extent;
- this.bypassHistory = extent;
- this.bypassNone = extent;
- this.changeSet = new NullChangeSet(world);
- this.wrapper = Fawe.imp().getEditSessionWrapper(this);
- return;
- }
-
- // Wrap the world
- this.world = (world = WorldWrapper.wrap((AbstractWorld) world));
-
- // Delegate some methods to an implementation specific class
- this.wrapper = Fawe.imp().getEditSessionWrapper(this);
-
- // Not a player; bypass history
- if ((actor == null) || !actor.isPlayer()) {
- this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
- queue.addEditSession(this);
- Extent extent = primaryExtent = new FastWorldEditExtent(world, queue);
- // Everything bypasses
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE);
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
- // History
- if (Settings.CONSOLE_HISTORY) {
- this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, CONSOLE) : (Settings.COMBINE_HISTORY_STAGE && Settings.COMPRESSION_LEVEL == 0) ? new CPUOptimizedChangeSet(world) : new MemoryOptimizedHistory(world);
- if (Settings.COMBINE_HISTORY_STAGE) {
- changeSet.addChangeTask(queue);
- } else {
- extent = history = new HistoryExtent(this, limit, extent, changeSet, queue);
- }
- }
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
- this.bypassReorderHistory = primaryExtent;
- this.bypassHistory = primaryExtent;
- this.bypassNone = extent;
- this.changeSet = new NullChangeSet(world);
- return;
- }
-
- Extent extent;
- RegionWrapper[] mask;
- final FawePlayer fp = FawePlayer.wrap(actor);
- final LocalSession session = fp.getSession();
- this.fastmode = session.hasFastMode();
- boolean bypass = fp.hasWorldEditBypass();
- this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), bypass, true);
- queue.setProgressTracker(new DefaultProgressTracker(fp));
- if (bypass) {
- queue.addEditSession(this);
- // Bypass skips processing and area restrictions
- extent = primaryExtent = new FastWorldEditExtent(world, queue);
- if (this.hasFastMode()) {
- // Fastmode skips history and memory checks
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE);
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
- this.bypassReorderHistory = extent;
- this.bypassHistory = extent;
- this.bypassNone = extent;
- return;
- }
- mask = null;
- } else {
- queue.addEditSession(this);
- this.limit = fp.getLimit();
- mask = WEManager.IMP.getMask(fp);
- if (mask.length == 0) {
- // No allowed area; return null extent
- extent = this.regionExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_NO_REGION);
- this.bypassReorderHistory = extent;
- this.bypassHistory = extent;
- this.bypassNone = extent;
- return;
- }
- extent = primaryExtent = new FastWorldEditExtent(world, queue);
- if (this.hasFastMode()) {
- // Fastmode skips history, masking, and memory checks
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE);
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
- // Restrictions
- extent = new ProcessedWEExtent(extent, mask, limit);
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
- this.bypassReorderHistory = extent;
- this.bypassHistory = extent;
- this.bypassNone = extent;
- return;
- } else {
- if (MemUtil.isMemoryLimited()) {
- fp.sendMessage(BBC.WORLDEDIT_CANCEL_REASON.format(BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY.s()));
- if (Perm.hasPermission(fp, "worldedit.fast")) {
- BBC.WORLDEDIT_OOM_ADMIN.send(fp);
- }
- // Memory limit reached; return null extent
- extent = this.regionExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
- this.bypassReorderHistory = extent;
- this.bypassHistory = extent;
- this.bypassNone = extent;
- return;
- }
- }
- // Perform memory checks after reorder
- extent = new MemoryCheckingExtent(fp, extent);
- }
- // Include history, masking and memory checking.
- Extent wrapped;
- // First two events
- extent = wrapped = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE);
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
-
- // History
- this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : (Settings.COMBINE_HISTORY_STAGE && Settings.COMPRESSION_LEVEL == 0) ? new CPUOptimizedChangeSet(world) : new MemoryOptimizedHistory(world);
- this.changeSet = this.wrapper.wrapChangeSet(this, limit, extent, this.changeSet, queue, fp);
- if (Settings.COMBINE_HISTORY_STAGE) {
- changeSet.addChangeTask(queue);
- } else {
- extent = history = new HistoryExtent(this, limit, extent, changeSet, queue);
- }
- // Region restrictions if mask is not null
- if (mask != null) {
- extent = this.regionExtent = new ProcessedWEExtent(extent, mask, limit);
- }
-
- // Masking
- final Player skp = (Player) actor;
- final int item = skp.getItemInHand();
- boolean hasMask = session.getMask() != null;
- if ((item != 0) && (!hasMask)) {
- try {
- final Tool tool = session.getTool(item);
- if ((tool != null) && (tool instanceof BrushTool)) {
- hasMask = ((BrushTool) tool).getMask() != null;
- }
- } catch (final Exception e) {}
- }
- if (hasMask) {
- extent = this.maskingExtent = new MaskingExtent(extent, Masks.alwaysTrue());
- }
-
- // Before history event
- extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
-
- this.bypassReorderHistory = wrapped;
- this.bypassHistory = wrapped;
- this.bypassNone = extent;
- return;
+ this(world, null, null, null, null, true, null, null, null, blockBag, eventBus, event);
}
public FaweRegionExtent getRegionExtent() {
- return regionExtent;
+ ExtentTraverser traverser = new ExtentTraverser(bypassNone).find(FaweRegionExtent.class);
+ return traverser == null ? null : traverser.get();
}
/**
@@ -391,27 +311,24 @@ public class EditSession implements Extent {
* @return
*/
@Nullable
- public Actor getActor() {
- return actor;
+ public FawePlayer getPlayer() {
+ return player;
}
public boolean cancel() {
- // Cancel this
- if (primaryExtent != null && queue != null) {
- try {
- WEManager.IMP.cancelEdit(primaryExtent, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
- } catch (Throwable ignore) {}
- NullExtent nullExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
- primaryExtent = nullExtent;
- regionExtent = nullExtent;
- bypassReorderHistory = nullExtent;
- bypassHistory = nullExtent;
- bypassNone = nullExtent;
- dequeue();
- queue.clear();
- return true;
+ ExtentTraverser traverser = new ExtentTraverser(bypassNone);
+ NullExtent nullExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
+ while (traverser != null) {
+ ExtentTraverser next = traverser.next();
+ traverser.setNext(nullExtent);
+ traverser = next;
}
- return false;
+ bypassHistory = nullExtent;
+ bypassNone = nullExtent;
+ bypassAll = nullExtent;
+ dequeue();
+ queue.clear();
+ return true;
}
public void dequeue() {
@@ -426,12 +343,8 @@ public class EditSession implements Extent {
}
}
- public FastWorldEditExtent getPrimaryExtent() {
- return (FastWorldEditExtent) primaryExtent;
- }
-
public void debug(BBC message, Object... args) {
- message.send(actor, args);
+ message.send(player, args);
}
public FaweQueue getQueue() {
@@ -474,15 +387,21 @@ public class EditSession implements Extent {
* @return the change set
*/
public ChangeSet getChangeSet() {
- return this.changeSet;
+ return history != null ? history.getChangeSet() : changeTask;
}
public void setChangeSet(FaweChangeSet set) {
- if (history != null) {
- history.setChangeSet(set);
+ if (set == null) {
+ disableHistory(true);
+ } else {
+ if (history != null) {
+ history.setChangeSet(set);
+ } else {
+ changeTask = set;
+ set.addChangeTask(queue);
+ }
}
changes++;
- this.changeSet = set;
}
/**
@@ -510,14 +429,13 @@ public class EditSession implements Extent {
* @return whether the queue is enabled
*/
public boolean isQueueEnabled() {
- return false;
+ return true;
}
/**
* Queue certain types of block for better reproduction of those blocks.
*/
- public void enableQueue() {
- }
+ public void enableQueue() {}
/**
* Disable the queue. This will flush the queue.
@@ -534,7 +452,8 @@ public class EditSession implements Extent {
* @return mask, may be null
*/
public Mask getMask() {
- return this.oldMask;
+ ExtentTraverser maskingExtent = new ExtentTraverser(bypassNone).find(MaskingExtent.class);
+ return maskingExtent != null ? maskingExtent.get().getMask() : null;
}
/**
@@ -542,15 +461,15 @@ public class EditSession implements Extent {
*
* @param mask mask or null
*/
- public void setMask(final Mask mask) {
- if (this.maskingExtent == null) {
- return;
- }
- this.oldMask = mask;
+ public void setMask(Mask mask) {
if (mask == null) {
- this.maskingExtent.setMask(Masks.alwaysTrue());
- } else {
- this.maskingExtent.setMask(mask);
+ mask = Masks.alwaysTrue();
+ }
+ ExtentTraverser maskingExtent = new ExtentTraverser(bypassNone).find(MaskingExtent.class);
+ if (maskingExtent != null) {
+ maskingExtent.get().setMask(mask);
+ } else if (mask != Masks.alwaysTrue()) {
+ bypassNone = new MaskingExtent(bypassNone, mask);
}
}
@@ -575,10 +494,12 @@ public class EditSession implements Extent {
* @return the survival simulation extent
*/
public SurvivalModeExtent getSurvivalExtent() {
- if (this.lazySurvivalExtent == null) {
- this.lazySurvivalExtent = new SurvivalModeExtent(bypassReorderHistory, world);
+ ExtentTraverser survivalExtent = new ExtentTraverser(bypassNone).find(SurvivalModeExtent.class);
+ if (survivalExtent != null) {
+ return survivalExtent.get();
+ } else {
+ return (SurvivalModeExtent) (bypassNone = new SurvivalModeExtent(bypassNone, getWorld()));
}
- return lazySurvivalExtent;
}
/**
@@ -590,7 +511,31 @@ public class EditSession implements Extent {
* @param enabled true to enable
*/
public void setFastMode(final boolean enabled) {
- this.fastmode = enabled;
+ disableHistory(enabled);
+ }
+
+ /**
+ * Disable history (or re-enable)
+ * @param disableHistory
+ */
+ public void disableHistory(boolean disableHistory) {
+ if (history == null) {
+ return;
+ }
+ ExtentTraverser traverseHistory = new ExtentTraverser(bypassNone).find(HistoryExtent.class);
+ if (disableHistory) {
+ if (traverseHistory != null) {
+ ExtentTraverser beforeHistory = traverseHistory.previous();
+ ExtentTraverser afterHistory = traverseHistory.next();
+ beforeHistory.setNext(afterHistory.get());
+ }
+ } else if (traverseHistory == null) {
+ ExtentTraverser traverseBypass = new ExtentTraverser(bypassNone).find(bypassHistory);
+ if (traverseBypass != null) {
+ ExtentTraverser beforeHistory = traverseBypass.previous();
+ beforeHistory.setNext(history);
+ }
+ }
}
/**
@@ -602,7 +547,7 @@ public class EditSession implements Extent {
* @return true if enabled
*/
public boolean hasFastMode() {
- return this.fastmode;
+ return history == null;
}
/**
@@ -661,16 +606,17 @@ public class EditSession implements Extent {
}
public BaseBlock getLazyBlock(int x, int y, int z) {
- if (limit != null && limit.MAX_CHECKS-- < 0) {
+ if (!limit.MAX_CHECKS()) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
int combinedId4Data = queue.getCombinedId4DataDebug(x, y, z, 0, this);
- if (!FaweCache.hasNBT(combinedId4Data >> 4)) {
+ int id = FaweCache.getId(combinedId4Data);
+ if (!FaweCache.hasNBT(id)) {
return FaweCache.CACHE_BLOCK[combinedId4Data];
}
try {
- BaseBlock block = this.world.getBlock(new Vector(x, y, z));
- return block;
+ CompoundTag tile = queue.getTileEntity(x, y, z);
+ return new BaseBlock(id, FaweCache.getData(combinedId4Data), tile);
} catch (Throwable e) {
MainUtil.handleError(e);
return FaweCache.CACHE_BLOCK[combinedId4Data];
@@ -691,7 +637,7 @@ public class EditSession implements Extent {
*/
@Deprecated
public int getBlockType(final Vector position) {
- if (limit != null && limit.MAX_CHECKS-- < 0) {
+ if (!limit.MAX_CHECKS()) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
int combinedId4Data = queue.getCombinedId4DataDebug(position.getBlockX(), position.getBlockY(), position.getBlockZ(), 0, this);
@@ -707,7 +653,7 @@ public class EditSession implements Extent {
*/
@Deprecated
public int getBlockData(final Vector position) {
- if (limit != null && limit.MAX_CHECKS-- < 0) {
+ if (!limit.MAX_CHECKS()) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
int combinedId4Data = queue.getCombinedId4DataDebug(position.getBlockX(), position.getBlockY(), position.getBlockZ(), 0, this);
@@ -750,7 +696,104 @@ public class EditSession implements Extent {
* @return height of highest block found or 'minY'
*/
public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) {
- return this.wrapper.getHighestTerrainBlock(x, z, minY, maxY, naturalOnly);
+ Vector pt = new Vector(x, 0, z);
+ for (int y = maxY; y >= minY; --y) {
+ BaseBlock block = getLazyBlock(x, y, z);
+ final int id = block.getId();
+ int data;
+ switch (id) {
+ case 0: {
+ continue;
+ }
+ case 2:
+ case 4:
+ case 13:
+ case 14:
+ case 15:
+ case 20:
+ case 21:
+ case 22:
+ case 25:
+ case 30:
+ case 32:
+ case 37:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 51:
+ case 52:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 60:
+ case 61:
+ case 62:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 73:
+ case 74:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 87:
+ case 88:
+ case 101:
+ case 102:
+ case 103:
+ case 110:
+ case 112:
+ case 113:
+ case 117:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 129:
+ case 133:
+ case 138:
+ case 137:
+ case 140:
+ case 165:
+ case 166:
+ case 169:
+ case 170:
+ case 172:
+ case 173:
+ case 174:
+ case 176:
+ case 177:
+ case 181:
+ case 182:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ return y;
+ default:
+ data = 0;
+ }
+ if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) {
+ return y;
+ }
+ }
+ return minY;
}
/**
@@ -770,7 +813,7 @@ public class EditSession implements Extent {
case BEFORE_CHANGE:
return this.bypassHistory.setBlock(position, block);
case BEFORE_REORDER:
- return this.bypassReorderHistory.setBlock(position, block);
+ return this.bypassAll.setBlock(position, block);
}
throw new RuntimeException("New enum entry added that is unhandled here");
@@ -802,7 +845,7 @@ public class EditSession implements Extent {
public boolean smartSetBlock(final Vector position, final BaseBlock block) {
this.changes++;
try {
- return this.bypassReorderHistory.setBlock(position, block);
+ return this.bypassAll.setBlock(position, block);
} catch (final WorldEditException e) {
throw new RuntimeException("Unexpected exception", e);
}
@@ -894,7 +937,10 @@ public class EditSession implements Extent {
*/
@Deprecated
public void rememberChange(final Vector position, final BaseBlock existing, final BaseBlock block) {
- this.changeSet.add(new BlockChange(position.toBlockVector(), existing, block));
+ ChangeSet changeSet = getChangeSet();
+ if (changeSet != null) {
+ changeSet.add(new BlockChange(position.toBlockVector(), existing, block));
+ }
}
/**
@@ -904,9 +950,9 @@ public class EditSession implements Extent {
*/
public void undo(final EditSession editSession) {
final UndoContext context = new UndoContext();
- context.setExtent(editSession.primaryExtent);
+ context.setExtent(editSession.bypassAll);
editSession.getQueue().setChangeTask(null);
- Operations.completeSmart(ChangeSetExecutor.createUndo(this.changeSet, context), new Runnable() {
+ Operations.completeSmart(ChangeSetExecutor.createUndo(getChangeSet(), context), new Runnable() {
@Override
public void run() {
editSession.flushQueue();
@@ -922,9 +968,9 @@ public class EditSession implements Extent {
*/
public void redo(final EditSession editSession) {
final UndoContext context = new UndoContext();
- context.setExtent(editSession.primaryExtent);
+ context.setExtent(editSession.bypassAll);
editSession.getQueue().setChangeTask(null);
- Operations.completeSmart(ChangeSetExecutor.createRedo(this.changeSet, context), new Runnable() {
+ Operations.completeSmart(ChangeSetExecutor.createRedo(getChangeSet(), context), new Runnable() {
@Override
public void run() {
editSession.flushQueue();
@@ -973,7 +1019,7 @@ public class EditSession implements Extent {
} else {
queue.dequeue();
}
- if (changeSet != null) {
+ if (getChangeSet() != null) {
if (Settings.COMBINE_HISTORY_STAGE && queue.size() > 0) {
if (Fawe.get().isMainThread()) {
SetQueue.IMP.flush(queue);
@@ -988,13 +1034,13 @@ public class EditSession implements Extent {
TaskManager.IMP.wait(running, Settings.QUEUE_DISCARD_AFTER);
}
}
- changeSet.flush();
+ ((FaweChangeSet) getChangeSet()).flush();
}
}
@Override
public @Nullable Operation commit() {
- return this.bypassNone.commit();
+ return null;
}
/**
@@ -1708,8 +1754,8 @@ public class EditSession implements Extent {
if (pos.getBlockY() < 0) {
pos = pos.setY(0);
- } else if (((pos.getBlockY() + height) - 1) > this.world.getMaxY()) {
- height = (this.world.getMaxY() - pos.getBlockY()) + 1;
+ } else if (((pos.getBlockY() + height) - 1) > 255) {
+ height = (255 - pos.getBlockY()) + 1;
}
final double invRadiusX = 1 / radiusX;
@@ -1892,7 +1938,7 @@ public class EditSession implements Extent {
continue;
}
- for (int y = this.world.getMaxY(); y >= 1; --y) {
+ for (int y = 255; y >= 1; --y) {
final Vector pt = new Vector(x, y, z);
final int id = this.getBlockType(pt);
@@ -1946,7 +1992,7 @@ public class EditSession implements Extent {
continue;
}
- for (int y = this.world.getMaxY(); y >= 1; --y) {
+ for (int y = 255; y >= 1; --y) {
final Vector pt = new Vector(x, y, z);
final int id = this.getBlockType(pt);
@@ -1966,7 +2012,7 @@ public class EditSession implements Extent {
}
// Too high?
- if (y == this.world.getMaxY()) {
+ if (y == 255) {
break;
}
@@ -2020,7 +2066,7 @@ public class EditSession implements Extent {
continue;
}
- loop: for (int y = this.world.getMaxY(); y >= 1; --y) {
+ loop: for (int y = 255; y >= 1; --y) {
final Vector pt = new Vector(x, y, z);
final int id = this.getBlockType(pt);
final int data = this.getBlockData(pt);
@@ -2279,7 +2325,7 @@ public class EditSession implements Extent {
return FaweCache.getBlock((int) typeVariable.getValue(), (int) dataVariable.getValue());
} catch (final Exception e) {
- EditSession.this.log.log(Level.WARNING, "Failed to create shape", e);
+ Fawe.debug("Failed to create shape: " + e);
return null;
}
}
@@ -2594,7 +2640,7 @@ public class EditSession implements Extent {
return defaultBiomeType;
} catch (final Exception e) {
- EditSession.this.log.log(Level.WARNING, "Failed to create shape", e);
+ Fawe.debug("Failed to create shape: " + e);
return null;
}
}
@@ -2603,14 +2649,6 @@ public class EditSession implements Extent {
return shape.generate(this, biomeType, hollow);
}
- private final Vector[] recurseDirections = {
- PlayerDirection.NORTH.vector(),
- PlayerDirection.EAST.vector(),
- PlayerDirection.SOUTH.vector(),
- PlayerDirection.WEST.vector(),
- PlayerDirection.UP.vector(),
- PlayerDirection.DOWN.vector(), };
-
private double lengthSq(final double x, final double y, final double z) {
return (x * x) + (y * y) + (z * z);
}
diff --git a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java
index d1b35fdb..5e4c1223 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java
@@ -106,7 +106,7 @@ public class ClipboardCommands {
final int mx = origin.getBlockX();
final int my = origin.getBlockY();
final int mz = origin.getBlockZ();
- LazyClipboard lazyClipboard = new LazyClipboard() {
+ LazyClipboard lazyClipboard = new LazyClipboard(region) {
@Override
public BaseBlock getBlock(int x, int y, int z) {
return editSession.getLazyBlock(mx + x, my + y, mz + z);
diff --git a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
index 2b6eeb10..3857ab1f 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
@@ -117,9 +117,7 @@ public class SchematicCommands {
in = new FileInputStream(f);
}
in = new BufferedInputStream(in);
-
final ClipboardReader reader = format.getReader(in);
-
final WorldData worldData = player.getWorld().getWorldData();
final Clipboard clipboard;
if (reader instanceof SchematicReader) {
diff --git a/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java b/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java
index 652a6eb4..e2e739e0 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java
@@ -78,26 +78,21 @@ public class SelectionCommand extends SimpleCommand {
if (!testPermission(locals)) {
throw new CommandPermissionsException();
}
-
Contextual extends Operation> operationFactory = delegate.call(args, locals);
-
Actor actor = locals.get(Actor.class);
if (actor instanceof Player) {
try {
Player player = (Player) actor;
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
Region selection = session.getSelection(player.getWorld());
-
EditSession editSession = session.createEditSession(player);
editSession.enableQueue();
locals.put(EditSession.class, editSession);
session.tellVersion(player);
-
EditContext editContext = new EditContext();
editContext.setDestination(locals.get(EditSession.class));
editContext.setRegion(selection);
Operation operation = operationFactory.createFromContext(editContext);
-
// Shortcut
if (selection instanceof CuboidRegion && editSession.hasFastMode() && operation instanceof RegionVisitor) {
CuboidRegion cuboid = (CuboidRegion) selection;
diff --git a/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
index 822fcc82..c9a2cad1 100644
--- a/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
+++ b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
@@ -302,7 +302,7 @@ public final class CommandManager {
BBC.ACTION_COMPLETE.send(actor, (time / 1000d));
ChangeSet fcs = editSession.getChangeSet();
if (fcs != null && fcs instanceof FaweStreamChangeSet) {
- MainUtil.sendCompressedMessage((FaweStreamChangeSet) fcs, editSession.getActor());
+ MainUtil.sendCompressedMessage((FaweStreamChangeSet) fcs, editSession.getPlayer());
}
}
}
diff --git a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java
index a8872ad7..5ce30c25 100644
--- a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java
+++ b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java
@@ -23,6 +23,7 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.object.clipboard.FaweClipboard;
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
+import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
@@ -189,6 +190,13 @@ public class BlockArrayClipboard implements Clipboard {
return false;
}
+ public boolean setTile(int x, int y, int z, CompoundTag tag) {
+ x -= mx;
+ y -= my;
+ z -= mz;
+ return IMP.setTile(x, y, z, tag);
+ }
+
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
x -= mx;
y -= my;
diff --git a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java
index d4002df2..f8f5c053 100644
--- a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java
+++ b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java
@@ -19,12 +19,14 @@
package com.sk89q.worldedit.extent.clipboard.io;
+import com.boydti.fawe.object.FaweOutputStream;
+import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
+import com.boydti.fawe.object.schematic.FaweFormat;
import com.boydti.fawe.object.schematic.StructureFormat;
+import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
-
-import javax.annotation.Nullable;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -40,6 +42,8 @@ import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
+import javax.annotation.Nullable;
+
import static com.google.common.base.Preconditions.checkNotNull;
@@ -99,7 +103,10 @@ public enum ClipboardFormat {
return "schematic";
}
},
- // Added
+ /**
+ * The structure block format:
+ * http://minecraft.gamepedia.com/Structure_block_file_format
+ */
STRUCTURE("structure", "nbt") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
@@ -128,10 +135,91 @@ public enum ClipboardFormat {
public String getExtension() {
return "nbt";
}
- }
+ },
- // TODO add the FAWE clipboard / history formats
- // .bd, .nbtf, .nbtt, .rabd
+ /**
+ * The FAWE file format:
+ * - Streamable for known dimensions with mode 0
+ * - Streamable for unknown dimensions
+ * - 1: Max size 256 x 256 x 256
+ * - 2: Max size 65535 x 65535 x 65535
+ * - 3: Includes BlockChange information
+ * - O(1) Access to blocks if using compression level 0 and mode 0
+ *
+ * DiskOptimizedClipboard: compression/mode -> 0/0
+ * DiskStorageHistory: compression/mode -> Any/3
+ * MemoryOptimizedHistory: compression/mode -> Any/3
+ * FaweFormat: compression/mode -> Any/Any (slower)
+ *
+ */
+ FAWE("fawe") {
+ /**
+ * Read a clipboard from a compressed stream (the first byte indicates the compression level)
+ * @param inputStream the input stream
+ * @return
+ * @throws IOException
+ */
+ @Override
+ public ClipboardReader getReader(InputStream inputStream) throws IOException {
+ return new FaweFormat(MainUtil.getCompressedIS(inputStream));
+ }
+
+ /**
+ * Write a clipboard to a stream with compression level 8
+ * @param outputStream the output stream
+ * @return
+ * @throws IOException
+ */
+ @Override
+ public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
+ return getWriter(outputStream, 8);
+ }
+
+ /**
+ * Write a clipboard to a stream
+ * @param os
+ * @param compression
+ * @return
+ * @throws IOException
+ */
+ public ClipboardWriter getWriter(OutputStream os, int compression) throws IOException {
+ FaweFormat writer = new FaweFormat(new FaweOutputStream(os));
+ writer.compress(compression);
+ return writer;
+ }
+
+ /**
+ * Read or write blocks ids to a file
+ * @param file
+ * @return
+ * @throws IOException
+ */
+ public DiskOptimizedClipboard getUncompressedReadWrite(File file) throws IOException {
+ return new DiskOptimizedClipboard(file);
+ }
+
+ /**
+ * Read or write block ids to a new file
+ * @param width
+ * @param height
+ * @param length
+ * @param file
+ * @return
+ */
+ public DiskOptimizedClipboard createUncompressedReadWrite(int width, int height, int length, File file) {
+ return new DiskOptimizedClipboard(width, height, length, file);
+ }
+
+ @Override
+ public boolean isFormat(File file) {
+ return file.getName().endsWith(".fawe") || file.getName().endsWith(".bd");
+ }
+
+ @Override
+ public String getExtension() {
+ return "fawe";
+ }
+ },
;
@@ -144,7 +232,7 @@ public enum ClipboardFormat {
*
* @param aliases an array of aliases by which this format may be referred to
*/
- private ClipboardFormat(String ... aliases) {
+ ClipboardFormat(String ... aliases) {
this.aliases = aliases;
}
diff --git a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicWriter.java b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicWriter.java
new file mode 100644
index 00000000..1830e07b
--- /dev/null
+++ b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicWriter.java
@@ -0,0 +1,242 @@
+package com.sk89q.worldedit.extent.clipboard.io;
+
+import com.boydti.fawe.FaweCache;
+import com.boydti.fawe.object.RunnableVal2;
+import com.boydti.fawe.object.clipboard.FaweClipboard;
+import com.boydti.fawe.util.ReflectionUtils;
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.DoubleTag;
+import com.sk89q.jnbt.FloatTag;
+import com.sk89q.jnbt.IntTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.NBTOutputStream;
+import com.sk89q.jnbt.ShortTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.entity.BaseEntity;
+import com.sk89q.worldedit.entity.Entity;
+import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.util.Location;
+import com.sk89q.worldedit.world.registry.WorldData;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Writes schematic files based that are compatible with MCEdit and other editors.
+ */
+public class SchematicWriter implements ClipboardWriter {
+
+ private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE;
+ private final NBTOutputStream outputStream;
+
+ /**
+ * Create a new schematic writer.
+ *
+ * @param outputStream the output stream to write to
+ */
+ public SchematicWriter(NBTOutputStream outputStream) {
+ checkNotNull(outputStream);
+ this.outputStream = outputStream;
+ }
+
+ private static class ForEach extends RunnableVal2 {
+ int x = -1;
+ int y = 0;
+ int z = 0;
+ int index = 0;
+
+ public int[] yarea;
+ public int[] zwidth;
+ public byte[] blocks;
+ public byte[] blockData;
+ public byte[] addBlocks;
+ public List tileEntities;
+
+ public ForEach(int[] yarea, int[] zwidth, byte[] blocks, byte[] blockData, List tileEntities) {
+ this.yarea = yarea;
+ this.zwidth = zwidth;
+ this.blocks = blocks;
+ this.blockData = blockData;
+ this.tileEntities = tileEntities;
+ }
+
+ @Override
+ public void run(Vector point, BaseBlock block) {
+ int x = (int) point.x;
+ int y = (int) point.y;
+ int z = (int) point.z;
+ if (this.x == x - 1 && this.y == y && this.z == z) {
+ index++;
+ x++;
+ } else {
+ index = yarea[y] + zwidth[z] + x;
+ }
+ int id = block.getId();
+ blocks[index] = (byte) id;
+ if (FaweCache.hasData(id)) {
+ blockData[index] = (byte) block.getData();
+ if (id > 255) {
+ if (addBlocks == null) { // Lazily create section
+ addBlocks = new byte[(blocks.length >> 1) + 1];
+ }
+ addBlocks[index >> 1] = (byte) (((index & 1) == 0) ? addBlocks[index >> 1] & 0xF0 | (id >> 8) & 0xF : addBlocks[index >> 1] & 0xF | ((id >> 8) & 0xF) << 4);
+ }
+ }
+ CompoundTag rawTag = block.getNbtData();
+ if (rawTag != null) {
+ Map values = ReflectionUtils.getMap(rawTag.getValue());
+ values.put("id", new StringTag(block.getNbtId()));
+ values.put("x", new IntTag(x));
+ values.put("y", new IntTag(y));
+ values.put("z", new IntTag(z));
+ tileEntities.add(rawTag);
+ }
+ }
+ }
+
+ @Override
+ public void write(Clipboard clipboard, WorldData data) throws IOException {
+ outputStream.writeNamedTag("Schematic", writeTag(clipboard));
+ }
+
+ public static CompoundTag writeTag(Clipboard clipboard) {
+ Region region = clipboard.getRegion();
+ Vector origin = clipboard.getOrigin();
+ Vector min = region.getMinimumPoint();
+ Vector offset = min.subtract(origin);
+ int width = region.getWidth();
+ int height = region.getHeight();
+ int length = region.getLength();
+
+ if (width > MAX_SIZE) {
+ throw new IllegalArgumentException("Width of region too large for a .schematic");
+ }
+ if (height > MAX_SIZE) {
+ throw new IllegalArgumentException("Height of region too large for a .schematic");
+ }
+ if (length > MAX_SIZE) {
+ throw new IllegalArgumentException("Length of region too large for a .schematic");
+ }
+
+ // ====================================================================
+ // Metadata
+ // ====================================================================
+
+ HashMap schematic = new HashMap();
+ schematic.put("Width", new ShortTag((short) width));
+ schematic.put("Length", new ShortTag((short) length));
+ schematic.put("Height", new ShortTag((short) height));
+ schematic.put("Materials", new StringTag("Alpha"));
+ schematic.put("WEOriginX", new IntTag(min.getBlockX()));
+ schematic.put("WEOriginY", new IntTag(min.getBlockY()));
+ schematic.put("WEOriginZ", new IntTag(min.getBlockZ()));
+ schematic.put("WEOffsetX", new IntTag(offset.getBlockX()));
+ schematic.put("WEOffsetY", new IntTag(offset.getBlockY()));
+ schematic.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
+
+ final byte[] blocks = new byte[width * height * length];
+ byte[] addBlocks = null;
+ final byte[] blockData = new byte[width * height * length];
+ final List tileEntities = new ArrayList();
+ // Precalculate index vars
+ int area = width * length;
+ final int[] yarea = new int[height];
+ final int[] zwidth = new int[width];
+ for (int i = 0; i < height; i++) {
+ yarea[i] = i * area;
+ }
+ for (int i = 0; i < width; i++) {
+ zwidth[i] = i * width;
+ }
+ if (clipboard instanceof BlockArrayClipboard) {
+ FaweClipboard faweClip = ((BlockArrayClipboard) clipboard).IMP;
+ ForEach forEach = new ForEach(yarea, zwidth, blocks, blockData, tileEntities);
+ faweClip.forEach(forEach, false);
+ addBlocks = forEach.addBlocks;
+ } else {
+ final int mx = (int) min.x;
+ final int my = (int) min.y;
+ final int mz = (int) min.z;
+ Vector mutable = new Vector(0, 0, 0);
+ ForEach forEach = new ForEach(yarea, zwidth, blocks, blockData, tileEntities);
+ for (Vector point : region) {
+ mutable.x = point.x - mx;
+ mutable.y = point.y - my;
+ mutable.z = point.z - mz;
+ forEach.run(mutable, clipboard.getBlock(point));
+ }
+ addBlocks = forEach.addBlocks;
+ }
+
+ schematic.put("Blocks", new ByteArrayTag(blocks));
+ schematic.put("Data", new ByteArrayTag(blockData));
+ schematic.put("TileEntities", new ListTag(CompoundTag.class, tileEntities));
+
+ if (addBlocks != null) {
+ schematic.put("AddBlocks", new ByteArrayTag(addBlocks));
+ }
+
+ List entities = new ArrayList();
+ for (Entity entity : clipboard.getEntities()) {
+ BaseEntity state = entity.getState();
+
+ if (state != null) {
+ Map values = new HashMap();
+
+ // Put NBT provided data
+ CompoundTag rawTag = state.getNbtData();
+ if (rawTag != null) {
+ values.putAll(rawTag.getValue());
+ }
+
+ // Store our location data, overwriting any
+ values.put("id", new StringTag(state.getTypeId()));
+ values.put("Pos", writeVector(entity.getLocation().toVector(), "Pos"));
+ values.put("Rotation", writeRotation(entity.getLocation(), "Rotation"));
+
+ CompoundTag entityTag = new CompoundTag(values);
+ entities.add(entityTag);
+ }
+ }
+
+ schematic.put("Entities", new ListTag(CompoundTag.class, entities));
+
+ CompoundTag schematicTag = new CompoundTag(schematic);
+ return schematicTag;
+ }
+
+ private static Tag writeVector(Vector vector, String name) {
+ List list = new ArrayList();
+ list.add(new DoubleTag(vector.getX()));
+ list.add(new DoubleTag(vector.getY()));
+ list.add(new DoubleTag(vector.getZ()));
+ return new ListTag(DoubleTag.class, list);
+ }
+
+ private static Tag writeRotation(Location location, String name) {
+ List list = new ArrayList();
+ list.add(new FloatTag(location.getYaw()));
+ list.add(new FloatTag(location.getPitch()));
+ return new ListTag(FloatTag.class, list);
+ }
+
+ @Override
+ public void close() throws IOException {
+ outputStream.close();
+ }
+
+ public static Class> inject() {
+ return SchematicWriter.class;
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java b/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java
index 65f2ab8e..5df6d03d 100644
--- a/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java
+++ b/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java
@@ -38,11 +38,9 @@ public final class Operations {
* @throws WorldEditException WorldEdit exception
*/
public static void complete(Operation operation) throws WorldEditException {
- try {
- while (true) {
- operation = operation.resume(context);
- }
- } catch (NullPointerException ignore) {}
+ while (operation != null) {
+ operation = operation.resume(context);
+ }
}
/**
@@ -65,12 +63,12 @@ public final class Operations {
*/
public static void completeBlindly(Operation operation) {
try {
- while (true) {
+ while (operation != null) {
operation = operation.resume(context);
}
} catch (WorldEditException e) {
throw new RuntimeException(e);
- } catch (NullPointerException ignore) {}
+ }
}
public static void completeSmart(final Operation op, final Runnable whenDone, final boolean threadsafe) {
diff --git a/core/src/main/java/net/jpountz/lz4/LZ4InputStream.java b/core/src/main/java/net/jpountz/lz4/LZ4InputStream.java
index 1e1ef192..0acc8424 100644
--- a/core/src/main/java/net/jpountz/lz4/LZ4InputStream.java
+++ b/core/src/main/java/net/jpountz/lz4/LZ4InputStream.java
@@ -71,7 +71,6 @@ public class LZ4InputStream extends InputStream {
numBytesRemainingToSkip -= numBytesToSkip;
decompressedBufferPosition += numBytesToSkip;
}
-
return n - numBytesRemainingToSkip;
}
diff --git a/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java b/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java
index eb23d929..144828fd 100644
--- a/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java
+++ b/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java
@@ -4,6 +4,7 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
+import com.boydti.fawe.wrappers.PlayerWrapper;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.forge.ForgeWorldEdit;
import java.util.UUID;
@@ -73,6 +74,6 @@ public class ForgePlayer extends FawePlayer {
@Override
public Player getPlayer() {
- return ForgeWorldEdit.inst.wrap(this.parent);
+ return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
}
}
diff --git a/sponge/build.gradle b/sponge/build.gradle
index f3ef23fb..29a7889f 100644
--- a/sponge/build.gradle
+++ b/sponge/build.gradle
@@ -14,7 +14,7 @@ buildscript {
}
dependencies {
classpath 'net.minecrell:VanillaGradle:2.0.3_1'
- classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT'
+ classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT'
}
}
diff --git a/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java b/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java
index 49a6e435..fb79963c 100644
--- a/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java
+++ b/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java
@@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
+import com.boydti.fawe.wrappers.PlayerWrapper;
import java.util.UUID;
import net.minecraft.entity.player.EntityPlayerMP;
import org.spongepowered.api.Sponge;
@@ -71,6 +72,6 @@ public class SpongePlayer extends FawePlayer {
@Override
public com.sk89q.worldedit.entity.Player getPlayer() {
- return (com.sk89q.worldedit.entity.Player) Fawe. imp().getWorldEditPlugin().wrap((EntityPlayerMP) this.parent);
+ return PlayerWrapper.wrap(Fawe. imp().getWorldEditPlugin().wrap((EntityPlayerMP) this.parent));
}
}