package de.gerrygames.viarewind.protocol.protocol1_8to1_9.types; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.minecraft.Environment; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.minecraft.chunks.Chunk1_8; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; import us.myles.ViaVersion.api.type.PartialType; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; import java.util.ArrayList; import java.util.logging.Level; public class Chunk1_8Type extends PartialType<Chunk, ClientWorld> { private static final Type<ChunkSection> CHUNK_SECTION_TYPE = new ChunkSectionType1_8(); public Chunk1_8Type(ClientWorld param) { super(param, Chunk.class); } @Override public Chunk read(ByteBuf input, ClientWorld world) throws Exception { // Copied from ViaVersion, removed some things int chunkX = input.readInt(); int chunkZ = input.readInt(); boolean groundUp = input.readByte() != 0; int bitmask = input.readUnsignedShort(); int dataLength = Type.VAR_INT.read(input); if (bitmask == 0 && groundUp) { // This is a chunks unload packet if (dataLength >= 256) { //1.8 likes to send biome data in unload packets?! input.readerIndex(input.readerIndex() + 256); } return new Chunk1_8(chunkX, chunkZ); } // Data to be read ChunkSection[] sections = new ChunkSection[16]; int[] biomeData = null; int startIndex = input.readerIndex(); // Read blocks for (int i = 0; i < 16; i++) { if ((bitmask & 1 << i) == 0) continue; sections[i] = CHUNK_SECTION_TYPE.read(input); } // Read block light for (int i = 0; i < 16; i++) { if ((bitmask & 1 << i) == 0) continue; sections[i].readBlockLight(input); } // Read sky light int bytesLeft = dataLength - (input.readerIndex() - startIndex); if (bytesLeft >= ChunkSection.LIGHT_LENGTH) { for (int i = 0; i < 16; i++) { if ((bitmask & 1 << i) == 0) continue; sections[i].readSkyLight(input); bytesLeft -= ChunkSection.LIGHT_LENGTH; } } // Read biome data if (bytesLeft >= 256) { biomeData = new int[256]; for (int i = 0; i < 256; i++) { biomeData[i] = input.readByte() & 0xFF; } bytesLeft -= 256; } // Check remaining bytes if (bytesLeft > 0) { Via.getPlatform().getLogger().log(Level.WARNING, bytesLeft + " Bytes left after reading chunks! (" + groundUp + ")"); } // Return chunks return new Chunk1_8(chunkX, chunkZ, groundUp, bitmask, sections, biomeData, new ArrayList<>()); } @Override public void write(ByteBuf output, ClientWorld world, Chunk chunk) throws Exception { ByteBuf buf = output.alloc().buffer(); for (int i = 0; i < chunk.getSections().length; i++) { if ((chunk.getBitmask() & 1 << i) == 0) continue; CHUNK_SECTION_TYPE.write(buf, chunk.getSections()[i]); } for (int i = 0; i < chunk.getSections().length; i++) { if ((chunk.getBitmask() & 1 << i) == 0) continue; chunk.getSections()[i].writeBlockLight(buf); } boolean skyLight = world.getEnvironment() == Environment.NORMAL; if (skyLight) { for (int i = 0; i < chunk.getSections().length; i++) { if ((chunk.getBitmask() & 1 << i) == 0) continue; chunk.getSections()[i].writeSkyLight(buf); } } if (chunk.isGroundUp() && chunk.isBiomeData()) { for (int biome : chunk.getBiomeData()) { buf.writeByte((byte) biome); } } output.writeInt(chunk.getX()); output.writeInt(chunk.getZ()); output.writeBoolean(chunk.isGroundUp()); output.writeShort(chunk.getBitmask()); Type.VAR_INT.write(output, buf.readableBytes()); output.writeBytes(buf, buf.readableBytes()); buf.release(); } }