diff --git a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java index 338f88f7..9a20d908 100644 --- a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java +++ b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java @@ -227,8 +227,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) { nmsWorld.removeEntity(entity); } } diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java index 13399247..3ebfad15 100644 --- a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java @@ -505,8 +505,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0 255) { continue; } - int j = FaweCache.CACHE_J[y][x][z]; - if (array[j] != 0) { + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) { nmsWorld.removeEntity(entity); } } 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 27f5d697..3956e6aa 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -19,6 +19,7 @@ public class Settings { public static boolean ENABLE_HARD_LIMIT = true; public static boolean STORE_HISTORY_ON_DISK = false; public static boolean STORE_CLIPBOARD_ON_DISK = false; + public static boolean CONSOLE_HISTORY = true; public static int DELETE_HISTORY_AFTER_DAYS = 7; public static boolean CLEAN_HISTORY_ON_LOGOUT = true; public static int DELETE_CLIPBOARD_AFTER_DAYS = 1; @@ -98,6 +99,7 @@ public class Settings { options.put("history.chunk-wait-ms", CHUNK_WAIT); options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS); options.put("history.delete-on-logout", CLEAN_HISTORY_ON_LOGOUT); + options.put("history.enable-for-console", CONSOLE_HISTORY); options.put("region-restrictions", REGION_RESTRICTIONS); options.put("queue.extra-time-ms", ALLOCATE); options.put("queue.progress.display", DISPLAY_PROGRESS); @@ -144,6 +146,7 @@ public class Settings { DELETE_HISTORY_AFTER_DAYS = config.getInt("history.delete-after-days"); CLEAN_HISTORY_ON_LOGOUT = config.getBoolean("history.delete-on-logout"); CHUNK_WAIT = config.getInt("history.chunk-wait-ms"); + CONSOLE_HISTORY = config.getBoolean("history.enable-for-console"); ALLOCATE = config.getInt("queue.extra-time-ms"); QUEUE_SIZE = config.getInt("queue.target-size"); QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms"); diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java index f7186546..711a7562 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java @@ -1,9 +1,9 @@ package com.boydti.fawe.object.changeset; import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.change.MutableChunkChange; -import com.boydti.fawe.object.FaweQueue; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.World; @@ -25,8 +25,24 @@ public class CPUOptimizedChangeSet extends FaweChangeSet { char[][] previousIds = previous.getCombinedIdArrays(); char[][] nextIds = next.getCombinedIdArrays(); for (int i = 0; i < nextIds.length; i++) { - if (nextIds[i] != null && previousIds[i] == null) { - previous.fillCuboid(0, 15, i << 4, (i << 4) + 15, 0, 15, 0, (byte) 0); + char[] nextArray = nextIds[i]; + if (nextArray != null) { + char[] previousArray = previousIds[i]; + if (previousArray == null) { + previous.fillCuboid(0, 15, i << 4, (i << 4) + 15, 0, 15, 0, (byte) 0); + continue; + } + for (int k = 0; k < nextArray.length; k++) { + int combinedNext = nextArray[k]; + if (combinedNext > 0) { + int combinedPrevious = previousArray[k]; + if (combinedPrevious == 0) { + previousArray[k] = 1; + } + } else { + previousArray[k] = 0; + } + } } } changes.add(new MutableChunkChange(previous, next)); diff --git a/core/src/main/java/com/boydti/fawe/util/MainUtil.java b/core/src/main/java/com/boydti/fawe/util/MainUtil.java index 969fc565..8f99fceb 100644 --- a/core/src/main/java/com/boydti/fawe/util/MainUtil.java +++ b/core/src/main/java/com/boydti/fawe/util/MainUtil.java @@ -185,22 +185,22 @@ public class MainUtil { if (e == null) { return; } - if (!debug) { +// if (!debug) { e.printStackTrace(); return; - } - String header = "====== FAWE: " + e.getLocalizedMessage() + " ======"; - Fawe.debug(header); - String[] trace = getTrace(e); - for (int i = 0; i < trace.length && i < 8; i++) { - Fawe.debug(" - " + trace[i]); - } - String[] cause = getTrace(e.getCause()); - Fawe.debug("Cause: " + (cause.length == 0 ? "N/A" : "")); - for (int i = 0; i < cause.length && i < 8; i++) { - Fawe.debug(" - " + cause[i]); - } - Fawe.debug(StringMan.repeat("=", header.length())); +// } +// String header = "====== FAWE: " + e.getLocalizedMessage() + " ======"; +// Fawe.debug(header); +// String[] trace = getTrace(e); +// for (int i = 0; i < trace.length && i < 8; i++) { +// Fawe.debug(" - " + trace[i]); +// } +// String[] cause = getTrace(e.getCause()); +// Fawe.debug("Cause: " + (cause.length == 0 ? "N/A" : "")); +// for (int i = 0; i < cause.length && i < 8; i++) { +// Fawe.debug(" - " + cause[i]); +// } +// Fawe.debug(StringMan.repeat("=", header.length())); } public static String[] getTrace(Throwable e) { diff --git a/core/src/main/java/com/boydti/fawe/util/TaskManager.java b/core/src/main/java/com/boydti/fawe/util/TaskManager.java index 6607d58a..f0c88b69 100644 --- a/core/src/main/java/com/boydti/fawe/util/TaskManager.java +++ b/core/src/main/java/com/boydti/fawe/util/TaskManager.java @@ -141,6 +141,25 @@ public abstract class TaskManager { return sync(function, Integer.MAX_VALUE); } + public void wait(AtomicBoolean running, int timout) { + try { + synchronized (running) { + while (running.get()) { + running.wait(timout); + } + } + } catch (InterruptedException e) { + MainUtil.handleError(e); + } + } + + public void notify(AtomicBoolean running) { + running.set(false); + synchronized (running) { + running.notifyAll(); + } + } + /** * Quickly run a task on the main thread, and wait for execution to finish:
* - Useful if you need to access something from the Bukkit API from another thread
diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index b9b1769f..e156ea63 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -26,6 +26,7 @@ import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.EditSessionWrapper; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.HistoryExtent; import com.boydti.fawe.object.NullChangeSet; import com.boydti.fawe.object.RegionWrapper; @@ -41,7 +42,6 @@ import com.boydti.fawe.object.extent.MemoryCheckingExtent; import com.boydti.fawe.object.extent.NullExtent; import com.boydti.fawe.object.extent.ProcessedWEExtent; import com.boydti.fawe.object.progress.DefaultProgressTracker; -import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.Perm; @@ -131,6 +131,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; @@ -178,8 +180,9 @@ public class EditSession implements Extent { private FaweLimit limit = FaweLimit.MAX.copy(); private FaweQueue queue; - public static BaseBiome nullBiome = new BaseBiome(0); - public static BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0]; + 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]; /** * Create a new instance. @@ -252,9 +255,18 @@ public class EditSession implements Extent { // 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 = new HistoryExtent(this, limit, extent, changeSet, queue); + } + } extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY); - this.bypassReorderHistory = extent; - this.bypassHistory = extent; + this.bypassReorderHistory = primaryExtent; + this.bypassHistory = primaryExtent; this.bypassNone = extent; this.changeSet = new NullChangeSet(world); return; @@ -384,11 +396,16 @@ public class EditSession implements Extent { public boolean cancel() { // Cancel this if (primaryExtent != null && queue != null) { + System.out.println("CANCEL"); 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; @@ -883,7 +900,8 @@ public class EditSession implements Extent { */ public void undo(final EditSession editSession) { final UndoContext context = new UndoContext(); - context.setExtent(editSession.bypassHistory); + context.setExtent(editSession.primaryExtent); + editSession.getQueue().setChangeTask(null); Operations.completeSmart(ChangeSetExecutor.createUndo(this.changeSet, context), new Runnable() { @Override public void run() { @@ -900,7 +918,8 @@ public class EditSession implements Extent { */ public void redo(final EditSession editSession) { final UndoContext context = new UndoContext(); - context.setExtent(editSession.bypassHistory); + context.setExtent(editSession.primaryExtent); + editSession.getQueue().setChangeTask(null); Operations.completeSmart(ChangeSetExecutor.createRedo(this.changeSet, context), new Runnable() { @Override public void run() { @@ -943,9 +962,30 @@ public class EditSession implements Extent { * Finish off the queue. */ public void flushQueue() { - Operations.completeBlindly(EditSession.this.commit()); - if (queue != null) { - queue.enqueue(); + Operations.completeBlindly(commit()); + // Enqueue it + if (queue != null && queue.size() > 0) { + SetQueue.IMP.enqueue(queue); + } + if (changeSet != null) { + if (Settings.COMBINE_HISTORY_STAGE && queue.size() > 0) { + final AtomicBoolean running = new AtomicBoolean(true); + queue.addNotifyTask(new Runnable() { + @Override + public void run() { + TaskManager.IMP.async(new Runnable() { + @Override + public void run() { + changeSet.flush(); + TaskManager.IMP.notify(running); + } + }); + } + }); + TaskManager.IMP.wait(running, Settings.QUEUE_DISCARD_AFTER); + } else { + changeSet.flush(); + } } } diff --git a/core/src/main/java/com/sk89q/worldedit/LocalSession.java b/core/src/main/java/com/sk89q/worldedit/LocalSession.java index 492c2df2..a418a340 100644 --- a/core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -20,13 +20,7 @@ package com.sk89q.worldedit; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.changeset.FaweChangeSet; -import com.boydti.fawe.object.changeset.FaweStreamChangeSet; import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.SetQueue; -import com.boydti.fawe.util.TaskManager; import com.sk89q.jchronic.Chronic; import com.sk89q.jchronic.Options; import com.sk89q.jchronic.utils.Span; @@ -43,7 +37,6 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; -import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.internal.cui.CUIRegion; import com.sk89q.worldedit.internal.cui.SelectionShapeEvent; @@ -210,14 +203,6 @@ public class LocalSession { if (Settings.STORE_HISTORY_ON_DISK) { MAX_HISTORY_SIZE = Integer.MAX_VALUE; } - // Enqueue it - if (editSession.getQueue() != null) { - FaweQueue queue = editSession.getQueue(); - if (queue.size() > 0) { - SetQueue.IMP.enqueue(editSession.getQueue()); - } - } - // Don't store anything if no changes were made if (editSession.size() == 0 || editSession.hasFastMode()) return; @@ -227,32 +212,6 @@ public class LocalSession { history.remove(historyPointer); } } - ChangeSet set = editSession.getChangeSet(); - if (set instanceof FaweStreamChangeSet) { - final FaweStreamChangeSet fcs = (FaweStreamChangeSet) set; - if (Settings.COMBINE_HISTORY_STAGE) { - editSession.getQueue().addNotifyTask(new Runnable() { - @Override - public void run() { - TaskManager.IMP.async(new Runnable() { - @Override - public void run() { - if (fcs.flush() && append && sendMessage) { - MainUtil.sendCompressedMessage(fcs, editSession.getActor()); - } - } - }); - } - }); - } else { - if (fcs.flush() && append && sendMessage) { - MainUtil.sendCompressedMessage(fcs, editSession.getActor()); - } - } - - } else if (set instanceof FaweChangeSet) { - ((FaweChangeSet) set).flush(); - } if (append) { history.add(editSession); historyPointer = history.size(); 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 90e6d958..f7ee1f23 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 @@ -21,7 +21,9 @@ package com.sk89q.worldedit.extension.platform; import com.boydti.fawe.config.BBC; import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.changeset.FaweStreamChangeSet; import com.boydti.fawe.object.exception.FaweException; +import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.wrappers.PlayerWrapper; import com.google.common.base.Joiner; @@ -64,6 +66,7 @@ import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.function.factory.Deform; import com.sk89q.worldedit.function.factory.Deform.Mode; +import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.internal.command.ActorAuthorizer; import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import com.sk89q.worldedit.internal.command.UserCommandCompleter; @@ -288,29 +291,19 @@ public final class CommandManager { if (editSession != null) { editSession.flushQueue(); worldEdit.flushBlockBag(actor, editSession); + session.remember(editSession, true, true); } if (fp != null) { - if (editSession != null && editSession.size() > 0 && editSession.getQueue() != null) { - delayed = true; - editSession.getQueue().addNotifyTask(new Runnable() { - @Override - public void run() { - session.remember(editSession, true, true); - fp.deleteMeta("fawe_action"); - final long time = System.currentTimeMillis() - start; - if (time > 5) { - BBC.ACTION_COMPLETE.send(actor, (time / 1000d)); - } - } - }); + fp.deleteMeta("fawe_action"); + final long time = System.currentTimeMillis() - start; + if (time > 0) { + BBC.ACTION_COMPLETE.send(actor, (time / 50d)); + ChangeSet fcs = editSession.getChangeSet(); + if (fcs != null && fcs instanceof FaweStreamChangeSet) { + MainUtil.sendCompressedMessage((FaweStreamChangeSet) fcs, editSession.getActor()); + } } } - if (!delayed) { - if (fp != null) { - fp.deleteMeta("fawe_action"); - } - session.remember(editSession, true, true); - } } } }); diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 1d36eb38..db85f870 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -332,8 +332,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) { nmsWorld.removeEntity(entity); } } diff --git a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 96b2103e..6e7af89a 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -385,8 +385,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) { nmsWorld.removeEntity(entity); } } diff --git a/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_1_8.java b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_1_8.java index 0d9b3b4e..07f9a301 100644 --- a/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_1_8.java +++ b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_1_8.java @@ -334,8 +334,7 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) { nmsWorld.removeEntity(entity); } }