More work on optimized MCA reader
+ Fix for 1.7.10 gson import error
This commit is contained in:
parent
aeb13960a4
commit
a2589d4493
@ -20,9 +20,12 @@ shadowJar {
|
|||||||
dependencies {
|
dependencies {
|
||||||
include(dependency(':bukkit0'))
|
include(dependency(':bukkit0'))
|
||||||
include(dependency(':core'))
|
include(dependency(':core'))
|
||||||
|
include(dependency('com.google.code.gson:gson:2.2.4'))
|
||||||
}
|
}
|
||||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||||
destinationDir = file '../target'
|
destinationDir = file '../target'
|
||||||
|
|
||||||
|
relocate('com.google.gson', 'com.sk89q.worldedit.internal.gson')
|
||||||
}
|
}
|
||||||
shadowJar.doLast {
|
shadowJar.doLast {
|
||||||
task ->
|
task ->
|
||||||
|
@ -157,12 +157,7 @@ public class Fawe {
|
|||||||
INSTANCE = new Fawe(implementation);
|
INSTANCE = new Fawe(implementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static void debugPlain(String s) {
|
||||||
* Write something to the console
|
|
||||||
* @param s
|
|
||||||
*/
|
|
||||||
public static void debug(Object s) {
|
|
||||||
s = BBC.PREFIX.original() + " " + s;
|
|
||||||
if (INSTANCE != null) {
|
if (INSTANCE != null) {
|
||||||
INSTANCE.IMP.debug(StringMan.getString(s));
|
INSTANCE.IMP.debug(StringMan.getString(s));
|
||||||
} else {
|
} else {
|
||||||
@ -170,6 +165,14 @@ public class Fawe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write something to the console
|
||||||
|
* @param s
|
||||||
|
*/
|
||||||
|
public static void debug(Object s) {
|
||||||
|
debugPlain(BBC.PREFIX.original() + " " + s);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The platform specific implementation
|
* The platform specific implementation
|
||||||
*/
|
*/
|
||||||
|
@ -367,7 +367,7 @@ public enum BBC {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (actor == null) {
|
if (actor == null) {
|
||||||
Fawe.debug((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
|
Fawe.debug(this.format(args));
|
||||||
} else {
|
} else {
|
||||||
actor.print((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
|
actor.print((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
|
||||||
}
|
}
|
||||||
@ -382,7 +382,7 @@ public enum BBC {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
Fawe.debug((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
|
Fawe.debug(this.format(args));
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
|
player.sendMessage((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
|
||||||
}
|
}
|
||||||
|
22
core/src/main/java/com/boydti/fawe/jnbt/MCAChunk.java
Normal file
22
core/src/main/java/com/boydti/fawe/jnbt/MCAChunk.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package com.boydti.fawe.jnbt;
|
||||||
|
|
||||||
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
|
|
||||||
|
public class MCAChunk extends CharFaweChunk<Void> {
|
||||||
|
/**
|
||||||
|
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* @param x
|
||||||
|
* @param z
|
||||||
|
*/
|
||||||
|
public MCAChunk(FaweQueue parent, int x, int z) {
|
||||||
|
super(parent, x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void getNewChunk() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,146 @@
|
|||||||
package com.boydti.fawe.jnbt;
|
package com.boydti.fawe.jnbt;
|
||||||
|
|
||||||
|
import com.boydti.fawe.config.Settings;
|
||||||
|
import com.boydti.fawe.object.RunnableVal3;
|
||||||
|
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||||
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.zip.Inflater;
|
||||||
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
public class MCAFile {
|
public class MCAFile {
|
||||||
private final File file;
|
private final File file;
|
||||||
byte[] header;
|
private final BufferedRandomAccessFile raf;
|
||||||
|
public final byte[] locations;
|
||||||
|
private Field fieldBuf1;
|
||||||
|
private Field fieldBuf2;
|
||||||
|
private Field fieldBuf3;
|
||||||
|
|
||||||
public MCAFile(File regionFolder, int mcrX, int mcrZ) throws FileNotFoundException {
|
private byte[] buffer1 = new byte[Settings.HISTORY.BUFFER_SIZE];
|
||||||
// TODO load NBT
|
private byte[] buffer2 = new byte[Settings.HISTORY.BUFFER_SIZE];
|
||||||
this.file = new File(regionFolder, "r." + mcrX + "." + mcrZ + ".mca");
|
private byte[] buffer3 = new byte[720];
|
||||||
|
|
||||||
|
|
||||||
|
public MCAFile(File file) throws Exception {
|
||||||
|
this.file = file;
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
throw new FileNotFoundException(file.toString());
|
throw new FileNotFoundException(file.toString());
|
||||||
}
|
}
|
||||||
this.header = new byte[4096];
|
this.locations = new byte[4096];
|
||||||
|
this.raf = new BufferedRandomAccessFile(file, "rw", Settings.HISTORY.BUFFER_SIZE);
|
||||||
|
raf.read(locations);
|
||||||
|
fieldBuf1 = BufferedInputStream.class.getDeclaredField("buf");
|
||||||
|
fieldBuf1.setAccessible(true);
|
||||||
|
fieldBuf2 = InflaterInputStream.class.getDeclaredField("buf");
|
||||||
|
fieldBuf2.setAccessible(true);
|
||||||
|
fieldBuf3 = NBTInputStream.class.getDeclaredField("buf");
|
||||||
|
fieldBuf3.setAccessible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public MCAFile(File regionFolder, int mcrX, int mcrZ) throws Exception {
|
||||||
|
this(new File(regionFolder, "r." + mcrX + "." + mcrZ + ".mca"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param onEach cx, cz, offset
|
||||||
|
*/
|
||||||
|
public void forEachChunk(RunnableVal3<Integer, Integer, Integer> onEach) {
|
||||||
|
int i = 0;
|
||||||
|
for (int z = 0; z < 32; z++) {
|
||||||
|
for (int x = 0; x < 32; x++, i += 4) {
|
||||||
|
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF)));
|
||||||
|
int size = locations[i + 3] & 0xFF;
|
||||||
|
if (size != 0) {
|
||||||
|
onEach.run(x, z, offset << 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOffset(int cx, int cz) {
|
||||||
|
int i = (cx << 2) + (cz << 7);
|
||||||
|
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF)));
|
||||||
|
int size = locations[i + 3] & 0xFF;
|
||||||
|
return offset << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private NBTStreamer getChunkReader(int offset) throws Exception {
|
||||||
|
raf.seek(offset);
|
||||||
|
int size = raf.readInt();
|
||||||
|
int compression = raf.readByte();
|
||||||
|
byte[] data = new byte[size];
|
||||||
|
raf.read(data);
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||||
|
InflaterInputStream iis = new InflaterInputStream(bais, new Inflater(), 1);
|
||||||
|
fieldBuf2.set(iis, buffer2);
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(iis, 1);
|
||||||
|
fieldBuf1.set(bis, buffer1);
|
||||||
|
NBTInputStream nis = new NBTInputStream(bis);
|
||||||
|
fieldBuf3.set(nis, buffer3);
|
||||||
|
return new NBTStreamer(nis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countId(int offset, final int id) throws Exception {
|
||||||
|
try {
|
||||||
|
NBTStreamer streamer = getChunkReader(offset);
|
||||||
|
NBTStreamer.ByteReader reader = new NBTStreamer.ByteReader() {
|
||||||
|
public int countId = id;
|
||||||
|
public int count = 0;
|
||||||
|
@Override
|
||||||
|
public void run(int index, int byteValue) {
|
||||||
|
if (byteValue == countId) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
streamer.addReader(".Level.Sections.#.Blocks.#", reader);
|
||||||
|
streamer.readFully();
|
||||||
|
return reader.getClass().getField("count").getInt(reader);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
File folder = new File("../../mc/world/region");
|
||||||
|
long start = System.nanoTime();
|
||||||
|
final AtomicInteger count = new AtomicInteger();
|
||||||
|
final int id = 1;
|
||||||
|
for (File file : folder.listFiles()) {
|
||||||
|
// {
|
||||||
|
// File file = new File(folder, "r.0.0.mca");
|
||||||
|
System.out.println(file);
|
||||||
|
final MCAFile mca = new MCAFile(file);
|
||||||
|
mca.forEachChunk(new RunnableVal3<Integer, Integer, Integer>() {
|
||||||
|
@Override
|
||||||
|
public void run(Integer cx, Integer cz, Integer offset) {
|
||||||
|
try {
|
||||||
|
count.addAndGet(mca.countId(offset, id));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
long diff = System.nanoTime() - start;
|
||||||
|
System.out.println(diff / 1000000d);
|
||||||
|
|
||||||
|
System.out.println("Count: " + count);
|
||||||
|
|
||||||
|
// My results
|
||||||
|
// 496,772,342 stone
|
||||||
|
// 35,164 chunks
|
||||||
|
// 17.175 seconds
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
138
core/src/main/java/com/boydti/fawe/jnbt/MCAQueue.java
Normal file
138
core/src/main/java/com/boydti/fawe/jnbt/MCAQueue.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package com.boydti.fawe.jnbt;
|
||||||
|
|
||||||
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||||
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, MCAChunk, MCAChunk, char[]> {
|
||||||
|
|
||||||
|
private final FaweQueue parent;
|
||||||
|
|
||||||
|
public MCAQueue(FaweQueue parent) {
|
||||||
|
super(parent.getWorldName());
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFullbright(MCAChunk sections) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeLighting(MCAChunk sections, RelightMode mode, boolean hasSky) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void relight(int x, int y, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void relightBlock(int x, int y, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void relightSky(int x, int y, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSkyLight(char[] chars, int x, int y, int z, int value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlockLight(char[] chars, int x, int y, int z, int value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshChunk(FaweChunk fs) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharFaweChunk getPrevious(CharFaweChunk fs, MCAChunk sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundTag getTileEntity(MCAChunk mcaChunk, int x, int y, int z) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MCAChunk getChunk(FaweQueue faweQueue, int x, int z) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getImpWorld() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChunkLoaded(FaweQueue faweQueue, int x, int z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean regenerateChunk(FaweQueue faweQueue, int x, int z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweChunk getFaweChunk(int x, int z) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getSaveFolder() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSky() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadChunk(FaweQueue faweQueue, int x, int z, boolean generate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MCAChunk getCachedSections(FaweQueue faweQueue, int cx, int cz) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCombinedId4Data(char[] chars, int x, int y, int z) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSkyLight(char[] sections, int x, int y, int z) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEmmittedLight(char[] sections, int x, int y, int z) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ package com.boydti.fawe.object.clipboard;
|
|||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.BufferedRandomAccessFile;
|
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||||
import com.boydti.fawe.object.IntegerTrio;
|
import com.boydti.fawe.object.IntegerTrio;
|
||||||
import com.boydti.fawe.object.RunnableVal2;
|
import com.boydti.fawe.object.RunnableVal2;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.boydti.fawe.object;
|
package com.boydti.fawe.object.io;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -35,7 +35,7 @@ import java.util.Arrays;
|
|||||||
* Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com )
|
* Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class BufferedRandomAccessFile extends RandomAccessFile
|
public class BufferedRandomAccessFile extends RandomAccessFile
|
||||||
{
|
{
|
||||||
static final int LogBuffSz_ = 16; // 64K buffer
|
static final int LogBuffSz_ = 16; // 64K buffer
|
||||||
public static final int BuffSz_ = (1 << LogBuffSz_);
|
public static final int BuffSz_ = (1 << LogBuffSz_);
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.boydti.fawe.object.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
|
public class RandomAccessInputStream extends InputStream {
|
||||||
|
private final RandomAccessFile raf;
|
||||||
|
|
||||||
|
public RandomAccessInputStream(RandomAccessFile raf) {
|
||||||
|
this.raf = raf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
return raf.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return (int) (raf.length() - raf.getFilePointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
raf.close();
|
||||||
|
}
|
||||||
|
}
|
@ -178,7 +178,7 @@ public class FakePlayer extends LocalPlayer {
|
|||||||
parent.printRaw(msg);
|
parent.printRaw(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Fawe.debug(msg);
|
Fawe.get().debugPlain(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -187,7 +187,7 @@ public class FakePlayer extends LocalPlayer {
|
|||||||
parent.printDebug(msg);
|
parent.printDebug(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Fawe.debug(msg);
|
Fawe.get().debugPlain(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -196,7 +196,7 @@ public class FakePlayer extends LocalPlayer {
|
|||||||
parent.print(msg);
|
parent.print(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Fawe.debug(msg);
|
Fawe.get().debugPlain(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -205,7 +205,7 @@ public class FakePlayer extends LocalPlayer {
|
|||||||
parent.printError(msg);
|
parent.printError(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Fawe.debug(msg);
|
Fawe.get().debugPlain(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FakeSessionKey key;
|
private FakeSessionKey key;
|
||||||
|
@ -22,6 +22,7 @@ package com.sk89q.jnbt;
|
|||||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||||
import com.boydti.fawe.object.RunnableVal2;
|
import com.boydti.fawe.object.RunnableVal2;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
import java.io.DataInput;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -41,7 +42,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public final class NBTInputStream implements Closeable {
|
public final class NBTInputStream implements Closeable {
|
||||||
|
|
||||||
private final DataInputStream is;
|
private final DataInput is;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code NBTInputStream}, which will source its data
|
* Creates a new {@code NBTInputStream}, which will source its data
|
||||||
@ -54,6 +55,10 @@ public final class NBTInputStream implements Closeable {
|
|||||||
this.is = new DataInputStream(is);
|
this.is = new DataInputStream(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NBTInputStream(DataInput di) {
|
||||||
|
this.is = di;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads an NBT tag from the stream.
|
* Reads an NBT tag from the stream.
|
||||||
*
|
*
|
||||||
@ -99,6 +104,8 @@ public final class NBTInputStream implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] buf;
|
||||||
|
|
||||||
private void readTagPaylodLazy(int type, int depth, String node, RunnableVal2<String, RunnableVal2> getReader) throws IOException {
|
private void readTagPaylodLazy(int type, int depth, String node, RunnableVal2<String, RunnableVal2> getReader) throws IOException {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NBTConstants.TYPE_END:
|
case NBTConstants.TYPE_END:
|
||||||
@ -138,8 +145,40 @@ public final class NBTInputStream implements Closeable {
|
|||||||
}
|
}
|
||||||
if (reader instanceof NBTStreamer.ByteReader) {
|
if (reader instanceof NBTStreamer.ByteReader) {
|
||||||
NBTStreamer.ByteReader byteReader = (NBTStreamer.ByteReader) reader;
|
NBTStreamer.ByteReader byteReader = (NBTStreamer.ByteReader) reader;
|
||||||
for (int i = 0; i < length; i++) {
|
int i = 0;
|
||||||
byteReader.run(i, is.read());
|
if (is instanceof InputStream) {
|
||||||
|
DataInputStream dis = (DataInputStream) is;
|
||||||
|
if (length > 720) {
|
||||||
|
if (buf == null) {
|
||||||
|
buf = new byte[720];
|
||||||
|
}
|
||||||
|
int left = length;
|
||||||
|
for (; left > 720; left -= 720) {
|
||||||
|
dis.read(buf);
|
||||||
|
for (byte b : buf) {
|
||||||
|
byteReader.run(i++, b & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; i < length; i++) {
|
||||||
|
byteReader.run(i, dis.read());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (length > 720) {
|
||||||
|
if (buf == null) {
|
||||||
|
buf = new byte[720];
|
||||||
|
}
|
||||||
|
int left = length;
|
||||||
|
for (; left > 720; left -= 720) {
|
||||||
|
is.readFully(buf);
|
||||||
|
for (byte b : buf) {
|
||||||
|
byteReader.run(i++, b & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; i < length; i++) {
|
||||||
|
byteReader.run(i, is.readByte() & 0xFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
@ -349,7 +388,13 @@ public final class NBTInputStream implements Closeable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
is.close();
|
if (is instanceof AutoCloseable) {
|
||||||
|
try {
|
||||||
|
((AutoCloseable) is).close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user