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
This commit is contained in:
Jesse Boyd 2016-09-15 19:49:29 +10:00
parent 911e7e7751
commit f55a58a3f3
20 changed files with 583 additions and 408 deletions

View File

@ -23,7 +23,7 @@ ext {
git = org.ajoberstar.grgit.Grgit.open(file(".git")) git = org.ajoberstar.grgit.Grgit.open(file(".git"))
revision = "-${git.head().abbreviatedId}" revision = "-${git.head().abbreviatedId}"
parents = git.head().parentIds; parents = git.head().parentIds;
index = -43; // Offset to mach CI index = -45; // Offset to mach CI
for (;parents != null && !parents.isEmpty();index++) { for (;parents != null && !parents.isEmpty();index++) {
commit = git.getResolve().toCommit(parents.get(0)); commit = git.getResolve().toCommit(parents.get(0));
parents = commit.getParentIds(); parents = commit.getParentIds();

View File

@ -2,29 +2,8 @@ package com.boydti.fawe.bukkit.v1_10;
import com.boydti.fawe.bukkit.ABukkitMain; import com.boydti.fawe.bukkit.ABukkitMain;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0; 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.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 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 { public class BukkitMain_110 extends ABukkitMain {
@Override @Override
@ -40,128 +19,5 @@ public class BukkitMain_110 extends ABukkitMain {
@Override @Override
public void onEnable() { public void onEnable() {
super.onEnable(); super.onEnable();
if (Settings.EXPERIMENTAL.WORLD_COMPRESSION != -1) {
try {
ReflectionUtils.setFailsafeFieldValue(RegionFileCache.class.getDeclaredField("a"), null, new ConcurrentHashMap<File, RegionFile>(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<Boolean> 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();
}
}
} }
} }

View File

@ -199,11 +199,6 @@ public class Settings extends Config {
"Directly modify the region files.", "Directly modify the region files.",
}) })
public static boolean ANVIL_QUEUE_MODE = false; 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 { public static class WEB {

View File

@ -206,7 +206,6 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
public void end(FaweChunk chunk) { public void end(FaweChunk chunk) {
chunk.end(); chunk.end();
sendChunk(chunk);
} }
@Override @Override

View File

@ -259,7 +259,7 @@ public class MCAFile {
} }
FastByteArrayOutputStream baos = new FastByteArrayOutputStream(0); FastByteArrayOutputStream baos = new FastByteArrayOutputStream(0);
fieldBuf4.set(baos, buffer3); 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); fieldBuf5.set(deflater, buffer2);
BufferedOutputStream bos = new BufferedOutputStream(deflater, 1); BufferedOutputStream bos = new BufferedOutputStream(deflater, 1);
fieldBuf6.set(bos, buffer1); fieldBuf6.set(bos, buffer1);

View File

@ -3,8 +3,8 @@ package com.boydti.fawe.object.changeset;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweInputStream; import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream; 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.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
@ -21,23 +21,24 @@ import java.io.OutputStream;
*/ */
public class MemoryOptimizedHistory extends FaweStreamChangeSet { public class MemoryOptimizedHistory extends FaweStreamChangeSet {
private byte[] ids; private int size = 0;
private byte[][] ids;
private FastByteArrayOutputStream idsStream; private FastByteArrayOutputStream idsStream;
private FaweOutputStream idsStreamZip; private FaweOutputStream idsStreamZip;
private byte[] entC; private byte[][] entC;
private FastByteArrayOutputStream entCStream; private FastByteArrayOutputStream entCStream;
private NBTOutputStream entCStreamZip; private NBTOutputStream entCStreamZip;
private byte[] entR; private byte[][] entR;
private FastByteArrayOutputStream entRStream; private FastByteArrayOutputStream entRStream;
private NBTOutputStream entRStreamZip; private NBTOutputStream entRStreamZip;
private byte[] tileC; private byte[][] tileC;
private FastByteArrayOutputStream tileCStream; private FastByteArrayOutputStream tileCStream;
private NBTOutputStream tileCStreamZip; private NBTOutputStream tileCStreamZip;
private byte[] tileR; private byte[][] tileR;
private FastByteArrayOutputStream tileRStream; private FastByteArrayOutputStream tileRStream;
private NBTOutputStream tileRStreamZip; private NBTOutputStream tileRStreamZip;
@ -51,31 +52,32 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
try { try {
if (idsStream != null) { if (idsStream != null) {
idsStreamZip.close(); idsStreamZip.close();
ids = idsStream.toByteArray(); size = idsStream.getSize();
ids = idsStream.toByteArrays();
idsStream = null; idsStream = null;
idsStreamZip = null; idsStreamZip = null;
} }
if (entCStream != null) { if (entCStream != null) {
entCStreamZip.close(); entCStreamZip.close();
entC = entCStream.toByteArray(); entC = entCStream.toByteArrays();
entCStream = null; entCStream = null;
entCStreamZip = null; entCStreamZip = null;
} }
if (entRStream != null) { if (entRStream != null) {
entRStreamZip.close(); entRStreamZip.close();
entR = entRStream.toByteArray(); entR = entRStream.toByteArrays();
entRStream = null; entRStream = null;
entRStreamZip = null; entRStreamZip = null;
} }
if (tileCStream != null) { if (tileCStream != null) {
tileCStreamZip.close(); tileCStreamZip.close();
tileC = tileCStream.toByteArray(); tileC = tileCStream.toByteArrays();
tileCStream = null; tileCStream = null;
tileCStreamZip = null; tileCStreamZip = null;
} }
if (tileRStream != null) { if (tileRStream != null) {
tileRStreamZip.close(); tileRStreamZip.close();
tileR = tileRStream.toByteArray(); tileR = tileRStream.toByteArrays();
tileRStream = null; tileRStream = null;
tileRStreamZip = null; tileRStreamZip = null;
} }
@ -115,7 +117,7 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
if (ids == null) { if (ids == null) {
return null; return null;
} }
FaweInputStream result = MainUtil.getCompressedIS(new FastByteArrayInputStream(ids)); FaweInputStream result = MainUtil.getCompressedIS(new FastByteArraysInputStream(ids));
result.skip(FaweStreamChangeSet.HEADER_SIZE); result.skip(FaweStreamChangeSet.HEADER_SIZE);
return result; return result;
} }
@ -158,21 +160,21 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
@Override @Override
public NBTInputStream getEntityCreateIS() throws IOException { 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 @Override
public NBTInputStream getEntityRemoveIS() throws IOException { 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 @Override
public NBTInputStream getTileCreateIS() throws IOException { 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 @Override
public NBTInputStream getTileRemoveIS() throws IOException { 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)));
} }
} }

View File

@ -1,96 +1,245 @@
package com.boydti.fawe.object.io; package com.boydti.fawe.object.io;
import com.boydti.fawe.util.ByteArrays;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; 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 { public class FastByteArrayOutputStream extends OutputStream {
/** private static final int DEFAULT_BLOCK_SIZE = 8192;
* The array backing the output stream.
*/
public final static int DEFAULT_INITIAL_CAPACITY = 16;
/** private ArrayDeque<byte[]> buffers = new ArrayDeque<>();
* The array backing the output stream.
*/
public byte[] array;
/** private byte[] buffer;
* The number of valid bytes in {@link #array}. private int blockSize;
*/ private int index;
public int length; 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() { public FastByteArrayOutputStream() {
this(DEFAULT_INITIAL_CAPACITY); this(DEFAULT_BLOCK_SIZE);
} }
/** public FastByteArrayOutputStream(int aSize) {
* Creates a new array output stream with a given initial capacity. blockSize = aSize;
* buffer = new byte[blockSize];
* @param initialCapacity the initial length of the backing array.
*/
public FastByteArrayOutputStream(final int initialCapacity) {
array = new byte[initialCapacity];
} }
/**
* Creates a new array output stream wrapping a given byte array. public int getSize() {
* return size + index;
* @param a the byte array to wrap.
*/
public FastByteArrayOutputStream(final byte[] a) {
array = a;
} }
/** public byte[][] toByteArrays() {
* Marks this array output stream as empty. if (index > 0) {
*/ byte[] buf2 = new byte[index];
public void reset() { System.arraycopy(buffer, 0, buf2, 0, index);
length = 0; buffers.addLast(buf2);
position = 0; 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() { public byte[] toByteArray(ExecutorCompletionService service) {
this.array = ByteArrays.trim(this.array, this.length); 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() { public byte[] toByteArray() {
trim(); byte[] data = new byte[getSize()];
return array;
// 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) { public String toString() {
if (position >= array.length) array = ByteArrays.grow(array, position + 1, length); return new String(toByteArray());
array[position++] = (byte) b;
if (length < position) length = position;
} }
public void write(final byte[] b, final int off, final int len) throws IOException { @Override
ByteArrays.ensureOffsetLength(b, off, len); public void write(byte[] b) throws IOException {
if (position + len > array.length) array = ByteArrays.grow(array, position + len, position); if (b.length > blockSize) {
System.arraycopy(b, off, array, position, len); if (index > 0) {
if (position + len > length) length = position += len; 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) { public void write(int datum) {
if (position > Integer.MAX_VALUE) throw new IllegalArgumentException("Position too large: " + newPosition); if (index == blockSize) {
position = (int) newPosition; addBuffer();
}
// store the byte
buffer[index++] = (byte) datum;
} }
public long position() { public void write(byte[] data, int offset, int length) throws IOException {
return position; 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 { public void writeTo(OutputStream out) throws IOException {
return length; // 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;
} }
} }

View File

@ -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;
}
}

View File

@ -59,7 +59,7 @@ public class FaweSchematicHandler extends SchematicHandler {
Location pos1 = corners[0]; Location pos1 = corners[0];
Location pos2 = corners[1]; 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 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 mx = pos1.getX();
final int my = pos1.getY(); final int my = pos1.getY();
@ -144,12 +144,13 @@ public class FaweSchematicHandler extends SchematicHandler {
@Override @Override
public void run(OutputStream output) { public void run(OutputStream output) {
try { try {
GZIPOutputStream gzip = new GZIPOutputStream(output, true); try (GZIPOutputStream gzip = new GZIPOutputStream(output, true)) {
com.sk89q.jnbt.CompoundTag weTag = (com.sk89q.jnbt.CompoundTag) FaweCache.asTag(tag); com.sk89q.jnbt.CompoundTag weTag = (com.sk89q.jnbt.CompoundTag) FaweCache.asTag(tag);
NBTOutputStream nos = new NBTOutputStream(gzip); try (NBTOutputStream nos = new NBTOutputStream(gzip)) {
Map<String, com.sk89q.jnbt.Tag> map = weTag.getValue(); Map<String, com.sk89q.jnbt.Tag> map = weTag.getValue();
nos.writeNamedTag("Schematic", map.containsKey("Schematic") ? map.get("Schematic") : weTag); nos.writeNamedTag("Schematic", map.containsKey("Schematic") ? map.get("Schematic") : weTag);
gzip.flush(); }
}
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.util; package com.boydti.fawe.util;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory; import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
@ -20,10 +19,12 @@ import java.util.UUID;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
public class EditSessionBuilder { public class EditSessionBuilder {
private World world; private World world;
private String worldName;
private FaweQueue queue; private FaweQueue queue;
private FawePlayer player; private FawePlayer player;
private FaweLimit limit; private FaweLimit limit;
@ -57,8 +58,9 @@ public class EditSessionBuilder {
this.world = world; this.world = world;
} }
public EditSessionBuilder(@Nonnull String world) { public EditSessionBuilder(@Nonnull String worldName) {
this(FaweAPI.getWorld(world)); checkNotNull(worldName);
this.worldName = worldName;
} }
public EditSessionBuilder player(@Nullable FawePlayer player) { public EditSessionBuilder player(@Nullable FawePlayer player) {
@ -164,6 +166,6 @@ public class EditSessionBuilder {
} }
public EditSession build() { 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);
} }
} }

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.util; package com.boydti.fawe.util;
import com.boydti.fawe.object.RunnableVal;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; 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 String BIN_URL = "http://hastebin.com/documents", USER_AGENT = "Mozilla/5.0";
public static final Pattern PATTERN = Pattern.compile("\\{\"key\":\"([\\S\\s]*)\"\\}"); 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<DataOutputStream> writeTask) throws IOException {
final URL url = new URL(BIN_URL); final URL url = new URL(BIN_URL);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST"); connection.setRequestMethod("POST");
connection.setRequestProperty("User-Agent", USER_AGENT); connection.setRequestProperty("User-Agent", USER_AGENT);
connection.setDoOutput(true); connection.setDoOutput(true);
try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { writeTask.run(os);
outputStream.write(string.getBytes());
outputStream.flush();
} }
StringBuilder response; StringBuilder response;
@ -47,6 +46,19 @@ public class HastebinUtility {
} }
} }
public static String upload(final String s) throws IOException {
return upload(new RunnableVal<DataOutputStream>() {
@Override
public void run(DataOutputStream value) {
try {
value.writeChars(s);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public static String upload(final File file) throws IOException { public static String upload(final File file) throws IOException {
final StringBuilder content = new StringBuilder(); final StringBuilder content = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
@ -57,6 +69,7 @@ public class HastebinUtility {
} }
} }
return upload(content.toString()); return upload(content.toString());
} }
} }

View File

@ -3,12 +3,10 @@ package com.boydti.fawe.wrappers;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EditSessionFactory; import com.sk89q.worldedit.EditSessionFactory;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.PlayerDirection; import com.sk89q.worldedit.PlayerDirection;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit; 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) { public void floatAt(final int x, final int y, final int z, final boolean alwaysGlass) {
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory(); EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
final EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this); final EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this);
try { edit.setBlockFast(new Vector(x, y - 1, z), new BaseBlock( BlockType.GLASS.getID()));
edit.setBlock(new Vector(x, y - 1, z), new BaseBlock( BlockType.GLASS.getID())); LocalSession session = Fawe.get().getWorldEdit().getSession(this);
LocalSession session = Fawe.get().getWorldEdit().getSession(this); if (session != null) {
if (session != null) { session.remember(edit, true, false, FawePlayer.wrap(this).getLimit().MAX_HISTORY);
session.remember(edit, true, false, FawePlayer.wrap(this).getLimit().MAX_HISTORY);
}
} catch (MaxChangedBlocksException e) {
MainUtil.handleError(e);
} }
TaskManager.IMP.sync(new RunnableVal<Object>() { TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override @Override

View File

@ -1,10 +1,6 @@
package com.boydti.fawe.wrappers; package com.boydti.fawe.wrappers;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.extent.FaweRegionExtent;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.BlockVector2D;
@ -22,7 +18,6 @@ import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
@ -31,7 +26,6 @@ import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.WorldData; import com.sk89q.worldedit.world.registry.WorldData;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class WorldWrapper extends LocalWorld { public class WorldWrapper extends LocalWorld {
@ -250,101 +244,7 @@ public class WorldWrapper extends LocalWorld {
@Override @Override
public boolean regenerate(final Region region, final EditSession session) { public boolean regenerate(final Region region, final EditSession session) {
final FaweQueue queue = session.getQueue(); return session.regenerate(region);
queue.setChangeTask(null);
final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet();
final FaweRegionExtent fe = session.getRegionExtent();
session.setSize(1);
final boolean cuboid = region instanceof CuboidRegion;
Set<Vector2D> 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<Vector2D> r = new RunnableVal<Vector2D>() {
@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 @Override

View File

@ -689,7 +689,7 @@ public class CuboidClipboard {
if (noAir && block.isAir()) { if (noAir && block.isAir()) {
continue; continue;
} }
editSession.setBlock(new Vector(x, y, z).add(newOrigin), block); editSession.setBlockFast(new Vector(x, y, z).add(newOrigin), block);
} }
} }
} }

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
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.config.Settings; import com.boydti.fawe.config.Settings;
@ -33,6 +34,7 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HistoryExtent; import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.NullChangeSet; import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet; import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.changeset.FaweChangeSet;
@ -46,8 +48,11 @@ import com.boydti.fawe.util.ExtentTraverser;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.Perm; import com.boydti.fawe.util.Perm;
import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.WorldWrapper; import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
@ -144,7 +149,7 @@ import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
* {@link Extent}s that are chained together. For example, history is logged * {@link Extent}s that are chained together. For example, history is logged
* using the {@link ChangeSetExtent}.</p> * using the {@link ChangeSetExtent}.</p>
*/ */
public class EditSession implements Extent { public class EditSession extends AbstractWorld {
/** /**
* Used by {@link #setBlock(Vector, BaseBlock, Stage)} to * Used by {@link #setBlock(Vector, BaseBlock, Stage)} to
* determine which {@link Extent}s should be bypassed. * determine which {@link Extent}s should be bypassed.
@ -154,6 +159,7 @@ public class EditSession implements Extent {
} }
private World world; private World world;
private String worldName;
private FaweQueue queue; private FaweQueue queue;
private AbstractDelegateExtent extent; private AbstractDelegateExtent extent;
private HistoryExtent history; private HistoryExtent history;
@ -182,7 +188,14 @@ public class EditSession implements Extent {
PlayerDirection.UP.vector(), PlayerDirection.UP.vector(),
PlayerDirection.DOWN.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) { 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); this.world = world = WorldWrapper.wrap((AbstractWorld) world);
if (bus == null) { if (bus == null) {
bus = WorldEdit.getInstance().getEventBus(); bus = WorldEdit.getInstance().getEventBus();
@ -255,7 +268,7 @@ public class EditSession implements Extent {
if (world instanceof MCAWorld) { if (world instanceof MCAWorld) {
queue = ((MCAWorld) world).getQueue(); queue = ((MCAWorld) world).getQueue();
} else { } 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)) { } else if (Settings.EXPERIMENTAL.ANVIL_QUEUE_MODE && !(queue instanceof MCAQueue)) {
queue = new MCAQueue(queue); queue = new MCAQueue(queue);
@ -283,7 +296,7 @@ public class EditSession implements Extent {
} }
} }
this.extent = wrapExtent(this.extent, bus, event, Stage.BEFORE_HISTORY); 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 * @param naturalOnly look at natural blocks or all blocks
* @return height of highest block found or 'minY' * @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) { for (int y = maxY; y >= minY; --y) {
BaseBlock block = getLazyBlock(x, y, z); BaseBlock block = getLazyBlock(x, y, z);
final int id = block.getId(); final int id = block.getId();
@ -956,7 +971,11 @@ public class EditSession implements Extent {
} }
@Override @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++; this.changes++;
try { try {
return this.extent.setBlock(position, block); return this.extent.setBlock(position, block);
@ -975,7 +994,7 @@ public class EditSession implements Extent {
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public boolean setBlock(final Vector position, final Pattern pattern) throws MaxChangedBlocksException { 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 @Deprecated
public boolean setBlockIfAir(final Vector position, final BaseBlock block) throws MaxChangedBlocksException { 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 @Override
@ -1756,15 +1775,16 @@ public class EditSession implements Extent {
checkNotNull(origin); checkNotNull(origin);
checkArgument(radius >= 0, "radius >= 0 required"); checkArgument(radius >= 0, "radius >= 0 required");
Mask liquidMask; Mask liquidMask;
if (getWorld() != null) { // Not thread safe, use hardcoded liquidmask
liquidMask = getWorld().createLiquidMask(); // if (getWorld() != null) {
} else { // liquidMask = getWorld().createLiquidMask();
// } else {
liquidMask = new BlockMask(this, liquidMask = new BlockMask(this,
new BaseBlock(BlockID.STATIONARY_LAVA, -1), new BaseBlock(BlockID.STATIONARY_LAVA, -1),
new BaseBlock(BlockID.LAVA, -1), new BaseBlock(BlockID.LAVA, -1),
new BaseBlock(BlockID.STATIONARY_WATER, -1), new BaseBlock(BlockID.STATIONARY_WATER, -1),
new BaseBlock(BlockID.WATER, -1)); new BaseBlock(BlockID.WATER, -1));
} // }
final MaskIntersection mask = new MaskIntersection( final MaskIntersection mask = new MaskIntersection(
new BoundedHeightMask(0, EditSession.this.getMaximumPoint().getBlockY()), new BoundedHeightMask(0, EditSession.this.getMaximumPoint().getBlockY()),
new RegionMask( new RegionMask(
@ -2471,7 +2491,7 @@ public class EditSession implements Extent {
// read block from world // read block from world
BaseBlock material = FaweCache.CACHE_BLOCK[this.queue.getCombinedId4DataDebug(sourcePosition.getBlockX(), sourcePosition.getBlockY(), sourcePosition.getBlockZ(), 0, this)]; BaseBlock material = FaweCache.CACHE_BLOCK[this.queue.getCombinedId4DataDebug(sourcePosition.getBlockX(), sourcePosition.getBlockY(), sourcePosition.getBlockZ(), 0, this)];
// queue operation // queue operation
this.setBlock(position, material); this.setBlockFast(position, material);
} }
return changes; return changes;
} }
@ -2545,7 +2565,7 @@ public class EditSession implements Extent {
continue outer; continue outer;
} }
} }
this.setBlock(position, pattern.next(position)); this.setBlockFast(position, pattern.next(position));
} }
return changes; return changes;
@ -2812,6 +2832,156 @@ public class EditSession implements Extent {
return (x * x) + (z * z); 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<Vector2D> 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<Vector2D> r = new RunnableVal<Vector2D>() {
@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() { public static Class<?> inject() {
return EditSession.class; return EditSession.class;
} }

View File

@ -32,7 +32,6 @@ import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
@ -353,11 +352,7 @@ public class ClipboardCommands {
pos.x += relx; pos.x += relx;
pos.y += rely; pos.y += rely;
pos.z += relz; pos.z += relz;
try { editSession.setBlockFast(pos, block);
editSession.setBlock(pos, block);
} catch (MaxChangedBlocksException e) {
throw new RuntimeException(e);
}
} }
}, !ignoreAirBlocks); }, !ignoreAirBlocks);
} else { } else {

View File

@ -99,14 +99,13 @@ public class SelectionCommands {
} else { } else {
pos = player.getBlockIn(); pos = player.getBlockIn();
} }
pos = pos.clampY(0, editSession.getMaximumPoint().getBlockY());
if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos, ActorSelectorLimits.forActor(player))) { if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos, ActorSelectorLimits.forActor(player))) {
BBC.SELECTOR_ALREADY_SET.send(player); BBC.SELECTOR_ALREADY_SET.send(player);
return; return;
} }
session.getRegionSelector(player.getWorld()) session.getRegionSelector(player.getWorld()).explainPrimarySelection(player, session, pos);
.explainPrimarySelection(player, session, pos);
} }
@Command( @Command(
@ -134,7 +133,7 @@ public class SelectionCommands {
} else { } else {
pos = player.getBlockIn(); pos = player.getBlockIn();
} }
pos = pos.clampY(0, editSession.getMaximumPoint().getBlockY());
if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos, ActorSelectorLimits.forActor(player))) { if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos, ActorSelectorLimits.forActor(player))) {
BBC.SELECTOR_ALREADY_SET.send(player); BBC.SELECTOR_ALREADY_SET.send(player);
return; return;

View File

@ -50,18 +50,13 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
WorldVectorFace pos = getTargetFace(player); WorldVectorFace pos = getTargetFace(player);
if (pos == null) return false; if (pos == null) return false;
EditSession eS = session.createEditSession(player); EditSession eS = session.createEditSession(player);
try { if (secondary.getType() == BlockID.AIR) {
if (secondary.getType() == BlockID.AIR) { eS.setBlockFast(pos, secondary);
eS.setBlock(pos, secondary); } else {
} else { eS.setBlockFast(pos.getFaceVector(), secondary);
eS.setBlock(pos.getFaceVector(), secondary);
}
eS.flushQueue();
return true;
} catch (MaxChangedBlocksException e) {
// one block? eat it
} }
return false; eS.flushQueue();
return true;
} }
@ -70,18 +65,13 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
WorldVectorFace pos = getTargetFace(player); WorldVectorFace pos = getTargetFace(player);
if (pos == null) return false; if (pos == null) return false;
EditSession eS = session.createEditSession(player); EditSession eS = session.createEditSession(player);
try { if (primary.getType() == BlockID.AIR) {
if (primary.getType() == BlockID.AIR) { eS.setBlockFast(pos, primary);
eS.setBlock(pos, primary); } else {
} else { eS.setBlockFast(pos.getFaceVector(), primary);
eS.setBlock(pos.getFaceVector(), primary);
}
eS.flushQueue();
return true;
} catch (MaxChangedBlocksException e) {
// one block? eat it
} }
return false; eS.flushQueue();
return true;
} }
public WorldVectorFace getTargetFace(Player player) { public WorldVectorFace getTargetFace(Player player) {

View File

@ -66,9 +66,9 @@ public class GravityBrush implements Brush {
if (block != EditSession.nullBlock && (mask == null || mask.test(mutablePos))) { if (block != EditSession.nullBlock && (mask == null || mask.test(mutablePos))) {
if (freeSpot != y) { if (freeSpot != y) {
mutablePos.y = freeSpot; mutablePos.y = freeSpot;
editSession.setBlock(mutablePos, block); editSession.setBlockFast(mutablePos, block);
mutablePos.y = y; mutablePos.y = y;
editSession.setBlock(mutablePos, EditSession.nullBlock); editSession.setBlockFast(mutablePos, EditSession.nullBlock);
} }
freeSpot++; freeSpot++;
} }

View File

@ -1,7 +1,7 @@
package net.jpountz.lz4; package net.jpountz.lz4;
import com.boydti.fawe.object.io.FastByteArrayInputStream;
import com.boydti.fawe.object.io.FastByteArrayOutputStream; import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -19,7 +19,7 @@ public class LZ4StreamTest {
private Random rand; private Random rand;
private byte randomContent[]; private byte randomContent[];
private byte compressedOutput[]; private byte compressedOutput[][];
@Before @Before
public void setUp() throws IOException { public void setUp() throws IOException {
@ -69,13 +69,13 @@ public class LZ4StreamTest {
os.close(); os.close();
compressedOutput = compressedOutputStream.toByteArray(); compressedOutput = compressedOutputStream.toByteArrays();
} }
@Test @Test
public void randomizedTest() throws IOException { public void randomizedTest() throws IOException {
try { try {
InputStream is = new LZ4InputStream(new FastByteArrayInputStream(compressedOutput)); InputStream is = new LZ4InputStream(new FastByteArraysInputStream(compressedOutput));
int currentContentPosition = 0; int currentContentPosition = 0;