This commit is contained in:
Jesse Boyd 2016-04-28 08:10:17 +10:00
parent 72bd48a57d
commit 4ec9ed3a8d
10 changed files with 279 additions and 123 deletions

View File

@ -189,6 +189,16 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
*/
@Override
public FaweQueue getNewQueue(String world) {
try {
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
fieldDirtyCount.setAccessible(true);
int mod = fieldDirtyCount.getModifiers();
if ((mod & Modifier.VOLATILE) == 0) {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(fieldDirtyCount, mod + Modifier.VOLATILE);
}
} catch (Throwable ignore) {}
try {
if (FaweAPI.checkVersion(this.getVersion(), 1, 9, 0)) {
try {
@ -205,18 +215,6 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
return new BukkitQueue_1_8(world);
} catch (Throwable ignore) {}
if (hasNMS) {
try {
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
fieldDirtyCount.setAccessible(true);
int mod = fieldDirtyCount.getModifiers();
if ((mod & Modifier.VOLATILE) == 0) {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(fieldDirtyCount, mod + Modifier.VOLATILE);
}
} catch (Throwable e) {
e.printStackTrace();
}
debug("====== NO NMS BLOCK PLACER FOUND ======");
debug("FAWE couldn't find a fast block placer");
debug("Bukkit version: " + Bukkit.getVersion());

View File

@ -36,7 +36,7 @@ public class Settings {
public static int QUEUE_DISCARD_AFTER = 60000;
public static List<String> ALLOWED_3RDPARTY_EXTENTS;
public static boolean EXTENT_DEBUG = true;
public static int UNSAFE_PARALLEL_THREADS = 1;
public static boolean FIX_ALL_LIGHTING = true;
public static boolean ASYNC_LIGHTING = true;
@ -94,6 +94,7 @@ public class Settings {
options.put("history.buffer-size", BUFFER_SIZE);
options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS);
options.put("region-restrictions", REGION_RESTRICTIONS);
options.put("queue.parallel-threads", UNSAFE_PARALLEL_THREADS);
options.put("queue.extra-time-ms", ALLOCATE);
options.put("queue.target-size", QUEUE_SIZE);
options.put("queue.max-wait-ms", QUEUE_MAX_WAIT);
@ -134,6 +135,7 @@ public class Settings {
ALLOCATE = config.getInt("queue.extra-time-ms");
QUEUE_SIZE = config.getInt("queue.target-size");
QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms");
UNSAFE_PARALLEL_THREADS = config.getInt("queue.parallel-threads");
QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms");
ALLOWED_3RDPARTY_EXTENTS = config.getStringList("extent.allowed-plugins");
EXTENT_DEBUG = config.getBoolean("extent.debug");

View File

@ -52,6 +52,17 @@ public class FaweLimit {
return changed;
}
public FaweLimit copy() {
FaweLimit limit = new FaweLimit();
limit.MAX_CHANGES = MAX_CHANGES;
limit.MAX_BLOCKSTATES = MAX_BLOCKSTATES;
limit.MAX_CHECKS = MAX_CHECKS;
limit.MAX_ENTITIES = MAX_ENTITIES;
limit.MAX_FAILS = MAX_FAILS;
limit.MAX_ITERATIONS = MAX_ITERATIONS;
return limit;
}
@Override
public String toString() {
return MAX_CHANGES + "";

View File

@ -203,14 +203,19 @@ public class DiskOptimizedClipboard extends FaweClipboard {
}, 200);
}
private int ylast;
private int ylasti;
private int zlast;
private int zlasti;
@Override
public BaseBlock getBlock(int x, int y, int z) {
try {
if (raf == null) {
open();
}
lastAccessed = System.currentTimeMillis();
int i = x + z * width + y * area;
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1));
}
@ -244,7 +249,7 @@ public class DiskOptimizedClipboard extends FaweClipboard {
open();
}
lastAccessed = System.currentTimeMillis();
int i = x + z * width + y * area;
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1));
}

View File

@ -34,9 +34,14 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
entities = new HashSet<>();
}
private int ylast;
private int ylasti;
private int zlast;
private int zlasti;
@Override
public BaseBlock getBlock(int x, int y, int z) {
int i = x + z * width + (y >> 4) * area;
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y) >> 4) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
byte[] idArray = ids[i];
if (idArray == null) {
return FaweCache.CACHE_BLOCK[0];
@ -69,7 +74,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
final int id = block.getId();
switch (id) {
case 0: {
int i = x + z * width + (y >> 4) * area;
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y) >> 4) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
byte[] idArray = ids[i];
if (idArray != null) {
int y2 = y & 0xF;
@ -116,7 +121,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
if (block.hasNbtData()) {
nbtMap.put(new IntegerTrio(x, y, z), block.getNbtData());
}
int i = x + z * width + (y >> 4) * area;
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y) >> 4) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
@ -205,7 +210,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
case 190:
case 191:
case 192: {
int i = x + z * width + (y >> 4) * area;
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y) >> 4) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
@ -216,7 +221,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
return true;
}
default: {
int i = x + z * width + (y >> 4) * area;
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y) >> 4) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {

View File

@ -3,6 +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.boydti.fawe.object.RunnableVal2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
@ -29,6 +32,21 @@ public class SetQueue {
*/
private final LinkedBlockingDeque<Runnable> runnables = new LinkedBlockingDeque<>();
private final RunnableVal2<Long, FaweQueue> SET_TASK = new RunnableVal2<Long, FaweQueue>() {
@Override
public void run(Long free, FaweQueue queue) {
do {
final FaweChunk<?> current = queue.next();
if (current == null) {
lastSuccess = last;
if (inactiveQueues.size() == 0 && activeQueues.size() == 0) {
tasks();
}
return;
}
} while (((SetQueue.this.secondLast = System.currentTimeMillis()) - SetQueue.this.last) < free);
}
};
public SetQueue() {
activeQueues = new LinkedBlockingDeque();
@ -36,6 +54,10 @@ public class SetQueue {
TaskManager.IMP.repeat(new Runnable() {
@Override
public void run() {
if (inactiveQueues.size() == 0 && activeQueues.size() == 0) {
tasks();
return;
}
if (!MemUtil.isMemoryFree()) {
final int mem = MemUtil.calculateMemory();
if (mem != Integer.MAX_VALUE) {
@ -53,15 +75,45 @@ public class SetQueue {
return;
}
}
final long free = Settings.ALLOCATE + 50 + Math.min((50 + SetQueue.this.last) - (SetQueue.this.last = System.currentTimeMillis()), SetQueue.this.secondLast - System.currentTimeMillis());
do {
final FaweChunk<?> current = next();
if (current == null) {
lastSuccess = last;
SetQueue.this.tasks();
return;
SET_TASK.value1 = Settings.ALLOCATE + 50 + Math.min((50 + SetQueue.this.last) - (SetQueue.this.last = System.currentTimeMillis()), SetQueue.this.secondLast - System.currentTimeMillis());
SET_TASK.value2 = getNextQueue();
if (SET_TASK.value2 == null) {
return;
}
if (Settings.UNSAFE_PARALLEL_THREADS <= 1) {
SET_TASK.run();
} else {
boolean timingsEnabled = true;
try {
Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");
fieldEnabled.setAccessible(true);
timingsEnabled = (boolean) fieldEnabled.get(null);
if (timingsEnabled) {
fieldEnabled.set(null, false);
Method methodCheck = Class.forName("co.aikar.timings.TimingsManager").getDeclaredMethod("recheckEnabled");
methodCheck.setAccessible(true);
methodCheck.invoke(null);
}
} catch (Throwable ignore) {ignore.printStackTrace();}
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, false); } catch (Throwable ignore) {}
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < Settings.UNSAFE_PARALLEL_THREADS; i++) {
threads.add(new Thread(SET_TASK));
}
} while (((SetQueue.this.secondLast = System.currentTimeMillis()) - SetQueue.this.last) < free);
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled);
} catch (Throwable ignore) {ignore.printStackTrace();}
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {}
}
}
}, 1);
}
@ -94,13 +146,66 @@ public class SetQueue {
return queue;
}
public FaweQueue getNextQueue() {
while (activeQueues.size() > 0) {
FaweQueue queue = activeQueues.peek();
if (queue != null && queue.size() > 0) {
return queue;
} else {
activeQueues.poll();
}
}
if (inactiveQueues.size() > 0) {
ArrayList<FaweQueue> tmp = new ArrayList<>(inactiveQueues);
if (Settings.QUEUE_MAX_WAIT != -1) {
long now = System.currentTimeMillis();
if (lastSuccess == 0) {
lastSuccess = now;
}
long diff = now - lastSuccess;
if (diff > Settings.QUEUE_MAX_WAIT) {
for (FaweQueue queue : tmp) {
if (queue != null && queue.size() > 0) {
return queue;
} else {
activeQueues.poll();
}
}
if (diff > Settings.QUEUE_DISCARD_AFTER) {
// These edits never finished
inactiveQueues.clear();
}
return null;
}
}
if (Settings.QUEUE_SIZE != -1) {
int total = 0;
for (FaweQueue queue : tmp) {
total += queue.size();
}
if (total > Settings.QUEUE_SIZE) {
for (FaweQueue queue : tmp) {
if (queue != null && queue.size() > 0) {
return queue;
} else {
activeQueues.poll();
}
}
}
}
}
return null;
}
public FaweChunk<?> next() {
while (activeQueues.size() > 0) {
FaweQueue queue = activeQueues.poll();
final FaweChunk<?> set = queue.next();
if (set != null) {
activeQueues.add(queue);
return set;
if (queue != null) {
final FaweChunk<?> set = queue.next();
if (set != null) {
activeQueues.add(queue);
return set;
}
}
}
if (inactiveQueues.size() > 0) {
@ -166,7 +271,7 @@ public class SetQueue {
return false;
}
public boolean tasks() {
public synchronized boolean tasks() {
if (this.runnables.size() == 0) {
return false;
}

View File

@ -172,11 +172,11 @@ public class EditSession implements Extent {
public SurvivalModeExtent lazySurvivalExtent;
public boolean fastmode;
public Mask oldMask;
public FaweLimit limit = FaweLimit.MAX;
public FaweLimit limit = FaweLimit.MAX.copy();
public FaweQueue queue;
public static BaseBiome nullBiome = new BaseBiome(0);
public static BaseBlock nullBlock = new BaseBlock(0);
public static BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0];
/**
* Create a new instance.
@ -720,8 +720,9 @@ public class EditSession implements Extent {
* @return whether the block changed
*/
public boolean rawSetBlock(final Vector position, final BaseBlock block) {
this.changes++;
try {
return this.setBlock(position, block, Stage.BEFORE_CHANGE);
return this.bypassHistory.setBlock(position, block);
} catch (final WorldEditException e) {
throw new RuntimeException("Unexpected exception", e);
}
@ -735,8 +736,9 @@ public class EditSession implements Extent {
* @return whether the block changed
*/
public boolean smartSetBlock(final Vector position, final BaseBlock block) {
this.changes++;
try {
return this.setBlock(position, block, Stage.BEFORE_REORDER);
return this.bypassReorderHistory.setBlock(position, block);
} catch (final WorldEditException e) {
throw new RuntimeException("Unexpected exception", e);
}
@ -744,8 +746,9 @@ public class EditSession implements Extent {
@Override
public boolean setBlock(final Vector position, final BaseBlock block) throws MaxChangedBlocksException {
this.changes++;
try {
return this.setBlock(position, block, Stage.BEFORE_HISTORY);
return this.bypassNone.setBlock(position, block);
} catch (final MaxChangedBlocksException e) {
throw e;
} catch (final WorldEditException e) {

View File

@ -23,6 +23,7 @@ import com.boydti.fawe.object.clipboard.LazyClipboard;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
@ -37,18 +38,19 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional;
import java.util.Iterator;
import java.util.List;
@ -199,19 +201,58 @@ public class ClipboardCommands {
public void paste(Player player, LocalSession session, EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
Operation operation = holder
.createPaste(editSession, editSession.getWorld().getWorldData())
.to(to)
.ignoreAirBlocks(ignoreAirBlocks)
.build();
Operations.completeLegacy(operation);
Region region = clipboard.getRegion().clone();
Vector origin = clipboard.getOrigin();
if (region instanceof CuboidRegion) {
CuboidRegion cuboid = (CuboidRegion) region;
Vector min = cuboid.getMinimumPoint();
origin = origin.subtract(cuboid.getMinimumPoint());
cuboid.setPos2(cuboid.getMaximumPoint().subtract(min));
cuboid.setPos1(new Vector(0, 0, 0));
}
Vector to = atOrigin ? origin : session.getPlacementPosition(player);
int mx = region.getMinimumPoint().getBlockX();
int my = region.getMinimumPoint().getBlockY();
int mz = region.getMinimumPoint().getBlockZ();
int tx = to.getBlockX() - origin.getBlockX();
int ty = to.getBlockY() - origin.getBlockY();
int tz = to.getBlockZ() - origin.getBlockZ();
Iterator<BlockVector> iter = region.iterator();
if (clipboard instanceof BlockArrayClipboard) {
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
while (iter.hasNext()) {
BlockVector loc = iter.next();
int x = (int) loc.x;
int y = (int) loc.y;
int z = (int) loc.z;
BaseBlock block = bac.getBlockAbs(x, y, z);
if (block == EditSession.nullBlock && ignoreAirBlocks) {
continue;
}
loc.x += tx;
loc.y += ty;
loc.z += tz;
editSession.setBlock(loc, block);
}
} else {
while (iter.hasNext()) {
BlockVector loc = iter.next();
BaseBlock block = clipboard.getBlock(loc);
if (block == EditSession.nullBlock && ignoreAirBlocks) {
continue;
}
loc.x += tx;
loc.y += ty;
loc.z += tz;
editSession.setBlock(loc, block);
}
}
// entities
for (Entity entity : clipboard.getEntities()) {
editSession.createEntity(entity.getLocation(), entity.getState());
}
if (selectPasted) {
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max);
@ -219,7 +260,6 @@ public class ClipboardCommands {
selector.learnChanges();
selector.explainRegionAdjust(player, session);
}
player.print("The clipboard has been pasted at " + to);
}

View File

@ -19,14 +19,6 @@
package com.sk89q.worldedit.command.composition;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.WEManager;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
@ -36,25 +28,16 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.List;
@ -99,60 +82,60 @@ public class SelectionCommand extends SimpleCommand<Operation> {
Operation operation = operationFactory.createFromContext(editContext);
// Shortcut
if (selection instanceof CuboidRegion && editSession.hasFastMode() && operation instanceof RegionVisitor) {
CuboidRegion cuboid = (CuboidRegion) selection;
RegionFunction function = ((RegionVisitor) operation).function;
RegionWrapper current = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint());
FawePlayer fp = FawePlayer.wrap(player);
HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
if (function instanceof BlockReplace && mask.size() == 1 && mask.iterator().next().contains(current)) {
try {
BlockReplace replace = ((BlockReplace) function);
Field field = replace.getClass().getDeclaredField("pattern");
field.setAccessible(true);
Pattern pattern = (Pattern) field.get(replace);
if (pattern instanceof BlockPattern) {
BaseBlock block = ((BlockPattern) pattern).getBlock();
final FaweQueue queue = editSession.getQueue();
final int minY = cuboid.getMinimumY();
final int maxY = cuboid.getMaximumY();
final int id = block.getId();
final byte data = (byte) block.getData();
final FaweChunk<?> fc = queue.getChunk(0, 0);
fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data);
int bcx = (current.minX) >> 4;
int bcz = (current.minZ) >> 4;
int tcx = (current.maxX) >> 4;
int tcz = (current.maxZ) >> 4;
// [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge]
MainUtil.chunkTaskSync(current, new RunnableVal<int[]>() {
@Override
public void run(int[] value) {
FaweChunk newChunk;
if (value[6] == 0) {
newChunk = fc.copy(true);
newChunk.setLoc(queue, value[0], value[1]);
} else {
newChunk = queue.getChunk(value[0], value[1]);
newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, id, data);
}
newChunk.addToQueue();
}
});
queue.enqueue();
editSession.setChangeSet(new NullChangeSet());
actor.print("[FAWE] Finished queueing " + cuboid.getArea() + " blocks.");
return null;
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
// if (selection instanceof CuboidRegion && editSession.hasFastMode() && operation instanceof RegionVisitor) {
// CuboidRegion cuboid = (CuboidRegion) selection;
// RegionFunction function = ((RegionVisitor) operation).function;
// RegionWrapper current = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint());
// FawePlayer fp = FawePlayer.wrap(player);
// HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
//
// if (function instanceof BlockReplace && mask.size() == 1 && mask.iterator().next().contains(current)) {
// try {
// BlockReplace replace = ((BlockReplace) function);
// Field field = replace.getClass().getDeclaredField("pattern");
// field.setAccessible(true);
// Pattern pattern = (Pattern) field.get(replace);
// if (pattern instanceof BlockPattern) {
// BaseBlock block = ((BlockPattern) pattern).getBlock();
// final FaweQueue queue = editSession.getQueue();
// final int minY = cuboid.getMinimumY();
// final int maxY = cuboid.getMaximumY();
//
// final int id = block.getId();
// final byte data = (byte) block.getData();
// final FaweChunk<?> fc = queue.getChunk(0, 0);
// fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data);
//
// int bcx = (current.minX) >> 4;
// int bcz = (current.minZ) >> 4;
//
// int tcx = (current.maxX) >> 4;
// int tcz = (current.maxZ) >> 4;
// // [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge]
// MainUtil.chunkTaskSync(current, new RunnableVal<int[]>() {
// @Override
// public void run(int[] value) {
// FaweChunk newChunk;
// if (value[6] == 0) {
// newChunk = fc.copy(true);
// newChunk.setLoc(queue, value[0], value[1]);
// } else {
// newChunk = queue.getChunk(value[0], value[1]);
// newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, id, data);
// }
// newChunk.addToQueue();
// }
// });
// queue.enqueue();
// editSession.setChangeSet(new NullChangeSet());
// actor.print("[FAWE] Finished queueing " + cuboid.getArea() + " blocks.");
// return null;
// }
// } catch (Throwable e) {
// e.printStackTrace();
// }
// }
// }
Operations.completeBlindly(operation);
List<String> messages = Lists.newArrayList();

View File

@ -169,6 +169,10 @@ public class BlockArrayClipboard implements Clipboard {
return EditSession.nullBlock;
}
public BaseBlock getBlockAbs(int x, int y, int z) {
return IMP.getBlock(x, y, z);
}
@Override
public BaseBlock getLazyBlock(Vector position) {
return getBlock(position);