summaryrefslogtreecommitdiffstats
path: root/src/Protocol/Packetizer.h
blob: 5993fe70c53db0f29efea3bf85fcb2780e424b87 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

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



class cByteBuffer;


// fwd:
class cUUID;





/** Macros used to read packets more easily */
#define HANDLE_READ(ByteBuf, Proc, Type, Var) \
	Type Var;                                 \
	do                                        \
	{                                         \
		if (!ByteBuf.Proc(Var))               \
		{                                     \
			return;                           \
		}                                     \
	}                                         \
	while (false)





#define HANDLE_PACKET_READ(ByteBuf, Proc, Type, Var) \
	Type Var;                                        \
	do                                               \
	{                                                \
		{                                            \
			if (!ByteBuf.Proc(Var))                  \
			{                                        \
				ByteBuf.CheckValid();                \
				return false;                        \
			}                                        \
			ByteBuf.CheckValid();                    \
		}                                            \
	}                                                \
	while (false)





/** 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, cProtocol::ePacketType 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.WriteVarInt32(m_Protocol.GetPacketID(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 WriteBEUInt8(UInt8 a_Value) { VERIFY(m_Out.WriteBEUInt8(a_Value)); }


	inline void WriteBEInt8(Int8 a_Value) { VERIFY(m_Out.WriteBEInt8(a_Value)); }


	inline void WriteBEInt16(Int16 a_Value) { VERIFY(m_Out.WriteBEInt16(a_Value)); }


	inline void WriteBEUInt16(UInt16 a_Value) { VERIFY(m_Out.WriteBEUInt16(a_Value)); }


	inline void WriteBEInt32(Int32 a_Value) { VERIFY(m_Out.WriteBEInt32(a_Value)); }


	inline void WriteBEUInt32(UInt32 a_Value) { VERIFY(m_Out.WriteBEUInt32(a_Value)); }


	inline void WriteBEInt64(Int64 a_Value) { VERIFY(m_Out.WriteBEInt64(a_Value)); }


	inline void WriteBEUInt64(UInt64 a_Value) { VERIFY(m_Out.WriteBEUInt64(a_Value)); }


	inline void WriteBEFloat(float a_Value) { VERIFY(m_Out.WriteBEFloat(a_Value)); }


	inline void WriteBEDouble(double a_Value) { VERIFY(m_Out.WriteBEDouble(a_Value)); }


	inline void WriteVarInt32(UInt32 a_Value) { VERIFY(m_Out.WriteVarInt32(a_Value)); }


	inline void WriteString(const AString & a_Value) { VERIFY(m_Out.WriteVarUTF8String(a_Value)); }


	inline void WriteBuf(const ContiguousByteBufferView a_Data) { VERIFY(m_Out.Write(a_Data.data(), a_Data.size())); }


	/** Writes the specified block position as a single encoded 64-bit BigEndian integer.
	The three coordinates are written in XYZ order. */
	inline void WriteXYZPosition64(int a_BlockX, int a_BlockY, int a_BlockZ)
	{
		VERIFY(m_Out.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ));
	}

	/** Writes the specified block position as a single encoded 64-bit BigEndian integer.
	The three coordinates are written in XYZ order. */
	inline void WriteXYZPosition64(const Vector3i a_Position)
	{
		VERIFY(m_Out.WriteXYZPosition64(a_Position.x, a_Position.y, a_Position.z));
	}

	/** Writes the specified block position as a single encoded 64-bit BigEndian integer.
	The three coordinates are written in XZY order, in 1.14+. */
	inline void WriteXZYPosition64(int a_BlockX, int a_BlockY, int a_BlockZ)
	{
		VERIFY(m_Out.WriteXZYPosition64(a_BlockX, a_BlockY, a_BlockZ));
	}

	/** Writes the specified block position as a single encoded 64-bit BigEndian integer.
	The three coordinates are written in XZY order, in 1.14+. */
	inline void WriteXZYPosition64(const Vector3i a_Position)
	{
		VERIFY(m_Out.WriteXZYPosition64(a_Position.x, a_Position.y, a_Position.z));
	}

	/** 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 cUUID & a_UUID);

	cProtocol::ePacketType GetPacketType() const { return m_PacketType; }

	/** Returns the human-readable representation of the packet type.
	Used for logging the packets. */
	static AString PacketTypeToStr(cProtocol::ePacketType a_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. */
	cProtocol::ePacketType m_PacketType;
};