diff options
Diffstat (limited to 'src/Protocol/ChunkDataSerializer.cpp')
-rw-r--r-- | src/Protocol/ChunkDataSerializer.cpp | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index ebe61631b..268cf4a9f 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -8,6 +8,8 @@ #include "Globals.h" #include "ChunkDataSerializer.h" #include "zlib/zlib.h" +#include "ByteBuffer.h" +#include "Protocol18x.h" @@ -30,7 +32,7 @@ cChunkDataSerializer::cChunkDataSerializer( -const AString & cChunkDataSerializer::Serialize(int a_Version) +const AString & cChunkDataSerializer::Serialize(int a_Version, int a_ChunkX, int a_ChunkZ) { Serializations::const_iterator itr = m_Serializations.find(a_Version); if (itr != m_Serializations.end()) @@ -43,6 +45,7 @@ const AString & cChunkDataSerializer::Serialize(int a_Version) { case RELEASE_1_2_5: Serialize29(data); break; case RELEASE_1_3_2: Serialize39(data); break; + case RELEASE_1_8_0: Serialize80(data, a_ChunkX, a_ChunkZ); break; // TODO: Other protocol versions may serialize the data differently; implement here default: @@ -52,7 +55,10 @@ const AString & cChunkDataSerializer::Serialize(int a_Version) break; } } - m_Serializations[a_Version] = data; + if (!data.empty()) + { + m_Serializations[a_Version] = data; + } return m_Serializations[a_Version]; } @@ -174,3 +180,74 @@ void cChunkDataSerializer::Serialize39(AString & a_Data) + +void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_ChunkZ) +{ + // TODO: Do not copy data and then compress it; rather, compress partial blocks of data (zlib *can* stream) + + // Blocktypes converter (1.8 included the meta into the blocktype): + unsigned char Blocks[cChunkDef::NumBlocks * 2]; + size_t LastOffset = 0; + for (size_t Index = 0; Index < cChunkDef::NumBlocks; Index++) + { + BLOCKTYPE BlockType = m_BlockTypes[Index] & 0xFF; + NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; + Blocks[LastOffset] = (BlockType << 4) | ((unsigned char)BlockMeta); + Blocks[LastOffset + 1] = (unsigned char)BlockType >> 4; + LastOffset += 2; + } + + const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; + const int BlockLightOffset = sizeof(Blocks); + const int SkyLightOffset = BlockLightOffset + sizeof(m_BlockLight); + const int BiomeOffset = SkyLightOffset + sizeof(m_BlockSkyLight); + const int DataSize = BiomeOffset + BiomeDataSize; + + // Temporary buffer for the composed data: + char AllData [DataSize]; + memcpy(AllData, Blocks, sizeof(Blocks)); + memcpy(AllData + BlockLightOffset, m_BlockLight, sizeof(m_BlockLight)); + memcpy(AllData + SkyLightOffset, m_BlockSkyLight, sizeof(m_BlockSkyLight)); + memcpy(AllData + BiomeOffset, m_BiomeData, BiomeDataSize); + + cByteBuffer Packet(512 KiB); + Packet.WriteVarInt(0x21); // Packet id (Chunk Data packet) + Packet.WriteBEInt(a_ChunkX); + Packet.WriteBEInt(a_ChunkZ); + Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag + Packet.WriteBEShort(0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff + Packet.WriteVarInt(DataSize); // Chunk size + Packet.WriteBuf(AllData, DataSize); // Chunk data + + AString PacketData; + Packet.ReadAll(PacketData); + Packet.CommitRead(); + + cByteBuffer Buffer(20); + if (PacketData.size() >= 256) + { + if (!cProtocol180::CompressPacket(PacketData, a_Data)) + { + ASSERT(!"Packet compression failed."); + a_Data.clear(); + return; + } + } + else + { + AString PostData; + Buffer.WriteVarInt(Packet.GetUsedSpace() + 1); + Buffer.WriteVarInt(0); + Buffer.ReadAll(PostData); + Buffer.CommitRead(); + + a_Data.clear(); + a_Data.resize(PostData.size() + PacketData.size()); + a_Data.append(PostData.data(), PostData.size()); + a_Data.append(PacketData.data(), PacketData.size()); + } +} + + + + |