1
0
Fork 0

1.14 connection support

This commit is contained in:
Tiger Wang 2020-07-20 09:56:27 +01:00
parent 1673c84978
commit 99f8c44342
20 changed files with 609 additions and 71 deletions

View File

@ -472,7 +472,7 @@ bool cByteBuffer::ReadLEInt(int & a_Value)
bool cByteBuffer::ReadPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
bool cByteBuffer::ReadXYZPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
{
CHECK_THREAD
Int64 Value;
@ -488,7 +488,7 @@ bool cByteBuffer::ReadPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
// If the highest bit in the number's range is set, convert the number into negative:
a_BlockX = ((BlockXRaw & 0x02000000) == 0) ? static_cast<int>(BlockXRaw) : -(0x04000000 - static_cast<int>(BlockXRaw));
a_BlockY = ((BlockYRaw & 0x0800) == 0) ? static_cast<int>(BlockYRaw) : -(0x0800 - static_cast<int>(BlockYRaw));
a_BlockY = ((BlockYRaw & 0x0800) == 0) ? static_cast<int>(BlockYRaw) : -(0x01000 - static_cast<int>(BlockYRaw));
a_BlockZ = ((BlockZRaw & 0x02000000) == 0) ? static_cast<int>(BlockZRaw) : -(0x04000000 - static_cast<int>(BlockZRaw));
return true;
}
@ -497,6 +497,31 @@ bool cByteBuffer::ReadPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
bool cByteBuffer::ReadXZYPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
{
CHECK_THREAD
Int64 Value;
if (!ReadBEInt64(Value))
{
return false;
}
// Convert the 64 received bits into 3 coords:
UInt32 BlockXRaw = (Value >> 38) & 0x03ffffff; // Top 26 bits
UInt32 BlockZRaw = (Value >> 12) & 0x03ffffff; // Middle 26 bits
UInt32 BlockYRaw = (Value & 0x0fff); // Bottom 12 bits
// If the highest bit in the number's range is set, convert the number into negative:
a_BlockX = ((BlockXRaw & 0x02000000) == 0) ? static_cast<int>(BlockXRaw) : (static_cast<int>(BlockXRaw) - 0x04000000);
a_BlockY = ((BlockYRaw & 0x0800) == 0) ? static_cast<int>(BlockYRaw) : (static_cast<int>(BlockYRaw) - 0x01000);
a_BlockZ = ((BlockZRaw & 0x02000000) == 0) ? static_cast<int>(BlockZRaw) : (static_cast<int>(BlockZRaw) - 0x04000000);
return true;
}
bool cByteBuffer::ReadUUID(cUUID & a_Value)
{
CHECK_THREAD
@ -718,7 +743,7 @@ bool cByteBuffer::WriteVarUTF8String(const AString & a_Value)
bool cByteBuffer::WritePosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
bool cByteBuffer::WriteXYZPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
{
CHECK_THREAD
CheckValid();
@ -733,6 +758,21 @@ bool cByteBuffer::WritePosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ
bool cByteBuffer::WriteXZYPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
{
CHECK_THREAD
CheckValid();
return WriteBEInt64(
(static_cast<Int64>(a_BlockX & 0x3FFFFFF) << 38) |
(static_cast<Int64>(a_BlockZ & 0x3FFFFFF) << 26) |
(static_cast<Int64>(a_BlockY & 0xFFF))
);
}
bool cByteBuffer::ReadBuf(void * a_Buffer, size_t a_Count)
{
CHECK_THREAD

View File

@ -69,7 +69,8 @@ public:
bool ReadVarInt64 (UInt64 & a_Value);
bool ReadVarUTF8String (AString & a_Value); // string length as VarInt, then string as UTF-8
bool ReadLEInt (int & a_Value);
bool ReadPosition64 (int & a_BlockX, int & a_BlockY, int & a_BlockZ);
bool ReadXYZPosition64 (int & a_BlockX, int & a_BlockY, int & a_BlockZ);
bool ReadXZYPosition64 (int & a_BlockX, int & a_BlockY, int & a_BlockZ);
bool ReadUUID (cUUID & a_Value);
/** Reads VarInt, assigns it to anything that can be assigned from an UInt64 (unsigned short, char, Byte, double, ...) */
@ -100,7 +101,8 @@ public:
bool WriteVarInt64 (UInt64 a_Value);
bool WriteVarUTF8String (const AString & a_Value); // string length as VarInt, then string as UTF-8
bool WriteLEInt32 (Int32 a_Value);
bool WritePosition64 (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ);
bool WriteXYZPosition64 (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ);
bool WriteXZYPosition64 (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ);
/** Reads a_Count bytes into a_Buffer; returns true if successful */
bool ReadBuf(void * a_Buffer, size_t a_Count);

View File

@ -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
)

View File

@ -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;

View File

@ -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);

View File

@ -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. */

View File

@ -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 */

View File

@ -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))",

View File

@ -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;
}

View File

@ -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"

View File

@ -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)
*/

View File

@ -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

View File

@ -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;

View File

@ -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));
}

View File

@ -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 {}
};

View File

@ -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;
}

View File

@ -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
*/

View File

@ -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;

View File

@ -638,7 +638,7 @@ void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value,
void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, size_t a_NumElements)
void cFastNBTWriter::AddIntArray(const AString & a_Name, const Int32 * a_Value, size_t a_NumElements)
{
TagCommon(a_Name, TAG_IntArray);
UInt32 len = htonl(static_cast<UInt32>(a_NumElements));

View File

@ -336,7 +336,7 @@ public:
void AddDouble (const AString & a_Name, double a_Value);
void AddString (const AString & a_Name, const AString & a_Value);
void AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements);
void AddIntArray (const AString & a_Name, const int * a_Value, size_t a_NumElements);
void AddIntArray (const AString & a_Name, const Int32 * a_Value, size_t a_NumElements);
void AddByteArray(const AString & a_Name, const AString & a_Value)
{