package com.captainbern.minecraft.net.codec.play.server;
import com.captainbern.minecraft.net.codec.Codec;
import com.captainbern.minecraft.net.packet.play.server.PacketChunkData;
import com.captainbern.minecraft.net.packet.play.server.PacketMapChunkBulk;
import com.captainbern.minecraft.net.util.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public class CodecMapChunkBulk implements Codec<PacketMapChunkBulk> {
public ByteBuf encode(ByteBuf byteBuf, PacketMapChunkBulk packet) {
byteBuf.writeBoolean(packet.hasSkylight());
List<PacketChunkData> chunks = packet.getChunkData();
ByteBufUtils.writeVarInt(byteBuf, chunks.size());
// see: http://wiki.vg/Protocol#Map_Chunk_Bulk
for (PacketChunkData chunkData : chunks) {
byteBuf.writeInt(chunkData.getX());
byteBuf.writeInt(chunkData.getZ());
byteBuf.writeShort(chunkData.getBitmask());
}
for (PacketChunkData chunkData : chunks) {
byteBuf.writeBytes(chunkData.getData());
}
return byteBuf;
}
public PacketMapChunkBulk decode(ByteBuf byteBuf) {
boolean hasSkyLight = byteBuf.readBoolean();
List<PacketChunkData> chunks = new ArrayList<>();
int entries = ByteBufUtils.readVarInt(byteBuf);
List<ChunkData> chunkDataEntries = new ArrayList<>();
for (int i = 0; i < entries; i++) {
int x = byteBuf.readInt();
int z = byteBuf.readInt();
int bitMask = byteBuf.readUnsignedShort();
int chunkCount = Integer.bitCount(bitMask);
int length = (chunkCount * ((4096 * 2) + 2048)) + (hasSkyLight ? chunkCount * 2048 : 0) + 256;
chunkDataEntries.add(new ChunkData(x, z, bitMask, length));
}
for (ChunkData chunkData : chunkDataEntries) {
byte[] data = new byte[chunkData.getDataLength()];
byteBuf.readBytes(data);
chunks.add(new PacketChunkData(chunkData.getX(), chunkData.getZ(), true, chunkData.getBitMask(), data));
}
return new PacketMapChunkBulk(hasSkyLight, chunks);
}
private class ChunkData {
private int x;
private int z;
private int bitMask;
private int dataLength;
public ChunkData(int x, int z, int bitMask, int dataLength) {
this.x = x;
this.z = z;
this.bitMask = bitMask;
this.dataLength = dataLength;
}
public int getX() {
return this.x;
}
public int getZ() {
return this.z;
}
public int getBitMask() {
return this.bitMask;
}
public int getDataLength() {
return this.dataLength;
}
}
}