mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 21:56:33 +01:00
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
This commit is contained in:
parent
911e7e7751
commit
f55a58a3f3
@ -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();
|
||||
|
@ -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<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -206,7 +206,6 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
|
||||
public void end(FaweChunk chunk) {
|
||||
chunk.end();
|
||||
sendChunk(chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
@ -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<byte[]> 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<String, com.sk89q.jnbt.Tag> 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<String, com.sk89q.jnbt.Tag> map = weTag.getValue();
|
||||
nos.writeNamedTag("Schematic", map.containsKey("Schematic") ? map.get("Schematic") : weTag);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<DataOutputStream> 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<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 {
|
||||
final StringBuilder content = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
@ -57,6 +69,7 @@ public class HastebinUtility {
|
||||
}
|
||||
}
|
||||
return upload(content.toString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Object>() {
|
||||
@Override
|
||||
|
@ -1,10 +1,6 @@
|
||||
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.changeset.FaweChangeSet;
|
||||
import com.boydti.fawe.object.extent.FaweRegionExtent;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
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.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
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.registry.WorldData;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class WorldWrapper extends LocalWorld {
|
||||
@ -250,101 +244,7 @@ public class WorldWrapper extends LocalWorld {
|
||||
|
||||
@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;
|
||||
return session.regenerate(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -689,7 +689,7 @@ public class CuboidClipboard {
|
||||
if (noAir && block.isAir()) {
|
||||
continue;
|
||||
}
|
||||
editSession.setBlock(new Vector(x, y, z).add(newOrigin), block);
|
||||
editSession.setBlockFast(new Vector(x, y, z).add(newOrigin), block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
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.NullChangeSet;
|
||||
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.DiskStorageHistory;
|
||||
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.Perm;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
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
|
||||
* using the {@link ChangeSetExtent}.</p>
|
||||
*/
|
||||
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<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() {
|
||||
return EditSession.class;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user