Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-26 02:50:06 +01:00
Improve exceptions (#1256)
- Kick more exceptions further up the pipeline to be more likely to be shown to player - Try to avoid lots of console spamming when it's the same error multiple times - Allow parsing of FaweExceptions during commands to better give information to players
Dieser Commit ist enthalten in:
Ursprung
0c9270dbc1
Commit
fb7e95c440
@ -1,6 +1,7 @@
|
|||||||
package com.fastasyncworldedit.core;
|
package com.fastasyncworldedit.core;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
|
import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
|
||||||
import com.fastasyncworldedit.core.util.CachedTextureUtil;
|
import com.fastasyncworldedit.core.util.CachedTextureUtil;
|
||||||
import com.fastasyncworldedit.core.util.CleanTextureUtil;
|
import com.fastasyncworldedit.core.util.CleanTextureUtil;
|
||||||
@ -346,4 +347,50 @@ public class Fawe {
|
|||||||
return this.thread = Thread.currentThread();
|
return this.thread = Thread.currentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-api. Handles an input FAWE exception if not already handled, given the input boolean array.
|
||||||
|
* Looks at the {@link FaweException.Type} and decides what to do (rethrows if we want to attempt to show the error to the
|
||||||
|
* player, outputs to console where necessary).
|
||||||
|
* @param faweExceptionReasonsUsed boolean array that should be cached where this method is called from of length {@code
|
||||||
|
* FaweException.Type.values().length}
|
||||||
|
* @param e {@link FaweException} to handle
|
||||||
|
* @param logger {@link Logger} of the calling class
|
||||||
|
*/
|
||||||
|
public static void handleFaweException(
|
||||||
|
boolean[] faweExceptionReasonsUsed,
|
||||||
|
FaweException e,
|
||||||
|
final Logger logger
|
||||||
|
) {
|
||||||
|
FaweException.Type type = e.getType();
|
||||||
|
switch (type) {
|
||||||
|
case OTHER:
|
||||||
|
logger.catching(e);
|
||||||
|
throw e;
|
||||||
|
case LOW_MEMORY:
|
||||||
|
if (!faweExceptionReasonsUsed[type.ordinal()]) {
|
||||||
|
logger.warn("FaweException: " + e.getMessage());
|
||||||
|
faweExceptionReasonsUsed[type.ordinal()] = true;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
case MAX_TILES:
|
||||||
|
case NO_REGION:
|
||||||
|
case MAX_CHECKS:
|
||||||
|
case MAX_CHANGES:
|
||||||
|
case MAX_ENTITIES:
|
||||||
|
case MAX_ITERATIONS:
|
||||||
|
case OUTSIDE_REGION:
|
||||||
|
if (!faweExceptionReasonsUsed[type.ordinal()]) {
|
||||||
|
faweExceptionReasonsUsed[type.ordinal()] = true;
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if (!faweExceptionReasonsUsed[type.ordinal()]) {
|
||||||
|
faweExceptionReasonsUsed[type.ordinal()] = true;
|
||||||
|
logger.warn("FaweException: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package com.fastasyncworldedit.core;
|
|||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
import com.fastasyncworldedit.core.internal.exception.FaweBlockBagException;
|
import com.fastasyncworldedit.core.internal.exception.FaweBlockBagException;
|
||||||
import com.fastasyncworldedit.core.internal.exception.FaweChunkLoadException;
|
|
||||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
|
import com.fastasyncworldedit.core.internal.exception.FaweException.Type;
|
||||||
import com.fastasyncworldedit.core.math.BitArray;
|
import com.fastasyncworldedit.core.math.BitArray;
|
||||||
import com.fastasyncworldedit.core.math.BitArrayUnstretched;
|
import com.fastasyncworldedit.core.math.BitArrayUnstretched;
|
||||||
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
||||||
@ -132,20 +132,40 @@ public enum FaweCache implements Trimable {
|
|||||||
/*
|
/*
|
||||||
Exceptions
|
Exceptions
|
||||||
*/
|
*/
|
||||||
public static final FaweChunkLoadException CHUNK = new FaweChunkLoadException();
|
|
||||||
public static final FaweBlockBagException BLOCK_BAG = new FaweBlockBagException();
|
public static final FaweBlockBagException BLOCK_BAG = new FaweBlockBagException();
|
||||||
public static final FaweException MANUAL = new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.manual"));
|
public static final FaweException MANUAL = new FaweException(
|
||||||
public static final FaweException NO_REGION = new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.no.region"));
|
Caption.of("fawe.cancel.worldedit.cancel.reason.manual"),
|
||||||
|
Type.MANUAL
|
||||||
|
);
|
||||||
|
public static final FaweException NO_REGION = new FaweException(
|
||||||
|
Caption.of("fawe.cancel.worldedit.cancel.reason.no.region"),
|
||||||
|
Type.NO_REGION
|
||||||
|
);
|
||||||
public static final FaweException OUTSIDE_REGION = new FaweException(Caption.of(
|
public static final FaweException OUTSIDE_REGION = new FaweException(Caption.of(
|
||||||
"fawe.cancel.worldedit.cancel.reason.outside.region"));
|
"fawe.cancel.worldedit.cancel.reason.outside.region"),
|
||||||
public static final FaweException MAX_CHECKS = new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.max.checks"));
|
Type.OUTSIDE_REGION);
|
||||||
public static final FaweException MAX_CHANGES = new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.max.changes"));
|
public static final FaweException MAX_CHECKS = new FaweException(
|
||||||
public static final FaweException LOW_MEMORY = new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.low.memory"));
|
Caption.of("fawe.cancel.worldedit.cancel.reason.max" + ".checks"),
|
||||||
|
Type.MAX_CHECKS
|
||||||
|
);
|
||||||
|
public static final FaweException MAX_CHANGES = new FaweException(
|
||||||
|
Caption.of("fawe.cancel.worldedit.cancel.reason.max" + ".changes"),
|
||||||
|
Type.MAX_CHANGES
|
||||||
|
);
|
||||||
|
public static final FaweException LOW_MEMORY = new FaweException(
|
||||||
|
Caption.of("fawe.cancel.worldedit.cancel.reason.low" + ".memory"),
|
||||||
|
Type.LOW_MEMORY
|
||||||
|
);
|
||||||
public static final FaweException MAX_ENTITIES = new FaweException(Caption.of(
|
public static final FaweException MAX_ENTITIES = new FaweException(Caption.of(
|
||||||
"fawe.cancel.worldedit.cancel.reason.max.entities"));
|
"fawe.cancel.worldedit.cancel.reason.max.entities"),
|
||||||
public static final FaweException MAX_TILES = new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.max.tiles"));
|
Type.MAX_ENTITIES);
|
||||||
|
public static final FaweException MAX_TILES = new FaweException(Caption.of(
|
||||||
|
"fawe.cancel.worldedit.cancel.reason.max.tiles",
|
||||||
|
Type.MAX_TILES
|
||||||
|
));
|
||||||
public static final FaweException MAX_ITERATIONS = new FaweException(Caption.of(
|
public static final FaweException MAX_ITERATIONS = new FaweException(Caption.of(
|
||||||
"fawe.cancel.worldedit.cancel.reason.max.iterations"));
|
"fawe.cancel.worldedit.cancel.reason.max.iterations"),
|
||||||
|
Type.MAX_ITERATIONS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
thread cache
|
thread cache
|
||||||
@ -539,28 +559,55 @@ public enum FaweCache implements Trimable {
|
|||||||
Executors.defaultThreadFactory(),
|
Executors.defaultThreadFactory(),
|
||||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||||
) {
|
) {
|
||||||
protected void afterExecute(Runnable r, Throwable t) {
|
|
||||||
try {
|
// Array for lazy avoidance of concurrent modification exceptions and needless overcomplication of code (synchronisation is
|
||||||
super.afterExecute(r, t);
|
// not very important)
|
||||||
if (t == null && r instanceof Future<?>) {
|
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
|
||||||
try {
|
private int lastException = Integer.MIN_VALUE;
|
||||||
Future<?> future = (Future<?>) r;
|
private int count = 0;
|
||||||
if (future.isDone()) {
|
|
||||||
future.get();
|
protected synchronized void afterExecute(Runnable runnable, Throwable throwable) {
|
||||||
}
|
super.afterExecute(runnable, throwable);
|
||||||
} catch (CancellationException ce) {
|
if (throwable == null && runnable instanceof Future<?>) {
|
||||||
t = ce;
|
try {
|
||||||
} catch (ExecutionException ee) {
|
Future<?> future = (Future<?>) runnable;
|
||||||
t = ee.getCause();
|
if (future.isDone()) {
|
||||||
} catch (InterruptedException ie) {
|
future.get();
|
||||||
Thread.currentThread().interrupt();
|
}
|
||||||
|
} catch (CancellationException ce) {
|
||||||
|
throwable = ce;
|
||||||
|
} catch (ExecutionException ee) {
|
||||||
|
throwable = ee.getCause();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (throwable != null) {
|
||||||
|
if (throwable instanceof FaweException) {
|
||||||
|
handleFaweException((FaweException) throwable);
|
||||||
|
} else if (throwable.getCause() instanceof FaweException) {
|
||||||
|
handleFaweException((FaweException) throwable.getCause());
|
||||||
|
} else {
|
||||||
|
int hash = throwable.getMessage().hashCode();
|
||||||
|
if (hash != lastException) {
|
||||||
|
lastException = hash;
|
||||||
|
LOGGER.catching(throwable);
|
||||||
|
count = 0;
|
||||||
|
} else if (count < Settings.IMP.QUEUE.PARALLEL_THREADS) {
|
||||||
|
LOGGER.warn(throwable.getMessage());
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (t != null) {
|
}
|
||||||
t.printStackTrace();
|
}
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
private void handleFaweException(FaweException e) {
|
||||||
e.printStackTrace();
|
FaweException.Type type = e.getType();
|
||||||
|
if (e.getType() == FaweException.Type.OTHER) {
|
||||||
|
LOGGER.catching(e);
|
||||||
|
} else if (!faweExceptionReasonsUsed[type.ordinal()]) {
|
||||||
|
faweExceptionReasonsUsed[type.ordinal()] = true;
|
||||||
|
LOGGER.warn("FaweException: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -60,11 +60,7 @@ public class CatenaryBrush implements Brush, ResettableTool {
|
|||||||
}
|
}
|
||||||
List<BlockVector3> nodes = Arrays.asList(pos1, vertex, pos2);
|
List<BlockVector3> nodes = Arrays.asList(pos1, vertex, pos2);
|
||||||
vertex = null;
|
vertex = null;
|
||||||
try {
|
editSession.drawSpline(pattern, nodes, 0, 0, 0, 10, size, !shell);
|
||||||
editSession.drawSpline(pattern, nodes, 0, 0, 0, 10, size, !shell);
|
|
||||||
} catch (WorldEditException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
player.print(Caption.of("fawe.worldedit.brush.brush.line.secondary"));
|
player.print(Caption.of("fawe.worldedit.brush.brush.line.secondary"));
|
||||||
if (!select) {
|
if (!select) {
|
||||||
pos1 = null;
|
pos1 = null;
|
||||||
|
@ -78,11 +78,7 @@ public class SurfaceSpline implements Brush {
|
|||||||
}
|
}
|
||||||
if (radius == 0) {
|
if (radius == 0) {
|
||||||
BlockVector3 set = mutable.setComponents(tipx, tipy, tipz);
|
BlockVector3 set = mutable.setComponents(tipx, tipy, tipz);
|
||||||
try {
|
pattern.apply(editSession, set, set);
|
||||||
pattern.apply(editSession, set, set);
|
|
||||||
} catch (WorldEditException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
vset.add(tipx, tipy, tipz);
|
vset.add(tipx, tipy, tipz);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package com.fastasyncworldedit.core.extent.processor;
|
package com.fastasyncworldedit.core.extent.processor;
|
||||||
|
|
||||||
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
import com.fastasyncworldedit.core.queue.Filter;
|
import com.fastasyncworldedit.core.queue.Filter;
|
||||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.queue.IChunk;
|
import com.fastasyncworldedit.core.queue.IChunk;
|
||||||
@ -9,6 +12,8 @@ import com.fastasyncworldedit.core.queue.IChunkSet;
|
|||||||
import com.fastasyncworldedit.core.util.StringMan;
|
import com.fastasyncworldedit.core.util.StringMan;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -26,9 +31,16 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
public class MultiBatchProcessor implements IBatchProcessor {
|
public class MultiBatchProcessor implements IBatchProcessor {
|
||||||
|
|
||||||
private IBatchProcessor[] processors;
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
|
||||||
private final LoadingCache<Class<?>, Map<Long, Filter>> classToThreadIdToFilter =
|
private final LoadingCache<Class<?>, Map<Long, Filter>> classToThreadIdToFilter =
|
||||||
FaweCache.IMP.createCache((Supplier<Map<Long, Filter>>) ConcurrentHashMap::new);
|
FaweCache.IMP.createCache((Supplier<Map<Long, Filter>>) ConcurrentHashMap::new);
|
||||||
|
// Array for lazy avoidance of concurrent modification exceptions and needless overcomplication of code (synchronisation is
|
||||||
|
// not very important)
|
||||||
|
private boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
|
||||||
|
private IBatchProcessor[] processors;
|
||||||
|
private int lastException = Integer.MIN_VALUE;
|
||||||
|
private int exceptionCount = 0;
|
||||||
|
|
||||||
public MultiBatchProcessor(IBatchProcessor... processors) {
|
public MultiBatchProcessor(IBatchProcessor... processors) {
|
||||||
this.processors = processors;
|
this.processors = processors;
|
||||||
@ -72,41 +84,36 @@ public class MultiBatchProcessor implements IBatchProcessor {
|
|||||||
@Override
|
@Override
|
||||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||||
Map<Integer, Set<IBatchProcessor>> ordered = new HashMap<>();
|
Map<Integer, Set<IBatchProcessor>> ordered = new HashMap<>();
|
||||||
try {
|
IChunkSet chunkSet = set;
|
||||||
IChunkSet chunkSet = set;
|
for (IBatchProcessor processor : processors) {
|
||||||
for (IBatchProcessor processor : processors) {
|
if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) {
|
||||||
if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) {
|
ordered.merge(
|
||||||
ordered.merge(
|
processor.getScope().intValue(),
|
||||||
processor.getScope().intValue(),
|
new HashSet<>(Collections.singleton(processor)),
|
||||||
new HashSet<>(Collections.singleton(processor)),
|
(existing, theNew) -> {
|
||||||
(existing, theNew) -> {
|
existing.add(processor);
|
||||||
existing.add(processor);
|
return existing;
|
||||||
return existing;
|
}
|
||||||
}
|
);
|
||||||
);
|
continue;
|
||||||
|
}
|
||||||
|
chunkSet = processSet(processor, chunk, get, chunkSet);
|
||||||
|
}
|
||||||
|
if (ordered.size() > 0) {
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
Set<IBatchProcessor> processors = ordered.get(i);
|
||||||
|
if (processors == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
chunkSet = processSet(processor, chunk, get, chunkSet);
|
for (IBatchProcessor processor : processors) {
|
||||||
}
|
chunkSet = processSet(processor, chunk, get, chunkSet);
|
||||||
if (ordered.size() > 0) {
|
if (chunkSet == null) {
|
||||||
for (int i = 1; i <= 4; i++) {
|
return null;
|
||||||
Set<IBatchProcessor> processors = ordered.get(i);
|
|
||||||
if (processors == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (IBatchProcessor processor : processors) {
|
|
||||||
chunkSet = processSet(processor, chunk, get, chunkSet);
|
|
||||||
if (chunkSet == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return chunkSet;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
return chunkSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -139,7 +146,22 @@ public class MultiBatchProcessor implements IBatchProcessor {
|
|||||||
}
|
}
|
||||||
return CompletableFuture.completedFuture(set);
|
return CompletableFuture.completedFuture(set);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
if (e instanceof FaweException) {
|
||||||
|
Fawe.handleFaweException(faweExceptionReasonsUsed, (FaweException) e, LOGGER);
|
||||||
|
} else if (e.getCause() instanceof FaweException) {
|
||||||
|
Fawe.handleFaweException(faweExceptionReasonsUsed, (FaweException) e.getCause(), LOGGER);
|
||||||
|
} else {
|
||||||
|
String message = e.getMessage();
|
||||||
|
int hash = message.hashCode();
|
||||||
|
if (lastException != hash) {
|
||||||
|
lastException = hash;
|
||||||
|
exceptionCount = 0;
|
||||||
|
LOGGER.catching(e);
|
||||||
|
} else if (exceptionCount < Settings.IMP.QUEUE.PARALLEL_THREADS) {
|
||||||
|
exceptionCount++;
|
||||||
|
LOGGER.warn(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,4 +236,16 @@ public class MultiBatchProcessor implements IBatchProcessor {
|
|||||||
return ProcessorScope.valueOf(0);
|
return ProcessorScope.valueOf(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cached boolean array of length {@code FaweException.Type.values().length} that determines if a thrown
|
||||||
|
* {@link FaweException} of type {@link FaweException.Type} should be output to console, rethrown to attempt to be visible
|
||||||
|
* to the player, etc. Allows the same array to be used as widely as possible across the edit to avoid spam to console.
|
||||||
|
*
|
||||||
|
* @param faweExceptionReasonsUsed boolean array that should be cached where this method is called from of length {@code
|
||||||
|
* FaweException.Type.values().length}
|
||||||
|
*/
|
||||||
|
public void setFaweExceptionArray(final boolean[] faweExceptionReasonsUsed) {
|
||||||
|
this.faweExceptionReasonsUsed = faweExceptionReasonsUsed;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import com.sk89q.worldedit.regions.CuboidRegion;
|
|||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
public interface HeightMap {
|
public interface HeightMap {
|
||||||
@ -60,7 +61,7 @@ public interface HeightMap {
|
|||||||
.getConstructors()[0].newInstance(5, 1));
|
.getConstructors()[0].newInstance(5, 1));
|
||||||
int diameter = 2 * size + 1;
|
int diameter = 2 * size + 1;
|
||||||
data[1] = filter.filter(data[1], diameter, diameter);
|
data[1] = filter.filter(data[1], diameter, diameter);
|
||||||
} catch (Throwable e) {
|
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -864,25 +864,21 @@ public class NMSRelighter implements Relighter {
|
|||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
if (sky) {
|
||||||
if (sky) {
|
fixSkyLighting();
|
||||||
fixSkyLighting();
|
} else {
|
||||||
} else {
|
synchronized (this) {
|
||||||
synchronized (this) {
|
Map<Long, RelightSkyEntry> map = getSkyMap();
|
||||||
Map<Long, RelightSkyEntry> map = getSkyMap();
|
Iterator<Map.Entry<Long, RelightSkyEntry>> iter = map.entrySet().iterator();
|
||||||
Iterator<Map.Entry<Long, RelightSkyEntry>> iter = map.entrySet().iterator();
|
while (iter.hasNext()) {
|
||||||
while (iter.hasNext()) {
|
Map.Entry<Long, RelightSkyEntry> entry = iter.next();
|
||||||
Map.Entry<Long, RelightSkyEntry> entry = iter.next();
|
chunksToSend.put(entry.getKey(), entry.getValue().bitmask);
|
||||||
chunksToSend.put(entry.getKey(), entry.getValue().bitmask);
|
iter.remove();
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fixBlockLighting();
|
|
||||||
sendChunks();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
fixBlockLighting();
|
||||||
|
sendChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fixBlockLighting() {
|
public void fixBlockLighting() {
|
||||||
@ -930,11 +926,7 @@ public class NMSRelighter implements Relighter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void flush() {
|
public void flush() {
|
||||||
try {
|
close();
|
||||||
close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void sendChunks() {
|
public synchronized void sendChunks() {
|
||||||
|
@ -59,33 +59,28 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
|
|||||||
|
|
||||||
public int getHeight(Extent extent, int x, int y, int z) {
|
public int getHeight(Extent extent, int x, int y, int z) {
|
||||||
// return extent.getNearestSurfaceTerrainBlock(x, z, y, 0, maxY);
|
// return extent.getNearestSurfaceTerrainBlock(x, z, y, 0, maxY);
|
||||||
try {
|
int rx = x - cacheBotX + 16;
|
||||||
int rx = x - cacheBotX + 16;
|
int rz = z - cacheBotZ + 16;
|
||||||
int rz = z - cacheBotZ + 16;
|
int index;
|
||||||
int index;
|
if (((rx & 0xFF) != rx || (rz & 0xFF) != rz)) {
|
||||||
if (((rx & 0xFF) != rx || (rz & 0xFF) != rz)) {
|
cacheBotX = x - 16;
|
||||||
cacheBotX = x - 16;
|
cacheBotZ = z - 16;
|
||||||
cacheBotZ = z - 16;
|
rx = x - cacheBotX + 16;
|
||||||
rx = x - cacheBotX + 16;
|
rz = z - cacheBotZ + 16;
|
||||||
rz = z - cacheBotZ + 16;
|
index = rx + (rz << 8);
|
||||||
index = rx + (rz << 8);
|
if (cacheHeights == null) {
|
||||||
if (cacheHeights == null) {
|
cacheHeights = new byte[65536];
|
||||||
cacheHeights = new byte[65536];
|
|
||||||
} else {
|
|
||||||
Arrays.fill(cacheHeights, (byte) 0);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
index = rx + (rz << 8);
|
Arrays.fill(cacheHeights, (byte) 0);
|
||||||
}
|
}
|
||||||
int result = cacheHeights[index] & 0xFF;
|
} else {
|
||||||
if (y > result) {
|
index = rx + (rz << 8);
|
||||||
cacheHeights[index] = (byte) (result = lastY = extent.getNearestSurfaceTerrainBlock(x, z, lastY, minY, maxY));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
int result = cacheHeights[index] & 0xFF;
|
||||||
|
if (y > result) {
|
||||||
|
cacheHeights[index] = (byte) (result = lastY = extent.getNearestSurfaceTerrainBlock(x, z, lastY, minY, maxY));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean testSlope(Extent extent, int x, int y, int z) {
|
protected boolean testSlope(Extent extent, int x, int y, int z) {
|
||||||
|
@ -54,9 +54,6 @@ public class ExpressionPattern extends AbstractPattern {
|
|||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import com.fastasyncworldedit.core.configuration.Caption;
|
|||||||
public class FaweBlockBagException extends FaweException {
|
public class FaweBlockBagException extends FaweException {
|
||||||
|
|
||||||
public FaweBlockBagException() {
|
public FaweBlockBagException() {
|
||||||
super(Caption.of("fawe.error.worldedit.some.fails.blockbag"));
|
super(Caption.of("fawe.error.worldedit.some.fails.blockbag"), Type.BLOCK_BAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
package com.fastasyncworldedit.core.internal.exception;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
|
||||||
|
|
||||||
public class FaweChunkLoadException extends FaweException {
|
|
||||||
|
|
||||||
public FaweChunkLoadException() {
|
|
||||||
super(Caption.of("fawe.cancel.worldedit.failed.load.chunk"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -13,13 +13,28 @@ public class FaweException extends RuntimeException {
|
|||||||
public static final FaweException _disableQueue = new FaweException("disableQueue");
|
public static final FaweException _disableQueue = new FaweException("disableQueue");
|
||||||
|
|
||||||
private final Component message;
|
private final Component message;
|
||||||
|
private final Type type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New instance. Defaults to {@link FaweException.Type#OTHER}.
|
||||||
|
*/
|
||||||
public FaweException(String reason) {
|
public FaweException(String reason) {
|
||||||
this(TextComponent.of(reason));
|
this(TextComponent.of(reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New instance. Defaults to {@link FaweException.Type#OTHER}.
|
||||||
|
*/
|
||||||
public FaweException(Component reason) {
|
public FaweException(Component reason) {
|
||||||
|
this(reason, Type.OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New instance of a given {@link FaweException.Type}
|
||||||
|
*/
|
||||||
|
public FaweException(Component reason, Type type) {
|
||||||
this.message = reason;
|
this.message = reason;
|
||||||
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -31,6 +46,14 @@ public class FaweException extends RuntimeException {
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link FaweException.Type}
|
||||||
|
* @return the {@link FaweException.Type}
|
||||||
|
*/
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
public static FaweException get(Throwable e) {
|
public static FaweException get(Throwable e) {
|
||||||
if (e instanceof FaweException) {
|
if (e instanceof FaweException) {
|
||||||
return (FaweException) e;
|
return (FaweException) e;
|
||||||
@ -52,4 +75,19 @@ public class FaweException extends RuntimeException {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
MANUAL,
|
||||||
|
NO_REGION,
|
||||||
|
OUTSIDE_REGION,
|
||||||
|
MAX_CHECKS,
|
||||||
|
MAX_CHANGES,
|
||||||
|
LOW_MEMORY,
|
||||||
|
MAX_ENTITIES,
|
||||||
|
MAX_TILES,
|
||||||
|
MAX_ITERATIONS,
|
||||||
|
BLOCK_BAG,
|
||||||
|
CHUNK,
|
||||||
|
OTHER
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.fastasyncworldedit.core.queue.implementation;
|
package com.fastasyncworldedit.core.queue.implementation;
|
||||||
|
|
||||||
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
import com.fastasyncworldedit.core.extent.NullExtent;
|
import com.fastasyncworldedit.core.extent.NullExtent;
|
||||||
@ -10,7 +11,9 @@ import com.fastasyncworldedit.core.extent.filter.DistrFilter;
|
|||||||
import com.fastasyncworldedit.core.extent.filter.LinkedFilter;
|
import com.fastasyncworldedit.core.extent.filter.LinkedFilter;
|
||||||
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
|
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
|
||||||
import com.fastasyncworldedit.core.extent.processor.BatchProcessorHolder;
|
import com.fastasyncworldedit.core.extent.processor.BatchProcessorHolder;
|
||||||
|
import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder;
|
import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder;
|
||||||
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
import com.fastasyncworldedit.core.queue.Filter;
|
import com.fastasyncworldedit.core.queue.Filter;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||||
@ -22,6 +25,7 @@ import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
|||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
@ -31,6 +35,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
|||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -40,19 +45,32 @@ import java.util.stream.IntStream;
|
|||||||
|
|
||||||
public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrapper {
|
public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrapper {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
|
||||||
private final World world;
|
private final World world;
|
||||||
private final QueueHandler handler;
|
private final QueueHandler handler;
|
||||||
private final BatchProcessorHolder processor;
|
private final BatchProcessorHolder processor;
|
||||||
private final BatchProcessorHolder postProcessor;
|
private final BatchProcessorHolder postProcessor;
|
||||||
|
// Array for lazy avoidance of concurrent modification exceptions and needless overcomplication of code (synchronisation is
|
||||||
|
// not very important)
|
||||||
|
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
|
||||||
private int changes;
|
private int changes;
|
||||||
private final boolean fastmode;
|
private final boolean fastmode;
|
||||||
|
private int lastException = Integer.MIN_VALUE;
|
||||||
|
private int exceptionCount = 0;
|
||||||
|
|
||||||
public ParallelQueueExtent(QueueHandler handler, World world, boolean fastmode) {
|
public ParallelQueueExtent(QueueHandler handler, World world, boolean fastmode) {
|
||||||
super(handler.getQueue(world, new BatchProcessorHolder(), new BatchProcessorHolder()));
|
super(handler.getQueue(world, new BatchProcessorHolder(), new BatchProcessorHolder()));
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.processor = (BatchProcessorHolder) getExtent().getProcessor();
|
this.processor = (BatchProcessorHolder) getExtent().getProcessor();
|
||||||
|
if (this.processor.getProcessor() instanceof MultiBatchProcessor) {
|
||||||
|
((MultiBatchProcessor) this.processor.getProcessor()).setFaweExceptionArray(faweExceptionReasonsUsed);
|
||||||
|
}
|
||||||
this.postProcessor = (BatchProcessorHolder) getExtent().getPostProcessor();
|
this.postProcessor = (BatchProcessorHolder) getExtent().getPostProcessor();
|
||||||
|
if (this.postProcessor.getProcessor() instanceof MultiBatchProcessor) {
|
||||||
|
((MultiBatchProcessor) this.postProcessor.getProcessor()).setFaweExceptionArray(faweExceptionReasonsUsed);
|
||||||
|
}
|
||||||
this.fastmode = fastmode;
|
this.fastmode = fastmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,29 +117,49 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
|
|||||||
try {
|
try {
|
||||||
final Filter newFilter = filter.fork();
|
final Filter newFilter = filter.fork();
|
||||||
// Create a chunk that we will reuse/reset for each operation
|
// Create a chunk that we will reuse/reset for each operation
|
||||||
final IQueueExtent<IQueueChunk> queue = getNewQueue();
|
final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue();
|
||||||
queue.setFastMode(fastmode);
|
queue.setFastMode(fastmode);
|
||||||
|
queue.setFaweExceptionArray(faweExceptionReasonsUsed);
|
||||||
synchronized (queue) {
|
synchronized (queue) {
|
||||||
ChunkFilterBlock block = null;
|
try {
|
||||||
|
ChunkFilterBlock block = null;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Get the next chunk posWeakChunk
|
// Get the next chunk posWeakChunk
|
||||||
final int chunkX;
|
final int chunkX;
|
||||||
final int chunkZ;
|
final int chunkZ;
|
||||||
synchronized (chunksIter) {
|
synchronized (chunksIter) {
|
||||||
if (!chunksIter.hasNext()) {
|
if (!chunksIter.hasNext()) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
final BlockVector2 pos = chunksIter.next();
|
||||||
|
chunkX = pos.getX();
|
||||||
|
chunkZ = pos.getZ();
|
||||||
}
|
}
|
||||||
final BlockVector2 pos = chunksIter.next();
|
block = queue.apply(block, newFilter, region, chunkX, chunkZ, full);
|
||||||
chunkX = pos.getX();
|
}
|
||||||
chunkZ = pos.getZ();
|
queue.flush();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
if (t instanceof FaweException) {
|
||||||
|
Fawe.handleFaweException(faweExceptionReasonsUsed, (FaweException) t, LOGGER);
|
||||||
|
} else if (t.getCause() instanceof FaweException) {
|
||||||
|
Fawe.handleFaweException(faweExceptionReasonsUsed, (FaweException) t.getCause(), LOGGER);
|
||||||
|
} else {
|
||||||
|
throw t;
|
||||||
}
|
}
|
||||||
block = queue.apply(block, newFilter, region, chunkX, chunkZ, full);
|
|
||||||
}
|
}
|
||||||
queue.flush();
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
String message = e.getMessage();
|
||||||
|
int hash = message.hashCode();
|
||||||
|
if (lastException != hash) {
|
||||||
|
lastException = hash;
|
||||||
|
exceptionCount = 0;
|
||||||
|
LOGGER.catching(e);
|
||||||
|
} else if (exceptionCount < Settings.IMP.QUEUE.PARALLEL_THREADS) {
|
||||||
|
exceptionCount++;
|
||||||
|
LOGGER.warn(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})).toArray(ForkJoinTask[]::new);
|
})).toArray(ForkJoinTask[]::new);
|
||||||
// Join filters
|
// Join filters
|
||||||
|
@ -41,8 +41,9 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
* Single threaded implementation for IQueueExtent (still abstract) - Does not implement creation of
|
* Single threaded implementation for IQueueExtent (still abstract) - Does not implement creation of
|
||||||
* chunks (that has to implemented by the platform e.g., Bukkit)
|
* chunks (that has to implemented by the platform e.g., Bukkit)
|
||||||
* <p>
|
* <p>
|
||||||
* This queue is reusable {@link #init(Extent, IChunkCache, IChunkCache)} }
|
* This queue is reusable {@link #init(Extent, IChunkCache, IChunkCache)}
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implements IQueueExtent<IQueueChunk> {
|
public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implements IQueueExtent<IQueueChunk> {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
@ -51,28 +52,28 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
// private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
// private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
||||||
// Chunks currently being queued / worked on
|
// Chunks currently being queued / worked on
|
||||||
private final Long2ObjectLinkedOpenHashMap<IQueueChunk> chunks = new Long2ObjectLinkedOpenHashMap<>();
|
private final Long2ObjectLinkedOpenHashMap<IQueueChunk> chunks = new Long2ObjectLinkedOpenHashMap<>();
|
||||||
|
private final ConcurrentLinkedQueue<Future> submissions = new ConcurrentLinkedQueue<>();
|
||||||
|
private final ReentrantLock getChunkLock = new ReentrantLock();
|
||||||
private World world = null;
|
private World world = null;
|
||||||
private int minY = 0;
|
private int minY = 0;
|
||||||
private int maxY = 255;
|
private int maxY = 255;
|
||||||
|
|
||||||
private IChunkCache<IChunkGet> cacheGet;
|
private IChunkCache<IChunkGet> cacheGet;
|
||||||
private IChunkCache<IChunkSet> cacheSet;
|
private IChunkCache<IChunkSet> cacheSet;
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
|
|
||||||
private Thread currentThread;
|
private Thread currentThread;
|
||||||
private final ConcurrentLinkedQueue<Future> submissions = new ConcurrentLinkedQueue<>();
|
|
||||||
// Last access pointers
|
// Last access pointers
|
||||||
private IQueueChunk lastChunk;
|
private IQueueChunk lastChunk;
|
||||||
private long lastPair = Long.MAX_VALUE;
|
private long lastPair = Long.MAX_VALUE;
|
||||||
|
|
||||||
private boolean enabledQueue = true;
|
private boolean enabledQueue = true;
|
||||||
|
|
||||||
private boolean fastmode = false;
|
private boolean fastmode = false;
|
||||||
|
// Array for lazy avoidance of concurrent modification exceptions and needless overcomplication of code (synchronisation is
|
||||||
|
// not very important)
|
||||||
|
private boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
|
||||||
|
private int lastException = Integer.MIN_VALUE;
|
||||||
|
private int exceptionCount = 0;
|
||||||
|
|
||||||
private final ReentrantLock getChunkLock = new ReentrantLock();
|
public SingleThreadQueueExtent() {
|
||||||
|
}
|
||||||
public SingleThreadQueueExtent() {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* New instance given inclusive world height bounds.
|
* New instance given inclusive world height bounds.
|
||||||
@ -114,13 +115,13 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFastMode(boolean fastmode) {
|
public boolean isFastMode() {
|
||||||
this.fastmode = fastmode;
|
return fastmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFastMode() {
|
public void setFastMode(boolean fastmode) {
|
||||||
return fastmode;
|
this.fastmode = fastmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -133,6 +134,18 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
return maxY;
|
return maxY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cached boolean array of length {@code FaweException.Type.values().length} that determines if a thrown
|
||||||
|
* {@link FaweException} of type {@link FaweException.Type} should be output to console, rethrown to attempt to be visible
|
||||||
|
* to the player, etc. Allows the same array to be used as widely as possible across the edit to avoid spam to console.
|
||||||
|
*
|
||||||
|
* @param faweExceptionReasonsUsed boolean array that should be cached where this method is called from of length {@code
|
||||||
|
* FaweException.Type.values().length}
|
||||||
|
*/
|
||||||
|
public void setFaweExceptionArray(final boolean[] faweExceptionReasonsUsed) {
|
||||||
|
this.faweExceptionReasonsUsed = faweExceptionReasonsUsed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the queue.
|
* Resets the queue.
|
||||||
*/
|
*/
|
||||||
@ -372,41 +385,11 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
if (aggressive) {
|
if (aggressive) {
|
||||||
if (targetSize == 0) {
|
if (targetSize == 0) {
|
||||||
while (!submissions.isEmpty()) {
|
while (!submissions.isEmpty()) {
|
||||||
Future future = submissions.poll();
|
iterateSubmissions();
|
||||||
try {
|
|
||||||
while (future != null) {
|
|
||||||
future = (Future) future.get();
|
|
||||||
}
|
|
||||||
} catch (FaweException messageOnly) {
|
|
||||||
LOGGER.warn(messageOnly.getMessage());
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
if (e.getCause() instanceof FaweException) {
|
|
||||||
LOGGER.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage());
|
|
||||||
} else {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < overflow; i++) {
|
for (int i = 0; i < overflow; i++) {
|
||||||
Future first = submissions.poll();
|
iterateSubmissions();
|
||||||
try {
|
|
||||||
while (first != null) {
|
|
||||||
first = (Future) first.get();
|
|
||||||
}
|
|
||||||
} catch (FaweException messageOnly) {
|
|
||||||
LOGGER.warn(messageOnly.getMessage());
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
if (e.getCause() instanceof FaweException) {
|
|
||||||
LOGGER.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage());
|
|
||||||
} else {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < overflow; i++) {
|
for (int i = 0; i < overflow; i++) {
|
||||||
@ -416,19 +399,23 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
Future after = null;
|
Future after = null;
|
||||||
try {
|
try {
|
||||||
after = (Future) next.get();
|
after = (Future) next.get();
|
||||||
} catch (FaweException messageOnly) {
|
} catch (FaweException e) {
|
||||||
LOGGER.warn(messageOnly.getMessage());
|
Fawe.handleFaweException(faweExceptionReasonsUsed, e, LOGGER);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
if (e.getCause() instanceof FaweException) {
|
if (e.getCause() instanceof FaweException) {
|
||||||
LOGGER.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage());
|
Fawe.handleFaweException(faweExceptionReasonsUsed, (FaweException) e.getCause(), LOGGER);
|
||||||
} else {
|
} else {
|
||||||
e.printStackTrace();
|
String message = e.getMessage();
|
||||||
|
int hash = message.hashCode();
|
||||||
|
if (lastException != hash) {
|
||||||
|
lastException = hash;
|
||||||
|
exceptionCount = 0;
|
||||||
|
LOGGER.catching(e);
|
||||||
|
} else if (exceptionCount < Settings.IMP.QUEUE.PARALLEL_THREADS) {
|
||||||
|
exceptionCount++;
|
||||||
|
LOGGER.warn(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LOGGER.error(
|
|
||||||
"Please report this error on our issue tracker: https://github.com/IntellectualSites/FastAsyncWorldEdit/issues");
|
|
||||||
e.getCause().printStackTrace();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
} finally {
|
||||||
/*
|
/*
|
||||||
* If the execution failed, namely next.get() threw an exception,
|
* If the execution failed, namely next.get() threw an exception,
|
||||||
@ -446,6 +433,32 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void iterateSubmissions() {
|
||||||
|
Future first = submissions.poll();
|
||||||
|
try {
|
||||||
|
while (first != null) {
|
||||||
|
first = (Future) first.get();
|
||||||
|
}
|
||||||
|
} catch (FaweException e) {
|
||||||
|
Fawe.handleFaweException(faweExceptionReasonsUsed, e, LOGGER);
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
if (e.getCause() instanceof FaweException) {
|
||||||
|
Fawe.handleFaweException(faweExceptionReasonsUsed, (FaweException) e.getCause(), LOGGER);
|
||||||
|
} else {
|
||||||
|
String message = e.getMessage();
|
||||||
|
int hash = message.hashCode();
|
||||||
|
if (lastException != hash) {
|
||||||
|
lastException = hash;
|
||||||
|
exceptionCount = 0;
|
||||||
|
LOGGER.catching(e);
|
||||||
|
} else if (exceptionCount < Settings.IMP.QUEUE.PARALLEL_THREADS) {
|
||||||
|
exceptionCount++;
|
||||||
|
LOGGER.warn(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void flush() {
|
public synchronized void flush() {
|
||||||
if (!chunks.isEmpty()) {
|
if (!chunks.isEmpty()) {
|
||||||
|
@ -193,7 +193,7 @@ public class ClipboardCommands {
|
|||||||
.getZ() + 1));
|
.getZ() + 1));
|
||||||
FaweLimit limit = actor.getLimit();
|
FaweLimit limit = actor.getLimit();
|
||||||
if (volume >= limit.MAX_CHECKS) {
|
if (volume >= limit.MAX_CHECKS) {
|
||||||
throw new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.max.checks"));
|
throw FaweCache.MAX_CHECKS;
|
||||||
}
|
}
|
||||||
session.setClipboard(null);
|
session.setClipboard(null);
|
||||||
ReadOnlyClipboard lazyClipboard = ReadOnlyClipboard.of(region, !skipEntities, copyBiomes);
|
ReadOnlyClipboard lazyClipboard = ReadOnlyClipboard.of(region, !skipEntities, copyBiomes);
|
||||||
@ -558,7 +558,7 @@ public class ClipboardCommands {
|
|||||||
PasteEvent event = new PasteEvent(player, clipboard, uri, editSession, to);
|
PasteEvent event = new PasteEvent(player, clipboard, uri, editSession, to);
|
||||||
WorldEdit.getInstance().getEventBus().post(event);
|
WorldEdit.getInstance().getEventBus().post(event);
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
throw new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.manual"));
|
throw FaweCache.MANUAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
@ -601,18 +601,13 @@ public class GenerationCommands {
|
|||||||
int[] count = new int[1];
|
int[] count = new int[1];
|
||||||
final BufferedImage finalImage = image;
|
final BufferedImage finalImage = image;
|
||||||
RegionVisitor visitor = new RegionVisitor(region, pos -> {
|
RegionVisitor visitor = new RegionVisitor(region, pos -> {
|
||||||
try {
|
int x = pos.getBlockX() - pos1.getBlockX();
|
||||||
int x = pos.getBlockX() - pos1.getBlockX();
|
int z = pos.getBlockZ() - pos1.getBlockZ();
|
||||||
int z = pos.getBlockZ() - pos1.getBlockZ();
|
int color = finalImage.getRGB(x, z);
|
||||||
int color = finalImage.getRGB(x, z);
|
BlockType block = tu.getNearestBlock(color);
|
||||||
BlockType block = tu.getNearestBlock(color);
|
count[0]++;
|
||||||
count[0]++;
|
if (block != null) {
|
||||||
if (block != null) {
|
return editSession.setBlock(pos, block.getDefaultState());
|
||||||
return editSession.setBlock(pos, block.getDefaultState());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}, editSession);
|
}, editSession);
|
||||||
|
@ -774,19 +774,18 @@ public final class PlatformCommandManager {
|
|||||||
}
|
}
|
||||||
actor.printError(e.getRichMessage());
|
actor.printError(e.getRichMessage());
|
||||||
} catch (CommandExecutionException e) {
|
} catch (CommandExecutionException e) {
|
||||||
|
handleUnknownException(actor, e.getCause());
|
||||||
|
} catch (CommandException e) {
|
||||||
if (e.getCause() instanceof FaweException) {
|
if (e.getCause() instanceof FaweException) {
|
||||||
actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason", ((FaweException) e.getCause()).getComponent()));
|
actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason", ((FaweException) e.getCause()).getComponent()));
|
||||||
} else {
|
} else {
|
||||||
handleUnknownException(actor, e.getCause());
|
Component msg = e.getRichMessage();
|
||||||
}
|
if (msg != TextComponent.empty()) {
|
||||||
} catch (CommandException e) {
|
List<String> argList = parseArgs(event.getArguments())
|
||||||
Component msg = e.getRichMessage();
|
.map(Substring::getSubstring)
|
||||||
if (msg != TextComponent.empty()) {
|
.collect(Collectors.toList());
|
||||||
actor.print(TextComponent.builder("")
|
printUsage(actor, argList);
|
||||||
.append(e.getRichMessage())
|
}
|
||||||
.build());
|
|
||||||
List<String> argList = parseArgs(event.getArguments()).map(Substring::getSubstring).collect(Collectors.toList());
|
|
||||||
printUsage(actor, argList);
|
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
handleUnknownException(actor, t);
|
handleUnknownException(actor, t);
|
||||||
|
@ -273,10 +273,9 @@ public interface Clipboard extends Extent, Iterable<BlockVector3>, Closeable {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Operations.completeLegacy(copy);
|
Operations.completeLegacy(copy);
|
||||||
} catch (MaxChangedBlocksException e) {
|
} finally {
|
||||||
e.printStackTrace();
|
editSession.close(); // Make sure editsession is always closed
|
||||||
}
|
}
|
||||||
editSession.flushQueue();
|
|
||||||
return editSession;
|
return editSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
package com.sk89q.worldedit.internal.command.exception;
|
package com.sk89q.worldedit.internal.command.exception;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.sk89q.worldedit.DisallowedItemException;
|
import com.sk89q.worldedit.DisallowedItemException;
|
||||||
import com.sk89q.worldedit.EmptyClipboardException;
|
import com.sk89q.worldedit.EmptyClipboardException;
|
||||||
@ -197,4 +198,11 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@ExceptionMatch
|
||||||
|
public void convert(FaweException e) throws CommandException {
|
||||||
|
throw newCommandException(e.getComponent(), e);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren