Fixes #89
brush fixes
optimizations
restructure
etc
This commit is contained in:
Jesse Boyd 2016-05-02 12:04:28 +10:00
parent ea6840535a
commit 9f0602f2ec
25 changed files with 400 additions and 406 deletions

View File

@ -1,8 +1,11 @@
package com.boydti.fawe.bukkit.logging; package com.boydti.fawe.bukkit.logging;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.util.FaweQueue;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import org.PrimeSoft.blocksHub.BlocksHub; import org.PrimeSoft.blocksHub.BlocksHub;
import org.PrimeSoft.blocksHub.IBlocksHubApi; import org.PrimeSoft.blocksHub.IBlocksHubApi;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -17,7 +20,7 @@ public class BlocksHubHook {
this.api = this.hub.getApi(); this.api = this.hub.getApi();
} }
public Extent getLoggingExtent(final Extent parent, final ChangeSet set, final FawePlayer<?> player) { public FaweChangeSet getLoggingChangeSet(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer<?> player) {
return new LoggingExtent(parent, set, (FawePlayer<Player>) player, this.api); return new LoggingChangeSet((FawePlayer<Player>) player, set, api);
} }
} }

View File

@ -0,0 +1,86 @@
package com.boydti.fawe.bukkit.logging;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.history.change.Change;
import java.util.Iterator;
import org.PrimeSoft.blocksHub.IBlocksHubApi;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
public class LoggingChangeSet implements FaweChangeSet {
private final FaweChangeSet parent;
private final IBlocksHubApi api;
private final World world;
private final Location loc;
private final String name;
public LoggingChangeSet(FawePlayer<Player> player, FaweChangeSet parent, IBlocksHubApi api) {
this.parent = parent;
this.name = player.getName();
this.api = api;
this.world = player.parent.getWorld();
this.loc = new Location(world, 0, 0, 0);
}
@Override
public boolean flush() {
return parent.flush();
}
@Override
public int getCompressedSize() {
return parent.getCompressedSize();
}
@Override
public void add(Vector location, BaseBlock from, BaseBlock to) {
loc.setX(location.getX());
loc.setY(location.getY());
loc.setZ(location.getZ());
api.logBlock(name, world, loc, from.getId(), (byte) from.getData(), to.getId(), (byte) to.getData());
parent.add(location, from, to);
}
@Override
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {
loc.setX(x);
loc.setY(y);
loc.setZ(z);
api.logBlock(name, world, loc, combinedId4DataFrom >> 4, (byte) (combinedId4DataFrom & 0xF), to.getId(), (byte) to.getData());
parent.add(x, y, z, combinedId4DataFrom, to);
}
@Override
public void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo) {
loc.setX(x);
loc.setY(y);
loc.setZ(z);
api.logBlock(name, world, loc, combinedId4DataFrom >> 4, (byte) (combinedId4DataFrom & 0xF), combinedId4DataTo >> 4, (byte) (combinedId4DataTo & 0xF));
parent.add(x, y, z, combinedId4DataFrom, combinedId4DataTo);
}
@Override
public void add(Change change) {
parent.add(change);
}
@Override
public Iterator<Change> backwardIterator() {
return parent.backwardIterator();
}
@Override
public Iterator<Change> forwardIterator() {
return parent.forwardIterator();
}
@Override
public int size() {
return parent.size();
}
}

View File

@ -24,10 +24,10 @@ public class BukkitEditSessionWrapper_0 extends EditSessionWrapper {
@Override @Override
public Extent getHistoryExtent(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer<?> player) { public Extent getHistoryExtent(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer<?> player) {
if (this.hook != null) { if (this.hook != null) {
// If we are doing logging, return a custom logging extent // If we are doing logging, use a custom logging ChangeSet
return this.hook.getLoggingExtent(parent, set, player); set = hook.getLoggingChangeSet(session, limit, parent, set, queue, player);
} }
// Otherwise return the normal history extent // Now return the normal history extent
return super.getHistoryExtent(session, limit, parent, set, queue, player); return super.getHistoryExtent(session, limit, parent, set, queue, player);
} }
} }

View File

@ -79,7 +79,7 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
ChunkListener.physicsFreeze = false; ChunkListener.physicsFreeze = false;
if (parallel) { if (parallel) {
try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled); try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled);
} catch (Throwable ignore) {ignore.printStackTrace();} } catch (Throwable ignore) {}
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {} try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {}
} }
} }

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v1_9;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.FaweQueue;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import net.minecraft.server.v1_9_R1.Block; import net.minecraft.server.v1_9_R1.Block;
import net.minecraft.server.v1_9_R1.DataBits; import net.minecraft.server.v1_9_R1.DataBits;
@ -96,7 +97,17 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
if (sectionPalettes == null) { if (sectionPalettes == null) {
sectionPalettes = new DataPaletteBlock[16]; sectionPalettes = new DataPaletteBlock[16];
} }
DataPaletteBlock palette = sectionPalettes[layer] = new DataPaletteBlock(); DataPaletteBlock palette;
try {
palette = sectionPalettes[layer] = new DataPaletteBlock();
} catch (Throwable e) {
try {
Constructor<DataPaletteBlock> constructor = DataPaletteBlock.class.getDeclaredConstructor(IBlockData[].class);
palette = sectionPalettes[layer] = constructor.newInstance(null);
} catch (Throwable e2) {
throw new RuntimeException(e2);
}
}
char[] blocks = getIdArray(layer); char[] blocks = getIdArray(layer);
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {

View File

@ -10,6 +10,7 @@ import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -224,6 +225,28 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
fieldSection.set(section, palette); fieldSection.set(section, palette);
} }
public ChunkSection newChunkSection(int y2, boolean flag, char[] array) {
try {
if (array == null) {
return new ChunkSection(y2, flag);
} else {
return new ChunkSection(y2, flag, array);
}
} catch (Throwable e) {
try {
if (array == null) {
Constructor<ChunkSection> constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, IBlockData[].class);
return constructor.newInstance(y2, flag, null);
} else {
Constructor<ChunkSection> constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, char[].class, IBlockData[].class);
return constructor.newInstance(y2, flag, array, null);
}
} catch (Throwable e2) {
throw new RuntimeException(e2);
}
}
}
@Override @Override
public boolean setComponents(final FaweChunk pc) { public boolean setComponents(final FaweChunk pc) {
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc; final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;
@ -268,9 +291,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
} }
} }
} }
if (removed) {
w.tileEntityListTick.clear();
}
// Trim entities // Trim entities
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {

View File

@ -336,6 +336,9 @@ public class Fawe {
} }
private void setupMemoryListener() { private void setupMemoryListener() {
if (Settings.MEM_FREE < 1) {
return;
}
final MemoryMXBean memBean = ManagementFactory.getMemoryMXBean(); final MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
final NotificationEmitter ne = (NotificationEmitter) memBean; final NotificationEmitter ne = (NotificationEmitter) memBean;

View File

@ -3,14 +3,10 @@ package com.boydti.fawe.command;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.extent.FaweExtent;
import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.WEManager;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.world.World;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -37,21 +33,8 @@ public class Cancel extends FaweCommand {
continue; continue;
} }
if (uuid.equals(actor.getUniqueId())) { if (uuid.equals(actor.getUniqueId())) {
// Cancel this if (session.cancel()) {
FaweExtent fe = session.getFaweExtent();
if (fe != null) {
cancelled++; cancelled++;
try {
WEManager.IMP.cancelEdit(fe, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
} catch (Throwable ignore) {}
World world = session.getWorld();
NullExtent nullExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
session.bypassHistory = nullExtent;
session.bypassNone = nullExtent;
session.bypassReorderHistory = nullExtent;
session.faweExtent = nullExtent;
queue.clear();
SetQueue.IMP.dequeue(queue);
} }
} }
} }

View File

@ -92,14 +92,14 @@ public class Settings {
options.put("history.use-disk", STORE_HISTORY_ON_DISK); options.put("history.use-disk", STORE_HISTORY_ON_DISK);
options.put("history.compress", false); options.put("history.compress", false);
options.put("history.chunk-wait-ms", CHUNK_WAIT); options.put("history.chunk-wait-ms", CHUNK_WAIT);
options.put("history.buffer-size", BUFFER_SIZE); // options.put("history.buffer-size", BUFFER_SIZE);
options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS); options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS);
options.put("region-restrictions", REGION_RESTRICTIONS); options.put("region-restrictions", REGION_RESTRICTIONS);
options.put("queue.parallel-threads", UNSAFE_PARALLEL_THREADS); options.put("queue.parallel-threads", UNSAFE_PARALLEL_THREADS);
options.put("queue.extra-time-ms", ALLOCATE); options.put("queue.extra-time-ms", ALLOCATE);
options.put("queue.target-size", QUEUE_SIZE); options.put("queue.target-size", QUEUE_SIZE);
options.put("queue.max-wait-ms", QUEUE_MAX_WAIT); options.put("queue.max-wait-ms", QUEUE_MAX_WAIT);
options.put("queue.discard-after-ms", QUEUE_DISCARD_AFTER); // options.put("queue.discard-after-ms", QUEUE_DISCARD_AFTER);
options.put("extent.allowed-plugins", new ArrayList<String>()); options.put("extent.allowed-plugins", new ArrayList<String>());
options.put("extent.debug", EXTENT_DEBUG); options.put("extent.debug", EXTENT_DEBUG);
options.put("metrics", METRICS); options.put("metrics", METRICS);
@ -140,7 +140,7 @@ public class Settings {
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");
UNSAFE_PARALLEL_THREADS = config.getInt("queue.parallel-threads"); UNSAFE_PARALLEL_THREADS = config.getInt("queue.parallel-threads");
QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms"); QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms", QUEUE_DISCARD_AFTER);
ALLOWED_3RDPARTY_EXTENTS = config.getStringList("extent.allowed-plugins"); ALLOWED_3RDPARTY_EXTENTS = config.getStringList("extent.allowed-plugins");
EXTENT_DEBUG = config.getBoolean("extent.debug"); EXTENT_DEBUG = config.getBoolean("extent.debug");
STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk"); STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk");

View File

@ -50,7 +50,6 @@ public class HistoryExtent extends AbstractDelegateExtent {
@Override @Override
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
if (super.setBlock(location, block)) {
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
@ -78,9 +77,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
this.changeSet.add(x, y, z, combined, block); this.changeSet.add(x, y, z, combined, block);
} }
} }
return true; return super.setBlock(location, block);
}
return false;
} }
@Nullable @Nullable

View File

@ -8,8 +8,12 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.Raster; import java.awt.image.Raster;
import java.io.File; import java.io.File;
@ -21,12 +25,33 @@ public class HeightBrush implements Brush {
public final HeightMap heightMap; public final HeightMap heightMap;
private final int rotation; private final int rotation;
double yscale = 1; double yscale = 1;
private final BrushTool tool;
public HeightBrush(File file, int rotation, double yscale) { public HeightBrush(File file, int rotation, double yscale, BrushTool tool, EditSession session, CuboidRegion selection) {
this.tool = tool;
this.rotation = (rotation / 90) % 4; this.rotation = (rotation / 90) % 4;
this.yscale = yscale; this.yscale = yscale;
if (file == null || !file.exists()) { if (file == null || !file.exists()) {
if (file.getName().equalsIgnoreCase("#selection.png") && selection != null) {
byte[][] heightArray = new byte[selection.getWidth()][selection.getLength()];
int minX = selection.getMinimumPoint().getBlockX();
int minZ = selection.getMinimumPoint().getBlockZ();
int minY = selection.getMinimumY() - 1;
int maxY = selection.getMaximumY() + 1;
int selHeight = selection.getHeight();
for (Vector pos : selection) {
int xx = pos.getBlockX();
int zz = pos.getBlockZ();
int worldPointHeight = session.getHighestTerrainBlock(xx, zz, minY, maxY);
int pointHeight = (256 * (worldPointHeight - minY)) / selHeight;
int x = xx - minX;
int z = zz - minZ;
heightArray[x][z] = (byte) pointHeight;
}
heightMap = new ArrayHeightMap(heightArray);
} else {
heightMap = new HeightMap(); heightMap = new HeightMap();
}
} else { } else {
try { try {
BufferedImage heightFile = ImageIO.read(file); BufferedImage heightFile = ImageIO.read(file);
@ -53,10 +78,12 @@ public class HeightBrush implements Brush {
@Override @Override
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
Mask mask = tool.getMask();
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null;
}
int size = (int) sizeDouble; int size = (int) sizeDouble;
heightMap.setSize(size); heightMap.setSize(size);
int size2 = size * size; int size2 = size * size;
int startY = position.getBlockY() + size; int startY = position.getBlockY() + size;
int endY = position.getBlockY() - size; int endY = position.getBlockY() - size;
@ -65,6 +92,7 @@ public class HeightBrush implements Brush {
Vector mutablePos = new Vector(0, 0, 0); Vector mutablePos = new Vector(0, 0, 0);
for (int x = -size; x <= size; x++) { for (int x = -size; x <= size; x++) {
int xx = cx + x; int xx = cx + x;
mutablePos.x = xx;
for (int z = -size; z <= size; z++) { for (int z = -size; z <= size; z++) {
int zz = cz + z; int zz = cz + z;
int raise; int raise;
@ -86,11 +114,18 @@ public class HeightBrush implements Brush {
if (raise == 0) { if (raise == 0) {
continue; continue;
} }
mutablePos.z = zz;
int foundHeight = Integer.MAX_VALUE; int foundHeight = Integer.MAX_VALUE;
BaseBlock block = null; BaseBlock block = null;
for (int y = startY; y >= endY; y--) { for (int y = startY; y >= endY; y--) {
block = editSession.getLazyBlock(xx, y, zz); block = editSession.getLazyBlock(xx, y, zz);
if (block != EditSession.nullBlock) { if (block != EditSession.nullBlock) {
if (mask != null) {
mutablePos.y = y;
if (!mask.test(mutablePos)) {
continue;
}
}
foundHeight = y; foundHeight = y;
break; break;
} }
@ -98,10 +133,17 @@ public class HeightBrush implements Brush {
if (foundHeight == Integer.MAX_VALUE) { if (foundHeight == Integer.MAX_VALUE) {
continue; continue;
} }
if (raise > 0) {
for (int y = foundHeight + 1; y <= foundHeight + raise; y++) { for (int y = foundHeight + 1; y <= foundHeight + raise; y++) {
mutablePos.x = xx;
mutablePos.y = y; mutablePos.y = y;
mutablePos.z = zz; editSession.setBlock(mutablePos, block);
}
} else {
for (int y = foundHeight; y > foundHeight + raise; y--) {
mutablePos.y = y;
editSession.setBlock(mutablePos, EditSession.nullBlock);
}
mutablePos.y = foundHeight + raise;
editSession.setBlock(mutablePos, block); editSession.setBlock(mutablePos, block);
} }
} }

View File

@ -152,6 +152,7 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory(); EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
EditSession edit = factory.getEditSession(world, -1, null, player); EditSession edit = factory.getEditSession(world, -1, null, player);
edit.setChangeSet(this); edit.setChangeSet(this);
edit.dequeue();
return edit; return edit;
} }

View File

@ -12,13 +12,14 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
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 com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.List; import java.util.List;
public class FastWorldEditExtent extends FaweExtent { public class FastWorldEditExtent extends AbstractDelegateExtent {
private final FaweQueue queue; private final FaweQueue queue;
@ -228,9 +229,4 @@ public class FastWorldEditExtent extends FaweExtent {
} }
} }
} }
@Override
public boolean contains(int x, int y, int z) {
return true;
}
} }

View File

@ -3,14 +3,13 @@ package com.boydti.fawe.object.extent;
import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
public abstract class FaweExtent extends AbstractDelegateExtent { public abstract class FaweRegionExtent extends AbstractDelegateExtent {
/** /**
* Create a new instance. * Create a new instance.
* *
* @param extent the extent * @param extent the extent
*/ */
protected FaweExtent(Extent extent) { public FaweRegionExtent(Extent extent) {
super(extent); super(extent);
} }

View File

@ -11,10 +11,10 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
public class SafeExtentWrapper extends AbstractDelegateExtent { public class MemoryCheckingExtent extends AbstractDelegateExtent {
private final FawePlayer<?> player; private final FawePlayer<?> player;
public SafeExtentWrapper(final FawePlayer<?> player, final Extent extent) { public MemoryCheckingExtent(final FawePlayer<?> player, final Extent extent) {
super(extent); super(extent);
this.player = player; this.player = player;
} }

View File

@ -15,18 +15,16 @@ import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
public class NullExtent extends FaweExtent { public class NullExtent implements Extent {
private final BBC reason; private final BBC reason;
/** /**
* Create a new instance. * Create a new instance.
*
* @param extent the extent
*/ */
public NullExtent(Extent extent, BBC failReason) { public NullExtent(BBC failReason) {
super(extent);
this.reason = failReason; this.reason = failReason;
} }
@ -50,6 +48,12 @@ public class NullExtent extends FaweExtent {
throw new FaweException(reason); throw new FaweException(reason);
} }
@Nullable
@Override
public Operation commit() {
return null;
}
@Override @Override
public boolean setBlock(final Vector arg0, final BaseBlock arg1) throws WorldEditException { public boolean setBlock(final Vector arg0, final BaseBlock arg1) throws WorldEditException {
throw new FaweException(reason); throw new FaweException(reason);
@ -79,17 +83,4 @@ public class NullExtent extends FaweExtent {
public Vector getMinimumPoint() { public Vector getMinimumPoint() {
return new Vector(0, 0, 0); return new Vector(0, 0, 0);
} }
@Override
public boolean contains(int x, int y, int z) { return false; }
@Override
protected Operation commitBefore() {
return null;
}
@Override
public Extent getExtent() {
return this;
}
} }

View File

@ -3,14 +3,9 @@ package com.boydti.fawe.object.extent;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.WEManager; import com.boydti.fawe.util.WEManager;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
@ -20,52 +15,30 @@ import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
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 com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
public class ProcessedWEExtent extends FaweExtent { public class ProcessedWEExtent extends FaweRegionExtent {
private final FaweQueue queue;
private final FaweLimit limit; private final FaweLimit limit;
private Extent parent; private final RegionWrapper[] mask;
private final FawePlayer<?> user; public ProcessedWEExtent(final Extent parent, final HashSet<RegionWrapper> mask, FaweLimit limit) {
private final HashSet<RegionWrapper> mask; super(parent);
this.mask = mask.toArray(new RegionWrapper[mask.size()]);
public ProcessedWEExtent(final World world, final FawePlayer<?> player, final HashSet<RegionWrapper> mask, FaweLimit limit, FaweQueue queue) {
super(world);
this.user = player;
this.queue = queue;
this.mask = mask;
this.limit = limit; this.limit = limit;
} }
public void setParent(final Extent parent) {
this.parent = parent;
}
@Override @Override
public Entity createEntity(final Location location, final BaseEntity entity) { public Entity createEntity(final Location location, final BaseEntity entity) {
if (limit.MAX_ENTITIES-- < 0 || entity == null) { if (limit.MAX_ENTITIES-- < 0 || entity == null) {
return null; return null;
} }
if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) { return super.createEntity(location, entity);
TaskManager.IMP.task(new Runnable() {
@Override
public void run() {
ProcessedWEExtent.super.createEntity(location, entity);
}
});
}
return null;
} }
@Override @Override
public BaseBiome getBiome(final Vector2D position) { public BaseBiome getBiome(final Vector2D position) {
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
return EditSession.nullBiome;
}
return super.getBiome(position); return super.getBiome(position);
} }
@ -74,21 +47,6 @@ public class ProcessedWEExtent extends FaweExtent {
@Override @Override
public BaseBlock getLazyBlock(final Vector position) { public BaseBlock getLazyBlock(final Vector position) {
// TODO get fast!
// TODO caches base blocks
if ((this.lastBlock != null) && this.lastVector.equals(position.toBlockVector())) {
return this.lastBlock;
}
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
try {
this.lastVector = position.toBlockVector();
return this.lastBlock = super.getBlock(position);
} catch (final Throwable e) {
return EditSession.nullBlock;
}
}
this.lastVector = position.toBlockVector();
return super.getLazyBlock(position); return super.getLazyBlock(position);
} }
@ -109,200 +67,27 @@ public class ProcessedWEExtent extends FaweExtent {
@Override @Override
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
final short id = (short) block.getType(); if (block.hasNbtData() && FaweCache.hasNBT(block.getType())) {
boolean nbt = true;
switch (id) {
case 63:
case 68:
if (block.hasNbtData() && !MainUtil.isValidSign(block.getNbtData())) {
nbt = false;
}
case 54:
case 130:
case 142:
case 27:
case 137:
case 52:
case 154:
case 84:
case 25:
case 144:
case 138:
case 176:
case 177:
case 119:
case 323:
case 117:
case 116:
case 28:
case 66:
case 157:
case 61:
case 62:
case 140:
case 146:
case 149:
case 150:
case 158:
case 23:
case 123:
case 124:
case 29:
case 33:
case 151:
case 178: {
if (limit.MAX_BLOCKSTATES-- < 0) { if (limit.MAX_BLOCKSTATES-- < 0) {
if (this.parent != null) { WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
this.parent = null;
}
return false; return false;
} }
final int x = location.getBlockX(); }
final int z = location.getBlockZ(); if (WEManager.IMP.maskContains(this.mask, (int) location.x, (int) location.z)) {
if (WEManager.IMP.maskContains(this.mask, x, z)) {
if (limit.MAX_CHANGES-- < 0) { if (limit.MAX_CHANGES-- < 0) {
if (this.parent != null) { WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
this.parent = null;
}
return false; return false;
} }
if (block.hasNbtData() && nbt) { return super.setBlock(location, block);
final Vector loc = new Vector(location.x, location.y, location.z);
queue.addTask(x >> 4, z >> 4, new Runnable() {
@Override
public void run() {
try {
ProcessedWEExtent.super.setBlock(loc, block);
} catch (WorldEditException e) {
e.printStackTrace();
}
}
});
return true;
}
queue.setBlock(x, location.getBlockY(), z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
return true;
} else if (limit.MAX_FAILS-- < 0) { } else if (limit.MAX_FAILS-- < 0) {
if (this.parent != null) { WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.parent = null;
}
} }
return false; return false;
} }
default: {
final int x = location.getBlockX();
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, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
this.parent = null;
return false;
}
switch (id) {
case 0:
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 25:
case 30:
case 32:
case 37:
case 39:
case 40:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 51:
case 52:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 10:
case 11:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 84:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 117:
case 121:
case 122:
case 123:
case 124:
case 129:
case 133:
case 138:
case 137:
case 140:
case 165:
case 166:
case 169:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192: {
queue.setBlock(x, y, z, id, (byte) 0);
return true;
}
default: {
queue.setBlock(x, y, z, id, (byte) block.getData());
return true;
}
}
} else if (limit.MAX_FAILS-- < 0) {
if (this.parent != null) {
WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.parent = null;
}
}
return false;
}
}
}
@Override @Override
public boolean setBiome(final Vector2D position, final BaseBiome biome) { public boolean setBiome(final Vector2D position, final BaseBiome biome) {
if (WEManager.IMP.maskContains(this.mask, position.getBlockX(), position.getBlockZ())) { return super.setBiome(position, biome);
queue.setBiome(position.getBlockX(), position.getBlockZ(), biome);
}
return false;
} }
@Override @Override

View File

@ -54,6 +54,16 @@ public abstract class FaweQueue {
public void endSet(boolean parallel) {} public void endSet(boolean parallel) {}
public int cancel() {
int count = 0;
for (EditSession session : sessions) {
if (session.cancel()) {
count++;
}
}
return count;
}
/** /**
* Gets the FaweChunk and sets the requested blocks * Gets the FaweChunk and sets the requested blocks
* @return * @return

View File

@ -79,12 +79,15 @@ public class SetQueue {
if (SET_TASK.value2 == null) { if (SET_TASK.value2 == null) {
return; return;
} }
if (Settings.UNSAFE_PARALLEL_THREADS <= 1) { if (Thread.currentThread() != Fawe.get().getMainThread()) {
SET_TASK.value2.startSet(false); throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread");
SET_TASK.run(); }
SET_TASK.value2.endSet(false); // Disable the async catcher as it can't discern async vs parallel
} else {
SET_TASK.value2.startSet(true); SET_TASK.value2.startSet(true);
try {
if (Settings.UNSAFE_PARALLEL_THREADS <= 1) {
SET_TASK.run();
} else {
ArrayList<Thread> threads = new ArrayList<Thread>(); ArrayList<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < Settings.UNSAFE_PARALLEL_THREADS; i++) { for (int i = 0; i < Settings.UNSAFE_PARALLEL_THREADS; i++) {
threads.add(new Thread(SET_TASK)); threads.add(new Thread(SET_TASK));
@ -99,6 +102,11 @@ public class SetQueue {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
// Enable it again (note that we are still on the main thread)
SET_TASK.value2.endSet(true); SET_TASK.value2.endSet(true);
} }
} }

View File

@ -26,7 +26,7 @@ public class WEManager {
try { try {
final Field field = AbstractDelegateExtent.class.getDeclaredField("extent"); final Field field = AbstractDelegateExtent.class.getDeclaredField("extent");
field.setAccessible(true); field.setAccessible(true);
field.set(parent, new NullExtent((Extent) field.get(parent), reason)); field.set(parent, new NullExtent(reason));
} catch (final Exception e) { } catch (final Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -42,6 +42,22 @@ public class WEManager {
return false; return false;
} }
public boolean maskContains(RegionWrapper[] mask, final int x, final int z) {
switch (mask.length) {
case 0:
return false;
case 1:
return mask[0].isIn(x, z);
default:
for (final RegionWrapper region : mask) {
if (region.isIn(x, z)) {
return true;
}
}
return false;
}
}
public HashSet<RegionWrapper> getMask(final FawePlayer<?> player) { public HashSet<RegionWrapper> getMask(final FawePlayer<?> player) {
final HashSet<RegionWrapper> regions = new HashSet<>(); final HashSet<RegionWrapper> regions = new HashSet<>();
if (player.hasPermission("fawe.bypass") || !Settings.REGION_RESTRICTIONS) { if (player.hasPermission("fawe.bypass") || !Settings.REGION_RESTRICTIONS) {

View File

@ -3,7 +3,7 @@ package com.boydti.fawe.wrappers;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.extent.FaweExtent; import com.boydti.fawe.object.extent.FaweRegionExtent;
import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.BlockVector2D;
@ -230,7 +230,7 @@ public class WorldWrapper extends AbstractWorld {
public boolean regenerate(final Region region, final EditSession session) { public boolean regenerate(final Region region, final EditSession session) {
final FaweQueue queue = session.getQueue(); final FaweQueue queue = session.getQueue();
final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet(); final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet();
final FaweExtent fe = session.getFaweExtent(); final FaweRegionExtent fe = session.getRegionExtent();
session.setChangeSet(fcs); session.setChangeSet(fcs);
final boolean cuboid = region instanceof CuboidRegion; final boolean cuboid = region instanceof CuboidRegion;
Set<Vector2D> chunks = region.getChunks(); Set<Vector2D> chunks = region.getChunks();

View File

@ -34,11 +34,10 @@ import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.FastWorldEditExtent; import com.boydti.fawe.object.extent.FastWorldEditExtent;
import com.boydti.fawe.object.extent.FaweExtent; import com.boydti.fawe.object.extent.FaweRegionExtent;
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.extent.SafeExtentWrapper;
import com.boydti.fawe.util.ExtentWrapper;
import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.Perm; import com.boydti.fawe.util.Perm;
@ -118,7 +117,6 @@ import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import java.lang.reflect.Field;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -164,8 +162,9 @@ public class EditSession implements Extent {
public Actor actor; public Actor actor;
public FaweChangeSet changeSet; public FaweChangeSet changeSet;
public EditSessionWrapper wrapper; public EditSessionWrapper wrapper;
public FaweExtent faweExtent;
public MaskingExtent maskingExtent; public MaskingExtent maskingExtent;
public FaweRegionExtent regionExtent;
public Extent primaryExtent;
public Extent bypassReorderHistory; public Extent bypassReorderHistory;
public Extent bypassHistory; public Extent bypassHistory;
public Extent bypassNone; public Extent bypassNone;
@ -204,7 +203,6 @@ public class EditSession implements Extent {
} }
private int changes = 0; private int changes = 0;
private int maxBlocks;
private BlockBag blockBag; private BlockBag blockBag;
/** /**
@ -220,13 +218,14 @@ public class EditSession implements Extent {
checkNotNull(eventBus); checkNotNull(eventBus);
checkArgument(maxBlocks >= -1, "maxBlocks >= -1 required"); checkArgument(maxBlocks >= -1, "maxBlocks >= -1 required");
checkNotNull(event); checkNotNull(event);
this.actor = event.getActor(); this.actor = event.getActor();
// Wrap world // TODO block bag
this.blockBag = blockBag; this.blockBag = blockBag;
this.maxBlocks = maxBlocks;
// Invalid; return null extent // Invalid world: return null extent
if (world == null) { if (world == null) {
FaweExtent extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); NullExtent extent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.bypassReorderHistory = extent; this.bypassReorderHistory = extent;
this.bypassHistory = extent; this.bypassHistory = extent;
this.bypassNone = extent; this.bypassNone = extent;
@ -234,26 +233,18 @@ public class EditSession implements Extent {
this.wrapper = Fawe.imp().getEditSessionWrapper(this); this.wrapper = Fawe.imp().getEditSessionWrapper(this);
return; return;
} }
// Set the world of the event to the actual world (workaround for CoreProtect)
try { // Wrap the world
Class<? extends EditSessionEvent> eventClass = event.getClass();
Field fieldWorld = eventClass.getDeclaredField("world");
fieldWorld.setAccessible(true);
if (world instanceof WorldWrapper) {
fieldWorld.set(event, ((WorldWrapper) world).getParent());
} else {
fieldWorld.set(event, world);
}
} catch (Throwable e) {
e.printStackTrace();
}
this.world = (world = new WorldWrapper((AbstractWorld) world)); this.world = (world = new WorldWrapper((AbstractWorld) world));
// Delegate some methods to an implementation specific class
this.wrapper = Fawe.imp().getEditSessionWrapper(this); this.wrapper = Fawe.imp().getEditSessionWrapper(this);
// Not a player; bypass history // Not a player; bypass history
if ((actor == null) || !actor.isPlayer()) { if ((actor == null) || !actor.isPlayer()) {
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true); this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
queue.addEditSession(this); queue.addEditSession(this);
Extent extent = (this.faweExtent = new FastWorldEditExtent(world, queue)); Extent extent = primaryExtent = new FastWorldEditExtent(world, queue);
// 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);
@ -264,8 +255,9 @@ public class EditSession implements Extent {
this.changeSet = new NullChangeSet(); this.changeSet = new NullChangeSet();
return; return;
} }
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
Extent extent; Extent extent;
HashSet<RegionWrapper> mask;
final FawePlayer fp = FawePlayer.wrap(actor); final FawePlayer fp = FawePlayer.wrap(actor);
final LocalSession session = fp.getSession(); final LocalSession session = fp.getSession();
this.fastmode = session.hasFastMode(); this.fastmode = session.hasFastMode();
@ -273,7 +265,7 @@ public class EditSession implements Extent {
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true); this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
queue.addEditSession(this); queue.addEditSession(this);
// Bypass skips processing and area restrictions // Bypass skips processing and area restrictions
extent = (this.faweExtent = new FastWorldEditExtent(world, queue)); extent = primaryExtent = new FastWorldEditExtent(world, queue);
if (this.hasFastMode()) { if (this.hasFastMode()) {
// Fastmode skips history and memory checks // Fastmode skips history and memory checks
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE);
@ -284,30 +276,28 @@ public class EditSession implements Extent {
this.bypassNone = extent; this.bypassNone = extent;
return; return;
} }
mask = null;
} else { } else {
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), false, true); this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), false, true);
queue.addEditSession(this); queue.addEditSession(this);
this.limit = fp.getLimit(); this.limit = fp.getLimit();
final HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp); mask = WEManager.IMP.getMask(fp);
if (mask.size() == 0) { if (mask.size() == 0) {
// No allowed area; return null extent // No allowed area; return null extent
extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); extent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.bypassReorderHistory = extent; this.bypassReorderHistory = extent;
this.bypassHistory = extent; this.bypassHistory = extent;
this.bypassNone = extent; this.bypassNone = extent;
return; return;
} }
// Process the WorldEdit action extent = primaryExtent = new FastWorldEditExtent(world, queue);
ProcessedWEExtent processed = (ProcessedWEExtent) (this.faweExtent = new ProcessedWEExtent(world, fp, mask, limit, queue));
extent = processed;
if (this.hasFastMode()) { if (this.hasFastMode()) {
// Fastmode skips history, masking, and memory checks // Fastmode skips history, masking, and memory checks
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);
// Restrictions
extent = new ProcessedWEExtent(extent, mask, limit);
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
extent = new ExtentWrapper(extent);
// Set the parent. This allows efficient cancelling
processed.setParent(extent);
this.bypassReorderHistory = extent; this.bypassReorderHistory = extent;
this.bypassHistory = extent; this.bypassHistory = extent;
this.bypassNone = extent; this.bypassNone = extent;
@ -318,9 +308,8 @@ public class EditSession implements Extent {
if (Perm.hasPermission(fp, "worldedit.fast")) { if (Perm.hasPermission(fp, "worldedit.fast")) {
BBC.WORLDEDIT_OOM_ADMIN.send(fp); BBC.WORLDEDIT_OOM_ADMIN.send(fp);
} }
// Memory limit reached; return null extent // Memory limit reached; return null extent
extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); extent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.bypassReorderHistory = extent; this.bypassReorderHistory = extent;
this.bypassHistory = extent; this.bypassHistory = extent;
this.bypassNone = extent; this.bypassNone = extent;
@ -328,14 +317,24 @@ public class EditSession implements Extent {
} }
} }
// Perform memory checks after reorder // Perform memory checks after reorder
extent = new SafeExtentWrapper(fp, extent); extent = new MemoryCheckingExtent(fp, extent);
processed.setParent(extent);
} }
// Include history, masking and memory checking. // Include history, masking and memory checking.
Extent wrapped; Extent wrapped;
// First two events
extent = wrapped = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE); extent = wrapped = 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
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
extent = this.wrapper.getHistoryExtent(this, limit, extent, this.changeSet, queue, fp); extent = this.wrapper.getHistoryExtent(this, limit, extent, this.changeSet, queue, fp);
// Region restrictions if mask is not null
if (mask != null) {
extent = this.regionExtent = new ProcessedWEExtent(extent, mask, limit);
}
// Masking
final Player skp = (Player) actor; final Player skp = (Player) actor;
final int item = skp.getItemInHand(); final int item = skp.getItemInHand();
boolean hasMask = session.getMask() != null; boolean hasMask = session.getMask() != null;
@ -351,14 +350,44 @@ public class EditSession implements Extent {
extent = this.maskingExtent = new MaskingExtent(extent, Masks.alwaysTrue()); extent = this.maskingExtent = new MaskingExtent(extent, Masks.alwaysTrue());
} }
// Before history event
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
extent = new SafeExtentWrapper(fp, extent);
this.bypassReorderHistory = wrapped; this.bypassReorderHistory = wrapped;
this.bypassHistory = wrapped; this.bypassHistory = wrapped;
this.bypassNone = extent; this.bypassNone = extent;
return; return;
} }
public FaweRegionExtent getRegionExtent() {
return regionExtent;
}
public boolean cancel() {
// Cancel this
if (primaryExtent != null && queue != null) {
try {
WEManager.IMP.cancelEdit(primaryExtent, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
} catch (Throwable ignore) {}
NullExtent nullExtent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
primaryExtent = nullExtent;
dequeue();
queue.clear();
return true;
}
return false;
}
public void dequeue() {
if (queue != null) {
SetQueue.IMP.dequeue(queue);
}
}
public FastWorldEditExtent getPrimaryExtent() {
return (FastWorldEditExtent) primaryExtent;
}
public void debug(BBC message, Object... args) { public void debug(BBC message, Object... args) {
message.send(actor, args); message.send(actor, args);
} }
@ -427,7 +456,7 @@ public class EditSession implements Extent {
* @return the limit (&gt;= 0) or -1 for no limit * @return the limit (&gt;= 0) or -1 for no limit
*/ */
public int getBlockChangeLimit() { public int getBlockChangeLimit() {
return this.maxBlocks; return -1;
} }
/** /**
@ -489,10 +518,6 @@ public class EditSession implements Extent {
} }
} }
public FaweExtent getFaweExtent() {
return this.faweExtent;
}
/** /**
* Set the mask. * Set the mask.
* *

View File

@ -29,6 +29,7 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
@ -51,6 +52,7 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.BlockMask;
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.regions.CuboidRegion;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
@ -226,13 +228,13 @@ public class BrushCommands {
BrushTool tool = session.getBrushTool(player.getItemInHand()); BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius); tool.setSize(radius);
tool.setBrush(new GravityBrush(fromMaxY), "worldedit.brush.gravity"); tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity");
BBC.BRUSH_GRAVITY.send(player, radius); BBC.BRUSH_GRAVITY.send(player, radius);
} }
@Command( @Command(
aliases = { "height", "high" }, aliases = { "height", "heightmap" },
usage = "[radius] [file] [rotation] [yscale]", usage = "[radius] [file|#selection|null] [rotation] [yscale]",
flags = "h", flags = "h",
desc = "Height brush", desc = "Height brush",
help = help =
@ -246,7 +248,12 @@ public class BrushCommands {
File file = new File(Fawe.imp().getDirectory(), "heightmap" + File.separator + (filename.endsWith(".png") ? filename : filename + ".png")); File file = new File(Fawe.imp().getDirectory(), "heightmap" + File.separator + (filename.endsWith(".png") ? filename : filename + ".png"));
BrushTool tool = session.getBrushTool(player.getItemInHand()); BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius); tool.setSize(radius);
tool.setBrush(new HeightBrush(file, rotation, yscale), "worldedit.brush.height"); try {
tool.setBrush(new HeightBrush(file, rotation, yscale, tool, editSession, (CuboidRegion) session.getSelection(player.getWorld())), "worldedit.brush.height");
} catch (IncompleteRegionException ignore) {
ignore.printStackTrace();
tool.setBrush(new HeightBrush(file, rotation, yscale, tool, editSession, null), "worldedit.brush.height");
}
BBC.BRUSH_HEIGHT.send(player, radius); BBC.BRUSH_HEIGHT.send(player, radius);
} }

View File

@ -47,6 +47,7 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
@ -278,7 +279,7 @@ public class ClipboardCommands {
final Vector origin = clipboard.getOrigin(); final Vector origin = clipboard.getOrigin();
final Vector to = atOrigin ? origin : session.getPlacementPosition(player); final Vector to = atOrigin ? origin : session.getPlacementPosition(player);
// Optimize for BlockArrayClipboard // Optimize for BlockArrayClipboard
if (clipboard instanceof BlockArrayClipboard) { if (clipboard instanceof BlockArrayClipboard && region instanceof CuboidRegion) {
// To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min) // To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min)
final int relx = to.getBlockX() + bot.getBlockX() - origin.getBlockX(); final int relx = to.getBlockX() + bot.getBlockX() - origin.getBlockX();
final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY(); final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY();

View File

@ -23,18 +23,27 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
public class GravityBrush implements Brush { public class GravityBrush implements Brush {
private final boolean fullHeight; private final boolean fullHeight;
private final BrushTool tool;
public GravityBrush(boolean fullHeight) { public GravityBrush(boolean fullHeight, BrushTool tool) {
this.fullHeight = fullHeight; this.fullHeight = fullHeight;
this.tool = tool;
} }
@Override @Override
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
Mask mask = tool.getMask();
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null;
}
int size = (int) sizeDouble; int size = (int) sizeDouble;
int endY = position.getBlockY() + size; int endY = position.getBlockY() + size;
int startPerformY = Math.max(0, position.getBlockY() - size); int startPerformY = Math.max(0, position.getBlockY() - size);
@ -51,11 +60,12 @@ public class GravityBrush implements Brush {
continue; continue;
} }
BaseBlock block = editSession.getLazyBlock(x, y, z); BaseBlock block = editSession.getLazyBlock(x, y, z);
if (block != EditSession.nullBlock) {
if (freeSpot != y) {
mutablePos.x = x; mutablePos.x = x;
mutablePos.y = freeSpot; mutablePos.y = y;
mutablePos.z = z; mutablePos.z = z;
if (block != EditSession.nullBlock && (mask == null || mask.test(mutablePos))) {
if (freeSpot != y) {
mutablePos.y = freeSpot;
editSession.setBlock(mutablePos, block); editSession.setBlock(mutablePos, block);
mutablePos.y = y; mutablePos.y = y;
editSession.setBlock(mutablePos, EditSession.nullBlock); editSession.setBlock(mutablePos, EditSession.nullBlock);