Fix limits / add cancellation messages

This commit is contained in:
Jesse Boyd 2016-04-21 04:22:47 +10:00
parent c1acacc208
commit de08ef85d7
14 changed files with 268 additions and 243 deletions

View File

@ -310,4 +310,9 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
fp.loadSessionFromDisk(fp.getWorld());
}
}
@Override
public String getPlatform() {
return "bukkit";
}
}

View File

@ -240,14 +240,52 @@ public class Fawe {
try {
CommandManager.inject();
} catch (Throwable e) {
debug("====== UPDATE WORLDEDIT TO 6.1.1 ======");
e.printStackTrace();
IMP.debug("Incompatible version of WorldEdit, please update the plugin or contact the Author!");
debug("=======================================");
debug("Update the plugin, or contact the Author!");
if (IMP.getPlatform().equals("bukkit")) {
debug(" - http://builds.enginehub.org/job/worldedit?branch=master");
} else {
debug(" - http://builds.enginehub.org/job/worldedit?branch=forge-archive%2F1.8.9 (FORGE)");
debug(" - https://ci.minecrell.net/job/worldedit-spongevanilla/ (SV)");
}
debug("=======================================");
}
try {
Native.load();
String arch = System.getenv("PROCESSOR_ARCHITECTURE");
String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432");
boolean x86OS = arch.endsWith("64") || wow64Arch != null && wow64Arch.endsWith("64") ? false : true;
boolean x86JVM = System.getProperty("sun.arch.data.model").equals("32");
if (x86OS != x86JVM) {
debug("====== UPGRADE TO 64-BIT JAVA ======");
debug("You are running 32-bit Java on a 64-bit machine");
debug(" - This is a recommendation");
debug("====================================");
}
} catch (Throwable e) {
debug("====== LZ4 COMPRESSION BINDING NOT FOUND ======");
e.printStackTrace();
debug("===============================================");
debug("FAWE will still work, but some things may be slower");
debug(" - Try updating your JVM / OS");
debug(" - Report this issue if you cannot resolve it");
debug("===============================================");
}
if (getJavaVersion() < 1.8) {
debug("====== UPGRADE TO JAVA 8 ======");
debug("You are running " + System.getProperty("java.version"));
debug(" - This is a recommendation");
debug("====================================");
}
}
static double getJavaVersion () {
String version = System.getProperty("java.version");
int pos = version.indexOf('.');
pos = version.indexOf('.', pos+1);
return Double.parseDouble (version.substring (0, pos));
}
private void setupMemoryListener() {

View File

@ -37,4 +37,6 @@ public interface IFawe {
public void startMetrics();
public Set<FawePlayer> getPlayers();
public String getPlatform();
}

View File

@ -40,6 +40,16 @@ public enum BBC {
WORLDEDIT_UNMASKED("&6Your WorldEdit is now unrestricted.", "Info"),
WORLDEDIT_RESTRICTED("&6Your WorldEdit is now restricted.", "Info"),
WORLDEDIT_OOM("&cYour WorldEdit action was cancelled due to low memory.", "Info"),
WORLDEDIT_CANCEL_REASON("&cYour WorldEdit action was cancelled:&7 %s0&c.", "Cancel"),
WORLDEDIT_CANCEL_REASON_LOW_MEMORY("Low memory", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_CHANGES("Too many blocks changed", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_CHECKS("Too many block checks", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_TILES("Too many blockstates", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_ENTITIES("Too many entities", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_ITERATIONS("Max iterations", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_FAILS("Outside allowed region", "Cancel"),
WORLDEDIT_OOM_ADMIN("&cPossible options:\n&8 - &7//fast\n&8 - &7Do smaller edits\n&8 - &7Allocate more memory\n&8 - &7Disable this safeguard", "Info"),
NOT_PLAYER("&cYou must be a player to perform this action!", "Error"),
COMPRESSED("History compressed. Saved ~ %s0b (%s1x smaller)", "Info"),

View File

@ -40,6 +40,12 @@ public class Settings {
public static FaweLimit getLimit(FawePlayer player) {
FaweLimit limit = new FaweLimit();
limit.MAX_CHANGES = 0;
limit.MAX_FAILS = 0;
limit.MAX_CHECKS = 0;
limit.MAX_ENTITIES = 0;
limit.MAX_BLOCKSTATES = 0;
limit.MAX_ITERATIONS = 0;
for (Entry<String, FaweLimit> entry : limits.entrySet()) {
String key = entry.getKey();
if (key.equals("default") || player.hasPermission("fawe.limit." + key)) {
@ -98,6 +104,7 @@ public class Settings {
for (String key : config.getConfigurationSection("limits").getKeys(false)) {
FaweLimit limit = new FaweLimit();
limit.load(config.getConfigurationSection("limits." + key), defaultLimit, false);
limits.put(key, limit);
}
for (final Entry<String, Object> node : options.entrySet()) {
if (!config.contains(node.getKey())) {

View File

@ -51,4 +51,9 @@ public class FaweLimit {
}
return changed;
}
@Override
public String toString() {
return MAX_CHANGES + "";
}
}

View File

@ -0,0 +1,27 @@
package com.boydti.fawe.object.exception;
import com.boydti.fawe.config.BBC;
public class FaweException extends RuntimeException {
private final String message;
public FaweException(BBC reason) {
this.message = reason.format();
}
@Override
public String getMessage() {
return message;
}
public static FaweException get(Throwable e) {
Throwable cause = e.getCause();
if (cause instanceof FaweException) {
return (FaweException) cause;
}
if (cause == null) {
return null;
}
return get(cause);
}
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.extent;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
@ -151,6 +152,10 @@ public class ProcessedWEExtent extends FaweExtent {
case 151:
case 178: {
if (limit.MAX_BLOCKSTATES-- < 0) {
if (this.parent != null) {
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
this.parent = null;
}
return false;
}
final int x = location.getBlockX();
@ -158,7 +163,7 @@ public class ProcessedWEExtent extends FaweExtent {
if (WEManager.IMP.maskContains(this.mask, x, z)) {
if (limit.MAX_CHANGES-- < 0) {
if (this.parent != null) {
WEManager.IMP.cancelEdit(this.parent);
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
this.parent = null;
}
return false;
@ -181,7 +186,7 @@ public class ProcessedWEExtent extends FaweExtent {
return true;
} else if (limit.MAX_FAILS-- < 0) {
if (this.parent != null) {
WEManager.IMP.cancelEdit(this.parent);
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.parent = null;
}
}
@ -192,8 +197,8 @@ public class ProcessedWEExtent extends FaweExtent {
final int y = location.getBlockY();
final int z = location.getBlockZ();
if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) {
if (limit.MAX_CHANGES--<0) {
WEManager.IMP.cancelEdit(this.parent);
if (limit.MAX_CHANGES -- <0) {
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
this.parent = null;
return false;
}
@ -288,7 +293,7 @@ public class ProcessedWEExtent extends FaweExtent {
}
} else if (limit.MAX_FAILS-- < 0) {
if (this.parent != null) {
WEManager.IMP.cancelEdit(this.parent);
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.parent = null;
}
}

View File

@ -29,7 +29,7 @@ public class SafeExtentWrapper extends AbstractDelegateExtent {
BBC.WORLDEDIT_OOM_ADMIN.send(this.player);
}
}
WEManager.IMP.cancelEdit(this);
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY);
return false;
}
return true;

View File

@ -5,9 +5,11 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.regions.FaweMask;
import com.boydti.fawe.regions.FaweMaskManager;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import java.lang.reflect.Field;
@ -20,7 +22,7 @@ public class WEManager {
public final ArrayDeque<FaweMaskManager> managers = new ArrayDeque<>();
public void cancelEdit(Extent parent) {
public void cancelEdit(Extent parent, BBC reason) throws WorldEditException {
try {
final Field field = AbstractDelegateExtent.class.getDeclaredField("extent");
field.setAccessible(true);
@ -28,6 +30,7 @@ public class WEManager {
} catch (final Exception e) {
e.printStackTrace();
}
throw new FaweException(reason);
}
public boolean maskContains(final HashSet<RegionWrapper> mask, final int x, final int z) {

View File

@ -32,6 +32,7 @@ import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.FastWorldEditExtent;
import com.boydti.fawe.object.extent.FaweExtent;
import com.boydti.fawe.object.extent.NullExtent;
@ -566,7 +567,7 @@ public class EditSession implements Extent {
public BaseBlock getLazyBlock(int x, int y, int z) {
if (limit != null && limit.MAX_CHECKS-- < 0) {
return nullBlock;
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
int combinedId4Data = queue.getCombinedId4Data(x, y, z);
if (!FaweCache.hasNBT(combinedId4Data >> 4)) {
@ -594,7 +595,7 @@ public class EditSession implements Extent {
@Deprecated
public int getBlockType(final Vector position) {
if (limit != null && limit.MAX_CHECKS-- < 0) {
return 0;
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
int combinedId4Data = queue.getCombinedId4Data(position.getBlockX(), position.getBlockY(), position.getBlockZ());
return combinedId4Data >> 4;
@ -610,7 +611,7 @@ public class EditSession implements Extent {
@Deprecated
public int getBlockData(final Vector position) {
if (limit != null && limit.MAX_CHECKS-- < 0) {
return 0;
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
int combinedId4Data = queue.getCombinedId4Data(position.getBlockX(), position.getBlockY(), position.getBlockZ());
return combinedId4Data & 0xF;
@ -866,15 +867,10 @@ public class EditSession implements Extent {
* Finish off the queue.
*/
public void flushQueue() {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
Operations.completeBlindly(EditSession.this.commit());
if (queue != null) {
queue.enqueue();
}
}
});
Operations.completeBlindly(EditSession.this.commit());
if (queue != null) {
queue.enqueue();
}
}
@Override
@ -962,35 +958,30 @@ public class EditSession implements Extent {
checkArgument(radius >= 0, "radius >= 0");
checkArgument(depth >= 1, "depth >= 1");
TaskManager.IMP.async(new Runnable() {
final MaskIntersection mask = new MaskIntersection(new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))), new BoundedHeightMask(Math.max(
(origin.getBlockY() - depth) + 1, 0), Math.min(EditSession.this.getWorld().getMaxY(), origin.getBlockY())), Masks.negate(new ExistingBlockMask(EditSession.this)));
// Want to replace blocks
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
// Pick how we're going to visit blocks
RecursiveVisitor visitor;
if (recursive) {
visitor = new RecursiveVisitor(mask, replace);
} else {
visitor = new DownwardVisitor(mask, replace, origin.getBlockY());
}
// Start at the origin
visitor.visit(origin);
// Execute
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
final MaskIntersection mask = new MaskIntersection(new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))), new BoundedHeightMask(Math.max(
(origin.getBlockY() - depth) + 1, 0), Math.min(EditSession.this.getWorld().getMaxY(), origin.getBlockY())), Masks.negate(new ExistingBlockMask(EditSession.this)));
// Want to replace blocks
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
// Pick how we're going to visit blocks
RecursiveVisitor visitor;
if (recursive) {
visitor = new RecursiveVisitor(mask, replace);
} else {
visitor = new DownwardVisitor(mask, replace, origin.getBlockY());
}
// Start at the origin
visitor.visit(origin);
// Execute
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1083,20 +1074,14 @@ public class EditSession implements Extent {
public int setBlocks(final Region region, final Pattern pattern) throws MaxChangedBlocksException {
checkNotNull(region);
checkNotNull(pattern);
TaskManager.IMP.async(new Runnable() {
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionVisitor visitor = new RegionVisitor(region, replace);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionVisitor visitor = new RegionVisitor(region, replace);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1146,21 +1131,15 @@ public class EditSession implements Extent {
checkNotNull(region);
checkNotNull(mask);
checkNotNull(pattern);
TaskManager.IMP.async(new Runnable() {
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionMaskingFilter filter = new RegionMaskingFilter(mask, replace);
final RegionVisitor visitor = new RegionVisitor(region, filter);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionMaskingFilter filter = new RegionMaskingFilter(mask, replace);
final RegionVisitor visitor = new RegionVisitor(region, filter);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1335,22 +1314,16 @@ public class EditSession implements Extent {
public int overlayCuboidBlocks(final Region region, final Pattern pattern) throws MaxChangedBlocksException {
checkNotNull(region);
checkNotNull(pattern);
TaskManager.IMP.async(new Runnable() {
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionOffset offset = new RegionOffset(new Vector(0, 1, 0), replace);
final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), offset);
final LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionOffset offset = new RegionOffset(new Vector(0, 1, 0), replace);
final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), offset);
final LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1364,22 +1337,15 @@ public class EditSession implements Extent {
*/
public int naturalizeCuboidBlocks(final Region region) throws MaxChangedBlocksException {
checkNotNull(region);
TaskManager.IMP.async(new Runnable() {
final Naturalizer naturalizer = new Naturalizer(EditSession.this);
final FlatRegion flatRegion = Regions.asFlatRegion(region);
final LayerVisitor visitor = new LayerVisitor(flatRegion, minimumBlockY(region), maximumBlockY(region), naturalizer);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
final Naturalizer naturalizer = new Naturalizer(EditSession.this);
final FlatRegion flatRegion = Regions.asFlatRegion(region);
final LayerVisitor visitor = new LayerVisitor(flatRegion, minimumBlockY(region), maximumBlockY(region), naturalizer);
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1397,26 +1363,20 @@ public class EditSession implements Extent {
checkNotNull(region);
checkNotNull(dir);
checkArgument(count >= 1, "count >= 1 required");
TaskManager.IMP.async(new Runnable() {
final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
final Vector to = region.getMinimumPoint();
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to);
copy.setRepetitions(count);
copy.setTransform(new AffineTransform().translate(dir.multiply(size)));
if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this));
}
Operations.completeSmart(copy, new Runnable() {
@Override
public void run() {
final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
final Vector to = region.getMinimumPoint();
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to);
copy.setRepetitions(count);
copy.setTransform(new AffineTransform().translate(dir.multiply(size)));
if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this));
}
Operations.completeSmart(copy, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1435,39 +1395,33 @@ public class EditSession implements Extent {
checkNotNull(region);
checkNotNull(dir);
checkArgument(distance >= 1, "distance >= 1 required");
final Vector to = region.getMinimumPoint();
TaskManager.IMP.async(new Runnable() {
// Remove the original blocks
final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? new BlockPattern(replacement) : new BlockPattern(new BaseBlock(BlockID.AIR));
final BlockReplace remove = new BlockReplace(EditSession.this, pattern);
// Copy to a buffer so we don't destroy our original before we can copy all the blocks from it
final ForgetfulExtentBuffer buffer = new ForgetfulExtentBuffer(EditSession.this, new RegionMask(region));
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, buffer, to);
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
copy.setSourceFunction(remove); // Remove
copy.setRemovingEntities(true);
if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this));
}
// Then we need to copy the buffer to the world
final BlockReplace replace = new BlockReplace(EditSession.this, buffer);
final RegionVisitor visitor = new RegionVisitor(buffer.asRegion(), replace);
final OperationQueue operation = new OperationQueue(copy, visitor);
Operations.completeSmart(operation, new Runnable() {
@Override
public void run() {
final Vector to = region.getMinimumPoint();
// Remove the original blocks
final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? new BlockPattern(replacement) : new BlockPattern(new BaseBlock(BlockID.AIR));
final BlockReplace remove = new BlockReplace(EditSession.this, pattern);
// Copy to a buffer so we don't destroy our original before we can copy all the blocks from it
final ForgetfulExtentBuffer buffer = new ForgetfulExtentBuffer(EditSession.this, new RegionMask(region));
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, buffer, to);
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
copy.setSourceFunction(remove); // Remove
copy.setRemovingEntities(true);
if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this));
}
// Then we need to copy the buffer to the world
final BlockReplace replace = new BlockReplace(EditSession.this, buffer);
final RegionVisitor visitor = new RegionVisitor(buffer.asRegion(), replace);
final OperationQueue operation = new OperationQueue(copy, visitor);
Operations.completeSmart(operation, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1497,31 +1451,25 @@ public class EditSession implements Extent {
public int drainArea(final Vector origin, final double radius) throws MaxChangedBlocksException {
checkNotNull(origin);
checkArgument(radius >= 0, "radius >= 0 required");
final MaskIntersection mask = new MaskIntersection(new BoundedHeightMask(0, EditSession.this.getWorld().getMaxY()), new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius,
radius, radius))), EditSession.this.getWorld().createLiquidMask());
TaskManager.IMP.async(new Runnable() {
final BlockReplace replace = new BlockReplace(EditSession.this, new BlockPattern(new BaseBlock(BlockID.AIR)));
final RecursiveVisitor visitor = new RecursiveVisitor(mask, replace);
// Around the origin in a 3x3 block
for (final BlockVector position : CuboidRegion.fromCenter(origin, 1)) {
if (mask.test(position)) {
visitor.visit(position);
}
}
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
final MaskIntersection mask = new MaskIntersection(new BoundedHeightMask(0, EditSession.this.getWorld().getMaxY()), new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius,
radius, radius))), EditSession.this.getWorld().createLiquidMask());
final BlockReplace replace = new BlockReplace(EditSession.this, new BlockPattern(new BaseBlock(BlockID.AIR)));
final RecursiveVisitor visitor = new RecursiveVisitor(mask, replace);
// Around the origin in a 3x3 block
for (final BlockVector position : CuboidRegion.fromCenter(origin, 1)) {
if (mask.test(position)) {
visitor.visit(position);
}
}
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -1538,39 +1486,32 @@ public class EditSession implements Extent {
public int fixLiquid(final Vector origin, final double radius, final int moving, final int stationary) throws MaxChangedBlocksException {
checkNotNull(origin);
checkArgument(radius >= 0, "radius >= 0 required");
// Our origins can only be liquids
final BlockMask liquidMask = new BlockMask(EditSession.this, new BaseBlock(moving, -1), new BaseBlock(stationary, -1));
TaskManager.IMP.async(new Runnable() {
// But we will also visit air blocks
final MaskIntersection blockMask = new MaskUnion(liquidMask, new BlockMask(EditSession.this, new BaseBlock(BlockID.AIR)));
// There are boundaries that the routine needs to stay in
final MaskIntersection mask = new MaskIntersection(new BoundedHeightMask(0, Math.min(origin.getBlockY(), EditSession.this.getWorld().getMaxY())), new RegionMask(new EllipsoidRegion(
null, origin, new Vector(radius, radius, radius))), blockMask);
final BlockReplace replace = new BlockReplace(EditSession.this, new BlockPattern(new BaseBlock(stationary)));
final NonRisingVisitor visitor = new NonRisingVisitor(mask, replace);
// Around the origin in a 3x3 block
for (final BlockVector position : CuboidRegion.fromCenter(origin, 1)) {
if (liquidMask.test(position)) {
visitor.visit(position);
}
}
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
// Our origins can only be liquids
final BlockMask liquidMask = new BlockMask(EditSession.this, new BaseBlock(moving, -1), new BaseBlock(stationary, -1));
// But we will also visit air blocks
final MaskIntersection blockMask = new MaskUnion(liquidMask, new BlockMask(EditSession.this, new BaseBlock(BlockID.AIR)));
// There are boundaries that the routine needs to stay in
final MaskIntersection mask = new MaskIntersection(new BoundedHeightMask(0, Math.min(origin.getBlockY(), EditSession.this.getWorld().getMaxY())), new RegionMask(new EllipsoidRegion(
null, origin, new Vector(radius, radius, radius))), blockMask);
final BlockReplace replace = new BlockReplace(EditSession.this, new BlockPattern(new BaseBlock(stationary)));
final NonRisingVisitor visitor = new NonRisingVisitor(mask, replace);
// Around the origin in a 3x3 block
for (final BlockVector position : CuboidRegion.fromCenter(origin, 1)) {
if (liquidMask.test(position)) {
visitor.visit(position);
}
}
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}
@ -2020,30 +1961,24 @@ public class EditSession implements Extent {
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int makePumpkinPatches(final Vector position, final int apothem) throws MaxChangedBlocksException {
// We want to generate pumpkins
final GardenPatchGenerator generator = new GardenPatchGenerator(EditSession.this);
generator.setPlant(GardenPatchGenerator.getPumpkinPattern());
TaskManager.IMP.async(new Runnable() {
// In a region of the given radius
final FlatRegion region = new CuboidRegion(EditSession.this.getWorld(), // Causes clamping of Y range
position.add(-apothem, -5, -apothem), position.add(apothem, 10, apothem));
final double density = 0.02;
final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), generator);
final LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
// We want to generate pumpkins
final GardenPatchGenerator generator = new GardenPatchGenerator(EditSession.this);
generator.setPlant(GardenPatchGenerator.getPumpkinPattern());
// In a region of the given radius
final FlatRegion region = new CuboidRegion(EditSession.this.getWorld(), // Causes clamping of Y range
position.add(-apothem, -5, -apothem), position.add(apothem, 10, apothem));
final double density = 0.02;
final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), generator);
final LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeSmart(visitor, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
EditSession.this.flushQueue();
}
});
}, true);
return this.changes = -1;
}

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extension.platform;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.PlayerWrapper;
@ -279,10 +280,15 @@ public final class CommandManager {
actor.printError("Usage: " + e.getSimpleUsageString("/"));
}
} catch (WrappedCommandException e) {
Throwable t = e.getCause();
actor.printError("Please report this error: [See console]");
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
log.log(Level.SEVERE, "An unexpected error while handling a WorldEdit command", t);
FaweException faweException = FaweException.get(e);
if (faweException != null) {
actor.printError(BBC.PREFIX.s() + " " + BBC.WORLDEDIT_CANCEL_REASON.format(faweException.getMessage()));
} else {
Throwable t = e.getCause();
actor.printError("Please report this error: [See console]");
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
log.log(Level.SEVERE, "An unexpected error while handling a WorldEdit command", t);
}
} catch (CommandException e) {
String message = e.getMessage();
if (message != null) {

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.function.operation;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
@ -72,38 +70,17 @@ public final class Operations {
while (operation != null) {
operation = operation.resume(new RunContext());
}
} catch (final Exception e) {
e.printStackTrace();
} catch (WorldEditException e) {
throw new RuntimeException(e);
}
}
public static void completeSmart(final Operation op, final Runnable whenDone, final boolean threadsafe) {
if (!threadsafe) {
completeBlindly(op);
if (whenDone != null) {
whenDone.run();
}
return;
completeBlindly(op);
if (whenDone != null) {
whenDone.run();
}
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
Operation operation = op;
while (operation != null) {
try {
operation = operation.resume(new RunContext());
} catch (final Exception e) {
e.printStackTrace();
}
}
TaskManager.IMP.task(whenDone);
}
});
};
});
return;
}
public static Class<?> inject() {

View File

@ -144,4 +144,9 @@ public class FaweSponge implements IFawe {
}
return players;
}
@Override
public String getPlatform() {
return "sponge";
}
}