From f55a58a3f303607dc19e212a32c57e780ded0549 Mon Sep 17 00:00:00 2001
From: Jesse Boyd
Date: Thu, 15 Sep 2016 19:49:29 +1000
Subject: [PATCH] Various
Reduce max memory allocation size
- Uses multiple byte arrays instead of one large one for streams
- Faster read/write as less dependent on arraycopy
Remove world compression (it was buggy / there was no interest)\
EditSession can now be used as a world
Fix pos1/pos2 being allowed outside the world
Fixed liquid mask not being thread safe
Fixed plot upload
Reduce packet sending
- Increase delay to being able to see blocks, but more efficient
---
build.gradle | 2 +-
.../fawe/bukkit/v1_10/BukkitMain_110.java | 144 ----------
.../java/com/boydti/fawe/config/Settings.java | 5 -
.../boydti/fawe/example/MappedFaweQueue.java | 1 -
.../com/boydti/fawe/jnbt/anvil/MCAFile.java | 2 +-
.../changeset/MemoryOptimizedHistory.java | 34 +--
.../object/io/FastByteArrayOutputStream.java | 271 ++++++++++++++----
.../object/io/FastByteArraysInputStream.java | 110 +++++++
.../general/plot/FaweSchematicHandler.java | 15 +-
.../boydti/fawe/util/EditSessionBuilder.java | 10 +-
.../com/boydti/fawe/util/HastebinUtility.java | 23 +-
.../boydti/fawe/wrappers/PlayerWrapper.java | 14 +-
.../boydti/fawe/wrappers/WorldWrapper.java | 102 +------
.../com/sk89q/worldedit/CuboidClipboard.java | 2 +-
.../java/com/sk89q/worldedit/EditSession.java | 196 ++++++++++++-
.../worldedit/command/ClipboardCommands.java | 7 +-
.../worldedit/command/SelectionCommands.java | 7 +-
.../command/tool/LongRangeBuildTool.java | 34 +--
.../command/tool/brush/GravityBrush.java | 4 +-
.../java/net/jpountz/lz4/LZ4StreamTest.java | 8 +-
20 files changed, 583 insertions(+), 408 deletions(-)
create mode 100644 core/src/main/java/com/boydti/fawe/object/io/FastByteArraysInputStream.java
diff --git a/build.gradle b/build.gradle
index 83a6bba2..d78de543 100644
--- a/build.gradle
+++ b/build.gradle
@@ -23,7 +23,7 @@ ext {
git = org.ajoberstar.grgit.Grgit.open(file(".git"))
revision = "-${git.head().abbreviatedId}"
parents = git.head().parentIds;
- index = -43; // Offset to mach CI
+ index = -45; // Offset to mach CI
for (;parents != null && !parents.isEmpty();index++) {
commit = git.getResolve().toCommit(parents.get(0));
parents = commit.getParentIds();
diff --git a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java
index a062d1cd..bf19d106 100644
--- a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java
+++ b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java
@@ -2,29 +2,8 @@ package com.boydti.fawe.bukkit.v1_10;
import com.boydti.fawe.bukkit.ABukkitMain;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
-import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweQueue;
-import com.boydti.fawe.object.io.BufferedRandomAccessFile;
-import com.boydti.fawe.object.io.FastByteArrayInputStream;
-import com.boydti.fawe.object.io.FastByteArrayOutputStream;
-import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.worldedit.world.World;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.lang.reflect.Field;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.InflaterInputStream;
-import net.minecraft.server.v1_10_R1.RegionFile;
-import net.minecraft.server.v1_10_R1.RegionFileCache;
public class BukkitMain_110 extends ABukkitMain {
@Override
@@ -40,128 +19,5 @@ public class BukkitMain_110 extends ABukkitMain {
@Override
public void onEnable() {
super.onEnable();
- if (Settings.EXPERIMENTAL.WORLD_COMPRESSION != -1) {
- try {
- ReflectionUtils.setFailsafeFieldValue(RegionFileCache.class.getDeclaredField("a"), null, new ConcurrentHashMap(8, 0.9f, 1) {
- @Override
- public RegionFile get(Object key) {
- RegionFile existing = super.get(key);
- if (existing != null) {
- return existing;
- }
- try {
- File file = (File) key;
- if (!file.exists()) {
- file.getParentFile().mkdirs();
- }
- if (size() >= 256) {
- RegionFileCache.a();
- }
- RegionFile regionFile = new RegionFile(file) {
-
- private int[] d = ReflectionUtils.getField(RegionFile.class.getDeclaredField("d"), this);
- private int[] e = ReflectionUtils.getField(RegionFile.class.getDeclaredField("e"), this);
- private List f = ReflectionUtils.getField(RegionFile.class.getDeclaredField("f"), this);
- public RandomAccessFile c = null;
-
- @Override
- public DataOutputStream b(final int i, final int j) {
- if (i < 0 || i >= 32 || j < 0 || j >= 32) {
- return null;
- }
-// if (Settings.EXPERIMENTAL.FAST_WORLD_COMPRESSION) {
-// try {
-// return new DataOutputStream(new AsyncBufferedOutputStream(new LZ4OutputStream(new FastByteArrayOutputStream() {
-// @Override
-// public void close() {
-// try {
-// super.close();
-// } catch (IOException e1) {
-// e1.printStackTrace();
-// }
-// a(i, j, array, length);
-// }
-// }, 16000)));
-// } catch (Throwable e) {
-// e.printStackTrace();
-// }
-// }
- return new DataOutputStream(new BufferedOutputStream(new DeflaterOutputStream(new FastByteArrayOutputStream() {
- @Override
- public void close() throws IOException {
- super.close();
- a(i, j, this.array, length);
- }
- }, new Deflater(Settings.EXPERIMENTAL.WORLD_COMPRESSION))));
- }
-
- @Override
- public synchronized DataInputStream a(int i, int j) {
- if ((i < 0) || (i >= 32) || (j < 0) || (j >= 32)) {
- return null;
- } else {
- try {
- int k = d[(i + j * 32)];
- if (k == 0) {
- return null;
- } else {
- int l = k >> 8;
- int i1 = k & 255;
- if (l + i1 > f.size()) {
- return null;
- } else {
- c.seek((long) (l * 4096));
- int j1 = this.c.readInt();
- if (j1 > 4096 * i1) {
- return null;
- } else if (j1 <= 0) {
- return null;
- } else {
- byte b0 = c.readByte();
- byte[] abyte;
- if (b0 == 1) {
- abyte = new byte[j1 - 1];
- c.read(abyte);
- return new DataInputStream(new BufferedInputStream(new GZIPInputStream(new FastByteArrayInputStream(abyte))));
- } else if (b0 == 2) {
- abyte = new byte[j1 - 1];
- c.read(abyte);
-// if (Settings.EXPERIMENTAL.FAST_WORLD_COMPRESSION) {
-// return new DataInputStream(new LZ4InputStream(new FastByteArrayInputStream(abyte)));
-// }
- return new DataInputStream(new BufferedInputStream(new InflaterInputStream(new FastByteArrayInputStream(abyte))));
- } else {
- return null;
- }
- }
- }
- }
- } catch (IOException var9) {
- var9.printStackTrace();
- return null;
- }
- }
- }
- };
- Field field = RegionFile.class.getDeclaredField("c");
- field.setAccessible(true);
- RandomAccessFile raf2 = (RandomAccessFile) field.get(regionFile);
- raf2.close();
- final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw");
- ReflectionUtils.setFailsafeFieldValue(field, regionFile, raf);
- put(file, regionFile);
- regionFile.getClass().getDeclaredField("c").set(regionFile, raf);
- return regionFile;
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- });
- ;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
}
}
\ No newline at end of file
diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java
index c470f2eb..ee4540de 100644
--- a/core/src/main/java/com/boydti/fawe/config/Settings.java
+++ b/core/src/main/java/com/boydti/fawe/config/Settings.java
@@ -199,11 +199,6 @@ public class Settings extends Config {
"Directly modify the region files.",
})
public static boolean ANVIL_QUEUE_MODE = false;
- @Comment({
- "Set the default world compression",
- " - Only supports Bukkit 1.10 right now"
- })
- public static int WORLD_COMPRESSION = -1;
}
public static class WEB {
diff --git a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
index 241dc6d0..356b6761 100644
--- a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
+++ b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
@@ -206,7 +206,6 @@ public abstract class MappedFaweQueue extends FaweQueue {
public void end(FaweChunk chunk) {
chunk.end();
- sendChunk(chunk);
}
@Override
diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java
index caff1dda..f71c760a 100644
--- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java
+++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java
@@ -259,7 +259,7 @@ public class MCAFile {
}
FastByteArrayOutputStream baos = new FastByteArrayOutputStream(0);
fieldBuf4.set(baos, buffer3);
- DeflaterOutputStream deflater = new DeflaterOutputStream(baos, new Deflater(Settings.EXPERIMENTAL.WORLD_COMPRESSION), 1, true);
+ DeflaterOutputStream deflater = new DeflaterOutputStream(baos, new Deflater(6), 1, true);
fieldBuf5.set(deflater, buffer2);
BufferedOutputStream bos = new BufferedOutputStream(deflater, 1);
fieldBuf6.set(bos, buffer1);
diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java
index b566074d..32e7f44b 100644
--- a/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java
+++ b/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java
@@ -3,8 +3,8 @@ package com.boydti.fawe.object.changeset;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
-import com.boydti.fawe.object.io.FastByteArrayInputStream;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
+import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
@@ -21,23 +21,24 @@ import java.io.OutputStream;
*/
public class MemoryOptimizedHistory extends FaweStreamChangeSet {
- private byte[] ids;
+ private int size = 0;
+ private byte[][] ids;
private FastByteArrayOutputStream idsStream;
private FaweOutputStream idsStreamZip;
- private byte[] entC;
+ private byte[][] entC;
private FastByteArrayOutputStream entCStream;
private NBTOutputStream entCStreamZip;
- private byte[] entR;
+ private byte[][] entR;
private FastByteArrayOutputStream entRStream;
private NBTOutputStream entRStreamZip;
- private byte[] tileC;
+ private byte[][] tileC;
private FastByteArrayOutputStream tileCStream;
private NBTOutputStream tileCStreamZip;
- private byte[] tileR;
+ private byte[][] tileR;
private FastByteArrayOutputStream tileRStream;
private NBTOutputStream tileRStreamZip;
@@ -51,31 +52,32 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
try {
if (idsStream != null) {
idsStreamZip.close();
- ids = idsStream.toByteArray();
+ size = idsStream.getSize();
+ ids = idsStream.toByteArrays();
idsStream = null;
idsStreamZip = null;
}
if (entCStream != null) {
entCStreamZip.close();
- entC = entCStream.toByteArray();
+ entC = entCStream.toByteArrays();
entCStream = null;
entCStreamZip = null;
}
if (entRStream != null) {
entRStreamZip.close();
- entR = entRStream.toByteArray();
+ entR = entRStream.toByteArrays();
entRStream = null;
entRStreamZip = null;
}
if (tileCStream != null) {
tileCStreamZip.close();
- tileC = tileCStream.toByteArray();
+ tileC = tileCStream.toByteArrays();
tileCStream = null;
tileCStreamZip = null;
}
if (tileRStream != null) {
tileRStreamZip.close();
- tileR = tileRStream.toByteArray();
+ tileR = tileRStream.toByteArrays();
tileRStream = null;
tileRStreamZip = null;
}
@@ -115,7 +117,7 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
if (ids == null) {
return null;
}
- FaweInputStream result = MainUtil.getCompressedIS(new FastByteArrayInputStream(ids));
+ FaweInputStream result = MainUtil.getCompressedIS(new FastByteArraysInputStream(ids));
result.skip(FaweStreamChangeSet.HEADER_SIZE);
return result;
}
@@ -158,21 +160,21 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
@Override
public NBTInputStream getEntityCreateIS() throws IOException {
- return entC == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArrayInputStream(entC)));
+ return entC == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArraysInputStream(entC)));
}
@Override
public NBTInputStream getEntityRemoveIS() throws IOException {
- return entR == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArrayInputStream(entR)));
+ return entR == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArraysInputStream(entR)));
}
@Override
public NBTInputStream getTileCreateIS() throws IOException {
- return tileC == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArrayInputStream(tileC)));
+ return tileC == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArraysInputStream(tileC)));
}
@Override
public NBTInputStream getTileRemoveIS() throws IOException {
- return tileR == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArrayInputStream(tileR)));
+ return tileR == null ? null : new NBTInputStream(MainUtil.getCompressedIS(new FastByteArraysInputStream(tileR)));
}
}
diff --git a/core/src/main/java/com/boydti/fawe/object/io/FastByteArrayOutputStream.java b/core/src/main/java/com/boydti/fawe/object/io/FastByteArrayOutputStream.java
index 9ca3da83..37daec6c 100644
--- a/core/src/main/java/com/boydti/fawe/object/io/FastByteArrayOutputStream.java
+++ b/core/src/main/java/com/boydti/fawe/object/io/FastByteArrayOutputStream.java
@@ -1,96 +1,245 @@
package com.boydti.fawe.object.io;
-import com.boydti.fawe.util.ByteArrays;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.io.Writer;
+import java.util.ArrayDeque;
+import java.util.Iterator;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorCompletionService;
+
+/**
+ * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
+ * does not copy buffers when it's expanded. There's also no copying of the internal buffer
+ * if it's contents is extracted with the writeTo(stream) method.
+ *
+ * @author Rickard ?berg
+ * @author Brat Baker (Atlassian)
+ * @author Alexey
+ * @version $Date: 2008-01-19 10:09:56 +0800 (Sat, 19 Jan 2008) $ $Id: FastByteArrayOutputStream.java 3000 2008-01-19 02:09:56Z tm_jee $
+ */
public class FastByteArrayOutputStream extends OutputStream {
- /**
- * The array backing the output stream.
- */
- public final static int DEFAULT_INITIAL_CAPACITY = 16;
+ private static final int DEFAULT_BLOCK_SIZE = 8192;
- /**
- * The array backing the output stream.
- */
- public byte[] array;
+ private ArrayDeque buffers = new ArrayDeque<>();
- /**
- * The number of valid bytes in {@link #array}.
- */
- public int length;
+ private byte[] buffer;
+ private int blockSize;
+ private int index;
+ private int size;
- /**
- * The current writing position.
- */
- private int position;
- /**
- * Creates a new array output stream with an initial capacity of {@link #DEFAULT_INITIAL_CAPACITY} bytes.
- */
public FastByteArrayOutputStream() {
- this(DEFAULT_INITIAL_CAPACITY);
+ this(DEFAULT_BLOCK_SIZE);
}
- /**
- * Creates a new array output stream with a given initial capacity.
- *
- * @param initialCapacity the initial length of the backing array.
- */
- public FastByteArrayOutputStream(final int initialCapacity) {
- array = new byte[initialCapacity];
+ public FastByteArrayOutputStream(int aSize) {
+ blockSize = aSize;
+ buffer = new byte[blockSize];
}
- /**
- * Creates a new array output stream wrapping a given byte array.
- *
- * @param a the byte array to wrap.
- */
- public FastByteArrayOutputStream(final byte[] a) {
- array = a;
+
+ public int getSize() {
+ return size + index;
}
- /**
- * Marks this array output stream as empty.
- */
- public void reset() {
- length = 0;
- position = 0;
+ public byte[][] toByteArrays() {
+ if (index > 0) {
+ byte[] buf2 = new byte[index];
+ System.arraycopy(buffer, 0, buf2, 0, index);
+ buffers.addLast(buf2);
+ size += index;
+ index = 0;
+ }
+ byte[][] res = new byte[buffers.size()][];
+ int i = 0;
+ for (byte[] bytes : buffers) {
+ res[i++] = bytes;
+ }
+ return res;
}
- public void trim() {
- this.array = ByteArrays.trim(this.array, this.length);
+ public byte[] toByteArray(ExecutorCompletionService service) {
+ if (buffers.size() < 8) {
+ return toByteArray();
+ }
+ final byte[] data = new byte[getSize()];
+ // Check if we have a list of buffers
+ int pos = 0;
+ int count = 0;
+ if (buffers != null) {
+ for (final byte[] bytes : buffers) {
+ final int finalPos = pos;
+ count++;
+ service.submit(new Callable() {
+ @Override
+ public Object call() throws Exception {
+ System.arraycopy(bytes, 0, data, finalPos, bytes.length);
+ return null;
+ }
+ });
+ pos += bytes.length;
+ }
+ }
+ try {
+ for (int i = 0; i < count; i++) {
+ service.take();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ // write the internal buffer directly
+ System.arraycopy(buffer, 0, data, pos, index);
+
+ return data;
}
public byte[] toByteArray() {
- trim();
- return array;
+ byte[] data = new byte[getSize()];
+
+ // Check if we have a list of buffers
+ int pos = 0;
+
+ if (buffers != null) {
+ for (byte[] bytes : buffers) {
+ System.arraycopy(bytes, 0, data, pos, bytes.length);
+ pos += bytes.length;
+ }
+ }
+
+ // write the internal buffer directly
+ System.arraycopy(buffer, 0, data, pos, index);
+
+ return data;
}
- public void write(final int b) {
- if (position >= array.length) array = ByteArrays.grow(array, position + 1, length);
- array[position++] = (byte) b;
- if (length < position) length = position;
+ public String toString() {
+ return new String(toByteArray());
}
- public void write(final byte[] b, final int off, final int len) throws IOException {
- ByteArrays.ensureOffsetLength(b, off, len);
- if (position + len > array.length) array = ByteArrays.grow(array, position + len, position);
- System.arraycopy(b, off, array, position, len);
- if (position + len > length) length = position += len;
+ @Override
+ public void write(byte[] b) throws IOException {
+ if (b.length > blockSize) {
+ if (index > 0) {
+ byte[] buf2 = new byte[index];
+ System.arraycopy(buffer, 0, buf2, 0, index);
+ buffer = buf2;
+ addBuffer();
+ }
+ size += b.length;
+ buffers.addLast(b);
+ } else {
+ write(b, 0, b.length);
+ }
}
- public void position(long newPosition) {
- if (position > Integer.MAX_VALUE) throw new IllegalArgumentException("Position too large: " + newPosition);
- position = (int) newPosition;
+ public void write(int datum) {
+ if (index == blockSize) {
+ addBuffer();
+ }
+ // store the byte
+ buffer[index++] = (byte) datum;
}
- public long position() {
- return position;
+ public void write(byte[] data, int offset, int length) throws IOException {
+ if ((offset < 0) || ((offset + length) > data.length) || (length < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else {
+ if ((index + length) > blockSize) {
+ int copyLength;
+
+ do {
+ if (index == blockSize) {
+ addBuffer();
+ }
+
+ copyLength = blockSize - index;
+
+ if (length < copyLength) {
+ copyLength = length;
+ }
+
+ System.arraycopy(data, offset, buffer, index, copyLength);
+ offset += copyLength;
+ index += copyLength;
+ length -= copyLength;
+ } while (length > 0);
+ } else {
+ // Copy in the subarray
+ System.arraycopy(data, offset, buffer, index, length);
+ index += length;
+ }
+ }
}
- public long length() throws IOException {
- return length;
+ public void writeTo(OutputStream out) throws IOException {
+ // Check if we have a list of buffers
+ if (buffers != null) {
+ Iterator iter = buffers.iterator();
+
+ while (iter.hasNext()) {
+ byte[] bytes = (byte[]) iter.next();
+ out.write(bytes, 0, blockSize);
+ }
+ }
+
+ // write the internal buffer directly
+ out.write(buffer, 0, index);
+ }
+
+ public void writeTo(RandomAccessFile out) throws IOException {
+ // Check if we have a list of buffers
+ if (buffers != null) {
+ Iterator iter = buffers.iterator();
+
+ while (iter.hasNext()) {
+ byte[] bytes = (byte[]) iter.next();
+ out.write(bytes, 0, blockSize);
+ }
+ }
+
+ // write the internal buffer directly
+ out.write(buffer, 0, index);
+ }
+
+ public void writeTo(Writer out, String encoding) throws IOException {
+ if (buffers != null) {
+ writeToViaSmoosh(out, encoding);
+ } else {
+ writeToViaString(out, encoding);
+ }
+ }
+
+ private void writeToViaString(Writer out, String encoding) throws IOException {
+ byte[] bufferToWrite = buffer; // this is always the last buffer to write
+ int bufferToWriteLen = index; // index points to our place in the last buffer
+ writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
+ }
+
+ private void writeToViaSmoosh(Writer out, String encoding) throws IOException {
+ byte[] bufferToWrite = toByteArray();
+ int bufferToWriteLen = bufferToWrite.length;
+ writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
+ }
+
+ private void writeToImpl(Writer out, String encoding, byte[] bufferToWrite, int bufferToWriteLen)
+ throws IOException {
+ String writeStr;
+ if (encoding != null) {
+ writeStr = new String(bufferToWrite, 0, bufferToWriteLen, encoding);
+ } else {
+ writeStr = new String(bufferToWrite, 0, bufferToWriteLen);
+ }
+ out.write(writeStr);
+ }
+
+ private void addBuffer() {
+ buffers.addLast(buffer);
+ buffer = new byte[blockSize];
+ size += index;
+ index = 0;
}
}
\ No newline at end of file
diff --git a/core/src/main/java/com/boydti/fawe/object/io/FastByteArraysInputStream.java b/core/src/main/java/com/boydti/fawe/object/io/FastByteArraysInputStream.java
new file mode 100644
index 00000000..d4900606
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/io/FastByteArraysInputStream.java
@@ -0,0 +1,110 @@
+package com.boydti.fawe.object.io;
+
+import java.io.InputStream;
+
+public class FastByteArraysInputStream extends InputStream {
+ private final byte[][] buffers;
+ private final int length;
+
+ private byte[] current;
+
+ private int layer;
+ private int localIndex;
+ private int globalIndex;
+ private int curLen;
+
+
+ public FastByteArraysInputStream(byte[][] buffers) {
+ this.buffers = buffers;
+ int size = 0;
+ for (byte[] bytes : buffers) {
+ size += bytes.length;
+ }
+ this.length = size;
+ current = buffers.length == 0 ? new byte[layer++] : buffers[layer++];
+ curLen = current.length;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void mark(int dummy) {
+ }
+
+ @Override
+ public int available() {
+ return this.length - this.globalIndex;
+ }
+
+ @Override
+ public long skip(long n) {
+ if (n <= this.length - this.globalIndex) {
+ this.globalIndex += (int) n;
+ this.localIndex += (int) n;
+ ensureBuffer();
+ return n;
+ }
+ n = this.length - this.globalIndex;
+ layer = buffers.length - 1;
+ this.current = buffers[layer];
+ this.curLen = current.length;
+ this.localIndex = current.length;
+ this.globalIndex = this.length;
+ return n;
+ }
+
+ @Override
+ public int read() {
+ if (curLen != localIndex) {
+ globalIndex++;
+ return this.current[localIndex++] & 0xFF;
+ } else if (length == globalIndex) {
+ return -1;
+ } else {
+ localIndex = 0;
+ current = buffers[layer++];
+ curLen = current.length;
+ globalIndex++;
+ return this.current[localIndex++] & 0xFF;
+ }
+ }
+
+ @Override
+ public int read(byte[] b, int offset, int length) {
+ if (this.length <= this.globalIndex) {
+ return length == 0 ? 0 : -1;
+ }
+ int n = Math.min(length, this.length - this.globalIndex);
+ int read = 0;
+ int amount = Math.min(curLen - localIndex, n - read);
+ System.arraycopy(this.current, localIndex, b, offset + read, amount);
+ read += amount;
+ localIndex += amount;
+ globalIndex += amount;
+ ensureBuffer();
+ return read;
+ }
+
+ public void ensureBuffer() {
+ while (localIndex >= curLen && layer < buffers.length) {
+ localIndex -= curLen;
+ current = buffers[layer++];
+ this.curLen = current.length;
+ }
+ }
+
+ public long length() {
+ return this.length;
+ }
+}
diff --git a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java
index c3f4646b..e5c12c69 100644
--- a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java
+++ b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java
@@ -59,7 +59,7 @@ public class FaweSchematicHandler extends SchematicHandler {
Location pos1 = corners[0];
Location pos2 = corners[1];
final CuboidRegion region = new CuboidRegion(new Vector(pos1.getX(), pos1.getY(), pos1.getZ()), new Vector(pos2.getX(), pos2.getY(), pos2.getZ()));
- final EditSession editSession = new EditSessionBuilder(pos1.getWorld()).checkMemory(false).fastmode(true).limitUnlimited().changeSetNull().autoQueue(false).build();
+ final EditSession editSession = new EditSessionBuilder(world).checkMemory(false).fastmode(true).limitUnlimited().changeSetNull().autoQueue(false).build();
final int mx = pos1.getX();
final int my = pos1.getY();
@@ -144,12 +144,13 @@ public class FaweSchematicHandler extends SchematicHandler {
@Override
public void run(OutputStream output) {
try {
- GZIPOutputStream gzip = new GZIPOutputStream(output, true);
- com.sk89q.jnbt.CompoundTag weTag = (com.sk89q.jnbt.CompoundTag) FaweCache.asTag(tag);
- NBTOutputStream nos = new NBTOutputStream(gzip);
- Map map = weTag.getValue();
- nos.writeNamedTag("Schematic", map.containsKey("Schematic") ? map.get("Schematic") : weTag);
- gzip.flush();
+ try (GZIPOutputStream gzip = new GZIPOutputStream(output, true)) {
+ com.sk89q.jnbt.CompoundTag weTag = (com.sk89q.jnbt.CompoundTag) FaweCache.asTag(tag);
+ try (NBTOutputStream nos = new NBTOutputStream(gzip)) {
+ Map map = weTag.getValue();
+ nos.writeNamedTag("Schematic", map.containsKey("Schematic") ? map.get("Schematic") : weTag);
+ }
+ }
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java b/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java
index 71abc746..d432bbcf 100644
--- a/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java
+++ b/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java
@@ -1,6 +1,5 @@
package com.boydti.fawe.util;
-import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.FaweLimit;
@@ -20,10 +19,12 @@ import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+
import static com.google.common.base.Preconditions.checkNotNull;
public class EditSessionBuilder {
private World world;
+ private String worldName;
private FaweQueue queue;
private FawePlayer player;
private FaweLimit limit;
@@ -57,8 +58,9 @@ public class EditSessionBuilder {
this.world = world;
}
- public EditSessionBuilder(@Nonnull String world) {
- this(FaweAPI.getWorld(world));
+ public EditSessionBuilder(@Nonnull String worldName) {
+ checkNotNull(worldName);
+ this.worldName = worldName;
}
public EditSessionBuilder player(@Nullable FawePlayer player) {
@@ -164,6 +166,6 @@ public class EditSessionBuilder {
}
public EditSession build() {
- return new EditSession(world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, eventBus, event);
+ return new EditSession(worldName, world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, eventBus, event);
}
}
diff --git a/core/src/main/java/com/boydti/fawe/util/HastebinUtility.java b/core/src/main/java/com/boydti/fawe/util/HastebinUtility.java
index 2e7ae290..0c110ef1 100644
--- a/core/src/main/java/com/boydti/fawe/util/HastebinUtility.java
+++ b/core/src/main/java/com/boydti/fawe/util/HastebinUtility.java
@@ -1,5 +1,6 @@
package com.boydti.fawe.util;
+import com.boydti.fawe.object.RunnableVal;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
@@ -16,17 +17,15 @@ public class HastebinUtility {
public static final String BIN_URL = "http://hastebin.com/documents", USER_AGENT = "Mozilla/5.0";
public static final Pattern PATTERN = Pattern.compile("\\{\"key\":\"([\\S\\s]*)\"\\}");
- public static String upload(final String string) throws IOException {
+ public static String upload(final RunnableVal writeTask) throws IOException {
final URL url = new URL(BIN_URL);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("User-Agent", USER_AGENT);
connection.setDoOutput(true);
-
- try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
- outputStream.write(string.getBytes());
- outputStream.flush();
+ try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
+ writeTask.run(os);
}
StringBuilder response;
@@ -47,6 +46,19 @@ public class HastebinUtility {
}
}
+ public static String upload(final String s) throws IOException {
+ return upload(new RunnableVal() {
+ @Override
+ public void run(DataOutputStream value) {
+ try {
+ value.writeChars(s);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
public static String upload(final File file) throws IOException {
final StringBuilder content = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
@@ -57,6 +69,7 @@ public class HastebinUtility {
}
}
return upload(content.toString());
+
}
}
diff --git a/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java b/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java
index 20d43776..3911721e 100644
--- a/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java
+++ b/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java
@@ -3,12 +3,10 @@ package com.boydti.fawe.wrappers;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal;
-import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EditSessionFactory;
import com.sk89q.worldedit.LocalSession;
-import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.PlayerDirection;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
@@ -202,14 +200,10 @@ public class PlayerWrapper implements Player {
public void floatAt(final int x, final int y, final int z, final boolean alwaysGlass) {
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
final EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this);
- try {
- edit.setBlock(new Vector(x, y - 1, z), new BaseBlock( BlockType.GLASS.getID()));
- LocalSession session = Fawe.get().getWorldEdit().getSession(this);
- if (session != null) {
- session.remember(edit, true, false, FawePlayer.wrap(this).getLimit().MAX_HISTORY);
- }
- } catch (MaxChangedBlocksException e) {
- MainUtil.handleError(e);
+ edit.setBlockFast(new Vector(x, y - 1, z), new BaseBlock( BlockType.GLASS.getID()));
+ LocalSession session = Fawe.get().getWorldEdit().getSession(this);
+ if (session != null) {
+ session.remember(edit, true, false, FawePlayer.wrap(this).getLimit().MAX_HISTORY);
}
TaskManager.IMP.sync(new RunnableVal
*/
-public class EditSession implements Extent {
+public class EditSession extends AbstractWorld {
/**
* Used by {@link #setBlock(Vector, BaseBlock, Stage)} to
* determine which {@link Extent}s should be bypassed.
@@ -154,6 +159,7 @@ public class EditSession implements Extent {
}
private World world;
+ private String worldName;
private FaweQueue queue;
private AbstractDelegateExtent extent;
private HistoryExtent history;
@@ -182,7 +188,14 @@ public class EditSession implements Extent {
PlayerDirection.UP.vector(),
PlayerDirection.DOWN.vector(), };
+ @Deprecated
public EditSession(@Nonnull World world, @Nullable FaweQueue queue, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) {
+ this(null, world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, bus, event);
+ }
+
+ public EditSession(@Nullable String worldName, @Nullable World world, @Nullable FaweQueue queue, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) {
+ this.worldName = worldName == null ? world == null ? queue == null ? "" : queue.getWorldName() : world.getName() : worldName;
+ if (world == null && this.worldName != null) world = FaweAPI.getWorld(this.worldName);
this.world = world = WorldWrapper.wrap((AbstractWorld) world);
if (bus == null) {
bus = WorldEdit.getInstance().getEventBus();
@@ -255,7 +268,7 @@ public class EditSession implements Extent {
if (world instanceof MCAWorld) {
queue = ((MCAWorld) world).getQueue();
} else {
- queue = SetQueue.IMP.getNewQueue(world, fastmode, autoQueue);
+ queue = SetQueue.IMP.getNewQueue(this, fastmode, autoQueue);
}
} else if (Settings.EXPERIMENTAL.ANVIL_QUEUE_MODE && !(queue instanceof MCAQueue)) {
queue = new MCAQueue(queue);
@@ -283,7 +296,7 @@ public class EditSession implements Extent {
}
}
this.extent = wrapExtent(this.extent, bus, event, Stage.BEFORE_HISTORY);
- this.maxY = this.world == null ? 255 : world.getMaxY();
+ this.maxY = getWorld() == null ? 255 : world.getMaxY();
}
/**
@@ -791,7 +804,9 @@ public class EditSession implements Extent {
* @param naturalOnly look at natural blocks or all blocks
* @return height of highest block found or 'minY'
*/
- public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) {
+ public int getHighestTerrainBlock(final int x, final int z, int minY, int maxY, final boolean naturalOnly) {
+ maxY = Math.min(getMaximumPoint().getBlockY(), Math.max(0, maxY));
+ minY = Math.max(0, minY);
for (int y = maxY; y >= minY; --y) {
BaseBlock block = getLazyBlock(x, y, z);
final int id = block.getId();
@@ -956,7 +971,11 @@ public class EditSession implements Extent {
}
@Override
- public boolean setBlock(final Vector position, final BaseBlock block) throws MaxChangedBlocksException {
+ public boolean setBlock(final Vector position, final BaseBlock block, final boolean ignorePhysics) throws MaxChangedBlocksException {
+ return setBlockFast(position, block);
+ }
+
+ public boolean setBlockFast(final Vector position, final BaseBlock block) {
this.changes++;
try {
return this.extent.setBlock(position, block);
@@ -975,7 +994,7 @@ public class EditSession implements Extent {
*/
@SuppressWarnings("deprecation")
public boolean setBlock(final Vector position, final Pattern pattern) throws MaxChangedBlocksException {
- return this.setBlock(position, pattern.next(position));
+ return this.setBlockFast(position, pattern.next(position));
}
/**
@@ -1020,7 +1039,7 @@ public class EditSession implements Extent {
*/
@Deprecated
public boolean setBlockIfAir(final Vector position, final BaseBlock block) throws MaxChangedBlocksException {
- return this.getBlock(position).isAir() && this.setBlock(position, block);
+ return this.getBlock(position).isAir() && this.setBlockFast(position, block);
}
@Override
@@ -1756,15 +1775,16 @@ public class EditSession implements Extent {
checkNotNull(origin);
checkArgument(radius >= 0, "radius >= 0 required");
Mask liquidMask;
- if (getWorld() != null) {
- liquidMask = getWorld().createLiquidMask();
- } else {
+ // Not thread safe, use hardcoded liquidmask
+// if (getWorld() != null) {
+// liquidMask = getWorld().createLiquidMask();
+// } else {
liquidMask = new BlockMask(this,
new BaseBlock(BlockID.STATIONARY_LAVA, -1),
new BaseBlock(BlockID.LAVA, -1),
new BaseBlock(BlockID.STATIONARY_WATER, -1),
new BaseBlock(BlockID.WATER, -1));
- }
+// }
final MaskIntersection mask = new MaskIntersection(
new BoundedHeightMask(0, EditSession.this.getMaximumPoint().getBlockY()),
new RegionMask(
@@ -2471,7 +2491,7 @@ public class EditSession implements Extent {
// read block from world
BaseBlock material = FaweCache.CACHE_BLOCK[this.queue.getCombinedId4DataDebug(sourcePosition.getBlockX(), sourcePosition.getBlockY(), sourcePosition.getBlockZ(), 0, this)];
// queue operation
- this.setBlock(position, material);
+ this.setBlockFast(position, material);
}
return changes;
}
@@ -2545,7 +2565,7 @@ public class EditSession implements Extent {
continue outer;
}
}
- this.setBlock(position, pattern.next(position));
+ this.setBlockFast(position, pattern.next(position));
}
return changes;
@@ -2812,6 +2832,156 @@ public class EditSession implements Extent {
return (x * x) + (z * z);
}
+
+ @Override
+ public String getName() {
+ return worldName;
+ }
+
+ @Override
+ public int getBlockLightLevel(Vector position) {
+ return queue.getEmmittedLight((int) position.x, (int) position.y, (int) position.z);
+ }
+
+ @Override
+ public boolean clearContainerBlockContents(Vector position) {
+ BaseBlock block = getBlock(position);
+ CompoundTag nbt = block.getNbtData();
+ if (nbt != null) {
+ if (nbt.containsKey("items")) {
+ block.setNbtData(null);
+ try {
+ return setBlock(position, block);
+ } catch (WorldEditException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean regenerate(final Region region) {
+ return regenerate(region, this);
+ }
+
+ @Override
+ public boolean regenerate(final Region region, final EditSession session) {
+ final FaweQueue queue = session.getQueue();
+ queue.setChangeTask(null);
+ final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet();
+ final FaweRegionExtent fe = session.getRegionExtent();
+ session.setSize(1);
+ final boolean cuboid = region instanceof CuboidRegion;
+ Set chunks = region.getChunks();
+ for (Vector2D chunk : chunks) {
+ final int cx = chunk.getBlockX();
+ final int cz = chunk.getBlockZ();
+ final int bx = cx << 4;
+ final int bz = cz << 4;
+ Vector cmin = new Vector(bx, 0, bz);
+ Vector cmax = cmin.add(15, getMaxY(), 15);
+ final boolean containsBot1 = (fe == null || fe.contains(cmin.getBlockX(), cmin.getBlockY(), cmin.getBlockZ()));
+ final boolean containsBot2 = region.contains(cmin);
+ final boolean containsTop1 = (fe == null || fe.contains(cmax.getBlockX(), cmax.getBlockY(), cmax.getBlockZ()));
+ final boolean containsTop2 = region.contains(cmax);
+ if ((containsBot2 && containsTop2 && !containsBot1 && !containsTop1)) {
+ continue;
+ }
+ RunnableVal r = new RunnableVal() {
+ @Override
+ public void run(Vector2D chunk) {
+ if (cuboid && containsBot1 && containsBot2 && containsTop1 && containsTop2) {
+ if (fcs != null) {
+ for (int x = 0; x < 16; x++) {
+ int xx = x + bx;
+ for (int z = 0; z < 16; z++) {
+ int zz = z + bz;
+ for (int y = 0; y < getMaxY() + 1; y++) {
+ int from = queue.getCombinedId4DataDebug(xx, y, zz, 0, session);
+ if (!FaweCache.hasNBT(from >> 4)) {
+ fcs.add(xx, y, zz, from, 0);
+ } else {
+ try {
+ Vector loc = new Vector(xx, y, zz);
+ BaseBlock block = getLazyBlock(loc);
+ fcs.add(loc, block, FaweCache.CACHE_BLOCK[0]);
+ } catch (Throwable e) {
+ fcs.add(xx, y, zz, from, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ Vector mutable = new Vector(0,0,0);
+ for (int x = 0; x < 16; x++) {
+ int xx = x + bx;
+ mutable.x = xx;
+ for (int z = 0; z < 16; z++) {
+ int zz = z + bz;
+ mutable.z = zz;
+ for (int y = 0; y < getMaxY() + 1; y++) {
+ mutable.y = y;
+ int from = queue.getCombinedId4Data(xx, y, zz);
+ boolean contains = (fe == null || fe.contains(xx, y, zz)) && region.contains(mutable);
+ if (contains) {
+ if (fcs != null) {
+ if (!FaweCache.hasNBT(from >> 4)) {
+ fcs.add(xx, y, zz, from, 0);
+ } else {
+ try {
+ BaseBlock block = getLazyBlock(mutable);
+ fcs.add(mutable, block, FaweCache.CACHE_BLOCK[0]);
+ } catch (Throwable e) {
+ fcs.add(xx, y, zz, from, 0);
+ }
+ }
+ }
+ } else {
+ short id = (short) (from >> 4);
+ byte data = (byte) (from & 0xf);
+ queue.setBlock(xx, y, zz, id, data);
+ if (FaweCache.hasNBT(id)) {
+ BaseBlock block = getBlock(new Vector(xx, y, zz));
+ if (block.hasNbtData()) {
+ queue.setTile(xx, y, zz, block.getNbtData());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ queue.regenerateChunk(cx, cz);
+ }
+ };
+ r.value = chunk;
+ TaskManager.IMP.sync(r);
+ }
+ session.flushQueue();
+ return false;
+ }
+
+ @Override
+ public void dropItem(Vector position, BaseItemStack item) {
+ if (getWorld() != null) {
+ getWorld().dropItem(position, item);
+ }
+ }
+
+ public boolean generateTree(TreeGenerator.TreeType type, Vector position) throws MaxChangedBlocksException {
+ return generateTree(type, this, position);
+ }
+
+ @Override
+ public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector position) throws MaxChangedBlocksException {
+ if (getWorld() != null) {
+ return getWorld().generateTree(type, editSession, position);
+ }
+ return false;
+ }
+
public static Class> inject() {
return EditSession.class;
}
diff --git a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java
index 524cfbd9..476b589f 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java
@@ -32,7 +32,6 @@ import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
-import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
@@ -353,11 +352,7 @@ public class ClipboardCommands {
pos.x += relx;
pos.y += rely;
pos.z += relz;
- try {
- editSession.setBlock(pos, block);
- } catch (MaxChangedBlocksException e) {
- throw new RuntimeException(e);
- }
+ editSession.setBlockFast(pos, block);
}
}, !ignoreAirBlocks);
} else {
diff --git a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java
index 7f335762..6ac397da 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java
@@ -99,14 +99,13 @@ public class SelectionCommands {
} else {
pos = player.getBlockIn();
}
-
+ pos = pos.clampY(0, editSession.getMaximumPoint().getBlockY());
if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos, ActorSelectorLimits.forActor(player))) {
BBC.SELECTOR_ALREADY_SET.send(player);
return;
}
- session.getRegionSelector(player.getWorld())
- .explainPrimarySelection(player, session, pos);
+ session.getRegionSelector(player.getWorld()).explainPrimarySelection(player, session, pos);
}
@Command(
@@ -134,7 +133,7 @@ public class SelectionCommands {
} else {
pos = player.getBlockIn();
}
-
+ pos = pos.clampY(0, editSession.getMaximumPoint().getBlockY());
if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos, ActorSelectorLimits.forActor(player))) {
BBC.SELECTOR_ALREADY_SET.send(player);
return;
diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java b/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java
index b45b1431..3b8e3330 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java
@@ -50,18 +50,13 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
WorldVectorFace pos = getTargetFace(player);
if (pos == null) return false;
EditSession eS = session.createEditSession(player);
- try {
- if (secondary.getType() == BlockID.AIR) {
- eS.setBlock(pos, secondary);
- } else {
- eS.setBlock(pos.getFaceVector(), secondary);
- }
- eS.flushQueue();
- return true;
- } catch (MaxChangedBlocksException e) {
- // one block? eat it
+ if (secondary.getType() == BlockID.AIR) {
+ eS.setBlockFast(pos, secondary);
+ } else {
+ eS.setBlockFast(pos.getFaceVector(), secondary);
}
- return false;
+ eS.flushQueue();
+ return true;
}
@@ -70,18 +65,13 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
WorldVectorFace pos = getTargetFace(player);
if (pos == null) return false;
EditSession eS = session.createEditSession(player);
- try {
- if (primary.getType() == BlockID.AIR) {
- eS.setBlock(pos, primary);
- } else {
- eS.setBlock(pos.getFaceVector(), primary);
- }
- eS.flushQueue();
- return true;
- } catch (MaxChangedBlocksException e) {
- // one block? eat it
+ if (primary.getType() == BlockID.AIR) {
+ eS.setBlockFast(pos, primary);
+ } else {
+ eS.setBlockFast(pos.getFaceVector(), primary);
}
- return false;
+ eS.flushQueue();
+ return true;
}
public WorldVectorFace getTargetFace(Player player) {
diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java b/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java
index 777a05ce..927fc7fa 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java
@@ -66,9 +66,9 @@ public class GravityBrush implements Brush {
if (block != EditSession.nullBlock && (mask == null || mask.test(mutablePos))) {
if (freeSpot != y) {
mutablePos.y = freeSpot;
- editSession.setBlock(mutablePos, block);
+ editSession.setBlockFast(mutablePos, block);
mutablePos.y = y;
- editSession.setBlock(mutablePos, EditSession.nullBlock);
+ editSession.setBlockFast(mutablePos, EditSession.nullBlock);
}
freeSpot++;
}
diff --git a/core/src/main/java/net/jpountz/lz4/LZ4StreamTest.java b/core/src/main/java/net/jpountz/lz4/LZ4StreamTest.java
index 5bc47412..160f8549 100644
--- a/core/src/main/java/net/jpountz/lz4/LZ4StreamTest.java
+++ b/core/src/main/java/net/jpountz/lz4/LZ4StreamTest.java
@@ -1,7 +1,7 @@
package net.jpountz.lz4;
-import com.boydti.fawe.object.io.FastByteArrayInputStream;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
+import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.boydti.fawe.util.MainUtil;
import java.io.IOException;
import java.io.InputStream;
@@ -19,7 +19,7 @@ public class LZ4StreamTest {
private Random rand;
private byte randomContent[];
- private byte compressedOutput[];
+ private byte compressedOutput[][];
@Before
public void setUp() throws IOException {
@@ -69,13 +69,13 @@ public class LZ4StreamTest {
os.close();
- compressedOutput = compressedOutputStream.toByteArray();
+ compressedOutput = compressedOutputStream.toByteArrays();
}
@Test
public void randomizedTest() throws IOException {
try {
- InputStream is = new LZ4InputStream(new FastByteArrayInputStream(compressedOutput));
+ InputStream is = new LZ4InputStream(new FastByteArraysInputStream(compressedOutput));
int currentContentPosition = 0;