Archived
0

сериализация полного чанка

This commit is contained in:
2021-06-27 18:54:30 +03:00
parent 9ed6db2484
commit c1854c8f73
18 changed files with 203 additions and 190 deletions

View File

@@ -2,17 +2,12 @@ package mc.protocol.packets.play.server;
import io.netty.buffer.Unpooled;
import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import mc.protocol.buffer.NetByteBuf;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.pool.ProtocolObjectPool;
import mc.protocol.world.Block;
import mc.protocol.utils.ChunkSerializeUtil;
import mc.protocol.world.Chunk;
import mc.protocol.world.ChunkSection;
import mc.utils.array.BitArray;
import mc.utils.array.BitByteArray;
import mc.utils.array.BitLongArray;
/**
* Данные чанка.
@@ -79,9 +74,7 @@ import mc.utils.array.BitLongArray;
@Data
public class ChunkDataPacket implements ServerSidePacket {
private static final int BITS_PER_BLOCK = 13;
private static final int FULL_BIT_MASK = 0b11111111_11111111;
private static final int _16_16_16 = 16 * 16 * 16;
private Chunk chunk;
@@ -90,12 +83,10 @@ public class ChunkDataPacket implements ServerSidePacket {
netByteBuf.writeInt(chunk.getX()); // Chunk X
netByteBuf.writeInt(chunk.getZ()); // Chunk Z
AvailableSections availableSections = createAvailableSections();
boolean fullChunk = availableSections.getBitMask() == FULL_BIT_MASK;
netByteBuf.writeBoolean(fullChunk); // Is Full chunk
netByteBuf.writeVarInt(availableSections.getBitMask()); // Available Sections
netByteBuf.writeBoolean(true); // Is Full chunk
netByteBuf.writeVarInt(FULL_BIT_MASK); // Available Sections
NetByteBuf data = createDataStructure(availableSections.getMaxHeight(), fullChunk);
NetByteBuf data = createDataStructure();
netByteBuf.writeVarInt(data.readableBytes()); // Size of Data
netByteBuf.writeBytes(data); // Data
@@ -105,108 +96,26 @@ public class ChunkDataPacket implements ServerSidePacket {
ProtocolObjectPool.getNetByteBufPool().returnObject(data);
}
private AvailableSections createAvailableSections() {
int bitMask = 0;
int maxH = 0;
for (int h = 15; h >= 0; h--) {
bitMask = bitMask << 1;
ChunkSection chunkSection = chunk.getSection(h);
if (chunkSection != null && chunkSection.getY() == h) {
bitMask |= 0x01;
maxH++;
} else {
bitMask |= 0x00;
}
}
return new AvailableSections(bitMask, maxH);
}
private NetByteBuf createDataStructure(int maxHeight, boolean fillBiomes) {
private NetByteBuf createDataStructure() {
NetByteBuf dataStructure = ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer());
NetByteBuf biomes = fillBiomes ? ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer()) : null;
for (int h = 0; h < maxHeight; h++) {
for (int h = 0; h < 16; h++) {
ChunkSection section = chunk.getSection(h);
if (section == null) {
continue;
}
NetByteBuf data = createData(section, biomes);
NetByteBuf data = ChunkSerializeUtil.serializeSection(section);
dataStructure.writeBytes(data); // Data
ProtocolObjectPool.getNetByteBufPool().returnObject(data);
}
if (fillBiomes) {
dataStructure.writeBytes(biomes); // Biomes
ProtocolObjectPool.getNetByteBufPool().returnObject(biomes);
// <Biomes>
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
dataStructure.writeByte(chunk.getBiome(
(chunk.getX() << 4) + x,
(chunk.getZ() << 4) + z));
}
}
// </Biomes>
return dataStructure;
}
private NetByteBuf createData(ChunkSection section, NetByteBuf biomes) {
NetByteBuf data = ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer());
BitArray blockLight = new BitByteArray(4, 2048 * 2);
BitArray skyLight = new BitByteArray(4, 2048 * 2);
// <Bits Per Block>
data.writeUnsignedByte(BITS_PER_BLOCK);
// </Bits Per Block>
// <Palette>
data.writeVarInt(0); // Direct mode
// </Palette>
// <Data Array Length>
data.writeVarInt(_16_16_16);
// </Data Array Length>
// <Data Array>
BitArray dataArray = new BitLongArray(BITS_PER_BLOCK, _16_16_16);
boolean writeBiomes = biomes != null;
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
Block block = section.getBlock(x, y, z);
int blockState = (block.getId() << 4) | block.getMeta();
dataArray.put(blockState);
blockLight.put(block.getLight());
skyLight.put(section.getSkyLight(x, y, z));
if (writeBiomes) {
biomes.writeByte(chunk.getBiome(
(chunk.getX() << 4) + x,
(chunk.getZ() << 4) + z));
if (x == 15 && z == 15) {
writeBiomes = false;
}
}
}
}
}
data.writeBytes(dataArray.byteBuffer());
// </Data Array>
// <Block Light>
data.writeBytes(blockLight.byteBuffer());
// </Block Light>
// <Sky Light>
data.writeBytes(skyLight.byteBuffer());
// </Sky Light>
return data;
}
@RequiredArgsConstructor
@Getter
private static class AvailableSections {
private final int bitMask;
private final int maxHeight;
}
}

View File

@@ -0,0 +1,48 @@
package mc.protocol.utils;
import io.netty.buffer.Unpooled;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import mc.protocol.buffer.NetByteBuf;
import mc.protocol.pool.ProtocolObjectPool;
import mc.protocol.world.Block;
import mc.protocol.world.ChunkSection;
import mc.utils.array.BitArray;
import mc.utils.array.BitByteArray;
import mc.utils.array.BitLongArray;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ChunkSerializeUtil {
private static final int BITS_PER_BLOCK = 13;
private static final int ALL_BLOCKS = 16 * 16 * 16;
public static NetByteBuf serializeSection(ChunkSection section) {
BitArray blockArray = new BitLongArray(BITS_PER_BLOCK, ALL_BLOCKS);
BitArray blockLight = new BitByteArray(4, ALL_BLOCKS);
BitArray skyLight = new BitByteArray(4, ALL_BLOCKS);
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
Block block = section.getBlock(x, y, z);
int blockState = (block.getId() << 4) | block.getMeta();
blockArray.put(blockState);
blockLight.put(block.getLight());
skyLight.put(section.getSkyLight(x, y, z));
}
}
}
NetByteBuf result = ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer());
result.writeUnsignedByte(BITS_PER_BLOCK); // Bits Per Block
result.writeVarInt(0); // Palette, Direct mode
result.writeVarInt(blockArray.size()); // Data Array Length
result.writeBytes(blockArray.byteBuffer()); // Data Array
result.writeBytes(blockLight.byteBuffer()); // Block Light
result.writeBytes(skyLight.byteBuffer()); // Sky Light
return result;
}
}