mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 01:37:37 +00:00
finish overhaul of NBT stream api
This commit is contained in:
parent
9cf02fe654
commit
f0ab1d5f18
@ -1,90 +0,0 @@
|
|||||||
package com.boydti.fawe.jnbt;
|
|
||||||
|
|
||||||
import com.boydti.fawe.FaweCache;
|
|
||||||
import com.boydti.fawe.config.BBC;
|
|
||||||
import com.boydti.fawe.object.exception.FaweException;
|
|
||||||
|
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
public class NBTStreamer {
|
|
||||||
private final NBTInputStream is;
|
|
||||||
private final HashMap<String, BiConsumer> readers;
|
|
||||||
|
|
||||||
public NBTStreamer(NBTInputStream stream) {
|
|
||||||
this.is = stream;
|
|
||||||
readers = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the entire stream and runs the applicable readers
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void readFully() throws IOException {
|
|
||||||
is.readNamedTagLazy(readers::get);
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the stream until all readers have been used<br>
|
|
||||||
* - Use readFully if you expect a reader to appear more than once
|
|
||||||
* - Can exit early without having reading the entire file
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void readQuick() throws IOException {
|
|
||||||
try {
|
|
||||||
is.readNamedTagLazy(node -> {
|
|
||||||
if (readers.isEmpty()) {
|
|
||||||
throw FaweCache.MANUAL;
|
|
||||||
}
|
|
||||||
return readers.remove(node);
|
|
||||||
});
|
|
||||||
} catch (FaweException ignore) {}
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T, V> void addReader(String node, BiConsumer<T, V> run) {
|
|
||||||
if (run instanceof NBTStreamReader) {
|
|
||||||
((NBTStreamReader) run).init(node);
|
|
||||||
}
|
|
||||||
readers.put(node, run);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static abstract class NBTStreamReader<T, V> implements BiConsumer<T, V> {
|
|
||||||
private String node;
|
|
||||||
|
|
||||||
public void init(String node) {
|
|
||||||
this.node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNode() {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static abstract class ByteReader implements BiConsumer<Integer, Integer> {
|
|
||||||
@Override
|
|
||||||
public void accept(Integer index, Integer value) {
|
|
||||||
run(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void run(int index, int byteValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface LazyReader extends BiConsumer<Integer, DataInputStream> {}
|
|
||||||
|
|
||||||
public static abstract class LongReader implements BiConsumer<Integer, Long> {
|
|
||||||
@Override
|
|
||||||
public void accept(Integer index, Long value) {
|
|
||||||
run(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void run(int index, long byteValue);
|
|
||||||
}
|
|
||||||
}
|
|
@ -81,10 +81,10 @@ public class SchematicStreamer extends NBTStreamer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
addReader("Schematic.Blocks.?", idInit);
|
addReader("Schematic.Blocks", NBTStreamer.ReadType.INFO, idInit);
|
||||||
addReader("Schematic.Data.?", dataInit);
|
addReader("Schematic.Data", NBTStreamer.ReadType.INFO, dataInit);
|
||||||
addReader("Schematic.AddBlocks.?", addInit);
|
addReader("Schematic.AddBlocks", NBTStreamer.ReadType.INFO, addInit);
|
||||||
addReader("Schematic.Blocks.#", new ByteReader() {
|
addReader("Schematic.Blocks", NBTStreamer.ReadType.ELEM, new ByteReader() {
|
||||||
@Override
|
@Override
|
||||||
public void run(int index, int value) {
|
public void run(int index, int value) {
|
||||||
try {
|
try {
|
||||||
@ -94,7 +94,7 @@ public class SchematicStreamer extends NBTStreamer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
addReader("Schematic.Data.#", new ByteReader() {
|
addReader("Schematic.Data", NBTStreamer.ReadType.ELEM, new ByteReader() {
|
||||||
@Override
|
@Override
|
||||||
public void run(int index, int value) {
|
public void run(int index, int value) {
|
||||||
try {
|
try {
|
||||||
@ -104,7 +104,7 @@ public class SchematicStreamer extends NBTStreamer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
addReader("Schematic.AddBlocks.#", new ByteReader() {
|
addReader("Schematic.AddBlocks", NBTStreamer.ReadType.ELEM, new ByteReader() {
|
||||||
@Override
|
@Override
|
||||||
public void run(int index, int value) {
|
public void run(int index, int value) {
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
@ -134,13 +134,13 @@ public class SchematicStreamer extends NBTStreamer {
|
|||||||
if (fc == null) setupClipboard(length * width * height);
|
if (fc == null) setupClipboard(length * width * height);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
addReader("Schematic.AWEBiomes.?", initializer23);
|
addReader("Schematic.AWEBiomes", NBTStreamer.ReadType.INFO,initializer23);
|
||||||
addReader("Schematic.Biomes.?", initializer23);
|
addReader("Schematic.Biomes", NBTStreamer.ReadType.INFO,initializer23);
|
||||||
addReader("Schematic.AWEBiomes.#", biomeReader); // AWE stores as an int[]
|
addReader("Schematic.AWEBiomes", NBTStreamer.ReadType.ELEM,biomeReader); // AWE stores as an int[]
|
||||||
addReader("Schematic.Biomes.#", biomeReader); // FAWE stores as a byte[] (4x smaller)
|
addReader("Schematic.Biomes", NBTStreamer.ReadType.ELEM,biomeReader); // FAWE stores as a byte[] (4x smaller)
|
||||||
|
|
||||||
// Tiles
|
// Tiles
|
||||||
addReader("Schematic.TileEntities.#", (BiConsumer<Integer, CompoundTag>) (index, value) -> {
|
addReader("Schematic.TileEntities", NBTStreamer.ReadType.ELEM,(BiConsumer<Integer, CompoundTag>) (index, value) -> {
|
||||||
if (fc == null) {
|
if (fc == null) {
|
||||||
setupClipboard(0);
|
setupClipboard(0);
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ public class SchematicStreamer extends NBTStreamer {
|
|||||||
fc.setTile(x, y, z, value);
|
fc.setTile(x, y, z, value);
|
||||||
});
|
});
|
||||||
// Entities
|
// Entities
|
||||||
addReader("Schematic.Entities.#", (BiConsumer<Integer, CompoundTag>) (index, compound) -> {
|
addReader("Schematic.Entities", NBTStreamer.ReadType.ELEM,(BiConsumer<Integer, CompoundTag>) (index, compound) -> {
|
||||||
if (fc == null) {
|
if (fc == null) {
|
||||||
setupClipboard(0);
|
setupClipboard(0);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
public interface ElemReader<T> extends StreamReader<T> {
|
||||||
|
void apply(int index, T value);
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
public interface InfoReader extends StreamReader<Integer> {
|
||||||
|
void apply(int length, int type);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void apply(int i, Integer value) {
|
||||||
|
apply(i, value.intValue());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
public interface IntValueReader extends ValueReader<Integer> {
|
||||||
|
void applyInt(int index, int value);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void apply(int index, Integer value) {
|
||||||
|
applyInt(index, value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
|
||||||
|
public interface LazyReader extends StreamReader<DataInputStream> {
|
||||||
|
void apply(int index, NBTInputStream stream);
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
public interface LongValueReader extends ValueReader<Long> {
|
||||||
|
void applyLong(int index, long value);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void apply(int index, Long value) {
|
||||||
|
applyLong(index, value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
public enum ReaderType {
|
||||||
|
VALUE,
|
||||||
|
INFO,
|
||||||
|
ELEM,
|
||||||
|
}
|
@ -0,0 +1,224 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.NBTConstants;
|
||||||
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class StreamDelegate {
|
||||||
|
private static final byte[][] ZERO_KEYS = new byte[0][];
|
||||||
|
private static final StreamDelegate[] ZERO_VALUES = new StreamDelegate[0];
|
||||||
|
|
||||||
|
private byte[] buffer;
|
||||||
|
private byte[][] keys;
|
||||||
|
private StreamDelegate[] values;
|
||||||
|
|
||||||
|
private LazyReader lazyReader;
|
||||||
|
private ElemReader elemReader;
|
||||||
|
private InfoReader infoReader;
|
||||||
|
private ValueReader valueReader;
|
||||||
|
|
||||||
|
public StreamDelegate() {
|
||||||
|
keys = ZERO_KEYS;
|
||||||
|
values = ZERO_VALUES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate addAndGetParent(String name) {
|
||||||
|
add(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate add() {
|
||||||
|
return add("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate add(String name) {
|
||||||
|
return add(name, new StreamDelegate());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StreamDelegate add(String name, StreamDelegate scope) {
|
||||||
|
if (valueReader != null) {
|
||||||
|
System.out.println("Scope " + name + " | " + scope + " may not run, as the stream is only read once, and a value reader is already set");
|
||||||
|
}
|
||||||
|
byte[] bytes = name.getBytes(NBTConstants.CHARSET);
|
||||||
|
int maxSize = bytes.length;
|
||||||
|
|
||||||
|
byte[][] tmpKeys = new byte[keys.length + 1][];
|
||||||
|
StreamDelegate[] tmpValues = new StreamDelegate[keys.length + 1];
|
||||||
|
tmpKeys[keys.length] = bytes;
|
||||||
|
tmpValues[keys.length] = scope;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < keys.length; i++) {
|
||||||
|
byte[] key = keys[i];
|
||||||
|
if (key.length >= bytes.length) {
|
||||||
|
tmpKeys[i] = bytes;
|
||||||
|
tmpValues[i] = scope;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmpKeys[i] = key;
|
||||||
|
tmpValues[i] = values[i];
|
||||||
|
maxSize = Math.max(maxSize, key.length);
|
||||||
|
}
|
||||||
|
for (; i < keys.length; i++) {
|
||||||
|
byte[] key = keys[i];
|
||||||
|
tmpKeys[i + 1] = key;
|
||||||
|
tmpValues[i + 1] = values[i];
|
||||||
|
maxSize = Math.max(maxSize, key.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.keys = tmpKeys;
|
||||||
|
this.values = tmpValues;
|
||||||
|
if (this.buffer == null || buffer.length < maxSize) {
|
||||||
|
buffer = new byte[maxSize];
|
||||||
|
}
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate get0() {
|
||||||
|
if (keys.length > 0 && keys[0].length == 0) {
|
||||||
|
return values[0];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate get(DataInputStream is) throws IOException {
|
||||||
|
int nameLength = is.readShort() & 0xFFFF;
|
||||||
|
if (nameLength == 0 && keys.length > 0 && keys[0].length == 0) {
|
||||||
|
return values[0];
|
||||||
|
}
|
||||||
|
if (nameLength > buffer.length) {
|
||||||
|
is.skipBytes(nameLength);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
outer:
|
||||||
|
switch (keys.length) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
for (; index < keys.length; index++) {
|
||||||
|
byte[] key = keys[index];
|
||||||
|
if (key.length < nameLength) continue;
|
||||||
|
if (key.length == nameLength) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index != keys.length - 1) {
|
||||||
|
int max;
|
||||||
|
for (max = index + 1; max < keys.length;) {
|
||||||
|
byte[] key = keys[max];
|
||||||
|
if (key.length == nameLength) {
|
||||||
|
max++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (index != max) {
|
||||||
|
is.readFully(buffer, 0, nameLength);
|
||||||
|
middle:
|
||||||
|
for (int i = index; i < max; i++) {
|
||||||
|
byte[] key = keys[i];
|
||||||
|
for (int j = 0; j < nameLength; j++) {
|
||||||
|
if (buffer[j] != key[j]) {
|
||||||
|
continue middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
byte[] key = keys[index];
|
||||||
|
if (key.length == nameLength) {
|
||||||
|
int i = 0;
|
||||||
|
for (; nameLength > 0; nameLength--, i++) {
|
||||||
|
byte b = is.readByte();
|
||||||
|
buffer[i] = b;
|
||||||
|
if (b != key[i]) {
|
||||||
|
nameLength--;
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return values[index];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is.skipBytes(nameLength);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate withLong(LongValueReader valueReader) {
|
||||||
|
return withValue(valueReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate withInt(IntValueReader valueReader) {
|
||||||
|
return withValue(valueReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate withValue(ValueReader valueReader) {
|
||||||
|
if (keys.length != 0) {
|
||||||
|
System.out.println("Reader " + valueReader + " may not run, as the stream is only read once, and a value reader is already set");
|
||||||
|
}
|
||||||
|
this.valueReader = valueReader;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate withStream(LazyReader lazyReader) {
|
||||||
|
this.lazyReader = lazyReader;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate withElem(ElemReader elemReader) {
|
||||||
|
this.elemReader = elemReader;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate withInfo(InfoReader infoReader) {
|
||||||
|
this.infoReader = infoReader;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void acceptRoot(NBTInputStream is, int type, int depth) throws IOException {
|
||||||
|
if (lazyReader != null) {
|
||||||
|
lazyReader.apply(0, is);
|
||||||
|
} else if (elemReader != null) {
|
||||||
|
Object raw = is.readTagPaylodRaw(type, depth);
|
||||||
|
elemReader.apply(0, raw);
|
||||||
|
} else if (valueReader != null) {
|
||||||
|
Object raw = is.readTagPaylodRaw(type, depth);
|
||||||
|
valueReader.apply(0, raw);
|
||||||
|
} else {
|
||||||
|
is.readTagPaylodLazy(type, depth + 1, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueReader getValueReader() {
|
||||||
|
return valueReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElemReader getElemReader() {
|
||||||
|
return elemReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void acceptInfo(int length, int type) {
|
||||||
|
if (infoReader != null) {
|
||||||
|
infoReader.apply(length, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean acceptLazy(int length, NBTInputStream is) {
|
||||||
|
if (lazyReader != null) {
|
||||||
|
lazyReader.apply(length, is);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
public interface StreamReader<T> {
|
||||||
|
void apply(int i, T value);
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
public interface ValueReader<T> extends StreamReader<T> {
|
||||||
|
void apply(int index, T value);
|
||||||
|
|
||||||
|
default void applyInt(int index, int value) {
|
||||||
|
apply(index, (T) (Integer) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void applyLong(int index, long value) {
|
||||||
|
apply(index, (T) (Long) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void applyFloat(int index, float value) {
|
||||||
|
apply(index, (T) (Float) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void applyDouble(int index, double value) {
|
||||||
|
apply(index, (T) (Double) value);
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,8 @@ import com.sk89q.jnbt.ListTag;
|
|||||||
import com.sk89q.jnbt.NBTConstants;
|
import com.sk89q.jnbt.NBTConstants;
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
import com.sk89q.jnbt.NBTOutputStream;
|
import com.sk89q.jnbt.NBTOutputStream;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
@ -31,6 +33,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -55,7 +58,27 @@ public class WritableMCAChunk implements IChunkSet {
|
|||||||
|
|
||||||
public WritableMCAChunk() {}
|
public WritableMCAChunk() {}
|
||||||
|
|
||||||
|
private boolean readLayer(Section section) {
|
||||||
|
if (section.palette == null || section.palette[section.palette.length - 1] == null || section.layer == -1 || section.blocks == null) {
|
||||||
|
// not initialized
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO load
|
||||||
|
section.layer = -1;
|
||||||
|
section.blocks = null;
|
||||||
|
section.palette = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Section {
|
||||||
|
public int layer = -1;
|
||||||
|
public long[] blocks;
|
||||||
|
public BlockState[] palette;
|
||||||
|
}
|
||||||
|
|
||||||
public WritableMCAChunk(NBTInputStream nis, int chunkX, int chunkZ, boolean readPos) throws IOException {
|
public WritableMCAChunk(NBTInputStream nis, int chunkX, int chunkZ, boolean readPos) throws IOException {
|
||||||
|
this.chunkX = chunkX;
|
||||||
|
this.chunkZ = chunkZ;
|
||||||
NBTStreamer streamer = new NBTStreamer(nis);
|
NBTStreamer streamer = new NBTStreamer(nis);
|
||||||
streamer.addReader(".Level.InhabitedTime", new RunnableVal2<Integer, Long>() {
|
streamer.addReader(".Level.InhabitedTime", new RunnableVal2<Integer, Long>() {
|
||||||
@Override
|
@Override
|
||||||
@ -69,21 +92,49 @@ public class WritableMCAChunk implements IChunkSet {
|
|||||||
lastUpdate = value;
|
lastUpdate = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
streamer.addReader(".Level.Sections.#", new RunnableVal2<Integer, CompoundTag>() {
|
|
||||||
|
|
||||||
|
Section section = new Section();
|
||||||
|
streamer.addReader(".Level.Sections.Y", new RunnableVal2<Integer, Byte>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Integer index, CompoundTag tag) {
|
public void run(Integer index, Byte y) {
|
||||||
int layer = tag.getByte("Y");
|
section.layer = y;
|
||||||
// "Palette"
|
readLayer(section);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
streamer.addReader(".Level.Sections.Palette.#", new RunnableVal2<Integer, CompoundTag>() {
|
streamer.addReader(".Level.Sections.Palette", NBTStreamer.ReadType.ELEM,new RunnableVal2<Integer, CompoundTag>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Integer index, CompoundTag entry) {
|
public void run(Integer index, CompoundTag compound) {
|
||||||
String name = entry.getString("Name");
|
String name = compound.getString("Name");
|
||||||
entry.
|
BlockType type = BlockTypes.get(name);
|
||||||
|
BlockState state = type.getDefaultState();
|
||||||
|
CompoundTag properties = (CompoundTag) compound.getValue().get("Properties");
|
||||||
|
if (properties != null) {
|
||||||
|
for (Map.Entry<String, Tag> entry : properties.getValue().entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = ((StringTag) entry.getValue()).getValue();
|
||||||
|
Property property = type.getProperty(key);
|
||||||
|
state = state.with(property, property.getValueFor(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.palette[index] = state;
|
||||||
|
readLayer(section);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
streamer.addReader(".Level.TileEntities.#", new RunnableVal2<Integer, CompoundTag>() {
|
streamer.addReader(".Level.Sections", NBTStreamer.ReadType.INFO,new RunnableVal2<Integer, Integer>() {
|
||||||
|
@Override
|
||||||
|
public void run(Integer value1, Integer value2) {
|
||||||
|
section.layer = -1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
streamer.addReader(".Level.Sections.BlockStates", new RunnableVal2<Integer, long[]>() {
|
||||||
|
@Override
|
||||||
|
public void run(Integer value1, long[] values) {
|
||||||
|
section.blocks = values;
|
||||||
|
readLayer(section);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
streamer.addReader(".Level.TileEntities", NBTStreamer.ReadType.ELEM,new RunnableVal2<Integer, CompoundTag>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Integer index, CompoundTag tile) {
|
public void run(Integer index, CompoundTag tile) {
|
||||||
int x = tile.getInt("x") & 15;
|
int x = tile.getInt("x") & 15;
|
||||||
@ -92,7 +143,7 @@ public class WritableMCAChunk implements IChunkSet {
|
|||||||
tiles.put(x, y, z, tile);
|
tiles.put(x, y, z, tile);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
streamer.addReader(".Level.Entities.#", new RunnableVal2<Integer, CompoundTag>() {
|
streamer.addReader(".Level.Entities", NBTStreamer.ReadType.ELEM,new RunnableVal2<Integer, CompoundTag>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Integer index, CompoundTag entityTag) {
|
public void run(Integer index, CompoundTag entityTag) {
|
||||||
long least = entityTag.getLong("UUIDLeast");
|
long least = entityTag.getLong("UUIDLeast");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.boydti.fawe.object.clipboard;
|
package com.boydti.fawe.object.clipboard;
|
||||||
|
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||||
import com.boydti.fawe.object.IntegerTrio;
|
import com.boydti.fawe.object.IntegerTrio;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
@ -8,7 +8,6 @@ import com.sk89q.jnbt.IntTag;
|
|||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
@ -16,8 +15,6 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -67,12 +64,12 @@ public class CPUOptimizedClipboard extends LinearClipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void streamBiomes(NBTStreamer.ByteReader task) {
|
public void streamBiomes(IntValueReader task) {
|
||||||
if (!hasBiomes()) return;
|
if (!hasBiomes()) return;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (int z = 0; z < getLength(); z++) {
|
for (int z = 0; z < getLength(); z++) {
|
||||||
for (int x = 0; x < getWidth(); x++, index++) {
|
for (int x = 0; x < getWidth(); x++, index++) {
|
||||||
task.run(index, biomes[index].getInternalId());
|
task.applyInt(index, biomes[index].getInternalId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,22 @@
|
|||||||
package com.boydti.fawe.object.clipboard;
|
package com.boydti.fawe.object.clipboard;
|
||||||
|
|
||||||
import com.boydti.fawe.beta.IBatchProcessor;
|
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
|
||||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.function.generator.GenBase;
|
|
||||||
import com.sk89q.worldedit.function.generator.Resource;
|
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
|
||||||
import com.sk89q.worldedit.function.operation.Operation;
|
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
|
||||||
import com.sk89q.worldedit.util.Countable;
|
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class DelegateClipboard implements Clipboard {
|
public class DelegateClipboard implements Clipboard {
|
||||||
@ -172,4 +157,9 @@ public class DelegateClipboard implements Clipboard {
|
|||||||
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||||
return parent.setBiome(x, y, z, biome);
|
return parent.setBiome(x, y, z, biome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
parent.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package com.boydti.fawe.object.clipboard;
|
|||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||||
import com.boydti.fawe.object.IntegerTrio;
|
import com.boydti.fawe.object.IntegerTrio;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
@ -197,14 +197,14 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void streamBiomes(NBTStreamer.ByteReader task) {
|
public void streamBiomes(IntValueReader task) {
|
||||||
if (!hasBiomes()) return;
|
if (!hasBiomes()) return;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int mbbIndex = HEADER_SIZE + (getVolume() << 1);
|
int mbbIndex = HEADER_SIZE + (getVolume() << 1);
|
||||||
for (int z = 0; z < getLength(); z++) {
|
for (int z = 0; z < getLength(); z++) {
|
||||||
for (int x = 0; x < getWidth(); x++, index++, mbbIndex++) {
|
for (int x = 0; x < getWidth(); x++, index++, mbbIndex++) {
|
||||||
int biome = byteBuffer.get(mbbIndex) & 0xFF;
|
int biome = byteBuffer.get(mbbIndex) & 0xFF;
|
||||||
task.run(index, biome);
|
task.applyInt(index, biome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
package com.boydti.fawe.object.clipboard;
|
package com.boydti.fawe.object.clipboard;
|
||||||
|
|
||||||
import com.boydti.fawe.beta.AbstractFilterBlock;
|
import com.boydti.fawe.beta.AbstractFilterBlock;
|
||||||
import com.boydti.fawe.beta.SingleFilterBlock;
|
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
|
||||||
import com.google.common.collect.ForwardingIterator;
|
import com.google.common.collect.ForwardingIterator;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.IntTag;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.collection.DoubleArrayList;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Best used when clipboard selections are small, or using legacy formats
|
* Best used when clipboard selections are small, or using legacy formats
|
||||||
@ -48,7 +39,7 @@ public abstract class LinearClipboard extends SimpleClipboard implements Clipboa
|
|||||||
* @param task
|
* @param task
|
||||||
* @param air
|
* @param air
|
||||||
*/
|
*/
|
||||||
public abstract void streamBiomes(NBTStreamer.ByteReader task);
|
public abstract void streamBiomes(IntValueReader task);
|
||||||
|
|
||||||
public abstract Collection<CompoundTag> getTileEntities();
|
public abstract Collection<CompoundTag> getTileEntities();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.boydti.fawe.object.clipboard;
|
package com.boydti.fawe.object.clipboard;
|
||||||
|
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||||
import com.boydti.fawe.object.IntegerTrio;
|
import com.boydti.fawe.object.IntegerTrio;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
@ -10,7 +10,6 @@ import com.sk89q.jnbt.IntTag;
|
|||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
@ -20,6 +19,8 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -29,10 +30,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.jpountz.util.SafeUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class MemoryOptimizedClipboard extends LinearClipboard {
|
public class MemoryOptimizedClipboard extends LinearClipboard {
|
||||||
|
|
||||||
private static final int BLOCK_SIZE = 1048576 * 2;
|
private static final int BLOCK_SIZE = 1048576 * 2;
|
||||||
@ -101,12 +98,12 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void streamBiomes(NBTStreamer.ByteReader task) {
|
public void streamBiomes(IntValueReader task) {
|
||||||
if (!hasBiomes()) return;
|
if (!hasBiomes()) return;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (int z = 0; z < getLength(); z++) {
|
for (int z = 0; z < getLength(); z++) {
|
||||||
for (int x = 0; x < getWidth(); x++, index++) {
|
for (int x = 0; x < getWidth(); x++, index++) {
|
||||||
task.run(index, biomes[index] & 0xFF);
|
task.applyInt(index, biomes[index] & 0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,14 @@
|
|||||||
package com.boydti.fawe.object.clipboard;
|
package com.boydti.fawe.object.clipboard;
|
||||||
|
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class ReadOnlyClipboard extends SimpleClipboard {
|
public abstract class ReadOnlyClipboard extends SimpleClipboard {
|
||||||
|
@ -72,7 +72,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ public class WorldCutClipboard extends WorldCopyClipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() {
|
||||||
if (extent instanceof EditSession) {
|
if (extent instanceof EditSession) {
|
||||||
((EditSession) extent).flushQueue();
|
((EditSession) extent).flushQueue();
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
package com.sk89q.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
import com.boydti.fawe.jnbt.streamer.ElemReader;
|
||||||
|
import com.boydti.fawe.jnbt.streamer.StreamDelegate;
|
||||||
|
import com.boydti.fawe.jnbt.streamer.ValueReader;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@ -29,8 +31,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
|
* This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
|
||||||
@ -86,19 +86,23 @@ public final class NBTInputStream implements Closeable {
|
|||||||
return readTagPayload(type, 0);
|
return readTagPayload(type, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readNamedTagLazy(Function<String, BiConsumer> getReader) throws IOException {
|
public void readNamedTagLazy(StreamDelegate scope) throws IOException {
|
||||||
int type = is.readByte();
|
try {
|
||||||
String name = readNamedTagName(type);
|
int type = is.readByte();
|
||||||
BiConsumer reader = getReader.apply(name);
|
if (type == NBTConstants.TYPE_END) return;
|
||||||
if (reader != null) {
|
|
||||||
reader.accept(0, readTagPaylodRaw(type, 0));
|
StreamDelegate child = scope.get(is);
|
||||||
return;
|
if (child != null) {
|
||||||
|
child.acceptRoot(this, type, 0);
|
||||||
|
} else {
|
||||||
|
readTagPaylodLazy(type, 0);
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
readTagPaylodLazy(type, 0, name, getReader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readNamedTagName(int type) throws IOException {
|
public String readNamedTagName(int type) throws IOException {
|
||||||
String name;
|
|
||||||
if (type != NBTConstants.TYPE_END) {
|
if (type != NBTConstants.TYPE_END) {
|
||||||
int nameLength = is.readShort() & 0xFFFF;
|
int nameLength = is.readShort() & 0xFFFF;
|
||||||
byte[] nameBytes = new byte[nameLength];
|
byte[] nameBytes = new byte[nameLength];
|
||||||
@ -111,7 +115,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
|
|
||||||
private byte[] buf;
|
private byte[] buf;
|
||||||
|
|
||||||
public void readTagPaylodLazy(int type, int depth, String node, Function<String, BiConsumer> getReader) throws IOException {
|
public void readTagPaylodLazy(int type, int depth) throws IOException {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NBTConstants.TYPE_END:
|
case NBTConstants.TYPE_END:
|
||||||
return;
|
return;
|
||||||
@ -134,22 +138,121 @@ public final class NBTInputStream implements Closeable {
|
|||||||
is.skipBytes(8);
|
is.skipBytes(8);
|
||||||
return;
|
return;
|
||||||
case NBTConstants.TYPE_STRING:
|
case NBTConstants.TYPE_STRING:
|
||||||
int length = is.readShort();
|
int length = is.readShort() & 0xFFFF;
|
||||||
is.skipBytes(length);
|
is.skipBytes(length);
|
||||||
return;
|
return;
|
||||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||||
BiConsumer reader = getReader.apply(node + ".?");
|
is.skipBytes(is.readInt());
|
||||||
|
return;
|
||||||
|
case NBTConstants.TYPE_LIST: {
|
||||||
|
int childType = is.readByte();
|
||||||
length = is.readInt();
|
length = is.readInt();
|
||||||
if (reader != null) {
|
for (int i = 0; i < length; ++i) {
|
||||||
reader.accept(length, NBTConstants.TYPE_BYTE);
|
readTagPaylodLazy(childType, depth + 1);
|
||||||
}
|
}
|
||||||
reader = getReader.apply(node + ".#");
|
return;
|
||||||
if (reader == null) {
|
}
|
||||||
|
case NBTConstants.TYPE_COMPOUND: {
|
||||||
|
// readDataPayload
|
||||||
|
depth++;
|
||||||
|
while(true) {
|
||||||
|
int childType = is.readByte();
|
||||||
|
if (childType == NBTConstants.TYPE_END) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is.skipBytes(is.readShort() & 0xFFFF);
|
||||||
|
readTagPaylodLazy(childType, depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_INT_ARRAY: {
|
||||||
|
is.skipBytes(is.readInt() << 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_LONG_ARRAY: {
|
||||||
|
is.skipBytes(is.readInt() << 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new IOException("Invalid tag type: " + type + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readTagPaylodLazy(int type, int depth, StreamDelegate scope) throws IOException {
|
||||||
|
switch (type) {
|
||||||
|
case NBTConstants.TYPE_END:
|
||||||
|
return;
|
||||||
|
case NBTConstants.TYPE_BYTE: {
|
||||||
|
ValueReader value = scope.getValueReader();
|
||||||
|
if (value != null) {
|
||||||
|
value.applyInt(0, is.readByte());
|
||||||
|
} else {
|
||||||
|
is.skipBytes(1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_SHORT: {
|
||||||
|
ValueReader value = scope.getValueReader();
|
||||||
|
if (value != null) {
|
||||||
|
value.applyInt(0, is.readShort());
|
||||||
|
} else {
|
||||||
|
is.skipBytes(2);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_INT: {
|
||||||
|
ValueReader value = scope.getValueReader();
|
||||||
|
if (value != null) {
|
||||||
|
value.applyInt(0, is.readInt());
|
||||||
|
} else {
|
||||||
|
is.skipBytes(4);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_LONG: {
|
||||||
|
ValueReader value = scope.getValueReader();
|
||||||
|
if (value != null) {
|
||||||
|
value.applyLong(0, is.readLong());
|
||||||
|
} else {
|
||||||
|
is.skipBytes(8);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_FLOAT: {
|
||||||
|
ValueReader value = scope.getValueReader();
|
||||||
|
if (value != null) {
|
||||||
|
value.applyFloat(0, is.readFloat());
|
||||||
|
} else {
|
||||||
|
is.skipBytes(4);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_DOUBLE: {
|
||||||
|
ValueReader value = scope.getValueReader();
|
||||||
|
if (value != null) {
|
||||||
|
value.applyDouble(0, is.readDouble());
|
||||||
|
} else {
|
||||||
|
is.skipBytes(8);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_STRING: {
|
||||||
|
ValueReader value = scope.getValueReader();
|
||||||
|
int length = is.readShort() & 0xFFFF;
|
||||||
|
if (value != null) {
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
is.readFully(bytes);
|
||||||
|
value.apply(0, new String(bytes, NBTConstants.CHARSET));
|
||||||
|
} else {
|
||||||
is.skipBytes(length);
|
is.skipBytes(length);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (reader instanceof NBTStreamer.ByteReader) {
|
return;
|
||||||
NBTStreamer.ByteReader byteReader = (NBTStreamer.ByteReader) reader;
|
}
|
||||||
|
case NBTConstants.TYPE_BYTE_ARRAY: {
|
||||||
|
int length = is.readInt();
|
||||||
|
scope.acceptInfo(length, NBTConstants.TYPE_BYTE);
|
||||||
|
if (scope.acceptLazy(length, this)) return;
|
||||||
|
ValueReader valueReader = scope.getValueReader();
|
||||||
|
if (valueReader != null) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
DataInputStream dis = is;
|
DataInputStream dis = is;
|
||||||
if (length > 1024) {
|
if (length > 1024) {
|
||||||
@ -160,109 +263,102 @@ public final class NBTInputStream implements Closeable {
|
|||||||
for (; left > 1024; left -= 1024) {
|
for (; left > 1024; left -= 1024) {
|
||||||
dis.readFully(buf);
|
dis.readFully(buf);
|
||||||
for (byte b : buf) {
|
for (byte b : buf) {
|
||||||
byteReader.run(i++, b & 0xFF);
|
valueReader.applyInt(i++, b & 0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; i < length; i++) {
|
for (; i < length; i++) {
|
||||||
byteReader.run(i, dis.read());
|
valueReader.applyInt(i, dis.read());
|
||||||
}
|
|
||||||
} else if (reader instanceof NBTStreamer.LazyReader) {
|
|
||||||
reader.accept(length, is);
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
reader.accept(i, is.readByte());
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
is.skipBytes(length);
|
||||||
return;
|
return;
|
||||||
case NBTConstants.TYPE_LIST:
|
}
|
||||||
|
case NBTConstants.TYPE_LIST: {
|
||||||
int childType = is.readByte();
|
int childType = is.readByte();
|
||||||
if (childType == NBTConstants.TYPE_LIST) {
|
int length = is.readInt();
|
||||||
childType = NBTConstants.TYPE_COMPOUND;
|
StreamDelegate child;
|
||||||
}
|
scope.acceptInfo(length, childType);
|
||||||
length = is.readInt();
|
ValueReader valueReader = scope.getValueReader();
|
||||||
reader = getReader.apply(node + ".?");
|
if (valueReader != null) {
|
||||||
if (reader != null) {
|
|
||||||
reader.accept(length, childType);
|
|
||||||
}
|
|
||||||
node += ".#";
|
|
||||||
reader = getReader.apply(node);
|
|
||||||
depth++;
|
|
||||||
if (reader == null) {
|
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
readTagPaylodLazy(childType, depth, node, getReader);
|
valueReader.apply(i, readTagPaylodRaw(childType, depth + 1));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < length; ++i) {
|
child = scope.get0();
|
||||||
reader.accept(i, readTagPayload(childType, depth));
|
if (child == null) {
|
||||||
}
|
for (int i = 0; i < length; ++i) {
|
||||||
return;
|
readTagPaylodLazy(childType, depth + 1);
|
||||||
case NBTConstants.TYPE_COMPOUND:
|
|
||||||
depth++;
|
|
||||||
// 3
|
|
||||||
for (int i = 0; ; i++) {
|
|
||||||
childType = is.readByte();
|
|
||||||
if (childType == NBTConstants.TYPE_END) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
String name = readNamedTagName(childType);
|
|
||||||
String childNode = node + "." + name;
|
|
||||||
reader = getReader.apply(childNode);
|
|
||||||
if (reader == null) {
|
|
||||||
readTagPaylodLazy(childType, depth, childNode, getReader);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
reader.accept(i, readTagPaylodRaw(childType, depth));
|
|
||||||
}
|
|
||||||
case NBTConstants.TYPE_INT_ARRAY: {
|
|
||||||
length = is.readInt();
|
|
||||||
reader = getReader.apply(node + ".?");
|
|
||||||
if (reader != null) {
|
|
||||||
reader.accept(length, NBTConstants.TYPE_INT);
|
|
||||||
}
|
|
||||||
reader = getReader.apply(node + ".#");
|
|
||||||
if (reader == null) {
|
|
||||||
is.skipBytes(length << 2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (reader instanceof NBTStreamer.ByteReader) {
|
|
||||||
NBTStreamer.ByteReader byteReader = (NBTStreamer.ByteReader) reader;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
byteReader.run(i, is.readInt());
|
|
||||||
}
|
|
||||||
} else if (reader instanceof NBTStreamer.LazyReader) {
|
|
||||||
reader.accept(length, is);
|
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; ++i) {
|
||||||
reader.accept(i, is.readInt());
|
readTagPaylodLazy(childType, depth + 1, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case NBTConstants.TYPE_LONG_ARRAY: {
|
case NBTConstants.TYPE_COMPOUND: {
|
||||||
length = is.readInt();
|
// readDataPayload
|
||||||
reader = getReader.apply(node + ".?");
|
depth++;
|
||||||
if (reader != null) {
|
scope.acceptInfo(-1, NBTConstants.TYPE_BYTE);
|
||||||
reader.accept(length, NBTConstants.TYPE_LONG);
|
ValueReader valueReader = scope.getValueReader();
|
||||||
}
|
if (valueReader != null) {
|
||||||
reader = getReader.apply(node + ".#");
|
valueReader.apply(0, this.readDataPayload(type, depth));
|
||||||
if (reader == null) {
|
|
||||||
is.skipBytes(length << 3);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (reader instanceof NBTStreamer.LongReader) {
|
ElemReader elem = scope.getElemReader();
|
||||||
NBTStreamer.LongReader longReader = (NBTStreamer.LongReader) reader;
|
if (elem != null) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; ; i++) {
|
||||||
longReader.run(i, is.readLong());
|
int childType = is.readByte();
|
||||||
}
|
if (childType == NBTConstants.TYPE_END) {
|
||||||
} else if (reader instanceof NBTStreamer.LazyReader) {
|
return;
|
||||||
reader.accept(length, is);
|
}
|
||||||
} else {
|
is.skipBytes(is.readShort() & 0xFFFF);
|
||||||
for (int i = 0; i < length; i++) {
|
Object child = readTagPaylodRaw(childType, depth);
|
||||||
reader.accept(i, is.readLong());
|
elem.apply(i, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while(true) {
|
||||||
|
int childType = is.readByte();
|
||||||
|
if (childType == NBTConstants.TYPE_END) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StreamDelegate child = scope.get(is);
|
||||||
|
if (child == null) {
|
||||||
|
readTagPaylodLazy(childType, depth + 1);
|
||||||
|
} else {
|
||||||
|
readTagPaylodLazy(childType, depth + 1, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_INT_ARRAY: {
|
||||||
|
int length = is.readInt();
|
||||||
|
scope.acceptInfo(length, NBTConstants.TYPE_INT);
|
||||||
|
if (scope.acceptLazy(length, this)) return;
|
||||||
|
ValueReader valueReader = scope.getValueReader();
|
||||||
|
if (valueReader != null) {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
valueReader.applyInt(i, is.readInt());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is.skipBytes(length << 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NBTConstants.TYPE_LONG_ARRAY: {
|
||||||
|
int length = is.readInt();
|
||||||
|
scope.acceptInfo(length, NBTConstants.TYPE_LONG);
|
||||||
|
if (scope.acceptLazy(length, this)) return;
|
||||||
|
ValueReader valueReader = scope.getValueReader();
|
||||||
|
if (valueReader != null) {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
valueReader.applyLong(i, is.readLong());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is.skipBytes(length << 3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +390,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object readTagPaylodRaw(int type, int depth) throws IOException {
|
public Object readTagPaylodRaw(int type, int depth) throws IOException {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NBTConstants.TYPE_END:
|
case NBTConstants.TYPE_END:
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
@ -327,9 +423,6 @@ public final class NBTInputStream implements Closeable {
|
|||||||
return (new String(bytes, NBTConstants.CHARSET));
|
return (new String(bytes, NBTConstants.CHARSET));
|
||||||
case NBTConstants.TYPE_LIST:
|
case NBTConstants.TYPE_LIST:
|
||||||
int childType = is.readByte();
|
int childType = is.readByte();
|
||||||
if (childType == NBTConstants.TYPE_LIST) {
|
|
||||||
childType = NBTConstants.TYPE_COMPOUND;
|
|
||||||
}
|
|
||||||
length = is.readInt();
|
length = is.readInt();
|
||||||
List<Tag> tagList = new ArrayList<>();
|
List<Tag> tagList = new ArrayList<>();
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
@ -432,9 +525,6 @@ public final class NBTInputStream implements Closeable {
|
|||||||
return new StringTag(new String(bytes, NBTConstants.CHARSET));
|
return new StringTag(new String(bytes, NBTConstants.CHARSET));
|
||||||
case NBTConstants.TYPE_LIST:
|
case NBTConstants.TYPE_LIST:
|
||||||
int childType = is.readByte();
|
int childType = is.readByte();
|
||||||
if (childType == NBTConstants.TYPE_LIST) {
|
|
||||||
childType = NBTConstants.TYPE_COMPOUND;
|
|
||||||
}
|
|
||||||
length = is.readInt();
|
length = is.readInt();
|
||||||
List<Tag> tagList = new ArrayList<>();
|
List<Tag> tagList = new ArrayList<>();
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
@ -514,9 +604,6 @@ public final class NBTInputStream implements Closeable {
|
|||||||
return new String(bytes, NBTConstants.CHARSET);
|
return new String(bytes, NBTConstants.CHARSET);
|
||||||
case NBTConstants.TYPE_LIST:
|
case NBTConstants.TYPE_LIST:
|
||||||
int childType = is.readByte();
|
int childType = is.readByte();
|
||||||
if (childType == NBTConstants.TYPE_LIST) {
|
|
||||||
childType = NBTConstants.TYPE_COMPOUND;
|
|
||||||
}
|
|
||||||
length = is.readInt();
|
length = is.readInt();
|
||||||
ArrayList<Object> list = new ArrayList<>();
|
ArrayList<Object> list = new ArrayList<>();
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
@ -526,22 +613,18 @@ public final class NBTInputStream implements Closeable {
|
|||||||
}
|
}
|
||||||
list.add(obj);
|
list.add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
case NBTConstants.TYPE_COMPOUND:
|
case NBTConstants.TYPE_COMPOUND:
|
||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
while (true) {
|
while (true) {
|
||||||
int newType = is.readByte();
|
int newType = is.readByte();
|
||||||
|
if (newType == NBTConstants.TYPE_END) {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
String name = readNamedTagName(newType);
|
String name = readNamedTagName(newType);
|
||||||
Object data = readDataPayload(newType, depth + 1);
|
Object data = readDataPayload(newType, depth + 1);
|
||||||
if (data == null) {
|
map.put(name, data);
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
map.put(name, data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
|
||||||
case NBTConstants.TYPE_INT_ARRAY: {
|
case NBTConstants.TYPE_INT_ARRAY: {
|
||||||
length = is.readInt();
|
length = is.readInt();
|
||||||
int[] data = new int[length];
|
int[] data = new int[length];
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
package com.sk89q.jnbt.anvil;
|
|
||||||
|
|
||||||
public class MCAWorld {
|
|
||||||
}
|
|
@ -77,13 +77,6 @@ public class BlockArrayClipboard extends DelegateClipboard implements Clipboard,
|
|||||||
this.origin = region.getMinimumPoint();
|
this.origin = region.getMinimumPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
if (getParent() instanceof Closeable) {
|
|
||||||
((Closeable) getParent()).close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Region getRegion() {
|
public Region getRegion() {
|
||||||
return region;
|
return region;
|
||||||
|
@ -34,6 +34,7 @@ import com.sk89q.worldedit.regions.Regions;
|
|||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.Closeable;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -41,7 +42,7 @@ import java.util.UUID;
|
|||||||
/**
|
/**
|
||||||
* Specifies an object that implements something suitable as a "clipboard."
|
* Specifies an object that implements something suitable as a "clipboard."
|
||||||
*/
|
*/
|
||||||
public interface Clipboard extends Extent, Iterable<BlockVector3> {
|
public interface Clipboard extends Extent, Iterable<BlockVector3>, Closeable {
|
||||||
static Clipboard create(BlockVector3 size, UUID uuid) {
|
static Clipboard create(BlockVector3 size, UUID uuid) {
|
||||||
if (Settings.IMP.CLIPBOARD.USE_DISK) {
|
if (Settings.IMP.CLIPBOARD.USE_DISK) {
|
||||||
return new DiskOptimizedClipboard(size, uuid);
|
return new DiskOptimizedClipboard(size, uuid);
|
||||||
@ -144,4 +145,9 @@ public interface Clipboard extends Extent, Iterable<BlockVector3> {
|
|||||||
return apply((Iterable<BlockVector3>) region, filter);
|
return apply((Iterable<BlockVector3>) region, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void close() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,56 +19,38 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extent.clipboard.io;
|
package com.sk89q.worldedit.extent.clipboard.io;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
import com.boydti.fawe.jnbt.streamer.StreamDelegate;
|
||||||
import com.boydti.fawe.jnbt.NBTStreamer.LazyReader;
|
import com.boydti.fawe.jnbt.streamer.ValueReader;
|
||||||
import com.boydti.fawe.object.FaweInputStream;
|
|
||||||
import com.boydti.fawe.object.FaweOutputStream;
|
|
||||||
import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
|
import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
|
||||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||||
import com.boydti.fawe.object.clipboard.LinearClipboard;
|
import com.boydti.fawe.object.clipboard.LinearClipboard;
|
||||||
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
|
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
|
||||||
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.IOUtil;
|
|
||||||
import com.sk89q.jnbt.ByteArrayTag;
|
import com.sk89q.jnbt.ByteArrayTag;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.IntTag;
|
import com.sk89q.jnbt.IntTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
import com.sk89q.jnbt.StringTag;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
|
||||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.util.Location;
|
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import org.slf4j.Logger;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import org.slf4j.LoggerFactory;
|
||||||
import com.sk89q.worldedit.world.entity.EntityType;
|
|
||||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads schematic files using the Sponge Schematic Specification.
|
* Reads schematic files using the Sponge Schematic Specification.
|
||||||
@ -149,140 +131,151 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
FastByteArrayOutputStream blocksOut = new FastByteArrayOutputStream();
|
FastByteArrayOutputStream blocksOut = new FastByteArrayOutputStream();
|
||||||
FastByteArrayOutputStream biomesOut = new FastByteArrayOutputStream();
|
FastByteArrayOutputStream biomesOut = new FastByteArrayOutputStream();
|
||||||
|
|
||||||
|
StreamDelegate root = new StreamDelegate();
|
||||||
|
StreamDelegate schematic = root.add("Schematic");
|
||||||
|
schematic.add("DataVersion").withInt((i, v) -> dataVersion = v);
|
||||||
|
schematic.add("Width").withInt((i, v) -> width = v);
|
||||||
|
schematic.add("Height").withInt((i, v) -> height = v);
|
||||||
|
schematic.add("Length").withInt((i, v) -> length = v);
|
||||||
|
schematic.add("Offset").withValue((ValueReader<int[]>) (index, v) -> min = BlockVector3.at(v[0], v[1], v[2]));
|
||||||
|
|
||||||
|
StreamDelegate metadata = schematic.add("Metadata");
|
||||||
|
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
|
||||||
|
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
|
||||||
|
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
|
||||||
|
|
||||||
|
StreamDelegate paletteDelegate = schematic.add("Palette");
|
||||||
|
paletteDelegate.withValue(new ValueReader<Map<String, Object>>() {
|
||||||
|
@Override
|
||||||
|
public void apply(int index, Map<String, Object> value) {
|
||||||
|
|
||||||
NBTStreamer streamer = new NBTStreamer(inputStream);
|
|
||||||
streamer.addReader("Schematic.DataVersion", (BiConsumer<Integer, Short>) (i, v) -> dataVersion = v);
|
|
||||||
streamer.addReader("Schematic.Width", (BiConsumer<Integer, Short>) (i, v) -> width = v);
|
|
||||||
streamer.addReader("Schematic.Height", (BiConsumer<Integer, Short>) (i, v) -> height = v);
|
|
||||||
streamer.addReader("Schematic.Length", (BiConsumer<Integer, Short>) (i, v) -> length = v);
|
|
||||||
streamer.addReader("Schematic.Offset", (BiConsumer<Integer, int[]>) (i, v) -> min = BlockVector3.at(v[0], v[1], v[2]));
|
|
||||||
streamer.addReader("Schematic.Metadata.WEOffsetX", (BiConsumer<Integer, Integer>) (i, v) -> offsetX = v);
|
|
||||||
streamer.addReader("Schematic.Metadata.WEOffsetY", (BiConsumer<Integer, Integer>) (i, v) -> offsetY = v);
|
|
||||||
streamer.addReader("Schematic.Metadata.WEOffsetZ", (BiConsumer<Integer, Integer>) (i, v) -> offsetZ = v);
|
|
||||||
streamer.addReader("Schematic.Palette", (BiConsumer<Integer, HashMap<String, Tag>>) (i, v) -> {
|
|
||||||
palette = new char[v.size()];
|
|
||||||
for (Map.Entry<String, Tag> entry : v.entrySet()) {
|
|
||||||
BlockState state = null;
|
|
||||||
try {
|
|
||||||
String palettePart = fix(entry.getKey());
|
|
||||||
state = BlockState.get(palettePart);
|
|
||||||
} catch (InputParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
int index = ((IntTag) entry.getValue()).getValue();
|
|
||||||
palette[index] = (char) state.getOrdinal();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/// readBiomes
|
// schematic.add("Palette", (BiConsumer<Integer, HashMap<String, Tag>>) (i, v) -> {
|
||||||
|
// palette = new char[v.size()];
|
||||||
streamer.addReader("Schematic.BlockData.#", (LazyReader) (arrayLen, dis) -> {
|
// for (Map.Entry<String, Tag> entry : v.entrySet()) {
|
||||||
try (FaweOutputStream blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut))) {
|
// BlockState state = null;
|
||||||
IOUtil.copy(dis, blocks, arrayLen);
|
// try {
|
||||||
} catch (IOException e) {
|
// String palettePart = fix(entry.getKey());
|
||||||
e.printStackTrace();
|
// state = BlockState.get(palettePart);
|
||||||
}
|
// } catch (InputParseException e) {
|
||||||
});
|
// e.printStackTrace();
|
||||||
streamer.addReader("Schematic.Biomes.#", (LazyReader) (arrayLen, dis) -> {
|
// }
|
||||||
try (FaweOutputStream biomes = new FaweOutputStream(new LZ4BlockOutputStream(biomesOut))) {
|
// int index = ((IntTag) entry.getValue()).getValue();
|
||||||
IOUtil.copy(dis, biomes, arrayLen);
|
// palette[index] = (char) state.getOrdinal();
|
||||||
} catch (IOException e) {
|
// }
|
||||||
e.printStackTrace();
|
// });
|
||||||
}
|
//
|
||||||
});
|
// /// readBiomes
|
||||||
streamer.addReader("Schematic.TileEntities.#", (BiConsumer<Integer, CompoundTag>) (index, value) -> {
|
//
|
||||||
if (fc == null) {
|
// streamer.addReader("Schematic.BlockData", NBTStreamer.ReadType.ELEM, (NBTStreamer.LazyReader) (arrayLen, dis) -> {
|
||||||
setupClipboard(0, uuid);
|
// try (FaweOutputStream blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut))) {
|
||||||
}
|
// IOUtil.copy(dis, blocks, arrayLen);
|
||||||
int[] pos = value.getIntArray("Pos");
|
// } catch (IOException e) {
|
||||||
int x,y,z;
|
// e.printStackTrace();
|
||||||
if (pos.length != 3) {
|
// }
|
||||||
System.out.println("Invalid tile " + value);
|
// });
|
||||||
if (!value.containsKey("x") || !value.containsKey("y") || !value.containsKey("z")) {
|
// streamer.addReader("Schematic.BlockData", NBTStreamer.ReadType.ELEM, (NBTStreamer.LazyReader) (arrayLen, dis) -> {
|
||||||
return;
|
// try (FaweOutputStream biomes = new FaweOutputStream(new LZ4BlockOutputStream(biomesOut))) {
|
||||||
}
|
// IOUtil.copy(dis, biomes, arrayLen);
|
||||||
x = value.getInt("x");
|
// } catch (IOException e) {
|
||||||
y = value.getInt("y");
|
// e.printStackTrace();
|
||||||
z = value.getInt("z");
|
// }
|
||||||
} else {
|
// });
|
||||||
x = pos[0];
|
// streamer.addReader("Schematic.TileEntities", NBTStreamer.ReadType.ELEM,(BiConsumer<Integer, CompoundTag>) (index, value) -> {
|
||||||
y = pos[1];
|
// if (fc == null) {
|
||||||
z = pos[2];
|
// setupClipboard(0, uuid);
|
||||||
}
|
// }
|
||||||
Map<String, Tag> values = value.getValue();
|
// int[] pos = value.getIntArray("Pos");
|
||||||
Tag id = values.get("Id");
|
// int x,y,z;
|
||||||
if (id != null) {
|
// if (pos.length != 3) {
|
||||||
values.put("x", new IntTag(x));
|
// System.out.println("Invalid tile " + value);
|
||||||
values.put("y", new IntTag(y));
|
// if (!value.containsKey("x") || !value.containsKey("y") || !value.containsKey("z")) {
|
||||||
values.put("z", new IntTag(z));
|
// return;
|
||||||
values.put("id", id);
|
// }
|
||||||
}
|
// x = value.getInt("x");
|
||||||
values.remove("Id");
|
// y = value.getInt("y");
|
||||||
values.remove("Pos");
|
// z = value.getInt("z");
|
||||||
value = fixBlockEntity(value);
|
// } else {
|
||||||
fc.setTile(x, y, z, value);
|
// x = pos[0];
|
||||||
});
|
// y = pos[1];
|
||||||
streamer.addReader("Schematic.Entities.#", (BiConsumer<Integer, CompoundTag>) (index, compound) -> {
|
// z = pos[2];
|
||||||
if (fc == null) {
|
// }
|
||||||
setupClipboard(0, uuid);
|
// Map<String, Tag> values = value.getValue();
|
||||||
}
|
// Tag id = values.get("Id");
|
||||||
Map<String, Tag> value = compound.getValue();
|
// if (id != null) {
|
||||||
StringTag id = (StringTag) value.get("Id");
|
// values.put("x", new IntTag(x));
|
||||||
if (id == null) {
|
// values.put("y", new IntTag(y));
|
||||||
id = (StringTag) value.get("id");
|
// values.put("z", new IntTag(z));
|
||||||
if (id == null) {
|
// values.put("id", id);
|
||||||
return;
|
// }
|
||||||
}
|
// values.remove("Id");
|
||||||
} else {
|
// values.remove("Pos");
|
||||||
value.put("id", id);
|
// value = fixBlockEntity(value);
|
||||||
value.remove("Id");
|
// fc.setTile(x, y, z, value);
|
||||||
}
|
// });
|
||||||
|
// streamer.addReader("Schematic.Entities", NBTStreamer.ReadType.ELEM,(BiConsumer<Integer, CompoundTag>) (index, compound) -> {
|
||||||
EntityType type = EntityTypes.parse(id.getValue());
|
// if (fc == null) {
|
||||||
if (type != null) {
|
// setupClipboard(0, uuid);
|
||||||
compound = fixEntity(compound);
|
// }
|
||||||
BaseEntity state = new BaseEntity(type, compound);
|
// Map<String, Tag> value = compound.getValue();
|
||||||
Location loc = compound.getEntityLocation(fc);
|
// StringTag id = (StringTag) value.get("Id");
|
||||||
fc.createEntity(loc, state);
|
// if (id == null) {
|
||||||
} else {
|
// id = (StringTag) value.get("id");
|
||||||
Fawe.debug("Invalid entity: " + id);
|
// if (id == null) {
|
||||||
}
|
// return;
|
||||||
});
|
// }
|
||||||
streamer.readFully();
|
// } else {
|
||||||
if (fc == null) setupClipboard(length * width * height, uuid);
|
// value.put("id", id);
|
||||||
// fc.setDimensions(BlockVector3.at(width, height, length));
|
// value.remove("Id");
|
||||||
BlockVector3 origin = min;
|
// }
|
||||||
CuboidRegion region;
|
//
|
||||||
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
|
// EntityType type = EntityTypes.parse(id.getValue());
|
||||||
origin = origin.subtract(BlockVector3.at(offsetX, offsetY, offsetZ));
|
// if (type != null) {
|
||||||
}
|
// compound = fixEntity(compound);
|
||||||
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
|
// BaseEntity state = new BaseEntity(type, compound);
|
||||||
if (blocksOut.getSize() != 0) {
|
// Location loc = compound.getEntityLocation(fc);
|
||||||
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(blocksOut.toByteArrays())))) {
|
// fc.createEntity(loc, state);
|
||||||
int volume = width * height * length;
|
// } else {
|
||||||
if (palette.length < 128) {
|
// Fawe.debug("Invalid entity: " + id);
|
||||||
for (int index = 0; index < volume; index++) {
|
// }
|
||||||
BlockState state = BlockTypes.states[palette[fis.read()]];
|
// });
|
||||||
fc.setBlock(index, state);
|
// streamer.readFully();
|
||||||
}
|
// if (fc == null) setupClipboard(length * width * height, uuid);
|
||||||
} else {
|
//// fc.setDimensions(BlockVector3.at(width, height, length));
|
||||||
for (int index = 0; index < volume; index++) {
|
// BlockVector3 origin = min;
|
||||||
BlockState state = BlockTypes.states[palette[fis.readVarInt()]];
|
// CuboidRegion region;
|
||||||
fc.setBlock(index, state);
|
// if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
|
||||||
}
|
// origin = origin.subtract(BlockVector3.at(offsetX, offsetY, offsetZ));
|
||||||
}
|
// }
|
||||||
}
|
// region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
|
||||||
}
|
// if (blocksOut.getSize() != 0) {
|
||||||
if (biomesOut.getSize() != 0) {
|
// try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(blocksOut.toByteArrays())))) {
|
||||||
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(biomesOut.toByteArrays())))) {
|
// int volume = width * height * length;
|
||||||
int volume = width * length;
|
// if (palette.length < 128) {
|
||||||
for (int index = 0; index < volume; index++) {
|
// for (int index = 0; index < volume; index++) {
|
||||||
fc.setBiome(index, BiomeTypes.get(fis.read()));
|
// BlockState state = BlockTypes.states[palette[fis.read()]];
|
||||||
}
|
// fc.setBlock(index, state);
|
||||||
}
|
// }
|
||||||
}
|
// } else {
|
||||||
// clipboard.init(region, fc);
|
// for (int index = 0; index < volume; index++) {
|
||||||
clipboard.setOrigin(origin);
|
// BlockState state = BlockTypes.states[palette[fis.readVarInt()]];
|
||||||
|
// fc.setBlock(index, state);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (biomesOut.getSize() != 0) {
|
||||||
|
// try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(biomesOut.toByteArrays())))) {
|
||||||
|
// int volume = width * length;
|
||||||
|
// for (int index = 0; index < volume; index++) {
|
||||||
|
// fc.setBiome(index, BiomeTypes.get(fis.read()));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//// clipboard.init(region, fc);
|
||||||
|
// clipboard.setOrigin(origin);
|
||||||
return clipboard;
|
return clipboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.math.transform.Identity;
|
import com.sk89q.worldedit.math.transform.Identity;
|
||||||
import com.sk89q.worldedit.math.transform.Transform;
|
import com.sk89q.worldedit.math.transform.Transform;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -112,8 +114,8 @@ public class ClipboardHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
if (clipboard instanceof BlockArrayClipboard) {
|
if (clipboard != null) {
|
||||||
((BlockArrayClipboard) clipboard).close();
|
clipboard.close();
|
||||||
}
|
}
|
||||||
clipboard = null;
|
clipboard = null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user