diff options
Diffstat (limited to 'src/Protocol')
-rw-r--r-- | src/Protocol/ChunkDataSerializer.cpp | 223 | ||||
-rw-r--r-- | src/Protocol/ChunkDataSerializer.h | 47 | ||||
-rw-r--r-- | src/Protocol/Protocol.h | 2 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_8.h | 2 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_9.cpp | 32 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_9.h | 4 |
6 files changed, 114 insertions, 196 deletions
diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index 52782bbb7..bf8798d6f 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -4,9 +4,11 @@ #include "Protocol_1_8.h" #include "Protocol_1_9.h" #include "../ByteBuffer.h" +#include "../ClientHandle.h" #include "Palettes/Upgrade.h" #include "Palettes/Palette_1_13.h" +#include "Palettes/Palette_1_13_1.h" @@ -34,10 +36,14 @@ void ForEachSection(const cChunkData & a_Data, Func a_Func) // cChunkDataSerializer: cChunkDataSerializer::cChunkDataSerializer( + int a_ChunkX, + int a_ChunkZ, const cChunkData & a_Data, const unsigned char * a_BiomeData, const eDimension a_Dimension -): +) : + m_ChunkX(a_ChunkX), + m_ChunkZ(a_ChunkZ), m_Data(a_Data), m_BiomeData(a_BiomeData), m_Dimension(a_Dimension) @@ -48,49 +54,74 @@ cChunkDataSerializer::cChunkDataSerializer( -const AString & cChunkDataSerializer::Serialize(int a_Version, int a_ChunkX, int a_ChunkZ) +void cChunkDataSerializer::SendToClients(const std::unordered_set<cClientHandle *> & a_SendTo) { - Serializations::const_iterator itr = m_Serializations.find(a_Version); - if (itr != m_Serializations.end()) + std::unordered_map<cProtocol::Version, std::vector<cClientHandle *>> ClientProtocolVersions; + + for (const auto Client : a_SendTo) { - return itr->second; + const auto ClientProtocol = static_cast<cProtocol::Version>(Client->GetProtocolVersion()); + ClientProtocolVersions[ClientProtocol].emplace_back(Client); } - AString data; - switch (a_Version) + for (const auto & Entry : ClientProtocolVersions) { - case RELEASE_1_8_0: Serialize47 (data, a_ChunkX, a_ChunkZ); break; - case RELEASE_1_9_0: Serialize107(data, a_ChunkX, a_ChunkZ); break; - case RELEASE_1_9_4: Serialize110(data, a_ChunkX, a_ChunkZ); break; - case RELEASE_1_13: Serialize393(data, a_ChunkX, a_ChunkZ); break; - - default: + switch (Entry.first) { - LOGERROR("cChunkDataSerializer::Serialize(): Unknown version: %d", a_Version); - ASSERT(!"Unknown chunk data serialization version"); - break; + case cProtocol::Version::Version_1_8_0: + { + Serialize47(Entry.second); + continue; + } + case cProtocol::Version::Version_1_9_0: + case cProtocol::Version::Version_1_9_1: + case cProtocol::Version::Version_1_9_2: + { + Serialize107(Entry.second); + continue; + } + case cProtocol::Version::Version_1_9_4: + case cProtocol::Version::Version_1_10_0: + case cProtocol::Version::Version_1_11_0: + case cProtocol::Version::Version_1_11_1: + case cProtocol::Version::Version_1_12: + case cProtocol::Version::Version_1_12_1: + case cProtocol::Version::Version_1_12_2: + { + Serialize110(Entry.second); + continue; + } + case cProtocol::Version::Version_1_13: + { + Serialize393And401<&Palette_1_13::FromBlock>(Entry.second); // This version didn't last very long xD + continue; + } + case cProtocol::Version::Version_1_13_1: + case cProtocol::Version::Version_1_13_2: + { + Serialize393And401<&Palette_1_13_1::FromBlock>(Entry.second); + continue; + } } + + LOGERROR("cChunkDataSerializer::Serialize(): Unknown version: %d", Entry.first); + ASSERT(!"Unknown chunk data serialization version"); } - if (!data.empty()) - { - m_Serializations[a_Version] = data; - } - return m_Serializations[a_Version]; } -void cChunkDataSerializer::Serialize47(AString & a_Data, int a_ChunkX, int a_ChunkZ) +void cChunkDataSerializer::Serialize47(const std::vector<cClientHandle *> & a_SendTo) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Create the packet: cByteBuffer Packet(512 KiB); Packet.WriteVarInt32(0x21); // Packet id (Chunk Data packet) - Packet.WriteBEInt32(a_ChunkX); - Packet.WriteBEInt32(a_ChunkZ); + Packet.WriteBEInt32(m_ChunkX); + Packet.WriteBEInt32(m_ChunkZ); Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag Packet.WriteBEUInt16(m_Data.GetSectionBitmask()); @@ -135,48 +166,22 @@ void cChunkDataSerializer::Serialize47(AString & a_Data, int a_ChunkX, int a_Chu // Write the biome data: Packet.WriteBuf(m_BiomeData, BiomeDataSize); - AString PacketData; - Packet.ReadAll(PacketData); - Packet.CommitRead(); - - cByteBuffer Buffer(20); - if (PacketData.size() >= 256) - { - if (!cProtocol_1_8_0::CompressPacket(PacketData, a_Data)) - { - ASSERT(!"Packet compression failed."); - a_Data.clear(); - return; - } - } - else - { - AString PostData; - Buffer.WriteVarInt32(static_cast<UInt32>(Packet.GetUsedSpace() + 1)); - Buffer.WriteVarInt32(0); - Buffer.ReadAll(PostData); - Buffer.CommitRead(); - - a_Data.clear(); - a_Data.reserve(PostData.size() + PacketData.size()); - a_Data.append(PostData.data(), PostData.size()); - a_Data.append(PacketData.data(), PacketData.size()); - } + CompressAndSend(Packet, a_SendTo); } -void cChunkDataSerializer::Serialize107(AString & a_Data, int a_ChunkX, int a_ChunkZ) +void cChunkDataSerializer::Serialize107(const std::vector<cClientHandle *> & a_SendTo) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Create the packet: cByteBuffer Packet(512 KiB); Packet.WriteVarInt32(0x20); // Packet id (Chunk Data packet) - Packet.WriteBEInt32(a_ChunkX); - Packet.WriteBEInt32(a_ChunkZ); + Packet.WriteBEInt32(m_ChunkX); + Packet.WriteBEInt32(m_ChunkZ); Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag Packet.WriteVarInt32(m_Data.GetSectionBitmask()); // Write the chunk size: @@ -268,48 +273,22 @@ void cChunkDataSerializer::Serialize107(AString & a_Data, int a_ChunkX, int a_Ch // Write the biome data Packet.WriteBuf(m_BiomeData, BiomeDataSize); - AString PacketData; - Packet.ReadAll(PacketData); - Packet.CommitRead(); - - cByteBuffer Buffer(20); - if (PacketData.size() >= 256) - { - if (!cProtocol_1_9_0::CompressPacket(PacketData, a_Data)) - { - ASSERT(!"Packet compression failed."); - a_Data.clear(); - return; - } - } - else - { - AString PostData; - Buffer.WriteVarInt32(static_cast<UInt32>(Packet.GetUsedSpace() + 1)); - Buffer.WriteVarInt32(0); - Buffer.ReadAll(PostData); - Buffer.CommitRead(); - - a_Data.clear(); - a_Data.reserve(PostData.size() + PacketData.size()); - a_Data.append(PostData.data(), PostData.size()); - a_Data.append(PacketData.data(), PacketData.size()); - } + CompressAndSend(Packet, a_SendTo); } -void cChunkDataSerializer::Serialize110(AString & a_Data, int a_ChunkX, int a_ChunkZ) +void cChunkDataSerializer::Serialize110(const std::vector<cClientHandle *> & a_SendTo) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Create the packet: cByteBuffer Packet(512 KiB); Packet.WriteVarInt32(0x20); // Packet id (Chunk Data packet) - Packet.WriteBEInt32(a_ChunkX); - Packet.WriteBEInt32(a_ChunkZ); + Packet.WriteBEInt32(m_ChunkX); + Packet.WriteBEInt32(m_ChunkZ); Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag Packet.WriteVarInt32(m_Data.GetSectionBitmask()); // Write the chunk size: @@ -404,48 +383,23 @@ void cChunkDataSerializer::Serialize110(AString & a_Data, int a_ChunkX, int a_Ch // Identify 1.9.4's tile entity list as empty Packet.WriteBEUInt8(0); - AString PacketData; - Packet.ReadAll(PacketData); - Packet.CommitRead(); - - cByteBuffer Buffer(20); - if (PacketData.size() >= 256) - { - if (!cProtocol_1_9_0::CompressPacket(PacketData, a_Data)) - { - ASSERT(!"Packet compression failed."); - a_Data.clear(); - return; - } - } - else - { - AString PostData; - Buffer.WriteVarInt32(static_cast<UInt32>(Packet.GetUsedSpace() + 1)); - Buffer.WriteVarInt32(0); - Buffer.ReadAll(PostData); - Buffer.CommitRead(); - - a_Data.clear(); - a_Data.reserve(PostData.size() + PacketData.size()); - a_Data.append(PostData.data(), PostData.size()); - a_Data.append(PacketData.data(), PacketData.size()); - } + CompressAndSend(Packet, a_SendTo); } -void cChunkDataSerializer::Serialize393(AString & a_Data, int a_ChunkX, int a_ChunkZ) +template <auto Palette> +void cChunkDataSerializer::Serialize393And401(const std::vector<cClientHandle *> & a_SendTo) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Create the packet: cByteBuffer Packet(512 KiB); Packet.WriteVarInt32(0x22); // Packet id (Chunk Data packet) - Packet.WriteBEInt32(a_ChunkX); - Packet.WriteBEInt32(a_ChunkZ); + Packet.WriteBEInt32(m_ChunkX); + Packet.WriteBEInt32(m_ChunkZ); Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag Packet.WriteVarInt32(m_Data.GetSectionBitmask()); @@ -486,7 +440,7 @@ void cChunkDataSerializer::Serialize393(AString & a_Data, int a_ChunkX, int a_Ch { UInt32 blockType = a_Section.m_BlockTypes[Index]; UInt32 blockMeta = (a_Section.m_BlockMetas[Index / 2] >> ((Index % 2) * 4)) & 0x0f; - UInt64 Value = Palette_1_13::FromBlock(PaletteUpgrade::FromBlock(blockType, blockMeta)); + UInt64 Value = Palette(PaletteUpgrade::FromBlock(blockType, blockMeta)); Value &= Mask; // It shouldn't go out of bounds, but it's still worth being careful // Painful part where we write data into the long array. Based off of the normal code. @@ -536,32 +490,27 @@ void cChunkDataSerializer::Serialize393(AString & a_Data, int a_ChunkX, int a_Ch // Identify 1.9.4's tile entity list as empty Packet.WriteVarInt32(0); + CompressAndSend(Packet, a_SendTo); +} + + + + + +void cChunkDataSerializer::CompressAndSend(cByteBuffer & a_Packet, const std::vector<cClientHandle *> & a_SendTo) +{ AString PacketData; - Packet.ReadAll(PacketData); - Packet.CommitRead(); + a_Packet.ReadAll(PacketData); - if (PacketData.size() >= 256) + AString ToSend; + if (!cProtocol_1_8_0::CompressPacket(PacketData, ToSend)) { - if (!cProtocol_1_9_0::CompressPacket(PacketData, a_Data)) - { - ASSERT(!"Packet compression failed."); - a_Data.clear(); - return; - } + ASSERT(!"Packet compression failed."); + return; } - else + + for (const auto Client : a_SendTo) { - cByteBuffer Buffer(20); - AString PostData; - - Buffer.WriteVarInt32(static_cast<UInt32>(Packet.GetUsedSpace() + 1)); - Buffer.WriteVarInt32(0); - Buffer.ReadAll(PostData); - Buffer.CommitRead(); - - a_Data.clear(); - a_Data.reserve(PostData.size() + PacketData.size()); - a_Data.append(PostData.data(), PostData.size()); - a_Data.append(PacketData.data(), PacketData.size()); + Client->SendChunkData(m_ChunkX, m_ChunkZ, ToSend); } } diff --git a/src/Protocol/ChunkDataSerializer.h b/src/Protocol/ChunkDataSerializer.h index 2670a0705..69e0a7689 100644 --- a/src/Protocol/ChunkDataSerializer.h +++ b/src/Protocol/ChunkDataSerializer.h @@ -7,6 +7,12 @@ +class cByteBuffer; + + + + + /** Serializes one chunk's data to (possibly multiple) protocol versions. Caches the serialized data for as long as this object lives, so that the same data can be sent to other clients using the same protocol. */ @@ -14,26 +20,31 @@ class cChunkDataSerializer { public: - enum - { - RELEASE_1_8_0 = 47, - RELEASE_1_9_0 = 107, - RELEASE_1_9_4 = 110, - RELEASE_1_13 = 393, - } ; - cChunkDataSerializer( - const cChunkData & a_Data, - const unsigned char * a_BiomeData, - const eDimension a_Dimension + int a_ChunkX, + int a_ChunkZ, + const cChunkData & a_Data, + const unsigned char * a_BiomeData, + const eDimension a_Dimension ); - /** Serializes the contained chunk data into the specified protocol version. */ - const AString & Serialize(int a_Version, int a_ChunkX, int a_ChunkZ); + /** For each client, serializes the chunk into their protocol version and sends it. */ + void SendToClients(const std::unordered_set<cClientHandle *> & a_SendTo); protected: - using Serializations = std::map<int, AString>; + void Serialize47 (const std::vector<cClientHandle *> & a_SendTo); // Release 1.8 + void Serialize107(const std::vector<cClientHandle *> & a_SendTo); // Release 1.9 + void Serialize110(const std::vector<cClientHandle *> & a_SendTo); // Release 1.9.4 + + template <auto Palette> + void Serialize393And401(const std::vector<cClientHandle *> & a_SendTo); // Release 1.13 - 1.13.1 + + /** Finalises the data, compresses it if required, and delivers it to all clients. */ + void CompressAndSend(cByteBuffer & a_Packet, const std::vector<cClientHandle *> & a_SendTo); + + /** The coordinates of the chunk to serialise. */ + int m_ChunkX, m_ChunkZ; /** The data read from the chunk, to be serialized. */ const cChunkData & m_Data; @@ -43,14 +54,6 @@ protected: /** The dimension where the chunk resides. */ const eDimension m_Dimension; - - /** The per-protocol serialized data, cached for reuse for other clients. */ - Serializations m_Serializations; - - void Serialize47 (AString & a_Data, int a_ChunkX, int a_ChunkZ); // Release 1.8 - void Serialize107(AString & a_Data, int a_ChunkX, int a_ChunkZ); // Release 1.9 - void Serialize110(AString & a_Data, int a_ChunkX, int a_ChunkZ); // Release 1.9.4 - void Serialize393(AString & a_Data, int a_ChunkX, int a_ChunkZ); // Release 1.13 } ; diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 817d0bef0..8636c350f 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -357,7 +357,7 @@ public: virtual void SendChat (const AString & a_Message, eChatType a_Type) = 0; virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) = 0; virtual void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type) = 0; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0; + virtual void SendChunkData (const std::string_view a_ChunkData) = 0; virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) = 0; virtual void SendDestroyEntity (const cEntity & a_Entity) = 0; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) = 0; diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index e7686577f..005cabfe3 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -46,7 +46,7 @@ public: virtual void SendChat (const AString & a_Message, eChatType a_Type) override; virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) override; virtual void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; + virtual void SendChunkData (const std::string_view a_ChunkData) override; virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 90e770134..73b499009 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -106,22 +106,6 @@ void cProtocol_1_9_0::SendAttachEntity(const cEntity & a_Entity, const cEntity & -void cProtocol_1_9_0::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) -{ - ASSERT(m_State == 3); // In game mode? - - // Serialize first, before creating the Packetizer (the packetizer locks a CS) - // This contains the flags and bitmasks, too - const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_9_0, a_ChunkX, a_ChunkZ); - - cCSLock Lock(m_CSPacket); - SendData(ChunkData.data(), ChunkData.size()); -} - - - - - void cProtocol_1_9_0::SendDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) { ASSERT(m_State == 3); // In game mode? @@ -2257,22 +2241,6 @@ cProtocol_1_9_4::cProtocol_1_9_4(cClientHandle * a_Client, const AString & a_Ser -void cProtocol_1_9_4::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) -{ - ASSERT(m_State == 3); // In game mode? - - // Serialize first, before creating the Packetizer (the packetizer locks a CS) - // This contains the flags and bitmasks, too - const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_9_4, a_ChunkX, a_ChunkZ); - - cCSLock Lock(m_CSPacket); - SendData(ChunkData.data(), ChunkData.size()); -} - - - - - void cProtocol_1_9_4::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h index cb96f6962..2debb9e13 100644 --- a/src/Protocol/Protocol_1_9.h +++ b/src/Protocol/Protocol_1_9.h @@ -42,7 +42,6 @@ public: /** Sending stuff to clients (alphabetically sorted): */ virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityMetadata (const cEntity & a_Entity) override; @@ -202,8 +201,7 @@ public: protected: - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; + virtual void SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; /** Returns 1.9.4. */ virtual Version GetProtocolVersion() override; |