Unified cPacketizer across all protocols.
This commit is contained in:
parent
8df9f1685a
commit
c626848393
|
@ -762,10 +762,10 @@ bool cByteBuffer::WriteLEInt32(Int32 a_Value)
|
||||||
CHECK_THREAD
|
CHECK_THREAD
|
||||||
CheckValid();
|
CheckValid();
|
||||||
#ifdef IS_LITTLE_ENDIAN
|
#ifdef IS_LITTLE_ENDIAN
|
||||||
return WriteBuf((const char *)&a_Value, 4);
|
return WriteBuf(reinterpret_cast<const char *>(&a_Value), 4);
|
||||||
#else
|
#else
|
||||||
int Value = ((a_Value >> 24) & 0xff) | ((a_Value >> 16) & 0xff00) | ((a_Value >> 8) & 0xff0000) | (a_Value & 0xff000000);
|
int Value = ((a_Value >> 24) & 0xff) | ((a_Value >> 16) & 0xff00) | ((a_Value >> 8) & 0xff0000) | (a_Value & 0xff000000);
|
||||||
return WriteBuf((const char *)&Value, 4);
|
return WriteBuf(reinterpret_cast<const char *>(&Value), 4);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,11 +773,15 @@ bool cByteBuffer::WriteLEInt32(Int32 a_Value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cByteBuffer::WritePosition(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
|
bool cByteBuffer::WritePosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
|
||||||
{
|
{
|
||||||
CHECK_THREAD
|
CHECK_THREAD
|
||||||
CheckValid();
|
CheckValid();
|
||||||
return WriteBEInt64(((Int64)a_BlockX & 0x3FFFFFF) << 38 | ((Int64)a_BlockY & 0xFFF) << 26 | ((Int64)a_BlockZ & 0x3FFFFFF));
|
return WriteBEInt64(
|
||||||
|
(static_cast<Int64>(a_BlockX & 0x3FFFFFF) << 38) |
|
||||||
|
(static_cast<Int64>(a_BlockY & 0xFFF) << 26) |
|
||||||
|
(static_cast<Int64>(a_BlockZ & 0x3FFFFFF))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ public:
|
||||||
bool WriteVarInt (UInt32 a_Value);
|
bool WriteVarInt (UInt32 a_Value);
|
||||||
bool WriteVarUTF8String (const AString & a_Value); // string length as VarInt, then string as UTF-8
|
bool WriteVarUTF8String (const AString & a_Value); // string length as VarInt, then string as UTF-8
|
||||||
bool WriteLEInt32 (Int32 a_Value);
|
bool WriteLEInt32 (Int32 a_Value);
|
||||||
bool WritePosition (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ);
|
bool WritePosition64 (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ);
|
||||||
|
|
||||||
/** Reads a_Count bytes into a_Buffer; returns true if successful */
|
/** Reads a_Count bytes into a_Buffer; returns true if successful */
|
||||||
bool ReadBuf(void * a_Buffer, size_t a_Count);
|
bool ReadBuf(void * a_Buffer, size_t a_Count);
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
/** Returns the item in the frame */
|
/** Returns the item in the frame */
|
||||||
const cItem & GetItem(void) { return m_Item; }
|
const cItem & GetItem(void) const { return m_Item; }
|
||||||
|
|
||||||
/** Set the item in the frame */
|
/** Set the item in the frame */
|
||||||
void SetItem(cItem & a_Item) { m_Item = a_Item; }
|
void SetItem(cItem & a_Item) { m_Item = a_Item; }
|
||||||
|
|
|
@ -10,22 +10,22 @@
|
||||||
class cCriticalSection
|
class cCriticalSection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void Lock(void);
|
void Lock(void);
|
||||||
void Unlock(void);
|
void Unlock(void);
|
||||||
|
|
||||||
// IsLocked/IsLockedByCurrentThread are only used in ASSERT statements, but because of the changes with ASSERT they must always be defined
|
// IsLocked/IsLockedByCurrentThread are only used in ASSERT statements, but because of the changes with ASSERT they must always be defined
|
||||||
// The fake versions (in Release) will not effect the program in any way
|
// The fake versions (in Release) will not effect the program in any way
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
cCriticalSection(void);
|
cCriticalSection(void);
|
||||||
bool IsLocked(void);
|
bool IsLocked(void);
|
||||||
bool IsLockedByCurrentThread(void);
|
bool IsLockedByCurrentThread(void);
|
||||||
#else
|
#else
|
||||||
bool IsLocked(void) { return false; }
|
bool IsLocked(void) { return false; }
|
||||||
bool IsLockedByCurrentThread(void) { return false; }
|
bool IsLockedByCurrentThread(void) { return false; }
|
||||||
#endif // _DEBUG
|
#endif // _DEBUG
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
int m_IsLocked; // Number of times this CS is locked
|
int m_IsLocked; // Number of times this CS is locked
|
||||||
std::thread::id m_OwningThreadID;
|
std::thread::id m_OwningThreadID;
|
||||||
|
|
|
@ -8,19 +8,23 @@ SET (SRCS
|
||||||
Authenticator.cpp
|
Authenticator.cpp
|
||||||
ChunkDataSerializer.cpp
|
ChunkDataSerializer.cpp
|
||||||
MojangAPI.cpp
|
MojangAPI.cpp
|
||||||
|
Packetizer.cpp
|
||||||
Protocol17x.cpp
|
Protocol17x.cpp
|
||||||
Protocol18x.cpp
|
Protocol18x.cpp
|
||||||
ProtocolRecognizer.cpp)
|
ProtocolRecognizer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
SET (HDRS
|
SET (HDRS
|
||||||
Authenticator.h
|
Authenticator.h
|
||||||
ChunkDataSerializer.h
|
ChunkDataSerializer.h
|
||||||
MojangAPI.h
|
MojangAPI.h
|
||||||
|
Packetizer.h
|
||||||
Protocol.h
|
Protocol.h
|
||||||
Protocol17x.h
|
Protocol17x.h
|
||||||
Protocol18x.h
|
Protocol18x.h
|
||||||
ProtocolRecognizer.h)
|
ProtocolRecognizer.h
|
||||||
|
)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if (NOT MSVC)
|
||||||
add_library(Protocol ${SRCS} ${HDRS})
|
add_library(Protocol ${SRCS} ${HDRS})
|
||||||
endif()
|
endif()
|
||||||
|
|
102
src/Protocol/Packetizer.cpp
Normal file
102
src/Protocol/Packetizer.cpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
|
||||||
|
// Packetizer.cpp
|
||||||
|
|
||||||
|
// Implements the cPacketizer class representing a wrapper for sending a single packet over a protocol.
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Packetizer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Converts the hex digit character to its value. */
|
||||||
|
static UInt8 HexDigitValue(char a_Character)
|
||||||
|
{
|
||||||
|
switch (a_Character)
|
||||||
|
{
|
||||||
|
case '0': return 0;
|
||||||
|
case '1': return 1;
|
||||||
|
case '2': return 2;
|
||||||
|
case '3': return 3;
|
||||||
|
case '4': return 4;
|
||||||
|
case '5': return 5;
|
||||||
|
case '6': return 6;
|
||||||
|
case '7': return 7;
|
||||||
|
case '8': return 8;
|
||||||
|
case '9': return 9;
|
||||||
|
case 'a': return 10;
|
||||||
|
case 'b': return 11;
|
||||||
|
case 'c': return 12;
|
||||||
|
case 'd': return 13;
|
||||||
|
case 'e': return 14;
|
||||||
|
case 'f': return 15;
|
||||||
|
case 'A': return 10;
|
||||||
|
case 'B': return 11;
|
||||||
|
case 'C': return 12;
|
||||||
|
case 'D': return 13;
|
||||||
|
case 'E': return 14;
|
||||||
|
case 'F': return 15;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
LOGWARNING("Bad hex digit: %c", a_Character);
|
||||||
|
ASSERT(!"Bad hex digit");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cPacketizer:
|
||||||
|
|
||||||
|
cPacketizer::~cPacketizer()
|
||||||
|
{
|
||||||
|
m_Protocol.SendPacket(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPacketizer::WriteByteAngle(double a_Angle)
|
||||||
|
{
|
||||||
|
WriteChar(static_cast<char>(255 * a_Angle / 360));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPacketizer::WriteFPInt(double a_Value)
|
||||||
|
{
|
||||||
|
Int32 Value = static_cast<Int32>(a_Value * 32);
|
||||||
|
WriteInt(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPacketizer::WriteUUID(const AString & a_UUID)
|
||||||
|
{
|
||||||
|
if (a_UUID.length() != 32)
|
||||||
|
{
|
||||||
|
LOGWARNING("%s: Attempt to send a bad uuid (length isn't 32): %s", __FUNCTION__, a_UUID.c_str());
|
||||||
|
ASSERT(!"Wrong uuid length!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 32; i += 2)
|
||||||
|
{
|
||||||
|
auto val = static_cast<UInt8>(HexDigitValue(a_UUID[i]) << 4 | HexDigitValue(a_UUID[i + 1]));
|
||||||
|
VERIFY(m_Out.WriteBEUInt8(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
149
src/Protocol/Packetizer.h
Normal file
149
src/Protocol/Packetizer.h
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
|
||||||
|
// Packetizer.h
|
||||||
|
|
||||||
|
// Declares the cPacketizer class representing a wrapper for sending a single packet over a protocol.
|
||||||
|
// The class provides auto-locking, serialization and send-on-instance-destroy semantics
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Protocol.h"
|
||||||
|
#include "../ByteBuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Composes an individual packet in the protocol's m_OutPacketBuffer; sends it just before being destructed. */
|
||||||
|
class cPacketizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Starts serializing a new packet into the protocol's m_OutPacketBuffer.
|
||||||
|
Locks the protocol's m_CSPacket to avoid multithreading issues. */
|
||||||
|
cPacketizer(cProtocol & a_Protocol, UInt32 a_PacketType) :
|
||||||
|
m_Protocol(a_Protocol),
|
||||||
|
m_Out(a_Protocol.m_OutPacketBuffer),
|
||||||
|
m_Lock(a_Protocol.m_CSPacket),
|
||||||
|
m_PacketType(a_PacketType) // Used for logging purposes
|
||||||
|
{
|
||||||
|
m_Out.WriteVarInt(a_PacketType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sends the packet via the contained protocol's SendPacket() function. */
|
||||||
|
~cPacketizer();
|
||||||
|
|
||||||
|
inline void WriteBool(bool a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBool(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void WriteByte(Byte a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEUInt8(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteChar(char a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEInt8(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteShort(short a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEInt16(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteBEUInt16(short a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEUInt16(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteInt(Int32 a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEInt32(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteUInt32(UInt32 a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEUInt32(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteInt64(Int64 a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEInt64(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteFloat(float a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEFloat(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteDouble(double a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteBEDouble(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteVarInt(UInt32 a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteVarInt(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteString(const AString & a_Value)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WriteVarUTF8String(a_Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void WriteBuf(const char * a_Data, size_t a_Size)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.Write(a_Data, a_Size));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Writes the specified block position as a single encoded 64-bit BigEndian integer. */
|
||||||
|
inline void WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
|
{
|
||||||
|
VERIFY(m_Out.WritePosition64(a_BlockX, a_BlockY, a_BlockZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Writes the specified angle using a single byte. */
|
||||||
|
void WriteByteAngle(double a_Angle);
|
||||||
|
|
||||||
|
/** Writes the double value as a 27:5 fixed-point integer. */
|
||||||
|
void WriteFPInt(double a_Value);
|
||||||
|
|
||||||
|
/** Writes the specified UUID as a 128-bit BigEndian integer. */
|
||||||
|
void WriteUUID(const AString & a_UUID);
|
||||||
|
|
||||||
|
UInt32 GetPacketType(void) const { return m_PacketType; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** The protocol instance in which the packet is being constructed. */
|
||||||
|
cProtocol & m_Protocol;
|
||||||
|
|
||||||
|
/** The protocol's buffer for the constructed packet data. */
|
||||||
|
cByteBuffer & m_Out;
|
||||||
|
|
||||||
|
/** The RAII lock preventing multithreaded access to the protocol buffer while constructing the packet. */
|
||||||
|
cCSLock m_Lock;
|
||||||
|
|
||||||
|
/** Type of the contained packet.
|
||||||
|
Used for logging purposes, the packet type is encoded into m_Out immediately in constructor. */
|
||||||
|
UInt32 m_PacketType;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../Endianness.h"
|
#include "../Endianness.h"
|
||||||
#include "../Scoreboard.h"
|
#include "../Scoreboard.h"
|
||||||
#include "../Map.h"
|
#include "../Map.h"
|
||||||
|
#include "../ByteBuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ class cChunkDataSerializer;
|
||||||
class cFallingBlock;
|
class cFallingBlock;
|
||||||
class cCompositeChat;
|
class cCompositeChat;
|
||||||
class cStatManager;
|
class cStatManager;
|
||||||
|
class cPacketizer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +49,9 @@ class cProtocol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cProtocol(cClientHandle * a_Client) :
|
cProtocol(cClientHandle * a_Client) :
|
||||||
m_Client(a_Client)
|
m_Client(a_Client),
|
||||||
|
m_OutPacketBuffer(64 KiB),
|
||||||
|
m_OutPacketLenBuffer(20) // 20 bytes is more than enough for one VarInt
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,11 +140,27 @@ public:
|
||||||
virtual AString GetAuthServerID(void) = 0;
|
virtual AString GetAuthServerID(void) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
cClientHandle * m_Client;
|
friend class cPacketizer;
|
||||||
cCriticalSection m_CSPacket; // Each SendXYZ() function must acquire this CS in order to send the whole packet at once
|
|
||||||
|
|
||||||
/// A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it
|
cClientHandle * m_Client;
|
||||||
|
|
||||||
|
/** Provides synchronization for sending the entire packet at once.
|
||||||
|
Each SendXYZ() function must acquire this CS in order to send the whole packet at once.
|
||||||
|
Automated via cPacketizer class. */
|
||||||
|
cCriticalSection m_CSPacket;
|
||||||
|
|
||||||
|
/** Buffer for composing the outgoing packets, through cPacketizer */
|
||||||
|
cByteBuffer m_OutPacketBuffer;
|
||||||
|
|
||||||
|
/** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */
|
||||||
|
cByteBuffer m_OutPacketLenBuffer;
|
||||||
|
|
||||||
|
/** A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it. */
|
||||||
virtual void SendData(const char * a_Data, size_t a_Size) = 0;
|
virtual void SendData(const char * a_Data, size_t a_Size) = 0;
|
||||||
|
|
||||||
|
/** Sends a single packet contained within the cPacketizer class.
|
||||||
|
The cPacketizer's destructor calls this to send the contained packet; protocol may transform the data (compression in 1.8 etc). */
|
||||||
|
virtual void SendPacket(cPacketizer & a_Packet) = 0;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ Implements the 1.7.x protocol classes:
|
||||||
#include "Protocol17x.h"
|
#include "Protocol17x.h"
|
||||||
#include "ChunkDataSerializer.h"
|
#include "ChunkDataSerializer.h"
|
||||||
#include "PolarSSL++/Sha1Checksum.h"
|
#include "PolarSSL++/Sha1Checksum.h"
|
||||||
|
#include "Packetizer.h"
|
||||||
|
|
||||||
#include "../ClientHandle.h"
|
#include "../ClientHandle.h"
|
||||||
#include "../Root.h"
|
#include "../Root.h"
|
||||||
|
@ -105,8 +106,6 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd
|
||||||
m_ServerPort(a_ServerPort),
|
m_ServerPort(a_ServerPort),
|
||||||
m_State(a_State),
|
m_State(a_State),
|
||||||
m_ReceivedData(32 KiB),
|
m_ReceivedData(32 KiB),
|
||||||
m_OutPacketBuffer(64 KiB),
|
|
||||||
m_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt
|
|
||||||
m_IsEncrypted(false),
|
m_IsEncrypted(false),
|
||||||
m_LastSentDimension(dimNotSet)
|
m_LastSentDimension(dimNotSet)
|
||||||
{
|
{
|
||||||
|
@ -381,7 +380,7 @@ void cProtocol172::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum
|
||||||
cPacketizer Pkt(*this, 0x04); // Entity Equipment packet
|
cPacketizer Pkt(*this, 0x04); // Entity Equipment packet
|
||||||
Pkt.WriteUInt32(a_Entity.GetUniqueID());
|
Pkt.WriteUInt32(a_Entity.GetUniqueID());
|
||||||
Pkt.WriteShort(a_SlotNum);
|
Pkt.WriteShort(a_SlotNum);
|
||||||
Pkt.WriteItem(a_Item);
|
WriteItem(Pkt, a_Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -421,7 +420,7 @@ void cProtocol172::SendEntityMetadata(const cEntity & a_Entity)
|
||||||
|
|
||||||
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
||||||
Pkt.WriteUInt32(a_Entity.GetUniqueID());
|
Pkt.WriteUInt32(a_Entity.GetUniqueID());
|
||||||
Pkt.WriteEntityMetadata(a_Entity);
|
WriteEntityMetadata(Pkt, a_Entity);
|
||||||
Pkt.WriteByte(0x7f); // The termination byte
|
Pkt.WriteByte(0x7f); // The termination byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +434,7 @@ void cProtocol172::SendEntityProperties(const cEntity & a_Entity)
|
||||||
|
|
||||||
cPacketizer Pkt(*this, 0x20); // Entity Properties packet
|
cPacketizer Pkt(*this, 0x20); // Entity Properties packet
|
||||||
Pkt.WriteUInt32(a_Entity.GetUniqueID());
|
Pkt.WriteUInt32(a_Entity.GetUniqueID());
|
||||||
Pkt.WriteEntityProperties(a_Entity);
|
WriteEntityProperties(Pkt, a_Entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -563,7 +562,7 @@ void cProtocol172::SendInventorySlot(char a_WindowID, short a_SlotNum, const cIt
|
||||||
cPacketizer Pkt(*this, 0x2f); // Set Slot packet
|
cPacketizer Pkt(*this, 0x2f); // Set Slot packet
|
||||||
Pkt.WriteChar(a_WindowID);
|
Pkt.WriteChar(a_WindowID);
|
||||||
Pkt.WriteShort(a_SlotNum);
|
Pkt.WriteShort(a_SlotNum);
|
||||||
Pkt.WriteItem(a_Item);
|
WriteItem(Pkt, a_Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -734,7 +733,7 @@ void cProtocol172::SendPickupSpawn(const cPickup & a_Pickup)
|
||||||
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
||||||
Pkt.WriteUInt32(a_Pickup.GetUniqueID());
|
Pkt.WriteUInt32(a_Pickup.GetUniqueID());
|
||||||
Pkt.WriteByte((0x05 << 5) | 10); // Slot type + index 10
|
Pkt.WriteByte((0x05 << 5) | 10); // Slot type + index 10
|
||||||
Pkt.WriteItem(a_Pickup.GetItem());
|
WriteItem(Pkt, a_Pickup.GetItem());
|
||||||
Pkt.WriteByte(0x7f); // End of metadata
|
Pkt.WriteByte(0x7f); // End of metadata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1157,7 +1156,7 @@ void cProtocol172::SendSpawnMob(const cMonster & a_Mob)
|
||||||
Pkt.WriteShort(static_cast<short>(a_Mob.GetSpeedX() * 400));
|
Pkt.WriteShort(static_cast<short>(a_Mob.GetSpeedX() * 400));
|
||||||
Pkt.WriteShort(static_cast<short>(a_Mob.GetSpeedY() * 400));
|
Pkt.WriteShort(static_cast<short>(a_Mob.GetSpeedY() * 400));
|
||||||
Pkt.WriteShort(static_cast<short>(a_Mob.GetSpeedZ() * 400));
|
Pkt.WriteShort(static_cast<short>(a_Mob.GetSpeedZ() * 400));
|
||||||
Pkt.WriteEntityMetadata(a_Mob);
|
WriteEntityMetadata(Pkt, a_Mob);
|
||||||
Pkt.WriteByte(0x7f); // Metadata terminator
|
Pkt.WriteByte(0x7f); // Metadata terminator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1341,7 +1340,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
|
||||||
}
|
}
|
||||||
Pkt.WriteByte(Action);
|
Pkt.WriteByte(Action);
|
||||||
|
|
||||||
Pkt.WriteBlockEntity(a_BlockEntity);
|
WriteBlockEntity(Pkt, a_BlockEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1412,7 +1411,7 @@ void cProtocol172::SendWholeInventory(const cWindow & a_Window)
|
||||||
a_Window.GetSlots(*(m_Client->GetPlayer()), Slots);
|
a_Window.GetSlots(*(m_Client->GetPlayer()), Slots);
|
||||||
for (cItems::const_iterator itr = Slots.begin(), end = Slots.end(); itr != end; ++itr)
|
for (cItems::const_iterator itr = Slots.begin(), end = Slots.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
Pkt.WriteItem(*itr);
|
WriteItem(Pkt, *itr);
|
||||||
} // for itr - Slots[]
|
} // for itr - Slots[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2383,6 +2382,39 @@ void cProtocol172::SendData(const char * a_Data, size_t a_Size)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cProtocol172::SendPacket(cPacketizer & a_Packet)
|
||||||
|
{
|
||||||
|
AString DataToSend;
|
||||||
|
|
||||||
|
// Send the packet length
|
||||||
|
UInt32 PacketLen = static_cast<UInt32>(m_OutPacketBuffer.GetUsedSpace());
|
||||||
|
|
||||||
|
m_OutPacketLenBuffer.WriteVarInt(PacketLen);
|
||||||
|
m_OutPacketLenBuffer.ReadAll(DataToSend);
|
||||||
|
SendData(DataToSend.data(), DataToSend.size());
|
||||||
|
m_OutPacketLenBuffer.CommitRead();
|
||||||
|
|
||||||
|
// Send the packet data:
|
||||||
|
m_OutPacketBuffer.ReadAll(DataToSend);
|
||||||
|
SendData(DataToSend.data(), DataToSend.size());
|
||||||
|
m_OutPacketBuffer.CommitRead();
|
||||||
|
|
||||||
|
// Log the comm into logfile:
|
||||||
|
if (g_ShouldLogCommOut)
|
||||||
|
{
|
||||||
|
AString Hex;
|
||||||
|
ASSERT(DataToSend.size() > 0);
|
||||||
|
CreateHexDump(Hex, DataToSend.data(), DataToSend.size(), 16);
|
||||||
|
m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload (incl. type):\n%s\n",
|
||||||
|
a_Packet.GetPacketType(), a_Packet.GetPacketType(), PacketLen, PacketLen, m_State, Hex.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cProtocol172::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item)
|
bool cProtocol172::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item)
|
||||||
{
|
{
|
||||||
HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemType);
|
HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemType);
|
||||||
|
@ -2542,43 +2574,7 @@ eBlockFace cProtocol172::FaceIntToBlockFace(Int8 a_BlockFace)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
void cProtocol172::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
|
||||||
// cProtocol172::cPacketizer:
|
|
||||||
|
|
||||||
cProtocol172::cPacketizer::~cPacketizer()
|
|
||||||
{
|
|
||||||
AString DataToSend;
|
|
||||||
|
|
||||||
// Send the packet length
|
|
||||||
UInt32 PacketLen = static_cast<UInt32>(m_Out.GetUsedSpace());
|
|
||||||
|
|
||||||
m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen);
|
|
||||||
m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend);
|
|
||||||
m_Protocol.SendData(DataToSend.data(), DataToSend.size());
|
|
||||||
m_Protocol.m_OutPacketLenBuffer.CommitRead();
|
|
||||||
|
|
||||||
// Send the packet data:
|
|
||||||
m_Out.ReadAll(DataToSend);
|
|
||||||
m_Protocol.SendData(DataToSend.data(), DataToSend.size());
|
|
||||||
m_Out.CommitRead();
|
|
||||||
|
|
||||||
// Log the comm into logfile:
|
|
||||||
if (g_ShouldLogCommOut)
|
|
||||||
{
|
|
||||||
AString Hex;
|
|
||||||
ASSERT(DataToSend.size() > 0);
|
|
||||||
CreateHexDump(Hex, DataToSend.data() + 1, DataToSend.size() - 1, 16);
|
|
||||||
m_Protocol.m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload:\n%s\n",
|
|
||||||
DataToSend[0], DataToSend[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
|
||||||
{
|
{
|
||||||
short ItemType = a_Item.m_ItemType;
|
short ItemType = a_Item.m_ItemType;
|
||||||
ASSERT(ItemType >= -1); // Check validity of packets in debug runtime
|
ASSERT(ItemType >= -1); // Check validity of packets in debug runtime
|
||||||
|
@ -2590,17 +2586,17 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
||||||
|
|
||||||
if (a_Item.IsEmpty())
|
if (a_Item.IsEmpty())
|
||||||
{
|
{
|
||||||
WriteShort(-1);
|
a_Pkt.WriteShort(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteShort(ItemType);
|
a_Pkt.WriteShort(ItemType);
|
||||||
WriteChar (a_Item.m_ItemCount);
|
a_Pkt.WriteChar (a_Item.m_ItemCount);
|
||||||
WriteShort(a_Item.m_ItemDamage);
|
a_Pkt.WriteShort(a_Item.m_ItemDamage);
|
||||||
|
|
||||||
if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
|
if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
|
||||||
{
|
{
|
||||||
WriteShort(-1);
|
a_Pkt.WriteShort(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2649,15 +2645,15 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
||||||
|
|
||||||
AString Compressed;
|
AString Compressed;
|
||||||
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
||||||
WriteShort((short)Compressed.size());
|
a_Pkt.WriteBEUInt16(static_cast<UInt16>(Compressed.size()));
|
||||||
WriteBuf(Compressed.data(), Compressed.size());
|
a_Pkt.WriteBuf(Compressed.data(), Compressed.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEntity)
|
void cProtocol172::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity)
|
||||||
{
|
{
|
||||||
cFastNBTWriter Writer;
|
cFastNBTWriter Writer;
|
||||||
|
|
||||||
|
@ -2665,46 +2661,41 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
{
|
{
|
||||||
case E_BLOCK_BEACON:
|
case E_BLOCK_BEACON:
|
||||||
{
|
{
|
||||||
cBeaconEntity & BeaconEntity = (cBeaconEntity &)a_BlockEntity;
|
auto & BeaconEntity = reinterpret_cast<const cBeaconEntity &>(a_BlockEntity);
|
||||||
|
Writer.AddInt("x", BeaconEntity.GetPosX());
|
||||||
Writer.AddInt("x", BeaconEntity.GetPosX());
|
Writer.AddInt("y", BeaconEntity.GetPosY());
|
||||||
Writer.AddInt("y", BeaconEntity.GetPosY());
|
Writer.AddInt("z", BeaconEntity.GetPosZ());
|
||||||
Writer.AddInt("z", BeaconEntity.GetPosZ());
|
Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect());
|
||||||
Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect());
|
|
||||||
Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect());
|
Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect());
|
||||||
Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel());
|
Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel());
|
||||||
Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_COMMAND_BLOCK:
|
case E_BLOCK_COMMAND_BLOCK:
|
||||||
{
|
{
|
||||||
cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;
|
auto & CommandBlockEntity = reinterpret_cast<const cCommandBlockEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
|
Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
|
||||||
Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
|
Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
|
||||||
Writer.AddInt("x", CommandBlockEntity.GetPosX());
|
Writer.AddInt("x", CommandBlockEntity.GetPosX());
|
||||||
Writer.AddInt("y", CommandBlockEntity.GetPosY());
|
Writer.AddInt("y", CommandBlockEntity.GetPosY());
|
||||||
Writer.AddInt("z", CommandBlockEntity.GetPosZ());
|
Writer.AddInt("z", CommandBlockEntity.GetPosZ());
|
||||||
Writer.AddString("Command", CommandBlockEntity.GetCommand().c_str());
|
Writer.AddString("Command", CommandBlockEntity.GetCommand().c_str());
|
||||||
// You can set custom names for windows in Vanilla
|
// You can set custom names for windows in Vanilla
|
||||||
// For a command block, this would be the 'name' prepended to anything it outputs into global chat
|
// For a command block, this would be the 'name' prepended to anything it outputs into global chat
|
||||||
// MCS doesn't have this, so just leave it @ '@'. (geddit?)
|
// MCS doesn't have this, so just leave it at '@'.
|
||||||
Writer.AddString("CustomName", "@");
|
Writer.AddString("CustomName", "@");
|
||||||
Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
|
|
||||||
if (!CommandBlockEntity.GetLastOutput().empty())
|
if (!CommandBlockEntity.GetLastOutput().empty())
|
||||||
{
|
{
|
||||||
AString Output;
|
Writer.AddString("LastOutput", Printf("{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str()));
|
||||||
Printf(Output, "{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str());
|
|
||||||
|
|
||||||
Writer.AddString("LastOutput", Output.c_str());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_HEAD:
|
case E_BLOCK_HEAD:
|
||||||
{
|
{
|
||||||
cMobHeadEntity & MobHeadEntity = (cMobHeadEntity &)a_BlockEntity;
|
auto & MobHeadEntity = reinterpret_cast<const cMobHeadEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddInt("x", MobHeadEntity.GetPosX());
|
Writer.AddInt("x", MobHeadEntity.GetPosX());
|
||||||
Writer.AddInt("y", MobHeadEntity.GetPosY());
|
Writer.AddInt("y", MobHeadEntity.GetPosY());
|
||||||
Writer.AddInt("z", MobHeadEntity.GetPosZ());
|
Writer.AddInt("z", MobHeadEntity.GetPosZ());
|
||||||
|
@ -2714,10 +2705,10 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_FLOWER_POT:
|
case E_BLOCK_FLOWER_POT:
|
||||||
{
|
{
|
||||||
cFlowerPotEntity & FlowerPotEntity = (cFlowerPotEntity &)a_BlockEntity;
|
auto & FlowerPotEntity = reinterpret_cast<const cFlowerPotEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddInt("x", FlowerPotEntity.GetPosX());
|
Writer.AddInt("x", FlowerPotEntity.GetPosX());
|
||||||
Writer.AddInt("y", FlowerPotEntity.GetPosY());
|
Writer.AddInt("y", FlowerPotEntity.GetPosY());
|
||||||
Writer.AddInt("z", FlowerPotEntity.GetPosZ());
|
Writer.AddInt("z", FlowerPotEntity.GetPosZ());
|
||||||
|
@ -2726,10 +2717,10 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_MOB_SPAWNER:
|
case E_BLOCK_MOB_SPAWNER:
|
||||||
{
|
{
|
||||||
cMobSpawnerEntity & MobSpawnerEntity = (cMobSpawnerEntity &)a_BlockEntity;
|
auto & MobSpawnerEntity = reinterpret_cast<const cMobSpawnerEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddInt("x", MobSpawnerEntity.GetPosX());
|
Writer.AddInt("x", MobSpawnerEntity.GetPosX());
|
||||||
Writer.AddInt("y", MobSpawnerEntity.GetPosY());
|
Writer.AddInt("y", MobSpawnerEntity.GetPosY());
|
||||||
Writer.AddInt("z", MobSpawnerEntity.GetPosZ());
|
Writer.AddInt("z", MobSpawnerEntity.GetPosZ());
|
||||||
|
@ -2738,41 +2729,26 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
Writer.AddString("id", "MobSpawner");
|
Writer.AddString("id", "MobSpawner");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Writer.Finish();
|
Writer.Finish();
|
||||||
|
|
||||||
AString Compressed;
|
AString Compressed;
|
||||||
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
||||||
WriteShort((short)Compressed.size());
|
a_Pkt.WriteBEUInt16(static_cast<UInt16>(Compressed.size()));
|
||||||
WriteBuf(Compressed.data(), Compressed.size());
|
a_Pkt.WriteBuf(Compressed.data(), Compressed.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::cPacketizer::WriteByteAngle(double a_Angle)
|
void cProtocol172::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity)
|
||||||
{
|
|
||||||
WriteChar(static_cast<char>(255 * a_Angle / 360));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::cPacketizer::WriteFPInt(double a_Value)
|
|
||||||
{
|
|
||||||
int Value = (int)(a_Value * 32);
|
|
||||||
WriteInt(Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
|
||||||
{
|
{
|
||||||
// Common metadata:
|
// Common metadata:
|
||||||
Byte Flags = 0;
|
Byte Flags = 0;
|
||||||
|
@ -2796,21 +2772,21 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
||||||
{
|
{
|
||||||
Flags |= 0x20;
|
Flags |= 0x20;
|
||||||
}
|
}
|
||||||
WriteByte(0); // Byte(0) + index 0
|
a_Pkt.WriteByte(0); // Byte(0) + index 0
|
||||||
WriteByte(Flags);
|
a_Pkt.WriteByte(Flags);
|
||||||
|
|
||||||
switch (a_Entity.GetEntityType())
|
switch (a_Entity.GetEntityType())
|
||||||
{
|
{
|
||||||
case cEntity::etPlayer: break; // TODO?
|
case cEntity::etPlayer: break; // TODO?
|
||||||
case cEntity::etPickup:
|
case cEntity::etPickup:
|
||||||
{
|
{
|
||||||
WriteByte((5 << 5) | 10); // Slot(5) + index 10
|
a_Pkt.WriteByte((5 << 5) | 10); // Slot(5) + index 10
|
||||||
WriteItem(((const cPickup &)a_Entity).GetItem());
|
WriteItem(a_Pkt, reinterpret_cast<const cPickup &>(a_Entity).GetItem());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case cEntity::etMinecart:
|
case cEntity::etMinecart:
|
||||||
{
|
{
|
||||||
WriteByte(0x51);
|
a_Pkt.WriteByte(0x51);
|
||||||
|
|
||||||
// The following expression makes Minecarts shake more with less health or higher damage taken
|
// The following expression makes Minecarts shake more with less health or higher damage taken
|
||||||
// It gets half the maximum health, and takes it away from the current health minus the half health:
|
// It gets half the maximum health, and takes it away from the current health minus the half health:
|
||||||
|
@ -2819,221 +2795,128 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
||||||
Health: 3 | 3 - (3 - 3) = 3
|
Health: 3 | 3 - (3 - 3) = 3
|
||||||
Health: 1 | 3 - (1 - 3) = 5
|
Health: 1 | 3 - (1 - 3) = 5
|
||||||
*/
|
*/
|
||||||
WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4);
|
auto & Minecart = reinterpret_cast<const cMinecart &>(a_Entity);
|
||||||
WriteByte(0x52);
|
a_Pkt.WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * Minecart.LastDamage()) * 4);
|
||||||
WriteInt(1); // Shaking direction, doesn't seem to affect anything
|
a_Pkt.WriteByte(0x52);
|
||||||
WriteByte(0x73);
|
a_Pkt.WriteInt(1); // Shaking direction, doesn't seem to affect anything
|
||||||
WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
|
a_Pkt.WriteByte(0x73);
|
||||||
|
a_Pkt.WriteFloat(static_cast<float>(Minecart.LastDamage() + 10)); // Damage taken / shake effect multiplyer
|
||||||
|
|
||||||
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpNone)
|
if (Minecart.GetPayload() == cMinecart::mpNone)
|
||||||
{
|
{
|
||||||
cRideableMinecart & RideableMinecart = ((cRideableMinecart &)a_Entity);
|
auto & RideableMinecart = reinterpret_cast<const cRideableMinecart &>(Minecart);
|
||||||
const cItem & MinecartContent = RideableMinecart.GetContent();
|
const cItem & MinecartContent = RideableMinecart.GetContent();
|
||||||
if (!MinecartContent.IsEmpty())
|
if (!MinecartContent.IsEmpty())
|
||||||
{
|
{
|
||||||
WriteByte(0x54);
|
a_Pkt.WriteByte(0x54);
|
||||||
int Content = MinecartContent.m_ItemType;
|
int Content = MinecartContent.m_ItemType;
|
||||||
Content |= MinecartContent.m_ItemDamage << 8;
|
Content |= MinecartContent.m_ItemDamage << 8;
|
||||||
WriteInt(Content);
|
a_Pkt.WriteInt(Content);
|
||||||
WriteByte(0x55);
|
a_Pkt.WriteByte(0x55);
|
||||||
WriteInt(RideableMinecart.GetBlockHeight());
|
a_Pkt.WriteInt(RideableMinecart.GetBlockHeight());
|
||||||
WriteByte(0x56);
|
a_Pkt.WriteByte(0x56);
|
||||||
WriteByte(1);
|
a_Pkt.WriteByte(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace)
|
else if (Minecart.GetPayload() == cMinecart::mpFurnace)
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0);
|
a_Pkt.WriteByte(reinterpret_cast<const cMinecartWithFurnace &>(Minecart).IsFueled() ? 1 : 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
} // case etMinecart
|
||||||
|
|
||||||
case cEntity::etProjectile:
|
case cEntity::etProjectile:
|
||||||
{
|
{
|
||||||
cProjectileEntity & Projectile = (cProjectileEntity &)a_Entity;
|
auto & Projectile = reinterpret_cast<const cProjectileEntity &>(a_Entity);
|
||||||
switch (Projectile.GetProjectileKind())
|
switch (Projectile.GetProjectileKind())
|
||||||
{
|
{
|
||||||
case cProjectileEntity::pkArrow:
|
case cProjectileEntity::pkArrow:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0);
|
a_Pkt.WriteByte(reinterpret_cast<const cArrowEntity &>(a_Entity).IsCritical() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case cProjectileEntity::pkFirework:
|
case cProjectileEntity::pkFirework:
|
||||||
{
|
{
|
||||||
WriteByte(0xA8);
|
a_Pkt.WriteByte(0xa8);
|
||||||
WriteItem(((const cFireworkEntity &)a_Entity).GetItem());
|
WriteItem(a_Pkt, reinterpret_cast<const cFireworkEntity &>(a_Entity).GetItem());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
} // case etProjectile
|
||||||
|
|
||||||
case cEntity::etMonster:
|
case cEntity::etMonster:
|
||||||
{
|
{
|
||||||
WriteMobMetadata((const cMonster &)a_Entity);
|
WriteMobMetadata(a_Pkt, reinterpret_cast<const cMonster &>(a_Entity));
|
||||||
break;
|
break;
|
||||||
}
|
} // case etMonster
|
||||||
|
|
||||||
case cEntity::etItemFrame:
|
case cEntity::etItemFrame:
|
||||||
{
|
{
|
||||||
cItemFrame & Frame = (cItemFrame &)a_Entity;
|
auto & Frame = reinterpret_cast<const cItemFrame &>(a_Entity);
|
||||||
WriteByte(0xA2);
|
a_Pkt.WriteByte(0xa2);
|
||||||
WriteItem(Frame.GetItem());
|
WriteItem(a_Pkt, Frame.GetItem());
|
||||||
WriteByte(0x3);
|
a_Pkt.WriteByte(0x03);
|
||||||
WriteByte(Frame.GetItemRotation() / 2);
|
a_Pkt.WriteByte(Frame.GetItemRotation() / 2);
|
||||||
|
break;
|
||||||
|
} // case etItemFrame
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
} // switch (EntityType)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
void cProtocol172::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob)
|
||||||
{
|
{
|
||||||
switch (a_Mob.GetMobType())
|
switch (a_Mob.GetMobType())
|
||||||
{
|
{
|
||||||
case mtCreeper:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : 0);
|
|
||||||
WriteByte(0x11);
|
|
||||||
WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtBat:
|
case mtBat:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0);
|
a_Pkt.WriteByte(reinterpret_cast<const cBat &>(a_Mob).IsHanging() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtBat
|
||||||
|
|
||||||
case mtPig:
|
case mtCreeper:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0);
|
a_Pkt.WriteByte(reinterpret_cast<const cCreeper &>(a_Mob).IsBlowing() ? 1 : 0);
|
||||||
|
a_Pkt.WriteByte(0x11);
|
||||||
|
a_Pkt.WriteByte(reinterpret_cast<const cCreeper &>(a_Mob).IsCharged() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtCreeper
|
||||||
|
|
||||||
case mtVillager:
|
|
||||||
{
|
|
||||||
WriteByte(0x50);
|
|
||||||
WriteInt(((const cVillager &)a_Mob).GetVilType());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtZombie:
|
|
||||||
{
|
|
||||||
WriteByte(0x0c);
|
|
||||||
WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0);
|
|
||||||
WriteByte(0x0d);
|
|
||||||
WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0);
|
|
||||||
WriteByte(0x0e);
|
|
||||||
WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtGhast:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(((const cGhast &)a_Mob).IsCharging());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtWolf:
|
|
||||||
{
|
|
||||||
const cWolf & Wolf = (const cWolf &)a_Mob;
|
|
||||||
Byte WolfStatus = 0;
|
|
||||||
if (Wolf.IsSitting())
|
|
||||||
{
|
|
||||||
WolfStatus |= 0x1;
|
|
||||||
}
|
|
||||||
if (Wolf.IsAngry())
|
|
||||||
{
|
|
||||||
WolfStatus |= 0x2;
|
|
||||||
}
|
|
||||||
if (Wolf.IsTame())
|
|
||||||
{
|
|
||||||
WolfStatus |= 0x4;
|
|
||||||
}
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(WolfStatus);
|
|
||||||
|
|
||||||
WriteByte(0x72);
|
|
||||||
WriteFloat((float)(a_Mob.GetHealth()));
|
|
||||||
WriteByte(0x13);
|
|
||||||
WriteByte(Wolf.IsBegging() ? 1 : 0);
|
|
||||||
WriteByte(0x14);
|
|
||||||
WriteByte(static_cast<Byte>(Wolf.GetCollarColor()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtSheep:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
Byte SheepMetadata = static_cast<Byte>(((const cSheep &)a_Mob).GetFurColor() & 0x0f);
|
|
||||||
if (((const cSheep &)a_Mob).IsSheared())
|
|
||||||
{
|
|
||||||
SheepMetadata |= 0x10;
|
|
||||||
}
|
|
||||||
WriteByte(SheepMetadata);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtEnderman:
|
case mtEnderman:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
auto & Enderman = reinterpret_cast<const cEnderman &>(a_Mob);
|
||||||
WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock()));
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(0x11);
|
a_Pkt.WriteByte((Byte)(Enderman.GetCarriedBlock()));
|
||||||
WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta()));
|
a_Pkt.WriteByte(0x11);
|
||||||
WriteByte(0x12);
|
a_Pkt.WriteByte((Byte)(Enderman.GetCarriedMeta()));
|
||||||
WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0);
|
a_Pkt.WriteByte(0x12);
|
||||||
|
a_Pkt.WriteByte(Enderman.IsScreaming() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtEnderman
|
||||||
|
|
||||||
case mtSkeleton:
|
case mtGhast:
|
||||||
{
|
{
|
||||||
WriteByte(0x0d);
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0);
|
a_Pkt.WriteByte(reinterpret_cast<const cGhast &>(a_Mob).IsCharging());
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtGhast
|
||||||
|
|
||||||
case mtWitch:
|
|
||||||
{
|
|
||||||
WriteByte(0x15);
|
|
||||||
WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtWither:
|
|
||||||
{
|
|
||||||
WriteByte(0x54); // Int at index 20
|
|
||||||
WriteInt(static_cast<int>(((const cWither &)a_Mob).GetWitherInvulnerableTicks()));
|
|
||||||
WriteByte(0x66); // Float at index 6
|
|
||||||
WriteFloat((float)(a_Mob.GetHealth()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtSlime:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(static_cast<Byte>(((const cSlime &)a_Mob).GetSize()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtMagmaCube:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(static_cast<Byte>(((const cMagmaCube &)a_Mob).GetSize()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtHorse:
|
case mtHorse:
|
||||||
{
|
{
|
||||||
const cHorse & Horse = (const cHorse &)a_Mob;
|
auto & Horse = reinterpret_cast<const cHorse &>(a_Mob);
|
||||||
int Flags = 0;
|
int Flags = 0;
|
||||||
if (Horse.IsTame())
|
if (Horse.IsTame())
|
||||||
{
|
{
|
||||||
|
@ -3063,19 +2946,123 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
||||||
{
|
{
|
||||||
Flags |= 0x80;
|
Flags |= 0x80;
|
||||||
}
|
}
|
||||||
WriteByte(0x50); // Int at index 16
|
a_Pkt.WriteByte(0x50); // Int at index 16
|
||||||
WriteInt(Flags);
|
a_Pkt.WriteInt(Flags);
|
||||||
WriteByte(0x13); // Byte at index 19
|
a_Pkt.WriteByte(0x13); // Byte at index 19
|
||||||
WriteByte(static_cast<Byte>(Horse.GetHorseType()));
|
a_Pkt.WriteByte(static_cast<Byte>(Horse.GetHorseType()));
|
||||||
WriteByte(0x54); // Int at index 20
|
a_Pkt.WriteByte(0x54); // Int at index 20
|
||||||
int Appearance = 0;
|
int Appearance = 0;
|
||||||
Appearance = Horse.GetHorseColor();
|
Appearance = Horse.GetHorseColor();
|
||||||
Appearance |= Horse.GetHorseStyle() << 8;
|
Appearance |= Horse.GetHorseStyle() << 8;
|
||||||
WriteInt(Appearance);
|
a_Pkt.WriteInt(Appearance);
|
||||||
WriteByte(0x56); // Int at index 22
|
a_Pkt.WriteByte(0x56); // Int at index 22
|
||||||
WriteInt(Horse.GetHorseArmour());
|
a_Pkt.WriteInt(Horse.GetHorseArmour());
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtHorse
|
||||||
|
|
||||||
|
case mtMagmaCube:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(static_cast<Byte>(reinterpret_cast<const cMagmaCube &>(a_Mob).GetSize()));
|
||||||
|
break;
|
||||||
|
} // case mtMagmaCube
|
||||||
|
|
||||||
|
case mtPig:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(reinterpret_cast<const cPig &>(a_Mob).IsSaddled() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtPig
|
||||||
|
|
||||||
|
case mtSheep:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
auto & Sheep = reinterpret_cast<const cSheep &>(a_Mob);
|
||||||
|
Byte SheepMetadata = static_cast<Byte>(Sheep.GetFurColor() & 0x0f);
|
||||||
|
if (Sheep.IsSheared())
|
||||||
|
{
|
||||||
|
SheepMetadata |= 0x10;
|
||||||
|
}
|
||||||
|
a_Pkt.WriteByte(SheepMetadata);
|
||||||
|
break;
|
||||||
|
} // case mtSheep
|
||||||
|
|
||||||
|
case mtSkeleton:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x0d);
|
||||||
|
a_Pkt.WriteByte(reinterpret_cast<const cSkeleton &>(a_Mob).IsWither() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtSkeleton
|
||||||
|
|
||||||
|
case mtSlime:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(static_cast<Byte>(reinterpret_cast<const cSlime &>(a_Mob).GetSize()));
|
||||||
|
break;
|
||||||
|
} // case mtSlime
|
||||||
|
|
||||||
|
case mtVillager:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x50);
|
||||||
|
a_Pkt.WriteInt(reinterpret_cast<const cVillager &>(a_Mob).GetVilType());
|
||||||
|
break;
|
||||||
|
} // case mtVillager
|
||||||
|
|
||||||
|
case mtWitch:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x15);
|
||||||
|
a_Pkt.WriteByte(reinterpret_cast<const cWitch &>(a_Mob).IsAngry() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtWitch
|
||||||
|
|
||||||
|
case mtWither:
|
||||||
|
{
|
||||||
|
a_Pkt.WriteByte(0x54); // Int at index 20
|
||||||
|
a_Pkt.WriteInt(static_cast<int>(reinterpret_cast<const cWither &>(a_Mob).GetWitherInvulnerableTicks()));
|
||||||
|
a_Pkt.WriteByte(0x66); // Float at index 6
|
||||||
|
a_Pkt.WriteFloat(static_cast<float>(a_Mob.GetHealth()));
|
||||||
|
break;
|
||||||
|
} // case mtWither
|
||||||
|
|
||||||
|
case mtWolf:
|
||||||
|
{
|
||||||
|
auto & Wolf = reinterpret_cast<const cWolf &>(a_Mob);
|
||||||
|
Byte WolfStatus = 0;
|
||||||
|
if (Wolf.IsSitting())
|
||||||
|
{
|
||||||
|
WolfStatus |= 0x1;
|
||||||
|
}
|
||||||
|
if (Wolf.IsAngry())
|
||||||
|
{
|
||||||
|
WolfStatus |= 0x2;
|
||||||
|
}
|
||||||
|
if (Wolf.IsTame())
|
||||||
|
{
|
||||||
|
WolfStatus |= 0x4;
|
||||||
|
}
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(WolfStatus);
|
||||||
|
|
||||||
|
a_Pkt.WriteByte(0x72);
|
||||||
|
a_Pkt.WriteFloat(static_cast<float>(a_Mob.GetHealth()));
|
||||||
|
a_Pkt.WriteByte(0x13);
|
||||||
|
a_Pkt.WriteByte(Wolf.IsBegging() ? 1 : 0);
|
||||||
|
a_Pkt.WriteByte(0x14);
|
||||||
|
a_Pkt.WriteByte(static_cast<Byte>(Wolf.GetCollarColor()));
|
||||||
|
break;
|
||||||
|
} // case mtWolf
|
||||||
|
|
||||||
|
case mtZombie:
|
||||||
|
{
|
||||||
|
auto & Zombie = reinterpret_cast<const cZombie &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x0c);
|
||||||
|
a_Pkt.WriteByte(Zombie.IsBaby() ? 1 : 0);
|
||||||
|
a_Pkt.WriteByte(0x0d);
|
||||||
|
a_Pkt.WriteByte(Zombie.IsVillagerZombie() ? 1 : 0);
|
||||||
|
a_Pkt.WriteByte(0x0e);
|
||||||
|
a_Pkt.WriteByte(Zombie.IsConverting() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtZombie
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -3087,10 +3074,10 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
||||||
// Custom name:
|
// Custom name:
|
||||||
if (a_Mob.HasCustomName())
|
if (a_Mob.HasCustomName())
|
||||||
{
|
{
|
||||||
WriteByte(0x8a);
|
a_Pkt.WriteByte(0x8a);
|
||||||
WriteString(a_Mob.GetCustomName());
|
a_Pkt.WriteString(a_Mob.GetCustomName());
|
||||||
WriteByte(0x0b);
|
a_Pkt.WriteByte(0x0b);
|
||||||
WriteByte(a_Mob.IsCustomNameAlwaysVisible() ? 1 : 0);
|
a_Pkt.WriteByte(a_Mob.IsCustomNameAlwaysVisible() ? 1 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3098,20 +3085,20 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
|
void cProtocol172::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity)
|
||||||
{
|
{
|
||||||
if (!a_Entity.IsMob())
|
if (!a_Entity.IsMob())
|
||||||
{
|
{
|
||||||
// No properties for anything else than mobs
|
// No properties for anything else than mobs
|
||||||
WriteInt(0);
|
a_Pkt.WriteInt(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const cMonster & Mob = (const cMonster &)a_Entity;
|
// auto & Mob = reinterpret_cast<const cMonster &>(a_Entity);
|
||||||
|
|
||||||
// TODO: Send properties and modifiers based on the mob type
|
// TODO: Send properties and modifiers based on the mob type
|
||||||
|
|
||||||
WriteInt(0); // NumProperties
|
a_Pkt.WriteInt(0); // NumProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -140,94 +140,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */
|
|
||||||
class cPacketizer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cPacketizer(cProtocol172 & a_Protocol, UInt32 a_PacketType) :
|
|
||||||
m_Protocol(a_Protocol),
|
|
||||||
m_Out(a_Protocol.m_OutPacketBuffer),
|
|
||||||
m_Lock(a_Protocol.m_CSPacket)
|
|
||||||
{
|
|
||||||
m_Out.WriteVarInt(a_PacketType);
|
|
||||||
}
|
|
||||||
|
|
||||||
~cPacketizer();
|
|
||||||
|
|
||||||
void WriteBool(bool a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBool(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteByte(Byte a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEUInt8(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteChar(char a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt8(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteShort(short a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt16(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteInt(Int32 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt32(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteUInt32(UInt32 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEUInt32(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteInt64(Int64 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt64(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteFloat(float a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEFloat(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteDouble(double a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEDouble(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteVarInt(UInt32 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteVarInt(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteString(const AString & a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteVarUTF8String(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteBuf(const char * a_Data, size_t a_Size)
|
|
||||||
{
|
|
||||||
m_Out.Write(a_Data, a_Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteItem(const cItem & a_Item);
|
|
||||||
void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte
|
|
||||||
void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer
|
|
||||||
void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f
|
|
||||||
void WriteMobMetadata(const cMonster & a_Mob); // Writes the mob-specific metadata for the specified mob
|
|
||||||
void WriteEntityProperties(const cEntity & a_Entity); // Writes the entity properties for the specified entity, including the Count field
|
|
||||||
void WriteBlockEntity(const cBlockEntity & a_BlockEntity);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
cProtocol172 & m_Protocol;
|
|
||||||
cByteBuffer & m_Out;
|
|
||||||
cCSLock m_Lock;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
AString m_ServerAddress;
|
AString m_ServerAddress;
|
||||||
|
|
||||||
UInt16 m_ServerPort;
|
UInt16 m_ServerPort;
|
||||||
|
@ -240,12 +152,6 @@ protected:
|
||||||
/** Buffer for the received data */
|
/** Buffer for the received data */
|
||||||
cByteBuffer m_ReceivedData;
|
cByteBuffer m_ReceivedData;
|
||||||
|
|
||||||
/** Buffer for composing the outgoing packets, through cPacketizer */
|
|
||||||
cByteBuffer m_OutPacketBuffer;
|
|
||||||
|
|
||||||
/** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */
|
|
||||||
cByteBuffer m_OutPacketLenBuffer;
|
|
||||||
|
|
||||||
bool m_IsEncrypted;
|
bool m_IsEncrypted;
|
||||||
|
|
||||||
cAesCfb128Decryptor m_Decryptor;
|
cAesCfb128Decryptor m_Decryptor;
|
||||||
|
@ -307,6 +213,9 @@ protected:
|
||||||
/** Sends the data to the client, encrypting them if needed. */
|
/** Sends the data to the client, encrypting them if needed. */
|
||||||
virtual void SendData(const char * a_Data, size_t a_Size) override;
|
virtual void SendData(const char * a_Data, size_t a_Size) override;
|
||||||
|
|
||||||
|
/** Sends the packet to the client. Called by the cPacketizer's destructor. */
|
||||||
|
virtual void SendPacket(cPacketizer & a_Packet) override;
|
||||||
|
|
||||||
void SendCompass(const cWorld & a_World);
|
void SendCompass(const cWorld & a_World);
|
||||||
|
|
||||||
/** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */
|
/** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */
|
||||||
|
@ -320,6 +229,21 @@ protected:
|
||||||
/** Converts the BlockFace received by the protocol into eBlockFace constants.
|
/** Converts the BlockFace received by the protocol into eBlockFace constants.
|
||||||
If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */
|
If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */
|
||||||
eBlockFace FaceIntToBlockFace(Int8 a_FaceInt);
|
eBlockFace FaceIntToBlockFace(Int8 a_FaceInt);
|
||||||
|
|
||||||
|
/** Writes the item data into a packet. */
|
||||||
|
void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item);
|
||||||
|
|
||||||
|
/** Writes the metadata for the specified entity, not including the terminating 0x7f. */
|
||||||
|
void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity);
|
||||||
|
|
||||||
|
/** Writes the mob-specific metadata for the specified mob */
|
||||||
|
void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob);
|
||||||
|
|
||||||
|
/** Writes the entity properties for the specified entity, including the Count field. */
|
||||||
|
void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity);
|
||||||
|
|
||||||
|
/** Writes the block entity data for the specified block entity into the packet. */
|
||||||
|
void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity);
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ Implements the 1.8.x protocol classes:
|
||||||
#include "Protocol18x.h"
|
#include "Protocol18x.h"
|
||||||
#include "ChunkDataSerializer.h"
|
#include "ChunkDataSerializer.h"
|
||||||
#include "PolarSSL++/Sha1Checksum.h"
|
#include "PolarSSL++/Sha1Checksum.h"
|
||||||
|
#include "Packetizer.h"
|
||||||
|
|
||||||
#include "../ClientHandle.h"
|
#include "../ClientHandle.h"
|
||||||
#include "../Root.h"
|
#include "../Root.h"
|
||||||
|
@ -105,8 +106,6 @@ cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAdd
|
||||||
m_ServerPort(a_ServerPort),
|
m_ServerPort(a_ServerPort),
|
||||||
m_State(a_State),
|
m_State(a_State),
|
||||||
m_ReceivedData(32 KiB),
|
m_ReceivedData(32 KiB),
|
||||||
m_OutPacketBuffer(64 KiB),
|
|
||||||
m_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt
|
|
||||||
m_IsEncrypted(false),
|
m_IsEncrypted(false),
|
||||||
m_LastSentDimension(dimNotSet)
|
m_LastSentDimension(dimNotSet)
|
||||||
{
|
{
|
||||||
|
@ -365,7 +364,7 @@ void cProtocol180::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum
|
||||||
cPacketizer Pkt(*this, 0x04); // Entity Equipment packet
|
cPacketizer Pkt(*this, 0x04); // Entity Equipment packet
|
||||||
Pkt.WriteVarInt(a_Entity.GetUniqueID());
|
Pkt.WriteVarInt(a_Entity.GetUniqueID());
|
||||||
Pkt.WriteShort(a_SlotNum);
|
Pkt.WriteShort(a_SlotNum);
|
||||||
Pkt.WriteItem(a_Item);
|
WriteItem(Pkt, a_Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,7 +405,7 @@ void cProtocol180::SendEntityMetadata(const cEntity & a_Entity)
|
||||||
|
|
||||||
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
||||||
Pkt.WriteVarInt(a_Entity.GetUniqueID());
|
Pkt.WriteVarInt(a_Entity.GetUniqueID());
|
||||||
Pkt.WriteEntityMetadata(a_Entity);
|
WriteEntityMetadata(Pkt, a_Entity);
|
||||||
Pkt.WriteByte(0x7f); // The termination byte
|
Pkt.WriteByte(0x7f); // The termination byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +419,7 @@ void cProtocol180::SendEntityProperties(const cEntity & a_Entity)
|
||||||
|
|
||||||
cPacketizer Pkt(*this, 0x20); // Entity Properties packet
|
cPacketizer Pkt(*this, 0x20); // Entity Properties packet
|
||||||
Pkt.WriteVarInt(a_Entity.GetUniqueID());
|
Pkt.WriteVarInt(a_Entity.GetUniqueID());
|
||||||
Pkt.WriteEntityProperties(a_Entity);
|
WriteEntityProperties(Pkt, a_Entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -550,7 +549,7 @@ void cProtocol180::SendInventorySlot(char a_WindowID, short a_SlotNum, const cIt
|
||||||
cPacketizer Pkt(*this, 0x2f); // Set Slot packet
|
cPacketizer Pkt(*this, 0x2f); // Set Slot packet
|
||||||
Pkt.WriteChar(a_WindowID);
|
Pkt.WriteChar(a_WindowID);
|
||||||
Pkt.WriteShort(a_SlotNum);
|
Pkt.WriteShort(a_SlotNum);
|
||||||
Pkt.WriteItem(a_Item);
|
WriteItem(Pkt, a_Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -730,7 +729,7 @@ void cProtocol180::SendPickupSpawn(const cPickup & a_Pickup)
|
||||||
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
|
||||||
Pkt.WriteVarInt(a_Pickup.GetUniqueID());
|
Pkt.WriteVarInt(a_Pickup.GetUniqueID());
|
||||||
Pkt.WriteByte((0x05 << 5) | 10); // Slot type + index 10
|
Pkt.WriteByte((0x05 << 5) | 10); // Slot type + index 10
|
||||||
Pkt.WriteItem(a_Pickup.GetItem());
|
WriteItem(Pkt, a_Pickup.GetItem());
|
||||||
Pkt.WriteByte(0x7f); // End of metadata
|
Pkt.WriteByte(0x7f); // End of metadata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1194,7 +1193,7 @@ void cProtocol180::SendSpawnMob(const cMonster & a_Mob)
|
||||||
Pkt.WriteShort((short)(a_Mob.GetSpeedX() * 400));
|
Pkt.WriteShort((short)(a_Mob.GetSpeedX() * 400));
|
||||||
Pkt.WriteShort((short)(a_Mob.GetSpeedY() * 400));
|
Pkt.WriteShort((short)(a_Mob.GetSpeedY() * 400));
|
||||||
Pkt.WriteShort((short)(a_Mob.GetSpeedZ() * 400));
|
Pkt.WriteShort((short)(a_Mob.GetSpeedZ() * 400));
|
||||||
Pkt.WriteEntityMetadata(a_Mob);
|
WriteEntityMetadata(Pkt, a_Mob);
|
||||||
Pkt.WriteByte(0x7f); // Metadata terminator
|
Pkt.WriteByte(0x7f); // Metadata terminator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1383,7 +1382,7 @@ void cProtocol180::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
|
||||||
}
|
}
|
||||||
Pkt.WriteByte(Action);
|
Pkt.WriteByte(Action);
|
||||||
|
|
||||||
Pkt.WriteBlockEntity(a_BlockEntity);
|
WriteBlockEntity(Pkt, a_BlockEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1452,7 +1451,7 @@ void cProtocol180::SendWholeInventory(const cWindow & a_Window)
|
||||||
a_Window.GetSlots(*(m_Client->GetPlayer()), Slots);
|
a_Window.GetSlots(*(m_Client->GetPlayer()), Slots);
|
||||||
for (cItems::const_iterator itr = Slots.begin(), end = Slots.end(); itr != end; ++itr)
|
for (cItems::const_iterator itr = Slots.begin(), end = Slots.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
Pkt.WriteItem(*itr);
|
WriteItem(Pkt, *itr);
|
||||||
} // for itr - Slots[]
|
} // for itr - Slots[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2782,56 +2781,58 @@ eBlockFace cProtocol180::FaceIntToBlockFace(Int8 a_BlockFace)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// cProtocol180::cPacketizer:
|
// cProtocol180::cPacketizer:
|
||||||
|
|
||||||
cProtocol180::cPacketizer::~cPacketizer()
|
void cProtocol180::SendPacket(cPacketizer & a_Pkt)
|
||||||
{
|
{
|
||||||
UInt32 PacketLen = (UInt32)m_Out.GetUsedSpace();
|
UInt32 PacketLen = static_cast<UInt32>(m_OutPacketBuffer.GetUsedSpace());
|
||||||
AString PacketData, CompressedPacket;
|
AString PacketData, CompressedPacket;
|
||||||
m_Out.ReadAll(PacketData);
|
m_OutPacketBuffer.ReadAll(PacketData);
|
||||||
m_Out.CommitRead();
|
m_OutPacketBuffer.CommitRead();
|
||||||
|
|
||||||
if ((m_Protocol.m_State == 3) && (PacketLen >= 256))
|
if ((m_State == 3) && (PacketLen >= 256))
|
||||||
{
|
{
|
||||||
|
// Compress the packet payload:
|
||||||
if (!cProtocol180::CompressPacket(PacketData, CompressedPacket))
|
if (!cProtocol180::CompressPacket(PacketData, CompressedPacket))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_Protocol.m_State == 3)
|
else if (m_State == 3)
|
||||||
{
|
{
|
||||||
m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen + 1);
|
// The packet is not compressed, indicate this in the packet header:
|
||||||
m_Protocol.m_OutPacketLenBuffer.WriteVarInt(0);
|
m_OutPacketLenBuffer.WriteVarInt(PacketLen + 1);
|
||||||
|
m_OutPacketLenBuffer.WriteVarInt(0);
|
||||||
AString LengthData;
|
AString LengthData;
|
||||||
m_Protocol.m_OutPacketLenBuffer.ReadAll(LengthData);
|
m_OutPacketLenBuffer.ReadAll(LengthData);
|
||||||
m_Protocol.SendData(LengthData.data(), LengthData.size());
|
SendData(LengthData.data(), LengthData.size());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen);
|
// Compression doesn't apply to this state, send raw data:
|
||||||
|
m_OutPacketLenBuffer.WriteVarInt(PacketLen);
|
||||||
AString LengthData;
|
AString LengthData;
|
||||||
m_Protocol.m_OutPacketLenBuffer.ReadAll(LengthData);
|
m_OutPacketLenBuffer.ReadAll(LengthData);
|
||||||
m_Protocol.SendData(LengthData.data(), LengthData.size());
|
SendData(LengthData.data(), LengthData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send the packet's payload, either direct or compressed:
|
||||||
if (CompressedPacket.empty())
|
if (CompressedPacket.empty())
|
||||||
{
|
{
|
||||||
m_Protocol.m_OutPacketLenBuffer.CommitRead();
|
m_OutPacketLenBuffer.CommitRead();
|
||||||
m_Protocol.SendData(PacketData.data(), PacketData.size());
|
SendData(PacketData.data(), PacketData.size());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Protocol.SendData(CompressedPacket.data(), CompressedPacket.size());
|
SendData(CompressedPacket.data(), CompressedPacket.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the comm into logfile:
|
// Log the comm into logfile:
|
||||||
if (g_ShouldLogCommOut && m_Protocol.m_CommLogFile.IsOpen())
|
if (g_ShouldLogCommOut && m_CommLogFile.IsOpen())
|
||||||
{
|
{
|
||||||
AString Hex;
|
AString Hex;
|
||||||
ASSERT(PacketData.size() > 0);
|
ASSERT(PacketData.size() > 0);
|
||||||
CreateHexDump(Hex, PacketData.data() + 1, PacketData.size() - 1, 16);
|
CreateHexDump(Hex, PacketData.data(), PacketData.size(), 16);
|
||||||
m_Protocol.m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload:\n%s\n",
|
m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload (incl. type):\n%s\n",
|
||||||
PacketData[0], PacketData[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str()
|
a_Pkt.GetPacketType(), a_Pkt.GetPacketType(), PacketLen, PacketLen, m_State, Hex.c_str()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2840,30 +2841,7 @@ cProtocol180::cPacketizer::~cPacketizer()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteUUID(const AString & a_UUID)
|
void cProtocol180::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
|
||||||
{
|
|
||||||
if (a_UUID.length() != 32)
|
|
||||||
{
|
|
||||||
LOGWARNING("Attempt to send a bad uuid (length isn't 32): %s", a_UUID.c_str());
|
|
||||||
ASSERT(!"Wrong uuid length!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
AString UUID_1 = a_UUID.substr(0, 16);
|
|
||||||
AString UUID_2 = a_UUID.substr(16);
|
|
||||||
|
|
||||||
Int64 Value_1, Value_2;
|
|
||||||
sscanf(UUID_1.c_str(), "%llx", &Value_1);
|
|
||||||
sscanf(UUID_2.c_str(), "%llx", &Value_2);
|
|
||||||
|
|
||||||
WriteInt64(Value_1);
|
|
||||||
WriteInt64(Value_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteItem(const cItem & a_Item)
|
|
||||||
{
|
{
|
||||||
short ItemType = a_Item.m_ItemType;
|
short ItemType = a_Item.m_ItemType;
|
||||||
ASSERT(ItemType >= -1); // Check validity of packets in debug runtime
|
ASSERT(ItemType >= -1); // Check validity of packets in debug runtime
|
||||||
|
@ -2875,17 +2853,17 @@ void cProtocol180::cPacketizer::WriteItem(const cItem & a_Item)
|
||||||
|
|
||||||
if (a_Item.IsEmpty())
|
if (a_Item.IsEmpty())
|
||||||
{
|
{
|
||||||
WriteShort(-1);
|
a_Pkt.WriteShort(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteShort(ItemType);
|
a_Pkt.WriteShort(ItemType);
|
||||||
WriteByte (a_Item.m_ItemCount);
|
a_Pkt.WriteByte (a_Item.m_ItemCount);
|
||||||
WriteShort(a_Item.m_ItemDamage);
|
a_Pkt.WriteShort(a_Item.m_ItemDamage);
|
||||||
|
|
||||||
if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
|
if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
|
||||||
{
|
{
|
||||||
WriteChar(0);
|
a_Pkt.WriteChar(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2928,24 +2906,24 @@ void cProtocol180::cPacketizer::WriteItem(const cItem & a_Item)
|
||||||
}
|
}
|
||||||
if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR))
|
if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR))
|
||||||
{
|
{
|
||||||
cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, (ENUM_ITEM_ID)a_Item.m_ItemType);
|
cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast<ENUM_ITEM_ID>(a_Item.m_ItemType));
|
||||||
}
|
}
|
||||||
Writer.Finish();
|
Writer.Finish();
|
||||||
|
|
||||||
AString Result = Writer.GetResult();
|
AString Result = Writer.GetResult();
|
||||||
if (Result.size() == 0)
|
if (Result.size() == 0)
|
||||||
{
|
{
|
||||||
WriteChar(0);
|
a_Pkt.WriteChar(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WriteBuf(Result.data(), Result.size());
|
a_Pkt.WriteBuf(Result.data(), Result.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEntity)
|
void cProtocol180::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity)
|
||||||
{
|
{
|
||||||
cFastNBTWriter Writer;
|
cFastNBTWriter Writer;
|
||||||
|
|
||||||
|
@ -2953,21 +2931,20 @@ void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
{
|
{
|
||||||
case E_BLOCK_BEACON:
|
case E_BLOCK_BEACON:
|
||||||
{
|
{
|
||||||
cBeaconEntity & BeaconEntity = (cBeaconEntity &)a_BlockEntity;
|
auto & BeaconEntity = reinterpret_cast<const cBeaconEntity &>(a_BlockEntity);
|
||||||
|
Writer.AddInt("x", BeaconEntity.GetPosX());
|
||||||
Writer.AddInt("x", BeaconEntity.GetPosX());
|
Writer.AddInt("y", BeaconEntity.GetPosY());
|
||||||
Writer.AddInt("y", BeaconEntity.GetPosY());
|
Writer.AddInt("z", BeaconEntity.GetPosZ());
|
||||||
Writer.AddInt("z", BeaconEntity.GetPosZ());
|
Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect());
|
||||||
Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect());
|
|
||||||
Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect());
|
Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect());
|
||||||
Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel());
|
Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel());
|
||||||
Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_COMMAND_BLOCK:
|
case E_BLOCK_COMMAND_BLOCK:
|
||||||
{
|
{
|
||||||
cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;
|
auto & CommandBlockEntity = reinterpret_cast<const cCommandBlockEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
|
Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
|
||||||
Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
|
Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
|
||||||
Writer.AddInt("x", CommandBlockEntity.GetPosX());
|
Writer.AddInt("x", CommandBlockEntity.GetPosX());
|
||||||
|
@ -2979,20 +2956,16 @@ void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
// MCS doesn't have this, so just leave it @ '@'. (geddit?)
|
// MCS doesn't have this, so just leave it @ '@'. (geddit?)
|
||||||
Writer.AddString("CustomName", "@");
|
Writer.AddString("CustomName", "@");
|
||||||
Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
|
|
||||||
if (!CommandBlockEntity.GetLastOutput().empty())
|
if (!CommandBlockEntity.GetLastOutput().empty())
|
||||||
{
|
{
|
||||||
AString Output;
|
Writer.AddString("LastOutput", Printf("{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str()));
|
||||||
Printf(Output, "{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str());
|
|
||||||
|
|
||||||
Writer.AddString("LastOutput", Output.c_str());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_HEAD:
|
case E_BLOCK_HEAD:
|
||||||
{
|
{
|
||||||
cMobHeadEntity & MobHeadEntity = (cMobHeadEntity &)a_BlockEntity;
|
auto & MobHeadEntity = reinterpret_cast<const cMobHeadEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddInt("x", MobHeadEntity.GetPosX());
|
Writer.AddInt("x", MobHeadEntity.GetPosX());
|
||||||
Writer.AddInt("y", MobHeadEntity.GetPosY());
|
Writer.AddInt("y", MobHeadEntity.GetPosY());
|
||||||
Writer.AddInt("z", MobHeadEntity.GetPosZ());
|
Writer.AddInt("z", MobHeadEntity.GetPosZ());
|
||||||
|
@ -3002,10 +2975,10 @@ void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_FLOWER_POT:
|
case E_BLOCK_FLOWER_POT:
|
||||||
{
|
{
|
||||||
cFlowerPotEntity & FlowerPotEntity = (cFlowerPotEntity &)a_BlockEntity;
|
auto & FlowerPotEntity = reinterpret_cast<const cFlowerPotEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddInt("x", FlowerPotEntity.GetPosX());
|
Writer.AddInt("x", FlowerPotEntity.GetPosX());
|
||||||
Writer.AddInt("y", FlowerPotEntity.GetPosY());
|
Writer.AddInt("y", FlowerPotEntity.GetPosY());
|
||||||
Writer.AddInt("z", FlowerPotEntity.GetPosZ());
|
Writer.AddInt("z", FlowerPotEntity.GetPosZ());
|
||||||
|
@ -3014,10 +2987,10 @@ void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_MOB_SPAWNER:
|
case E_BLOCK_MOB_SPAWNER:
|
||||||
{
|
{
|
||||||
cMobSpawnerEntity & MobSpawnerEntity = (cMobSpawnerEntity &)a_BlockEntity;
|
auto & MobSpawnerEntity = reinterpret_cast<const cMobSpawnerEntity &>(a_BlockEntity);
|
||||||
|
|
||||||
Writer.AddInt("x", MobSpawnerEntity.GetPosX());
|
Writer.AddInt("x", MobSpawnerEntity.GetPosX());
|
||||||
Writer.AddInt("y", MobSpawnerEntity.GetPosY());
|
Writer.AddInt("y", MobSpawnerEntity.GetPosY());
|
||||||
Writer.AddInt("z", MobSpawnerEntity.GetPosZ());
|
Writer.AddInt("z", MobSpawnerEntity.GetPosZ());
|
||||||
|
@ -3026,37 +2999,22 @@ void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||||
Writer.AddString("id", "MobSpawner");
|
Writer.AddString("id", "MobSpawner");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Writer.Finish();
|
Writer.Finish();
|
||||||
WriteBuf(Writer.GetResult().data(), Writer.GetResult().size());
|
a_Pkt.WriteBuf(Writer.GetResult().data(), Writer.GetResult().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteByteAngle(double a_Angle)
|
void cProtocol180::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity)
|
||||||
{
|
|
||||||
WriteByte((char)(255 * a_Angle / 360));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteFPInt(double a_Value)
|
|
||||||
{
|
|
||||||
int Value = (int)(a_Value * 32);
|
|
||||||
WriteInt(Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
|
||||||
{
|
{
|
||||||
// Common metadata:
|
// Common metadata:
|
||||||
Byte Flags = 0;
|
Byte Flags = 0;
|
||||||
|
@ -3080,21 +3038,21 @@ void cProtocol180::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
||||||
{
|
{
|
||||||
Flags |= 0x20;
|
Flags |= 0x20;
|
||||||
}
|
}
|
||||||
WriteByte(0); // Byte(0) + index 0
|
a_Pkt.WriteByte(0); // Byte(0) + index 0
|
||||||
WriteByte(Flags);
|
a_Pkt.WriteByte(Flags);
|
||||||
|
|
||||||
switch (a_Entity.GetEntityType())
|
switch (a_Entity.GetEntityType())
|
||||||
{
|
{
|
||||||
case cEntity::etPlayer: break; // TODO?
|
case cEntity::etPlayer: break; // TODO?
|
||||||
case cEntity::etPickup:
|
case cEntity::etPickup:
|
||||||
{
|
{
|
||||||
WriteByte((5 << 5) | 10); // Slot(5) + index 10
|
a_Pkt.WriteByte((5 << 5) | 10); // Slot(5) + index 10
|
||||||
WriteItem(((const cPickup &)a_Entity).GetItem());
|
WriteItem(a_Pkt, reinterpret_cast<const cPickup &>(a_Entity).GetItem());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case cEntity::etMinecart:
|
case cEntity::etMinecart:
|
||||||
{
|
{
|
||||||
WriteByte(0x51);
|
a_Pkt.WriteByte(0x51);
|
||||||
|
|
||||||
// The following expression makes Minecarts shake more with less health or higher damage taken
|
// The following expression makes Minecarts shake more with less health or higher damage taken
|
||||||
// It gets half the maximum health, and takes it away from the current health minus the half health:
|
// It gets half the maximum health, and takes it away from the current health minus the half health:
|
||||||
|
@ -3103,71 +3061,82 @@ void cProtocol180::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
||||||
Health: 3 | 3 - (3 - 3) = 3
|
Health: 3 | 3 - (3 - 3) = 3
|
||||||
Health: 1 | 3 - (1 - 3) = 5
|
Health: 1 | 3 - (1 - 3) = 5
|
||||||
*/
|
*/
|
||||||
WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4);
|
auto & Minecart = reinterpret_cast<const cMinecart &>(a_Entity);
|
||||||
WriteByte(0x52);
|
a_Pkt.WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * Minecart.LastDamage()) * 4);
|
||||||
WriteInt(1); // Shaking direction, doesn't seem to affect anything
|
a_Pkt.WriteByte(0x52);
|
||||||
WriteByte(0x73);
|
a_Pkt.WriteInt(1); // Shaking direction, doesn't seem to affect anything
|
||||||
WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
|
a_Pkt.WriteByte(0x73);
|
||||||
|
a_Pkt.WriteFloat(static_cast<float>(Minecart.LastDamage() + 10)); // Damage taken / shake effect multiplyer
|
||||||
|
|
||||||
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpNone)
|
if (Minecart.GetPayload() == cMinecart::mpNone)
|
||||||
{
|
{
|
||||||
cRideableMinecart & RideableMinecart = ((cRideableMinecart &)a_Entity);
|
auto & RideableMinecart = reinterpret_cast<const cRideableMinecart &>(Minecart);
|
||||||
const cItem & MinecartContent = RideableMinecart.GetContent();
|
const cItem & MinecartContent = RideableMinecart.GetContent();
|
||||||
if (!MinecartContent.IsEmpty())
|
if (!MinecartContent.IsEmpty())
|
||||||
{
|
{
|
||||||
WriteByte(0x54);
|
a_Pkt.WriteByte(0x54);
|
||||||
int Content = MinecartContent.m_ItemType;
|
int Content = MinecartContent.m_ItemType;
|
||||||
Content |= MinecartContent.m_ItemDamage << 8;
|
Content |= MinecartContent.m_ItemDamage << 8;
|
||||||
WriteInt(Content);
|
a_Pkt.WriteInt(Content);
|
||||||
WriteByte(0x55);
|
a_Pkt.WriteByte(0x55);
|
||||||
WriteInt(RideableMinecart.GetBlockHeight());
|
a_Pkt.WriteInt(RideableMinecart.GetBlockHeight());
|
||||||
WriteByte(0x56);
|
a_Pkt.WriteByte(0x56);
|
||||||
WriteByte(1);
|
a_Pkt.WriteByte(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace)
|
else if (Minecart.GetPayload() == cMinecart::mpFurnace)
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0);
|
a_Pkt.WriteByte(reinterpret_cast<const cMinecartWithFurnace &>(Minecart).IsFueled() ? 1 : 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
} // case etMinecart
|
||||||
|
|
||||||
case cEntity::etProjectile:
|
case cEntity::etProjectile:
|
||||||
{
|
{
|
||||||
cProjectileEntity & Projectile = (cProjectileEntity &)a_Entity;
|
auto & Projectile = reinterpret_cast<const cProjectileEntity &>(a_Entity);
|
||||||
switch (Projectile.GetProjectileKind())
|
switch (Projectile.GetProjectileKind())
|
||||||
{
|
{
|
||||||
case cProjectileEntity::pkArrow:
|
case cProjectileEntity::pkArrow:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
a_Pkt.WriteByte(0x10);
|
||||||
WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0);
|
a_Pkt.WriteByte(reinterpret_cast<const cArrowEntity &>(Projectile).IsCritical() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case cProjectileEntity::pkFirework:
|
case cProjectileEntity::pkFirework:
|
||||||
{
|
{
|
||||||
WriteByte(0xA8);
|
a_Pkt.WriteByte(0xa8);
|
||||||
WriteItem(((const cFireworkEntity &)a_Entity).GetItem());
|
WriteItem(a_Pkt, reinterpret_cast<const cFireworkEntity &>(Projectile).GetItem());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
} // case etProjectile
|
||||||
|
|
||||||
case cEntity::etMonster:
|
case cEntity::etMonster:
|
||||||
{
|
{
|
||||||
WriteMobMetadata((const cMonster &)a_Entity);
|
WriteMobMetadata(a_Pkt, reinterpret_cast<const cMonster &>(a_Entity));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case cEntity::etItemFrame:
|
case cEntity::etItemFrame:
|
||||||
{
|
{
|
||||||
cItemFrame & Frame = (cItemFrame &)a_Entity;
|
auto & Frame = reinterpret_cast<const cItemFrame &>(a_Entity);
|
||||||
WriteByte(0xA8);
|
a_Pkt.WriteByte(0xa8);
|
||||||
WriteItem(Frame.GetItem());
|
WriteItem(a_Pkt, Frame.GetItem());
|
||||||
WriteByte(0x09);
|
a_Pkt.WriteByte(0x09);
|
||||||
WriteByte(Frame.GetItemRotation());
|
a_Pkt.WriteByte(Frame.GetItemRotation());
|
||||||
|
break;
|
||||||
|
} // case etItemFrame
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3175,150 +3144,51 @@ void cProtocol180::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
void cProtocol180::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob)
|
||||||
{
|
{
|
||||||
switch (a_Mob.GetMobType())
|
switch (a_Mob.GetMobType())
|
||||||
{
|
{
|
||||||
case mtCreeper:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1);
|
|
||||||
WriteByte(0x11);
|
|
||||||
WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtBat:
|
case mtBat:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
auto & Bat = reinterpret_cast<const cBat &>(a_Mob);
|
||||||
WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0);
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(Bat.IsHanging() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtBat
|
||||||
|
|
||||||
case mtPig:
|
case mtCreeper:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
auto & Creeper = reinterpret_cast<const cCreeper &>(a_Mob);
|
||||||
WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0);
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(Creeper.IsBlowing() ? 1 : -1);
|
||||||
|
a_Pkt.WriteByte(0x11);
|
||||||
|
a_Pkt.WriteByte(Creeper.IsCharged() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtCreeper
|
||||||
|
|
||||||
case mtVillager:
|
|
||||||
{
|
|
||||||
WriteByte(0x50);
|
|
||||||
WriteInt(((const cVillager &)a_Mob).GetVilType());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtZombie:
|
|
||||||
{
|
|
||||||
WriteByte(0x0c);
|
|
||||||
WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0);
|
|
||||||
WriteByte(0x0d);
|
|
||||||
WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0);
|
|
||||||
WriteByte(0x0e);
|
|
||||||
WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtGhast:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(((const cGhast &)a_Mob).IsCharging());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtWolf:
|
|
||||||
{
|
|
||||||
const cWolf & Wolf = (const cWolf &)a_Mob;
|
|
||||||
Byte WolfStatus = 0;
|
|
||||||
if (Wolf.IsSitting())
|
|
||||||
{
|
|
||||||
WolfStatus |= 0x1;
|
|
||||||
}
|
|
||||||
if (Wolf.IsAngry())
|
|
||||||
{
|
|
||||||
WolfStatus |= 0x2;
|
|
||||||
}
|
|
||||||
if (Wolf.IsTame())
|
|
||||||
{
|
|
||||||
WolfStatus |= 0x4;
|
|
||||||
}
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(WolfStatus);
|
|
||||||
|
|
||||||
WriteByte(0x72);
|
|
||||||
WriteFloat((float)(a_Mob.GetHealth()));
|
|
||||||
WriteByte(0x13);
|
|
||||||
WriteByte(Wolf.IsBegging() ? 1 : 0);
|
|
||||||
WriteByte(0x14);
|
|
||||||
WriteByte(Wolf.GetCollarColor());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtSheep:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
Byte SheepMetadata = 0;
|
|
||||||
SheepMetadata = ((const cSheep &)a_Mob).GetFurColor();
|
|
||||||
if (((const cSheep &)a_Mob).IsSheared())
|
|
||||||
{
|
|
||||||
SheepMetadata |= 0x10;
|
|
||||||
}
|
|
||||||
WriteByte(SheepMetadata);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtEnderman:
|
case mtEnderman:
|
||||||
{
|
{
|
||||||
WriteByte(0x30);
|
auto & Enderman = reinterpret_cast<const cEnderman &>(a_Mob);
|
||||||
WriteShort((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock()));
|
a_Pkt.WriteByte(0x30);
|
||||||
WriteByte(0x11);
|
a_Pkt.WriteShort(static_cast<Byte>(Enderman.GetCarriedBlock()));
|
||||||
WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta()));
|
a_Pkt.WriteByte(0x11);
|
||||||
WriteByte(0x12);
|
a_Pkt.WriteByte(static_cast<Byte>(Enderman.GetCarriedMeta()));
|
||||||
WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0);
|
a_Pkt.WriteByte(0x12);
|
||||||
|
a_Pkt.WriteByte(Enderman.IsScreaming() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtEnderman
|
||||||
|
|
||||||
case mtSkeleton:
|
case mtGhast:
|
||||||
{
|
{
|
||||||
WriteByte(0x0d);
|
auto & Ghast = reinterpret_cast<const cGhast &>(a_Mob);
|
||||||
WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0);
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(Ghast.IsCharging());
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtGhast
|
||||||
|
|
||||||
case mtWitch:
|
|
||||||
{
|
|
||||||
WriteByte(0x15);
|
|
||||||
WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtWither:
|
|
||||||
{
|
|
||||||
WriteByte(0x54); // Int at index 20
|
|
||||||
WriteInt(((const cWither &)a_Mob).GetWitherInvulnerableTicks());
|
|
||||||
WriteByte(0x66); // Float at index 6
|
|
||||||
WriteFloat((float)(a_Mob.GetHealth()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtSlime:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(((const cSlime &)a_Mob).GetSize());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtMagmaCube:
|
|
||||||
{
|
|
||||||
WriteByte(0x10);
|
|
||||||
WriteByte(((const cMagmaCube &)a_Mob).GetSize());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case mtHorse:
|
case mtHorse:
|
||||||
{
|
{
|
||||||
const cHorse & Horse = (const cHorse &)a_Mob;
|
auto & Horse = reinterpret_cast<const cHorse &>(a_Mob);
|
||||||
int Flags = 0;
|
int Flags = 0;
|
||||||
if (Horse.IsTame())
|
if (Horse.IsTame())
|
||||||
{
|
{
|
||||||
|
@ -3348,19 +3218,131 @@ void cProtocol180::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
||||||
{
|
{
|
||||||
Flags |= 0x80;
|
Flags |= 0x80;
|
||||||
}
|
}
|
||||||
WriteByte(0x50); // Int at index 16
|
a_Pkt.WriteByte(0x50); // Int at index 16
|
||||||
WriteInt(Flags);
|
a_Pkt.WriteInt(Flags);
|
||||||
WriteByte(0x13); // Byte at index 19
|
a_Pkt.WriteByte(0x13); // Byte at index 19
|
||||||
WriteByte(Horse.GetHorseType());
|
a_Pkt.WriteByte(Horse.GetHorseType());
|
||||||
WriteByte(0x54); // Int at index 20
|
a_Pkt.WriteByte(0x54); // Int at index 20
|
||||||
int Appearance = 0;
|
int Appearance = 0;
|
||||||
Appearance = Horse.GetHorseColor();
|
Appearance = Horse.GetHorseColor();
|
||||||
Appearance |= Horse.GetHorseStyle() << 8;
|
Appearance |= Horse.GetHorseStyle() << 8;
|
||||||
WriteInt(Appearance);
|
a_Pkt.WriteInt(Appearance);
|
||||||
WriteByte(0x56); // Int at index 22
|
a_Pkt.WriteByte(0x56); // Int at index 22
|
||||||
WriteInt(Horse.GetHorseArmour());
|
a_Pkt.WriteInt(Horse.GetHorseArmour());
|
||||||
break;
|
break;
|
||||||
}
|
} // case mtHorse
|
||||||
|
|
||||||
|
case mtMagmaCube:
|
||||||
|
{
|
||||||
|
auto & MagmaCube = reinterpret_cast<const cMagmaCube &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(MagmaCube.GetSize());
|
||||||
|
break;
|
||||||
|
} // case mtMagmaCube
|
||||||
|
|
||||||
|
case mtPig:
|
||||||
|
{
|
||||||
|
auto & Pig = reinterpret_cast<const cPig &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(Pig.IsSaddled() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtPig
|
||||||
|
|
||||||
|
case mtSheep:
|
||||||
|
{
|
||||||
|
auto & Sheep = reinterpret_cast<const cSheep &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
Byte SheepMetadata = 0;
|
||||||
|
SheepMetadata = Sheep.GetFurColor();
|
||||||
|
if (Sheep.IsSheared())
|
||||||
|
{
|
||||||
|
SheepMetadata |= 0x10;
|
||||||
|
}
|
||||||
|
a_Pkt.WriteByte(SheepMetadata);
|
||||||
|
break;
|
||||||
|
} // case mtSheep
|
||||||
|
|
||||||
|
case mtSkeleton:
|
||||||
|
{
|
||||||
|
auto & Skeleton = reinterpret_cast<const cSkeleton &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x0d);
|
||||||
|
a_Pkt.WriteByte(Skeleton.IsWither() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtSkeleton
|
||||||
|
|
||||||
|
case mtSlime:
|
||||||
|
{
|
||||||
|
auto & Slime = reinterpret_cast<const cSlime &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(Slime.GetSize());
|
||||||
|
break;
|
||||||
|
} // case mtSlime
|
||||||
|
|
||||||
|
case mtVillager:
|
||||||
|
{
|
||||||
|
auto & Villager = reinterpret_cast<const cVillager &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x50);
|
||||||
|
a_Pkt.WriteInt(Villager.GetVilType());
|
||||||
|
break;
|
||||||
|
} // case mtVillager
|
||||||
|
|
||||||
|
case mtWitch:
|
||||||
|
{
|
||||||
|
auto & Witch = reinterpret_cast<const cWitch &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x15);
|
||||||
|
a_Pkt.WriteByte(Witch.IsAngry() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtWitch
|
||||||
|
|
||||||
|
case mtWither:
|
||||||
|
{
|
||||||
|
auto & Wither = reinterpret_cast<const cWither &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x54); // Int at index 20
|
||||||
|
a_Pkt.WriteInt(Wither.GetWitherInvulnerableTicks());
|
||||||
|
a_Pkt.WriteByte(0x66); // Float at index 6
|
||||||
|
a_Pkt.WriteFloat(static_cast<float>(a_Mob.GetHealth()));
|
||||||
|
break;
|
||||||
|
} // case mtWither
|
||||||
|
|
||||||
|
case mtWolf:
|
||||||
|
{
|
||||||
|
auto & Wolf = reinterpret_cast<const cWolf &>(a_Mob);
|
||||||
|
Byte WolfStatus = 0;
|
||||||
|
if (Wolf.IsSitting())
|
||||||
|
{
|
||||||
|
WolfStatus |= 0x1;
|
||||||
|
}
|
||||||
|
if (Wolf.IsAngry())
|
||||||
|
{
|
||||||
|
WolfStatus |= 0x2;
|
||||||
|
}
|
||||||
|
if (Wolf.IsTame())
|
||||||
|
{
|
||||||
|
WolfStatus |= 0x4;
|
||||||
|
}
|
||||||
|
a_Pkt.WriteByte(0x10);
|
||||||
|
a_Pkt.WriteByte(WolfStatus);
|
||||||
|
|
||||||
|
a_Pkt.WriteByte(0x72);
|
||||||
|
a_Pkt.WriteFloat(static_cast<float>(a_Mob.GetHealth()));
|
||||||
|
a_Pkt.WriteByte(0x13);
|
||||||
|
a_Pkt.WriteByte(Wolf.IsBegging() ? 1 : 0);
|
||||||
|
a_Pkt.WriteByte(0x14);
|
||||||
|
a_Pkt.WriteByte(Wolf.GetCollarColor());
|
||||||
|
break;
|
||||||
|
} // case mtWolf
|
||||||
|
|
||||||
|
case mtZombie:
|
||||||
|
{
|
||||||
|
auto & Zombie = reinterpret_cast<const cZombie &>(a_Mob);
|
||||||
|
a_Pkt.WriteByte(0x0c);
|
||||||
|
a_Pkt.WriteByte(Zombie.IsBaby() ? 1 : 0);
|
||||||
|
a_Pkt.WriteByte(0x0d);
|
||||||
|
a_Pkt.WriteByte(Zombie.IsVillagerZombie() ? 1 : 0);
|
||||||
|
a_Pkt.WriteByte(0x0e);
|
||||||
|
a_Pkt.WriteByte(Zombie.IsConverting() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
} // case mtZombie
|
||||||
} // switch (a_Mob.GetType())
|
} // switch (a_Mob.GetType())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3368,12 +3350,12 @@ void cProtocol180::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol180::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
|
void cProtocol180::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity)
|
||||||
{
|
{
|
||||||
if (!a_Entity.IsMob())
|
if (!a_Entity.IsMob())
|
||||||
{
|
{
|
||||||
// No properties for anything else than mobs
|
// No properties for anything else than mobs
|
||||||
WriteInt(0);
|
a_Pkt.WriteInt(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3381,7 +3363,7 @@ void cProtocol180::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
|
||||||
|
|
||||||
// TODO: Send properties and modifiers based on the mob type
|
// TODO: Send properties and modifiers based on the mob type
|
||||||
|
|
||||||
WriteInt(0); // NumProperties
|
a_Pkt.WriteInt(0); // NumProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -150,101 +150,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */
|
|
||||||
class cPacketizer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cPacketizer(cProtocol180 & a_Protocol, UInt32 a_PacketType) :
|
|
||||||
m_Protocol(a_Protocol),
|
|
||||||
m_Out(a_Protocol.m_OutPacketBuffer),
|
|
||||||
m_Lock(a_Protocol.m_CSPacket)
|
|
||||||
{
|
|
||||||
m_Out.WriteVarInt(a_PacketType);
|
|
||||||
}
|
|
||||||
|
|
||||||
~cPacketizer();
|
|
||||||
|
|
||||||
void WriteBool(bool a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBool(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteByte(UInt8 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEUInt8(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteChar(Int8 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt8(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteShort(Int16 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt16(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteInt(Int32 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt32(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteUInt32(UInt32 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEUInt32(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteInt64(Int64 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEInt64(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteFloat(float a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEFloat(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteDouble(double a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteBEDouble(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteVarInt(UInt32 a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteVarInt(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteString(const AString & a_Value)
|
|
||||||
{
|
|
||||||
m_Out.WriteVarUTF8String(a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ)
|
|
||||||
{
|
|
||||||
m_Out.WritePosition(a_BlockX, a_BlockY, a_BlockZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteUUID(const AString & a_UUID);
|
|
||||||
|
|
||||||
void WriteBuf(const char * a_Data, size_t a_Size)
|
|
||||||
{
|
|
||||||
m_Out.Write(a_Data, a_Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteItem(const cItem & a_Item);
|
|
||||||
void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte
|
|
||||||
void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer
|
|
||||||
void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f
|
|
||||||
void WriteMobMetadata(const cMonster & a_Mob); // Writes the mob-specific metadata for the specified mob
|
|
||||||
void WriteEntityProperties(const cEntity & a_Entity); // Writes the entity properties for the specified entity, including the Count field
|
|
||||||
void WriteBlockEntity(const cBlockEntity & a_BlockEntity);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
cProtocol180 & m_Protocol;
|
|
||||||
cByteBuffer & m_Out;
|
|
||||||
cCSLock m_Lock;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
AString m_ServerAddress;
|
AString m_ServerAddress;
|
||||||
|
|
||||||
UInt16 m_ServerPort;
|
UInt16 m_ServerPort;
|
||||||
|
@ -257,12 +162,6 @@ protected:
|
||||||
/** Buffer for the received data */
|
/** Buffer for the received data */
|
||||||
cByteBuffer m_ReceivedData;
|
cByteBuffer m_ReceivedData;
|
||||||
|
|
||||||
/** Buffer for composing the outgoing packets, through cPacketizer */
|
|
||||||
cByteBuffer m_OutPacketBuffer;
|
|
||||||
|
|
||||||
/** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */
|
|
||||||
cByteBuffer m_OutPacketLenBuffer;
|
|
||||||
|
|
||||||
bool m_IsEncrypted;
|
bool m_IsEncrypted;
|
||||||
|
|
||||||
cAesCfb128Decryptor m_Decryptor;
|
cAesCfb128Decryptor m_Decryptor;
|
||||||
|
@ -325,6 +224,9 @@ protected:
|
||||||
/** Sends the data to the client, encrypting them if needed. */
|
/** Sends the data to the client, encrypting them if needed. */
|
||||||
virtual void SendData(const char * a_Data, size_t a_Size) override;
|
virtual void SendData(const char * a_Data, size_t a_Size) override;
|
||||||
|
|
||||||
|
/** Sends the packet to the client. Called by the cPacketizer's destructor. */
|
||||||
|
virtual void SendPacket(cPacketizer & a_Packet) override;
|
||||||
|
|
||||||
void SendCompass(const cWorld & a_World);
|
void SendCompass(const cWorld & a_World);
|
||||||
|
|
||||||
/** Reads an item out of the received data, sets a_Item to the values read.
|
/** Reads an item out of the received data, sets a_Item to the values read.
|
||||||
|
@ -340,6 +242,21 @@ protected:
|
||||||
/** Converts the BlockFace received by the protocol into eBlockFace constants.
|
/** Converts the BlockFace received by the protocol into eBlockFace constants.
|
||||||
If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */
|
If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */
|
||||||
eBlockFace FaceIntToBlockFace(Int8 a_FaceInt);
|
eBlockFace FaceIntToBlockFace(Int8 a_FaceInt);
|
||||||
|
|
||||||
|
/** Writes the item data into a packet. */
|
||||||
|
void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item);
|
||||||
|
|
||||||
|
/** Writes the metadata for the specified entity, not including the terminating 0x7f. */
|
||||||
|
void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity);
|
||||||
|
|
||||||
|
/** Writes the mob-specific metadata for the specified mob */
|
||||||
|
void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob);
|
||||||
|
|
||||||
|
/** Writes the entity properties for the specified entity, including the Count field. */
|
||||||
|
void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity);
|
||||||
|
|
||||||
|
/** Writes the block entity data for the specified block entity into the packet. */
|
||||||
|
void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity);
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -982,3 +982,15 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cProtocolRecognizer::SendPacket(cPacketizer & a_Pkt)
|
||||||
|
{
|
||||||
|
// This function should never be called - it needs to exists so that cProtocolRecognizer can be instantiated,
|
||||||
|
// but the actual sending is done by the internal m_Protocol itself.
|
||||||
|
LOGWARNING("%s: This function shouldn't ever be called.", __FUNCTION__);
|
||||||
|
ASSERT(!"Function not to be called");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -136,9 +136,12 @@ protected:
|
||||||
|
|
||||||
/** Tries to recognize a protocol in the lengthed family (1.7+), based on m_Buffer; returns true if recognized.
|
/** Tries to recognize a protocol in the lengthed family (1.7+), based on m_Buffer; returns true if recognized.
|
||||||
The packet length and type have already been read, type is 0
|
The packet length and type have already been read, type is 0
|
||||||
The number of bytes remaining in the packet is passed as a_PacketLengthRemaining
|
The number of bytes remaining in the packet is passed as a_PacketLengthRemaining. **/
|
||||||
**/
|
|
||||||
bool TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRemaining);
|
bool TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRemaining);
|
||||||
|
|
||||||
|
/** Sends a single packet contained within the cPacketizer class.
|
||||||
|
The cPacketizer's destructor calls this to send the contained packet; protocol may transform the data (compression in 1.8 etc). */
|
||||||
|
virtual void SendPacket(cPacketizer & a_Pkt) override;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user