From b35875dfafe5e0e5174545a3041adda2c72ca647 Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR Date: Sat, 30 Jul 2016 16:34:48 -0300 Subject: [PATCH] Fix chunk data metadata DragonProxy's Chunk Data Translator has a bug where the block metadata simply didn't work in some blocks, example: Create a blue wool wall and relog, some of the wools were white and some were blue. This commit fixes the bug, and maybe also breaks Sign and Chest support, whoops. --- .../pc/PCMultiChunkDataPacketTranslator.java | 197 ++++++++++-------- 1 file changed, 108 insertions(+), 89 deletions(-) diff --git a/src/main/java/org/dragonet/proxy/network/translator/pc/PCMultiChunkDataPacketTranslator.java b/src/main/java/org/dragonet/proxy/network/translator/pc/PCMultiChunkDataPacketTranslator.java index e34b80b6d..5732111fa 100644 --- a/src/main/java/org/dragonet/proxy/network/translator/pc/PCMultiChunkDataPacketTranslator.java +++ b/src/main/java/org/dragonet/proxy/network/translator/pc/PCMultiChunkDataPacketTranslator.java @@ -14,10 +14,8 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.nio.ByteOrder; import org.dragonet.net.packet.minecraft.FullChunkPacket; import org.dragonet.net.packet.minecraft.PEPacket; -import org.dragonet.proxy.nbt.PENBT; import org.dragonet.proxy.network.UpstreamSession; import org.dragonet.proxy.network.translator.ItemBlockTranslator; import org.dragonet.proxy.network.translator.PCPacketTranslator; @@ -30,93 +28,114 @@ public class PCMultiChunkDataPacketTranslator implements PCPacketTranslator { - ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); - DataOutputStream dos1 = new DataOutputStream(bos1); - - ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); - DataOutputStream dos2 = new DataOutputStream(bos2); - - ByteArrayOutputStream bosTiles = new ByteArrayOutputStream(); - - try { - for (int col = 0; col < packet.getColumns(); col++) { - bos1.reset(); - bos2.reset(); - bosTiles.reset(); - - FullChunkPacket chunkToSend = new FullChunkPacket(); - chunkToSend.chunkX = packet.getX(col); - chunkToSend.chunkZ = packet.getZ(col); - chunkToSend.order = FullChunkPacket.ChunkOrder.COLUMNS; - Chunk[] pcChunks = packet.getChunks(col); - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - for (int y = 0; y < 128; y++) { - if (pcChunks[y >> 4] == null || pcChunks[y >> 4].isEmpty()) { - dos1.writeByte((byte) 0); - } else { - int pcBlock = pcChunks[y >> 4].getBlocks().getBlock(x, y % 16, z); - int peBlock = ItemBlockTranslator.translateToPE(pcBlock); - dos1.writeByte((byte) (peBlock & 0xFF)); - if (peBlock == 63 || peBlock == 68) { - PENBT.write(ItemBlockTranslator.newTileTag("Sign", (chunkToSend.chunkX << 4) | x, y, (chunkToSend.chunkZ << 4) | z), bosTiles, ByteOrder.LITTLE_ENDIAN); - } else if (peBlock == 54 || peBlock == 146) { - //TODO: Chest paring - /** - * META & 0b111 => [0] z- = x-,x+ [1] - * z-. [2] z-. [3] z+ = x-,x+. [4] x- = - * z-,z+. [5] x+ = z-,z+. - */ - PENBT.write(ItemBlockTranslator.newTileTag("Chest", (chunkToSend.chunkX << 4) | x, y, (chunkToSend.chunkZ << 4) | z), bosTiles, ByteOrder.LITTLE_ENDIAN); - } - } - } - } - } - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - for (int y = 0; y < 128; y += 2) { - byte data1 = pcChunks[y >> 4] == null || pcChunks[y >> 4].isEmpty() ? (byte) 0 : (byte) ((pcChunks[y >> 4].getBlocks().getData(x, y % 16, z) & 0xF) << 4); - data1 |= pcChunks[(y + 1) >> 4] == null || pcChunks[(y + 1) >> 4].isEmpty() ? (byte) 0 : (byte) (pcChunks[(y + 1) >> 4].getBlocks().getData(x, (y + 1) % 16, z) & 0xF); - dos1.writeByte(data1); - byte data2 = pcChunks[y >> 4] == null || pcChunks[y >> 4].isEmpty() ? (byte) 0 : (byte) ((pcChunks[y >> 4].getSkyLight().get(x, y % 16, z) & 0xF) << 4); - data2 |= pcChunks[(y + 1) >> 4] == null || pcChunks[(y + 1) >> 4].isEmpty() ? (byte) 0 : (byte) (pcChunks[(y + 1) >> 4].getSkyLight().get(x, (y + 1) % 16, z) & 0xF); - dos2.writeByte(data2); - } - } - } - dos1.write(bos2.toByteArray()); //Not bos1 contains previously generated data! Don't reset! - bos2.reset();//Now it's empty - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - for (int y = 0; y < 128; y += 2) { - byte data = pcChunks[y >> 4] == null || pcChunks[y >> 4].isEmpty() ? (byte) 0 : (byte) ((pcChunks[y >> 4].getBlockLight().get(x, y % 16, z) & 0xF) << 4); - data |= pcChunks[(y + 1) >> 4] == null || pcChunks[(y + 1) >> 4].isEmpty() ? (byte) 0 : (byte) (pcChunks[(y + 1) >> 4].getBlockLight().get(x, (y + 1) % 16, z) & 0xF); - dos1.writeByte(data); - } - } - } - //Height Map - for (int i = 0; i < 256; i++) { - dos1.writeByte((byte) 0xFF); - } - - //Biome Colors - for (int i = 0; i < 256; i++) { - dos1.writeByte((byte) 0x01); - dos1.writeByte((byte) 0x85); - dos1.writeByte((byte) 0xB2); - dos1.writeByte((byte) 0x4A); - } - - bos2.reset(); - - dos1.writeInt(0);//Extra data, should be little-endian but it's 0 here for now so it's okay. - - dos1.write(bosTiles.toByteArray()); - - chunkToSend.chunkData = bos1.toByteArray(); - session.sendPacket(chunkToSend, true); + ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); + DataOutputStream dos1 = new DataOutputStream(bos1); + + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); + DataOutputStream dos2 = new DataOutputStream(bos2); + + ByteArrayOutputStream bosTiles = new ByteArrayOutputStream(); + DataOutputStream dosTiles = new DataOutputStream(bosTiles); + + try { + for (int col = 0; col < packet.getColumns(); col++) { + bos1.reset(); + bos2.reset(); + bosTiles.reset(); + + FullChunkPacket pePacket = new FullChunkPacket(); + + pePacket.chunkX = packet.getX(col); + pePacket.chunkZ = packet.getZ(col); + pePacket.order = FullChunkPacket.ChunkOrder.COLUMNS; + Chunk[] pcChunks = packet.getChunks(col); + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = 0; y < 128; y++) { + if (pcChunks[y >> 4] == null || pcChunks[y >> 4].isEmpty()) { + dos1.writeByte((byte) 0); + } else { + int pcBlock = pcChunks[y >> 4].getBlocks().getBlock(x, y % 16, z); + int peBlock = pcBlock; + peBlock = ItemBlockTranslator.translateToPE(peBlock); + dos1.writeByte((byte) (peBlock & 0xFF)); + // dos1.writeByte((byte) 1); + } + } + } + } + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = 0; y < 128; y += 2) { + byte data1 = 0; + byte data2 = 0; + try { + data1 = (byte) pcChunks[y >> 4].getBlocks().getData(x, y % 16, z); + } catch (Exception e) { + + } + try { + data2 = (byte) pcChunks[y >> 4].getBlocks().getData(x, (y + 1) % 16, z); + } catch (Exception e) { + + } + + data1 |= ((data2 & 0xF) << 4); + + dos1.writeByte(data1); + } + } + } + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = 0; y < 128; y += 2) { + //if (noSkyLight) { + // temp.writeByte(0); + //} else { + byte data = 0; + try { + data = (byte) (pcChunks[y >> 4].getSkyLight().get(x, y & 0xF, z) & 0xF); + data |= (pcChunks[y >> 4].getSkyLight().get(x, (y + 1) & 0xF, z) & 0xF); + } catch (Exception e) { + + } + dos1.writeByte(data); + //} + } + } + } + dos1.write(bos2.toByteArray()); //Not bos1 contains previously generated data! Don't reset! + bos2.reset();//Now it's empty + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = 0; y < 128; y += 2) { + byte data = pcChunks[y >> 4] == null || pcChunks[y >> 4].isEmpty() ? (byte) 0 : (byte) ((pcChunks[y >> 4].getBlockLight().get(x, y % 16, z) & 0xF) << 4); + data |= pcChunks[(y + 1) >> 4] == null || pcChunks[(y + 1) >> 4].isEmpty() ? (byte) 0 : (byte) (pcChunks[(y + 1) >> 4].getBlockLight().get(x, (y + 1) % 16, z) & 0xF); + dos1.writeByte(data); + } + } + } + //Height Map + for (int i = 0; i < 256; i++) { + dos1.writeByte((byte) 0xFF); + } + + //Biome Colors + for (int i = 0; i < 256; i++) { + dos1.writeByte((byte) 0x01); + dos1.writeByte((byte) 0x85); + dos1.writeByte((byte) 0xB2); + dos1.writeByte((byte) 0x4A); + } + + bos2.reset(); + + dos1.writeInt(0);//Extra data, should be little-endian but it's 0 here for now so it's okay. + + dos1.write(bosTiles.toByteArray()); + + pePacket.chunkData = bos1.toByteArray(); + session.sendPacket(pePacket, true); } } catch (Exception e) { }