Chunk Zstd compression

This commit is contained in:
TheMode 2019-08-24 01:05:52 +02:00
parent b933a83c31
commit 7a557169bd
5 changed files with 33 additions and 6 deletions

View File

@ -16,5 +16,6 @@ dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
implementation 'com.github.Adamaq01:ozao-net:2.3.1'
compile 'com.github.Querz:NBT:4.1'
// https://mvnrepository.com/artifact/org.lz4/lz4-java
implementation 'com.github.luben:zstd-jni:1.4.3-1'
}

View File

@ -310,7 +310,8 @@ public abstract class Entity implements Viewable, DataContainer {
synchronized (entityById) {
entityById.remove(id);
}
instance.removeEntity(this);
if (instance != null)
instance.removeEntity(this);
}
public void scheduleRemove(long delay) {

View File

@ -142,6 +142,7 @@ public class Player extends LivingEntity {
setEventCallback(PlayerSpawnPacket.class, event -> {
System.out.println("TELEPORT");
setGameMode(GameMode.CREATIVE);
teleport(new Position(0, 66, 0));
for (int cx = 0; cx < 4; cx++)
for (int cz = 0; cz < 4; cz++) {

View File

@ -1,5 +1,6 @@
package fr.themode.minestom.instance;
import com.github.luben.zstd.Zstd;
import fr.themode.minestom.Main;
import fr.themode.minestom.utils.SerializerUtils;
@ -9,9 +10,10 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
// TODO compression
public class ChunkLoaderIO {
private static final int COMPRESSION_LEVEL = 1;
private ExecutorService chunkLoaderPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_CHUNK_IO);
private static File getChunkFile(int chunkX, int chunkZ, File folder) {
@ -27,8 +29,14 @@ public class ChunkLoaderIO {
File chunkFile = getChunkFile(chunk.getChunkX(), chunk.getChunkZ(), folder);
try (FileOutputStream fos = new FileOutputStream(chunkFile)) {
byte[] data = chunk.getSerializedData();
// Zstd.compress(data, 1)
fos.write(data);
byte[] decompressedLength = SerializerUtils.intToBytes(data.length);
byte[] compressed = Zstd.compress(data, COMPRESSION_LEVEL);
byte[] result = new byte[decompressedLength.length + compressed.length];
System.arraycopy(decompressedLength, 0, result, 0, decompressedLength.length);
System.arraycopy(compressed, 0, result, decompressedLength.length, compressed.length);
fos.write(result);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
@ -48,12 +56,27 @@ public class ChunkLoaderIO {
return;
}
byte[] array = new byte[0];
byte[] array;
try {
array = Files.readAllBytes(getChunkFile(chunkX, chunkZ, instance.getFolder()).toPath());
} catch (IOException e) {
e.printStackTrace();
instance.createChunk(chunkX, chunkZ, callback); // Unknown error, create new chunk by default
return;
}
int decompressedLength = SerializerUtils.bytesToInt(array);
byte[] compressedChunkData = new byte[array.length - 4];
System.arraycopy(array, 4, compressedChunkData, 0, compressedChunkData.length); // Remove the decompressed length from the array
byte[] decompressed = new byte[decompressedLength];
long result = Zstd.decompress(decompressed, compressedChunkData); // Decompressed in an array with the max size
array = new byte[(int) result];
System.arraycopy(decompressed, 0, array, 0, (int) result); // Resize the data array properly
DataInputStream stream = new DataInputStream(new ByteArrayInputStream(array));
Chunk chunk = null;
@ -65,6 +88,7 @@ public class ChunkLoaderIO {
int index = stream.readInt();
boolean isCustomBlock = stream.readBoolean();
short blockId = stream.readShort();
//System.out.println("id: " + blockId);
byte[] chunkPos = SerializerUtils.indexToChunkPosition(index);
if (isCustomBlock) {
@ -77,6 +101,7 @@ public class ChunkLoaderIO {
} catch (IOException e) {
e.printStackTrace();
}
callback.accept(chunk); // Success, null if file isn't properly encoded
});
}

View File

@ -112,7 +112,6 @@ public class LoginStartPacket implements ClientPreplayPacket {
// Next is optional TODO put all that somewhere else (LoginEvent)
// TODO LoginEvent in another thread (here we are in netty thread)
System.out.println("ADD WAITING PLAYER");
Main.getEntityManager().addWaitingPlayer(player);