Fix entity y value not within chunk
Fix combined stages CPUOptimizedHistory not restoring air in existing
sections on undo
Change EditSession to wait for completion on flush (you should be
flushing it async)
Added setting for edit session history with no session
This commit is contained in:
Jesse Boyd 2016-05-26 05:29:55 +10:00
parent 89222036ea
commit b168d1b336
12 changed files with 122 additions and 97 deletions

View File

@ -227,8 +227,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
if (array == null) { if (array == null) {
continue; continue;
} }
int j = FaweCache.CACHE_J[y][x][z]; if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (array[j] != 0) {
nmsWorld.removeEntity(entity); nmsWorld.removeEntity(entity);
} }
} }

View File

@ -505,8 +505,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
if (array == null || y < 0 || y > 255) { if (array == null || y < 0 || y > 255) {
continue; continue;
} }
int j = FaweCache.CACHE_J[y][x][z]; if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (array[j] != 0) {
nmsWorld.removeEntity(entity); nmsWorld.removeEntity(entity);
} }
} }

View File

@ -19,6 +19,7 @@ public class Settings {
public static boolean ENABLE_HARD_LIMIT = true; public static boolean ENABLE_HARD_LIMIT = true;
public static boolean STORE_HISTORY_ON_DISK = false; public static boolean STORE_HISTORY_ON_DISK = false;
public static boolean STORE_CLIPBOARD_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 int DELETE_HISTORY_AFTER_DAYS = 7;
public static boolean CLEAN_HISTORY_ON_LOGOUT = true; public static boolean CLEAN_HISTORY_ON_LOGOUT = true;
public static int DELETE_CLIPBOARD_AFTER_DAYS = 1; 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.chunk-wait-ms", CHUNK_WAIT);
options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS); options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS);
options.put("history.delete-on-logout", CLEAN_HISTORY_ON_LOGOUT); 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("region-restrictions", REGION_RESTRICTIONS);
options.put("queue.extra-time-ms", ALLOCATE); options.put("queue.extra-time-ms", ALLOCATE);
options.put("queue.progress.display", DISPLAY_PROGRESS); options.put("queue.progress.display", DISPLAY_PROGRESS);
@ -144,6 +146,7 @@ public class Settings {
DELETE_HISTORY_AFTER_DAYS = config.getInt("history.delete-after-days"); DELETE_HISTORY_AFTER_DAYS = config.getInt("history.delete-after-days");
CLEAN_HISTORY_ON_LOGOUT = config.getBoolean("history.delete-on-logout"); CLEAN_HISTORY_ON_LOGOUT = config.getBoolean("history.delete-on-logout");
CHUNK_WAIT = config.getInt("history.chunk-wait-ms"); CHUNK_WAIT = config.getInt("history.chunk-wait-ms");
CONSOLE_HISTORY = config.getBoolean("history.enable-for-console");
ALLOCATE = config.getInt("queue.extra-time-ms"); ALLOCATE = config.getInt("queue.extra-time-ms");
QUEUE_SIZE = config.getInt("queue.target-size"); QUEUE_SIZE = config.getInt("queue.target-size");
QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms"); QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms");

View File

@ -1,9 +1,9 @@
package com.boydti.fawe.object.changeset; package com.boydti.fawe.object.changeset;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.change.MutableChunkChange; import com.boydti.fawe.object.change.MutableChunkChange;
import com.boydti.fawe.object.FaweQueue;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -25,8 +25,24 @@ public class CPUOptimizedChangeSet extends FaweChangeSet {
char[][] previousIds = previous.getCombinedIdArrays(); char[][] previousIds = previous.getCombinedIdArrays();
char[][] nextIds = next.getCombinedIdArrays(); char[][] nextIds = next.getCombinedIdArrays();
for (int i = 0; i < nextIds.length; i++) { for (int i = 0; i < nextIds.length; i++) {
if (nextIds[i] != null && previousIds[i] == null) { char[] nextArray = nextIds[i];
previous.fillCuboid(0, 15, i << 4, (i << 4) + 15, 0, 15, 0, (byte) 0); 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)); changes.add(new MutableChunkChange(previous, next));

View File

@ -185,22 +185,22 @@ public class MainUtil {
if (e == null) { if (e == null) {
return; return;
} }
if (!debug) { // if (!debug) {
e.printStackTrace(); e.printStackTrace();
return; return;
} // }
String header = "====== FAWE: " + e.getLocalizedMessage() + " ======"; // String header = "====== FAWE: " + e.getLocalizedMessage() + " ======";
Fawe.debug(header); // Fawe.debug(header);
String[] trace = getTrace(e); // String[] trace = getTrace(e);
for (int i = 0; i < trace.length && i < 8; i++) { // for (int i = 0; i < trace.length && i < 8; i++) {
Fawe.debug(" - " + trace[i]); // Fawe.debug(" - " + trace[i]);
} // }
String[] cause = getTrace(e.getCause()); // String[] cause = getTrace(e.getCause());
Fawe.debug("Cause: " + (cause.length == 0 ? "N/A" : "")); // Fawe.debug("Cause: " + (cause.length == 0 ? "N/A" : ""));
for (int i = 0; i < cause.length && i < 8; i++) { // for (int i = 0; i < cause.length && i < 8; i++) {
Fawe.debug(" - " + cause[i]); // Fawe.debug(" - " + cause[i]);
} // }
Fawe.debug(StringMan.repeat("=", header.length())); // Fawe.debug(StringMan.repeat("=", header.length()));
} }
public static String[] getTrace(Throwable e) { public static String[] getTrace(Throwable e) {

View File

@ -141,6 +141,25 @@ public abstract class TaskManager {
return sync(function, Integer.MAX_VALUE); 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:<br> * Quickly run a task on the main thread, and wait for execution to finish:<br>
* - Useful if you need to access something from the Bukkit API from another thread<br> * - Useful if you need to access something from the Bukkit API from another thread<br>

View File

@ -26,6 +26,7 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.EditSessionWrapper; import com.boydti.fawe.object.EditSessionWrapper;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HistoryExtent; import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.NullChangeSet; import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper; 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.NullExtent;
import com.boydti.fawe.object.extent.ProcessedWEExtent; import com.boydti.fawe.object.extent.ProcessedWEExtent;
import com.boydti.fawe.object.progress.DefaultProgressTracker; import com.boydti.fawe.object.progress.DefaultProgressTracker;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.Perm; import com.boydti.fawe.util.Perm;
@ -131,6 +131,8 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -178,8 +180,9 @@ public class EditSession implements Extent {
private FaweLimit limit = FaweLimit.MAX.copy(); private FaweLimit limit = FaweLimit.MAX.copy();
private FaweQueue queue; private FaweQueue queue;
public static BaseBiome nullBiome = new BaseBiome(0); public static final UUID CONSOLE = UUID.fromString("1-1-3-3-7");
public static BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0]; public static final BaseBiome nullBiome = new BaseBiome(0);
public static final BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0];
/** /**
* Create a new instance. * Create a new instance.
@ -252,9 +255,18 @@ public class EditSession implements Extent {
// Everything bypasses // Everything bypasses
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE); 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_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); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
this.bypassReorderHistory = extent; this.bypassReorderHistory = primaryExtent;
this.bypassHistory = extent; this.bypassHistory = primaryExtent;
this.bypassNone = extent; this.bypassNone = extent;
this.changeSet = new NullChangeSet(world); this.changeSet = new NullChangeSet(world);
return; return;
@ -384,11 +396,16 @@ public class EditSession implements Extent {
public boolean cancel() { public boolean cancel() {
// Cancel this // Cancel this
if (primaryExtent != null && queue != null) { if (primaryExtent != null && queue != null) {
System.out.println("CANCEL");
try { try {
WEManager.IMP.cancelEdit(primaryExtent, BBC.WORLDEDIT_CANCEL_REASON_MANUAL); WEManager.IMP.cancelEdit(primaryExtent, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
} catch (Throwable ignore) {} } catch (Throwable ignore) {}
NullExtent nullExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MANUAL); NullExtent nullExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
primaryExtent = nullExtent; primaryExtent = nullExtent;
regionExtent = nullExtent;
bypassReorderHistory = nullExtent;
bypassHistory = nullExtent;
bypassNone = nullExtent;
dequeue(); dequeue();
queue.clear(); queue.clear();
return true; return true;
@ -883,7 +900,8 @@ public class EditSession implements Extent {
*/ */
public void undo(final EditSession editSession) { public void undo(final EditSession editSession) {
final UndoContext context = new UndoContext(); 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() { Operations.completeSmart(ChangeSetExecutor.createUndo(this.changeSet, context), new Runnable() {
@Override @Override
public void run() { public void run() {
@ -900,7 +918,8 @@ public class EditSession implements Extent {
*/ */
public void redo(final EditSession editSession) { public void redo(final EditSession editSession) {
final UndoContext context = new UndoContext(); 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() { Operations.completeSmart(ChangeSetExecutor.createRedo(this.changeSet, context), new Runnable() {
@Override @Override
public void run() { public void run() {
@ -943,9 +962,30 @@ public class EditSession implements Extent {
* Finish off the queue. * Finish off the queue.
*/ */
public void flushQueue() { public void flushQueue() {
Operations.completeBlindly(EditSession.this.commit()); Operations.completeBlindly(commit());
if (queue != null) { // Enqueue it
queue.enqueue(); 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();
}
} }
} }

View File

@ -20,13 +20,7 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import com.boydti.fawe.config.Settings; 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.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.Chronic;
import com.sk89q.jchronic.Options; import com.sk89q.jchronic.Options;
import com.sk89q.jchronic.utils.Span; 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.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks; 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.CUIEvent;
import com.sk89q.worldedit.internal.cui.CUIRegion; import com.sk89q.worldedit.internal.cui.CUIRegion;
import com.sk89q.worldedit.internal.cui.SelectionShapeEvent; import com.sk89q.worldedit.internal.cui.SelectionShapeEvent;
@ -210,14 +203,6 @@ public class LocalSession {
if (Settings.STORE_HISTORY_ON_DISK) { if (Settings.STORE_HISTORY_ON_DISK) {
MAX_HISTORY_SIZE = Integer.MAX_VALUE; 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 // Don't store anything if no changes were made
if (editSession.size() == 0 || editSession.hasFastMode()) return; if (editSession.size() == 0 || editSession.hasFastMode()) return;
@ -227,32 +212,6 @@ public class LocalSession {
history.remove(historyPointer); 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) { if (append) {
history.add(editSession); history.add(editSession);
historyPointer = history.size(); historyPointer = history.size();

View File

@ -21,7 +21,9 @@ package com.sk89q.worldedit.extension.platform;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.PlayerWrapper; import com.boydti.fawe.wrappers.PlayerWrapper;
import com.google.common.base.Joiner; 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.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.function.factory.Deform; import com.sk89q.worldedit.function.factory.Deform;
import com.sk89q.worldedit.function.factory.Deform.Mode; 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.ActorAuthorizer;
import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
import com.sk89q.worldedit.internal.command.UserCommandCompleter; import com.sk89q.worldedit.internal.command.UserCommandCompleter;
@ -288,29 +291,19 @@ public final class CommandManager {
if (editSession != null) { if (editSession != null) {
editSession.flushQueue(); editSession.flushQueue();
worldEdit.flushBlockBag(actor, editSession); worldEdit.flushBlockBag(actor, editSession);
session.remember(editSession, true, true);
} }
if (fp != null) { if (fp != null) {
if (editSession != null && editSession.size() > 0 && editSession.getQueue() != null) { fp.deleteMeta("fawe_action");
delayed = true; final long time = System.currentTimeMillis() - start;
editSession.getQueue().addNotifyTask(new Runnable() { if (time > 0) {
@Override BBC.ACTION_COMPLETE.send(actor, (time / 50d));
public void run() { ChangeSet fcs = editSession.getChangeSet();
session.remember(editSession, true, true); if (fcs != null && fcs instanceof FaweStreamChangeSet) {
fp.deleteMeta("fawe_action"); MainUtil.sendCompressedMessage((FaweStreamChangeSet) fcs, editSession.getActor());
final long time = System.currentTimeMillis() - start; }
if (time > 5) {
BBC.ACTION_COMPLETE.send(actor, (time / 1000d));
}
}
});
} }
} }
if (!delayed) {
if (fp != null) {
fp.deleteMeta("fawe_action");
}
session.remember(editSession, true, true);
}
} }
} }
}); });

View File

@ -332,8 +332,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
if (array == null) { if (array == null) {
continue; continue;
} }
int j = FaweCache.CACHE_J[y][x][z]; if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (array[j] != 0) {
nmsWorld.removeEntity(entity); nmsWorld.removeEntity(entity);
} }
} }

View File

@ -385,8 +385,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
if (array == null) { if (array == null) {
continue; continue;
} }
int j = FaweCache.CACHE_J[y][x][z]; if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (array[j] != 0) {
nmsWorld.removeEntity(entity); nmsWorld.removeEntity(entity);
} }
} }

View File

@ -334,8 +334,7 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
if (array == null) { if (array == null) {
continue; continue;
} }
int j = FaweCache.CACHE_J[y][x][z]; if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (array[j] != 0) {
nmsWorld.removeEntity(entity); nmsWorld.removeEntity(entity);
} }
} }