summaryrefslogtreecommitdiffstats
path: root/src/Protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/Protocol')
-rw-r--r--src/Protocol/CMakeLists.txt2
-rw-r--r--src/Protocol/ChunkDataSerializer.cpp118
-rw-r--r--src/Protocol/ChunkDataSerializer.h7
-rw-r--r--src/Protocol/Packetizer.h14
-rw-r--r--src/Protocol/Protocol.h3
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp18
-rw-r--r--src/Protocol/Protocol_1_11.cpp2
-rw-r--r--src/Protocol/Protocol_1_12.cpp2
-rw-r--r--src/Protocol/Protocol_1_12.h1
-rw-r--r--src/Protocol/Protocol_1_13.cpp27
-rw-r--r--src/Protocol/Protocol_1_13.h26
-rw-r--r--src/Protocol/Protocol_1_14.cpp305
-rw-r--r--src/Protocol/Protocol_1_14.h59
-rw-r--r--src/Protocol/Protocol_1_8.cpp26
-rw-r--r--src/Protocol/Protocol_1_8.h2
-rw-r--r--src/Protocol/Protocol_1_9.cpp12
16 files changed, 560 insertions, 64 deletions
diff --git a/src/Protocol/CMakeLists.txt b/src/Protocol/CMakeLists.txt
index f3d0e1901..fc7366efc 100644
--- a/src/Protocol/CMakeLists.txt
+++ b/src/Protocol/CMakeLists.txt
@@ -12,6 +12,7 @@ target_sources(
Protocol_1_11.cpp
Protocol_1_12.cpp
Protocol_1_13.cpp
+ Protocol_1_14.cpp
ProtocolRecognizer.cpp
RecipeMapper.cpp
@@ -27,6 +28,7 @@ target_sources(
Protocol_1_11.h
Protocol_1_12.h
Protocol_1_13.h
+ Protocol_1_14.h
ProtocolRecognizer.h
RecipeMapper.h
)
diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp
index 6577aaedd..d4e23f11f 100644
--- a/src/Protocol/ChunkDataSerializer.cpp
+++ b/src/Protocol/ChunkDataSerializer.cpp
@@ -5,10 +5,12 @@
#include "Protocol_1_9.h"
#include "../ByteBuffer.h"
#include "../ClientHandle.h"
+#include "../WorldStorage/FastNBT.h"
#include "Palettes/Upgrade.h"
#include "Palettes/Palette_1_13.h"
#include "Palettes/Palette_1_13_1.h"
+#include "Palettes/Palette_1_14.h"
@@ -102,6 +104,11 @@ void cChunkDataSerializer::SendToClients(const std::unordered_set<cClientHandle
Serialize393<&Palette_1_13_1::FromBlock>(Entry.second);
continue;
}
+ case cProtocol::Version::Version_1_14:
+ {
+ Serialize477(Entry.second);
+ continue;
+ }
}
LOGERROR("cChunkDataSerializer::Serialize(): Unknown version: %d", Entry.first);
@@ -497,6 +504,117 @@ void cChunkDataSerializer::Serialize393(const std::vector<cClientHandle *> & a_S
+void cChunkDataSerializer::Serialize477(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(m_ChunkX);
+ Packet.WriteBEInt32(m_ChunkZ);
+ Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag
+ Packet.WriteVarInt32(m_Data.GetSectionBitmask());
+
+ {
+ cFastNBTWriter Writer;
+ // TODO: client works fine without?
+ // std::array<Int64, 36> Longz = {};
+ // Writer.AddLongArray("MOTION_BLOCKING", Longz.data(), Longz.size());
+ Writer.Finish();
+ Packet.Write(Writer.GetResult().data(), Writer.GetResult().size());
+ }
+
+ // Write the chunk size in bytes:
+ const UInt8 BitsPerEntry = 14;
+ const size_t Mask = (1 << BitsPerEntry) - 1;
+ const size_t ChunkSectionDataArraySize = (cChunkData::SectionBlockCount * BitsPerEntry) / 8 / 8;
+ const size_t ChunkSectionSize = (
+ 2 + // Block count, BEInt16, 2 bytes
+ 1 + // Bits per entry, BEUInt8, 1 byte
+ Packet.GetVarIntSize(static_cast<UInt32>(ChunkSectionDataArraySize)) + // Field containing "size of whole section", VarInt32, variable size
+ ChunkSectionDataArraySize * 8 // Actual section data, lots of bytes (multiplier 1 long = 8 bytes)
+ );
+
+ const size_t BiomeDataSize = cChunkDef::Width * cChunkDef::Width;
+ const size_t ChunkSize = (
+ ChunkSectionSize * m_Data.NumPresentSections() +
+ BiomeDataSize * 4 // Biome data now BE ints
+ );
+ Packet.WriteVarInt32(static_cast<UInt32>(ChunkSize));
+
+ // Write each chunk section...
+ ForEachSection(m_Data, [&](const cChunkData::sChunkSection & a_Section)
+ {
+ Packet.WriteBEInt16(-1);
+ Packet.WriteBEUInt8(BitsPerEntry);
+ Packet.WriteVarInt32(static_cast<UInt32>(ChunkSectionDataArraySize));
+ WriteSectionDataSeamless(Packet, a_Section, BitsPerEntry);
+ }
+ );
+
+ // Write the biome data
+ for (size_t i = 0; i != BiomeDataSize; i++)
+ {
+ Packet.WriteBEUInt32(static_cast<UInt32>(m_BiomeData[i]) & 0xff);
+ }
+
+ // Identify 1.9.4's tile entity list as empty
+ Packet.WriteVarInt32(0);
+
+ CompressAndSend(Packet, a_SendTo);
+}
+
+
+
+
+
+void cChunkDataSerializer::WriteSectionDataSeamless(cByteBuffer & a_Packet, const cChunkData::sChunkSection & a_Section, const UInt8 a_BitsPerEntry)
+{
+ // https://wiki.vg/Chunk_Format#Data_structure
+
+ // We shift a UInt64 by a_BitsPerEntry, the latter cannot be too big:
+ ASSERT(a_BitsPerEntry < 64);
+
+ UInt64 Buffer = 0; // A buffer to compose multiple smaller bitsizes into one 64-bit number
+ unsigned char BitIndex = 0; // The bit-position in Buffer that represents where to write next
+
+ for (size_t Index = 0; Index != cChunkData::SectionBlockCount; Index++)
+ {
+ const UInt32 BlockType = a_Section.m_BlockTypes[Index];
+ const UInt32 BlockMeta = (a_Section.m_BlockMetas[Index / 2] >> ((Index % 2) * 4)) & 0x0f;
+ const UInt32 Value = Palette_1_14::FromBlock(PaletteUpgrade::FromBlock(BlockType, BlockMeta));
+
+ // Write as much as possible of Value, starting from BitIndex, into Buffer:
+ Buffer |= static_cast<UInt64>(Value) << BitIndex;
+
+ // The _signed_ count of bits in Value left to write
+ const char Remaining = a_BitsPerEntry - (64 - BitIndex);
+ if (Remaining >= 0)
+ {
+ // There were some bits remaining: we've filled the buffer. Flush it:
+ a_Packet.WriteBEUInt64(Buffer);
+
+ // And write the remaining bits, setting the new BitIndex:
+ Buffer = Value >> (a_BitsPerEntry - Remaining);
+ BitIndex = Remaining;
+ }
+ else
+ {
+ // It fit, sexcellent.
+ BitIndex += a_BitsPerEntry;
+ }
+ }
+
+ static_assert((cChunkData::SectionBlockCount % 64) == 0, "Section must fit wholly into a 64-bit long array");
+ ASSERT(BitIndex == 0);
+ ASSERT(Buffer == 0);
+}
+
+
+
+
+
void cChunkDataSerializer::CompressAndSend(cByteBuffer & a_Packet, const std::vector<cClientHandle *> & a_SendTo)
{
AString PacketData;
diff --git a/src/Protocol/ChunkDataSerializer.h b/src/Protocol/ChunkDataSerializer.h
index ed3e5c8b1..ce80cc481 100644
--- a/src/Protocol/ChunkDataSerializer.h
+++ b/src/Protocol/ChunkDataSerializer.h
@@ -36,9 +36,12 @@ protected:
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 Serialize393(const std::vector<cClientHandle *> & a_SendTo); // Release 1.13 - 1.13.1
+ void Serialize477(const std::vector<cClientHandle *> & a_SendTo); // Release 1.13 - 1.13.1
- template <auto Palette>
- void Serialize393(const std::vector<cClientHandle *> & a_SendTo); // Release 1.13 - 1.13.1
+ /** Writes all blocks in a chunk section into a series of Int64.
+ Writes start from the bit directly subsequent to the previous write's end, possibly crossing over to the next Int64. */
+ inline void WriteSectionDataSeamless(cByteBuffer & a_Packet, const cChunkData::sChunkSection & a_Section, const UInt8 a_BitsPerEntry);
/** Finalises the data, compresses it if required, and delivers it to all clients. */
void CompressAndSend(cByteBuffer & a_Packet, const std::vector<cClientHandle *> & a_SendTo);
diff --git a/src/Protocol/Packetizer.h b/src/Protocol/Packetizer.h
index e3a409cf0..22ef01ed9 100644
--- a/src/Protocol/Packetizer.h
+++ b/src/Protocol/Packetizer.h
@@ -125,10 +125,18 @@ public:
}
- /** Writes the specified block position as a single encoded 64-bit BigEndian integer. */
- inline void WritePosition64(int a_BlockX, int a_BlockY, int a_BlockZ)
+ /** Writes the specified block position as a single encoded 64-bit BigEndian integer.
+ The three coordinates are written in XYZ order. */
+ inline void WriteXYZPosition64(int a_BlockX, int a_BlockY, int a_BlockZ)
{
- VERIFY(m_Out.WritePosition64(a_BlockX, a_BlockY, a_BlockZ));
+ VERIFY(m_Out.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ));
+ }
+
+ /** Writes the specified block position as a single encoded 64-bit BigEndian integer.
+ The three coordinates are written in XZY order, in 1.14+. */
+ inline void WriteXZYPosition64(int a_BlockX, int a_BlockY, int a_BlockZ)
+ {
+ VERIFY(m_Out.WriteXZYPosition64(a_BlockX, a_BlockY, a_BlockZ));
}
/** Writes the specified angle using a single byte. */
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 8636c350f..1b2e74d7c 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -341,7 +341,8 @@ public:
Version_1_12_2 = 340,
Version_1_13 = 393,
Version_1_13_1 = 401,
- Version_1_13_2 = 404 // TODO: this constant should be in WebServer
+ Version_1_13_2 = 404, // TODO: this constant should be in WebServer
+ Version_1_14 = 477
};
/** Called when client sends some data */
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index a6aa901c9..813791485 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -13,6 +13,7 @@
#include "Protocol_1_11.h"
#include "Protocol_1_12.h"
#include "Protocol_1_13.h"
+#include "Protocol_1_14.h"
#include "../ClientHandle.h"
#include "../Root.h"
#include "../Server.h"
@@ -76,7 +77,9 @@ AString cMultiVersionProtocol::GetVersionTextFromInt(cProtocol::Version a_Protoc
case cProtocol::Version::Version_1_13: return "1.13";
case cProtocol::Version::Version_1_13_1: return "1.13.1";
case cProtocol::Version::Version_1_13_2: return "1.13.2";
+ case cProtocol::Version::Version_1_14: return "1.14";
}
+
ASSERT(!"Unknown protocol version");
return Printf("Unknown protocol (%d)", a_ProtocolVersion);
}
@@ -285,20 +288,21 @@ std::unique_ptr<cProtocol> cMultiVersionProtocol::TryRecognizeLengthedProtocol(c
switch (static_cast<cProtocol::Version>(ProtocolVersion))
{
- case cProtocol::Version::Version_1_8_0: return std::make_unique<cProtocol_1_8_0>(&a_Client, ServerAddress, ServerPort, NextState);
- case cProtocol::Version::Version_1_9_0: return std::make_unique<cProtocol_1_9_0>(&a_Client, ServerAddress, ServerPort, NextState);
- case cProtocol::Version::Version_1_9_1: return std::make_unique<cProtocol_1_9_1>(&a_Client, ServerAddress, ServerPort, NextState);
- case cProtocol::Version::Version_1_9_2: return std::make_unique<cProtocol_1_9_2>(&a_Client, ServerAddress, ServerPort, NextState);
- case cProtocol::Version::Version_1_9_4: return std::make_unique<cProtocol_1_9_4>(&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_8_0: return std::make_unique<cProtocol_1_8_0> (&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_9_0: return std::make_unique<cProtocol_1_9_0> (&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_9_1: return std::make_unique<cProtocol_1_9_1> (&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_9_2: return std::make_unique<cProtocol_1_9_2> (&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_9_4: return std::make_unique<cProtocol_1_9_4> (&a_Client, ServerAddress, ServerPort, NextState);
case cProtocol::Version::Version_1_10_0: return std::make_unique<cProtocol_1_10_0>(&a_Client, ServerAddress, ServerPort, NextState);
case cProtocol::Version::Version_1_11_0: return std::make_unique<cProtocol_1_11_0>(&a_Client, ServerAddress, ServerPort, NextState);
case cProtocol::Version::Version_1_11_1: return std::make_unique<cProtocol_1_11_1>(&a_Client, ServerAddress, ServerPort, NextState);
- case cProtocol::Version::Version_1_12: return std::make_unique<cProtocol_1_12>(&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_12: return std::make_unique<cProtocol_1_12> (&a_Client, ServerAddress, ServerPort, NextState);
case cProtocol::Version::Version_1_12_1: return std::make_unique<cProtocol_1_12_1>(&a_Client, ServerAddress, ServerPort, NextState);
case cProtocol::Version::Version_1_12_2: return std::make_unique<cProtocol_1_12_2>(&a_Client, ServerAddress, ServerPort, NextState);
- case cProtocol::Version::Version_1_13: return std::make_unique<cProtocol_1_13>(&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_13: return std::make_unique<cProtocol_1_13> (&a_Client, ServerAddress, ServerPort, NextState);
case cProtocol::Version::Version_1_13_1: return std::make_unique<cProtocol_1_13_1>(&a_Client, ServerAddress, ServerPort, NextState);
case cProtocol::Version::Version_1_13_2: return std::make_unique<cProtocol_1_13_2>(&a_Client, ServerAddress, ServerPort, NextState);
+ case cProtocol::Version::Version_1_14: return std::make_unique<cProtocol_1_14> (&a_Client, ServerAddress, ServerPort, NextState);
default:
{
LOGD("Client \"%s\" uses an unsupported protocol (lengthed, version %u (0x%x))",
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index 385dcb34a..dcb1e98fc 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -592,7 +592,7 @@ UInt32 cProtocol_1_11_0::GetProtocolMobType(eMonsterType a_MobType)
void cProtocol_1_11_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
{
int BlockX, BlockY, BlockZ;
- if (!a_ByteBuffer.ReadPosition64(BlockX, BlockY, BlockZ))
+ if (!a_ByteBuffer.ReadXYZPosition64(BlockX, BlockY, BlockZ))
{
return;
}
diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp
index 3be1fe672..a67a82eaf 100644
--- a/src/Protocol/Protocol_1_12.cpp
+++ b/src/Protocol/Protocol_1_12.cpp
@@ -4,6 +4,8 @@
/*
Implements the 1.12 protocol classes:
- release 1.12 protocol (#335)
+- release 1.12.1 protocol (#338)
+- release 1.12.2 protocol (#340)
*/
#include "Globals.h"
diff --git a/src/Protocol/Protocol_1_12.h b/src/Protocol/Protocol_1_12.h
index 42c8483c4..80f0b4680 100644
--- a/src/Protocol/Protocol_1_12.h
+++ b/src/Protocol/Protocol_1_12.h
@@ -9,7 +9,6 @@ Declares the 1.12 protocol classes:
- release 1.12.1 protocol (#338)
- cProtocol_1_12_2
- release 1.12.2 protocol (#340)
-(others may be added later in the future for the 1.12 release series)
*/
diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp
index c8c2e7383..3ca1cc3a8 100644
--- a/src/Protocol/Protocol_1_13.cpp
+++ b/src/Protocol/Protocol_1_13.cpp
@@ -4,11 +4,12 @@
/*
Implements the 1.13 protocol classes:
- release 1.13 protocol (#393)
+- release 1.13.1 protocol (#401)
+- release 1.13.2 protocol (#404)
*/
#include "Globals.h"
#include "Protocol_1_13.h"
-#include "Packetizer.h"
#include "../Entities/Boat.h"
#include "../Entities/Minecart.h"
@@ -29,7 +30,6 @@ Implements the 1.13 protocol classes:
#include "../Bindings/PluginManager.h"
-#include "Palettes/Upgrade.h"
#include "Palettes/Palette_1_13.h"
#include "Palettes/Palette_1_13_1.h"
@@ -85,7 +85,7 @@ void cProtocol_1_13::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, B
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktBlockChange);
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
Pkt.WriteVarInt32(Palette(PaletteUpgrade::FromBlock(a_BlockType, a_BlockMeta)));
}
@@ -102,27 +102,6 @@ void cProtocol_1_13::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBloc
-template <auto Palette>
-void cProtocol_1_13::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktBlockChanges);
- Pkt.WriteBEInt32(a_ChunkX);
- Pkt.WriteBEInt32(a_ChunkZ);
- Pkt.WriteVarInt32(static_cast<UInt32>(a_Changes.size()));
- for (const auto & Change : a_Changes)
- {
- Int16 Coords = static_cast<Int16>(Change.m_RelY | (Change.m_RelZ << 8) | (Change.m_RelX << 12));
- Pkt.WriteBEInt16(Coords);
- Pkt.WriteVarInt32(Palette(PaletteUpgrade::FromBlock(Change.m_BlockType, Change.m_BlockMeta)));
- } // for itr - a_Changes[]
-}
-
-
-
-
-
void cProtocol_1_13::SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY)
{
// TODO
diff --git a/src/Protocol/Protocol_1_13.h b/src/Protocol/Protocol_1_13.h
index fa4625f7e..bdc8bb33a 100644
--- a/src/Protocol/Protocol_1_13.h
+++ b/src/Protocol/Protocol_1_13.h
@@ -9,7 +9,6 @@ Declares the 1.13 protocol classes:
- release 1.13.1 protocol (#401)
- cProtocol_1_13_2
- release 1.13.2 protocol (#404)
-(others may be added later in the future for the 1.13 release series)
*/
@@ -19,6 +18,8 @@ Declares the 1.13 protocol classes:
#pragma once
#include "Protocol_1_12.h"
+#include "Packetizer.h"
+#include "Palettes/Upgrade.h"
@@ -35,11 +36,27 @@ public:
protected:
- // Packet sending:
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
template <auto Palette> void SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // Template to avoid virtual calls in tight loops
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
- template <auto Palette>void SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes); // Template to avoid virtual calls in tight loops
+
+ /** Common implementation of multiblock change sending, templated to avoid virtual calls in tight loops. */
+ template <auto Palette>void SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes)
+ {
+ ASSERT(m_State == 3); // In game mode?
+
+ cPacketizer Pkt(*this, pktBlockChanges);
+ Pkt.WriteBEInt32(a_ChunkX);
+ Pkt.WriteBEInt32(a_ChunkZ);
+ Pkt.WriteVarInt32(static_cast<UInt32>(a_Changes.size()));
+ for (const auto & Change : a_Changes)
+ {
+ Int16 Coords = static_cast<Int16>(Change.m_RelY | (Change.m_RelZ << 8) | (Change.m_RelX << 12));
+ Pkt.WriteBEInt16(Coords);
+ Pkt.WriteVarInt32(Palette(PaletteUpgrade::FromBlock(Change.m_BlockType, Change.m_BlockMeta)));
+ } // for itr - a_Changes[]
+ }
+
virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) override;
@@ -49,7 +66,7 @@ protected:
virtual void SendTabCompletionResults (const AStringVector & a_Results) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
- // Outgoing packet type translation:
+ /** Translates outgoing packet types. */
virtual UInt32 GetPacketID(ePacketType a_PacketType) override;
/** Returns 1.13. */
@@ -63,7 +80,6 @@ protected:
virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID);
virtual UInt32 GetProtocolIDFromItem(short a_ItemID, short a_ItemDamage);
- // Packet receiving:
virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override;
virtual void HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) override;
diff --git a/src/Protocol/Protocol_1_14.cpp b/src/Protocol/Protocol_1_14.cpp
new file mode 100644
index 000000000..d6751c6b1
--- /dev/null
+++ b/src/Protocol/Protocol_1_14.cpp
@@ -0,0 +1,305 @@
+
+// Protocol_1_14.cpp
+
+/*
+Implements the 1.14 protocol classes:
+- release 1.14 protocol (#477)
+*/
+
+#include "Globals.h"
+#include "Protocol_1_14.h"
+#include "Packetizer.h"
+#include "../Entities/Player.h"
+#include "../Root.h"
+#include "../Server.h"
+#include "../World.h"
+
+#include "Palettes/Upgrade.h"
+#include "Palettes/Palette_1_14.h"
+
+
+
+
+
+#define HANDLE_READ(ByteBuf, Proc, Type, Var) \
+ Type Var; \
+ do { \
+ if (!ByteBuf.Proc(Var))\
+ {\
+ return;\
+ } \
+ } while (false)
+
+
+
+
+
+#define HANDLE_PACKET_READ(ByteBuf, Proc, Type, Var) \
+ Type Var; \
+ do { \
+ { \
+ if (!ByteBuf.Proc(Var)) \
+ { \
+ ByteBuf.CheckValid(); \
+ return false; \
+ } \
+ ByteBuf.CheckValid(); \
+ } \
+ } while (false)
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cProtocol_1_14:
+
+void cProtocol_1_14::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::SendBlockBreakAnim(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
+{
+ SendBlockChange<&Palette_1_14::FromBlock>(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
+}
+
+
+
+
+
+template <auto Palette>
+void cProtocol_1_14::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
+{
+ ASSERT(m_State == 3); // In game mode?
+
+ cPacketizer Pkt(*this, pktBlockChange);
+ Pkt.WriteXZYPosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteVarInt32(Palette(PaletteUpgrade::FromBlock(a_BlockType, a_BlockMeta)));
+}
+
+
+
+
+
+void cProtocol_1_14::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes)
+{
+ cProtocol_1_13::SendBlockChanges<&Palette_1_14::FromBlock>(a_ChunkX, a_ChunkZ, a_Changes);
+}
+
+
+
+
+
+void cProtocol_1_14::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
+{
+ // Send the Join Game packet:
+ {
+ cServer * Server = cRoot::Get()->GetServer();
+ cPacketizer Pkt(*this, pktJoinGame);
+ Pkt.WriteBEUInt32(a_Player.GetUniqueID());
+ Pkt.WriteBEUInt8(static_cast<UInt8>(a_Player.GetEffectiveGameMode()) | (Server->IsHardcore() ? 0x08 : 0));
+ Pkt.WriteBEInt32(static_cast<Int32>(a_World.GetDimension()));
+ Pkt.WriteBEUInt8(static_cast<UInt8>(Clamp<size_t>(Server->GetMaxPlayers(), 0, 255)));
+ Pkt.WriteString("default");
+ Pkt.WriteVarInt32(a_World.GetMaxViewDistance());
+ Pkt.WriteBool(false);
+ }
+
+ // Send the spawn position:
+ {
+ cPacketizer Pkt(*this, pktSpawnPosition);
+ Pkt.WriteXZYPosition64(FloorC(a_World.GetSpawnX()), FloorC(a_World.GetSpawnY()), FloorC(a_World.GetSpawnZ()));
+ }
+
+ // Send the server difficulty:
+ {
+ // cPacketizer Pkt(*this, pktDifficulty);
+ // Pkt.WriteBEInt8(1);
+ }
+
+ // Send player abilities:
+ SendPlayerAbilities();
+}
+
+
+
+
+
+void cProtocol_1_14::SendPaintingSpawn(const cPainting & a_Painting)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::SendSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::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)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+}
+
+
+
+
+
+UInt32 cProtocol_1_14::GetPacketID(ePacketType a_PacketType)
+{
+ switch (a_PacketType)
+ {
+ case cProtocol::pktAttachEntity: return 0x4A;
+ case cProtocol::pktCameraSetTo: return 0x3E;
+ case cProtocol::pktCollectEntity: return 0x55;
+ case cProtocol::pktDestroyEntity: return 0x37;
+ case cProtocol::pktDisconnectDuringGame: return 0x1A;
+ case cProtocol::pktEntityEffect: return 0x59;
+ case cProtocol::pktEntityEquipment: return 0x46;
+ case cProtocol::pktEntityHeadLook: return 0x3B;
+ case cProtocol::pktEntityMeta: return 0x43;
+ case cProtocol::pktEntityProperties: return 0x58;
+ case cProtocol::pktEntityStatus: return 0x1B;
+ case cProtocol::pktEntityVelocity: return 0x45;
+ case cProtocol::pktExperience: return 0x47;
+ case cProtocol::pktExplosion: return 0x1C;
+ case cProtocol::pktGameMode: return 0x1E;
+ case cProtocol::pktHeldItemChange: return 0x3F;
+ case cProtocol::pktInventorySlot: return 0x16;
+ case cProtocol::pktKeepAlive: return 0x20;
+ case cProtocol::pktParticleEffect: return 0x23;
+ case cProtocol::pktPlayerAbilities: return 0x31;
+ case cProtocol::pktPlayerList: return 0x33;
+ case cProtocol::pktPlayerMoveLook: return 0x35;
+ case cProtocol::pktPluginMessage: return 0x18;
+ case cProtocol::pktRemoveEntityEffect: return 0x38;
+ case cProtocol::pktResourcePack: return 0x39;
+ case cProtocol::pktRespawn: return 0x3A;
+ case cProtocol::pktScoreboardObjective: return 0x49;
+ case cProtocol::pktSoundEffect: return 0x19;
+ case cProtocol::pktSoundParticleEffect: return 0x22;
+ case cProtocol::pktSpawnPosition: return 0x4D;
+ case cProtocol::pktTeleportEntity: return 0x56;
+ case cProtocol::pktTimeUpdate: return 0x4E;
+ case cProtocol::pktTitle: return 0x4F;
+ case cProtocol::pktUnloadChunk: return 0x1D;
+ case cProtocol::pktUnlockRecipe: return 0x36;
+ case cProtocol::pktUpdateHealth: return 0x48;
+ case cProtocol::pktUpdateScore: return 0x4C;
+ case cProtocol::pktUpdateSign: return 0x2F;
+ case cProtocol::pktWindowItems: return 0x14;
+ case cProtocol::pktWindowOpen: return 0x2E;
+ case cProtocol::pktWindowProperty: return 0x15;
+ default: return Super::GetPacketID(a_PacketType);
+ }
+}
+
+
+
+
+
+cProtocol::Version cProtocol_1_14::GetProtocolVersion()
+{
+ return Version::Version_1_14;
+}
+
+
+
+
+
+bool cProtocol_1_14::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
+{
+ if (m_State != 3)
+ {
+ return Super::HandlePacket(a_ByteBuffer, a_PacketType);
+ }
+
+ // Game
+ switch (a_PacketType)
+ {
+ default: AString dum; a_ByteBuffer.ReadAll(dum); a_ByteBuffer.CommitRead(); a_ByteBuffer.Write(" ", 1);
+ return true;
+ }
+}
+
+
+
+
+
+void cProtocol_1_14::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
+{
+}
+
+
+
+
+
+void cProtocol_1_14::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer)
+{
+}
+
+
+
+
+
+std::pair<short, short> cProtocol_1_14::GetItemFromProtocolID(UInt32 a_ProtocolID)
+{
+ return PaletteUpgrade::ToItem(Palette_1_14::ToItem(a_ProtocolID));
+}
+
+
+
+
+
+UInt32 cProtocol_1_14::GetProtocolIDFromItem(short a_ItemID, short a_ItemDamage)
+{
+ return Palette_1_14::FromItem(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage));
+}
diff --git a/src/Protocol/Protocol_1_14.h b/src/Protocol/Protocol_1_14.h
new file mode 100644
index 000000000..2b21246e5
--- /dev/null
+++ b/src/Protocol/Protocol_1_14.h
@@ -0,0 +1,59 @@
+
+// Protocol_1_14.h
+
+/*
+Declares the 1.14 protocol classes:
+ - cProtocol_1_14
+ - release 1.14 protocol (#477)
+*/
+
+
+
+
+
+#pragma once
+
+#include "Protocol_1_13.h"
+
+
+
+
+
+class cProtocol_1_14:
+ public cProtocol_1_13_2
+{
+ using Super = cProtocol_1_13_2;
+
+public:
+
+ using Super::cProtocol_1_13_2;
+
+protected:
+
+ virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
+ virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
+ virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
+ template <auto Palette> void SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
+ virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
+ virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
+ virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
+ virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
+ virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) 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 SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
+
+ virtual UInt32 GetPacketID(ePacketType a_PacketType) override;
+ virtual Version GetProtocolVersion() override;
+
+ virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override;
+ virtual void HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) override;
+ virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override;
+ virtual void HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) override;
+
+ virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) override;
+ virtual UInt32 GetProtocolIDFromItem(short a_ItemID, short a_ItemDamage) override;
+
+ virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override {}
+ virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override {}
+};
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index 50c70ef09..e865725ea 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -224,7 +224,7 @@ void cProtocol_1_8_0::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ,
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktBlockAction);
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
Pkt.WriteBEInt8(a_Byte1);
Pkt.WriteBEInt8(a_Byte2);
Pkt.WriteVarInt32(a_BlockType);
@@ -240,7 +240,7 @@ void cProtocol_1_8_0::SendBlockBreakAnim(UInt32 a_EntityID, int a_BlockX, int a_
cPacketizer Pkt(*this, pktBlockBreakAnim);
Pkt.WriteVarInt32(a_EntityID);
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
Pkt.WriteBEInt8(a_Stage);
}
@@ -253,7 +253,7 @@ void cProtocol_1_8_0::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ,
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktBlockChange);
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
Pkt.WriteVarInt32((static_cast<UInt32>(a_BlockType) << 4) | (static_cast<UInt32>(a_BlockMeta) & 15));
}
@@ -410,7 +410,7 @@ void cProtocol_1_8_0::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktEditSign);
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
}
@@ -776,7 +776,7 @@ void cProtocol_1_8_0::SendLogin(const cPlayer & a_Player, const cWorld & a_World
// Send the spawn position:
{
cPacketizer Pkt(*this, pktSpawnPosition);
- Pkt.WritePosition64(FloorC(a_World.GetSpawnX()), FloorC(a_World.GetSpawnY()), FloorC(a_World.GetSpawnZ()));
+ Pkt.WriteXYZPosition64(FloorC(a_World.GetSpawnX()), FloorC(a_World.GetSpawnY()), FloorC(a_World.GetSpawnZ()));
}
// Send the server difficulty:
@@ -826,7 +826,7 @@ void cProtocol_1_8_0::SendPaintingSpawn(const cPainting & a_Painting)
cPacketizer Pkt(*this, pktSpawnPainting);
Pkt.WriteVarInt32(a_Painting.GetUniqueID());
Pkt.WriteString(a_Painting.GetName());
- Pkt.WritePosition64(static_cast<Int32>(PosX), static_cast<Int32>(PosY), static_cast<Int32>(PosZ));
+ Pkt.WriteXYZPosition64(static_cast<Int32>(PosX), static_cast<Int32>(PosY), static_cast<Int32>(PosZ));
Pkt.WriteBEInt8(static_cast<Int8>(a_Painting.GetProtocolFacing()));
}
@@ -1339,7 +1339,7 @@ void cProtocol_1_8_0::SendSoundParticleEffect(const EffectID a_EffectID, int a_S
cPacketizer Pkt(*this, pktSoundParticleEffect);
Pkt.WriteBEInt32(static_cast<int>(a_EffectID));
- Pkt.WritePosition64(a_SrcX, a_SrcY, a_SrcZ);
+ Pkt.WriteXYZPosition64(a_SrcX, a_SrcY, a_SrcZ);
Pkt.WriteBEInt32(a_Data);
Pkt.WriteBool(false);
}
@@ -1526,7 +1526,7 @@ void cProtocol_1_8_0::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktUpdateBlockEntity);
- Pkt.WritePosition64(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), a_BlockEntity.GetPosZ());
+ Pkt.WriteXYZPosition64(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), a_BlockEntity.GetPosZ());
Byte Action = 0;
switch (a_BlockEntity.GetBlockType())
@@ -1553,7 +1553,7 @@ void cProtocol_1_8_0::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, c
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktUpdateSign);
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
AString Lines[] = { a_Line1, a_Line2, a_Line3, a_Line4 };
for (size_t i = 0; i < ARRAYCOUNT(Lines); i++)
@@ -1574,7 +1574,7 @@ void cProtocol_1_8_0::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_B
cPacketizer Pkt(*this, pktUseBed);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
}
@@ -2471,7 +2471,7 @@ void cProtocol_1_8_0::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status);
int BlockX, BlockY, BlockZ;
- if (!a_ByteBuffer.ReadPosition64(BlockX, BlockY, BlockZ))
+ if (!a_ByteBuffer.ReadXYZPosition64(BlockX, BlockY, BlockZ))
{
return;
}
@@ -2487,7 +2487,7 @@ void cProtocol_1_8_0::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer)
void cProtocol_1_8_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
{
int BlockX, BlockY, BlockZ;
- if (!a_ByteBuffer.ReadPosition64(BlockX, BlockY, BlockZ))
+ if (!a_ByteBuffer.ReadXYZPosition64(BlockX, BlockY, BlockZ))
{
return;
}
@@ -2805,7 +2805,7 @@ void cProtocol_1_8_0::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer)
void cProtocol_1_8_0::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer)
{
int BlockX, BlockY, BlockZ;
- if (!a_ByteBuffer.ReadPosition64(BlockX, BlockY, BlockZ))
+ if (!a_ByteBuffer.ReadXYZPosition64(BlockX, BlockY, BlockZ))
{
return;
}
diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h
index cd9e2f095..aec9e2e57 100644
--- a/src/Protocol/Protocol_1_8.h
+++ b/src/Protocol/Protocol_1_8.h
@@ -4,7 +4,7 @@
/*
Declares the 1.8 protocol classes:
- cProtocol_1_8_0
- - release 1.8 protocol (#47)
+ - release 1.8 protocol (#47), also used by 1.8.1 to 1.8.9
*/
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index 9bb0b7d08..5c5227b5f 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -285,7 +285,7 @@ void cProtocol_1_9_0::SendPaintingSpawn(const cPainting & a_Painting)
Pkt.WriteBEUInt64(0);
Pkt.WriteBEUInt64(a_Painting.GetUniqueID());
Pkt.WriteString(a_Painting.GetName());
- Pkt.WritePosition64(static_cast<Int32>(PosX), static_cast<Int32>(PosY), static_cast<Int32>(PosZ));
+ Pkt.WriteXYZPosition64(static_cast<Int32>(PosX), static_cast<Int32>(PosY), static_cast<Int32>(PosZ));
Pkt.WriteBEInt8(static_cast<Int8>(a_Painting.GetProtocolFacing()));
}
@@ -680,7 +680,7 @@ void cProtocol_1_9_0::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status);
int BlockX, BlockY, BlockZ;
- if (!a_ByteBuffer.ReadPosition64(BlockX, BlockY, BlockZ))
+ if (!a_ByteBuffer.ReadXYZPosition64(BlockX, BlockY, BlockZ))
{
return;
}
@@ -696,7 +696,7 @@ void cProtocol_1_9_0::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer)
void cProtocol_1_9_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
{
int BlockX, BlockY, BlockZ;
- if (!a_ByteBuffer.ReadPosition64(BlockX, BlockY, BlockZ))
+ if (!a_ByteBuffer.ReadXYZPosition64(BlockX, BlockY, BlockZ))
{
return;
}
@@ -873,7 +873,7 @@ void cProtocol_1_9_0::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer)
void cProtocol_1_9_0::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer)
{
int BlockX, BlockY, BlockZ;
- if (!a_ByteBuffer.ReadPosition64(BlockX, BlockY, BlockZ))
+ if (!a_ByteBuffer.ReadXYZPosition64(BlockX, BlockY, BlockZ))
{
return;
}
@@ -2171,7 +2171,7 @@ void cProtocol_1_9_1::SendLogin(const cPlayer & a_Player, const cWorld & a_World
// Send the spawn position:
{
cPacketizer Pkt(*this, pktSpawnPosition);
- Pkt.WritePosition64(FloorC(a_World.GetSpawnX()), FloorC(a_World.GetSpawnY()), FloorC(a_World.GetSpawnZ()));
+ Pkt.WriteXYZPosition64(FloorC(a_World.GetSpawnX()), FloorC(a_World.GetSpawnY()), FloorC(a_World.GetSpawnZ()));
}
// Send the server difficulty:
@@ -2218,7 +2218,7 @@ void cProtocol_1_9_4::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, c
// 1.9.4 removed the update sign packet and now uses Update Block Entity
cPacketizer Pkt(*this, pktUpdateBlockEntity);
- Pkt.WritePosition64(a_BlockX, a_BlockY, a_BlockZ);
+ Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
Pkt.WriteBEUInt8(9); // Action 9 - update sign
cFastNBTWriter Writer;