diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index 48899d61..c0b13b1d 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -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()); diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java index ad390906..39425d0a 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -36,7 +36,7 @@ public class Settings { public static int QUEUE_DISCARD_AFTER = 60000; public static List 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"); diff --git a/core/src/main/java/com/boydti/fawe/object/FaweLimit.java b/core/src/main/java/com/boydti/fawe/object/FaweLimit.java index 5efe587e..b7e4fe76 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweLimit.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweLimit.java @@ -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 + ""; diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java index 8179df87..ca0dfe95 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java @@ -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)); } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java index 6d4d5f62..ab8845f9 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java @@ -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) { diff --git a/core/src/main/java/com/boydti/fawe/util/SetQueue.java b/core/src/main/java/com/boydti/fawe/util/SetQueue.java index 93327493..87b9423e 100644 --- a/core/src/main/java/com/boydti/fawe/util/SetQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/SetQueue.java @@ -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 runnables = new LinkedBlockingDeque<>(); + private final RunnableVal2 SET_TASK = new RunnableVal2() { + @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 threads = new ArrayList(); + 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 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; } diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index d8eb6512..ce026546 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -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) { 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 e4947d6a..2ab2e236 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -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 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); } 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 c838ae11..e45cd58a 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 @@ -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 = 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 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() { - @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 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() { +// @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 messages = Lists.newArrayList(); 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 c3371e9d..a8872ad7 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 @@ -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);