ViaVersion/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_17to1_16_4/types/Chunk1_17Type.java

101 lines
3.7 KiB
Java

package us.myles.ViaVersion.protocols.protocol1_17to1_16_4.types;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.minecraft.chunks.BaseChunk;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
import us.myles.ViaVersion.api.type.types.version.Types1_16;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
public class Chunk1_17Type extends Type<Chunk> {
private static final CompoundTag[] EMPTY_COMPOUNDS = new CompoundTag[0];
private final int ySectionCount;
public Chunk1_17Type(int ySectionCount) {
super(Chunk.class);
Preconditions.checkArgument(ySectionCount > 0);
this.ySectionCount = ySectionCount;
}
@Override
public Chunk read(ByteBuf input) throws Exception {
int chunkX = input.readInt();
int chunkZ = input.readInt();
BitSet sectionsMask = BitSet.valueOf(Type.LONG_ARRAY_PRIMITIVE.read(input));
CompoundTag heightMap = Type.NBT.read(input);
int[] biomeData = Type.VAR_INT_ARRAY_PRIMITIVE.read(input);
Type.VAR_INT.readPrimitive(input); // data size in bytes
// Read sections
ChunkSection[] sections = new ChunkSection[ySectionCount];
for (int i = 0; i < ySectionCount; i++) {
if (!sectionsMask.get(i)) continue; // Section not set
short nonAirBlocksCount = input.readShort();
ChunkSection section = Types1_16.CHUNK_SECTION.read(input);
section.setNonAirBlocksCount(nonAirBlocksCount);
sections[i] = section;
}
List<CompoundTag> nbtData = new ArrayList<>(Arrays.asList(Type.NBT_ARRAY.read(input)));
// Read all the remaining bytes (workaround for #681)
if (input.readableBytes() > 0) {
byte[] array = Type.REMAINING_BYTES.read(input);
if (Via.getManager().isDebug()) {
Via.getPlatform().getLogger().warning("Found " + array.length + " more bytes than expected while reading the chunk: " + chunkX + "/" + chunkZ);
}
}
return new BaseChunk(chunkX, chunkZ, true, false, sectionsMask, sections, biomeData, heightMap, nbtData);
}
@Override
public void write(ByteBuf output, Chunk chunk) throws Exception {
output.writeInt(chunk.getX());
output.writeInt(chunk.getZ());
Type.LONG_ARRAY_PRIMITIVE.write(output, chunk.getChunkMask().toLongArray());
Type.NBT.write(output, chunk.getHeightMap());
// Write biome data
Type.VAR_INT_ARRAY_PRIMITIVE.write(output, chunk.getBiomeData());
ByteBuf buf = output.alloc().buffer();
try {
ChunkSection[] sections = chunk.getSections();
for (ChunkSection section : sections) {
if (section == null) continue; // Section not set
buf.writeShort(section.getNonAirBlocksCount());
Types1_16.CHUNK_SECTION.write(buf, section);
}
buf.readerIndex(0);
Type.VAR_INT.writePrimitive(output, buf.readableBytes());
output.writeBytes(buf);
} finally {
buf.release(); // release buffer
}
// Write Block Entities
Type.NBT_ARRAY.write(output, chunk.getBlockEntities().toArray(EMPTY_COMPOUNDS));
}
@Override
public Class<? extends Type> getBaseClass() {
return BaseChunkType.class;
}
}