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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
|
// Protocol.h
// Interfaces to the cProtocol class representing the generic interface that a protocol
// parser and serializer must implement
#pragma once
#include "../Defines.h"
#include "../Scoreboard.h"
#include "../ByteBuffer.h"
#include "../EffectID.h"
#include "../World.h"
class cMap;
class cExpOrb;
class cPlayer;
class cEntity;
class cWindow;
class cPainting;
class cWorld;
class cMonster;
class cCompositeChat;
class cPacketizer;
struct StatisticsManager;
class cProtocol
{
public:
cProtocol(cClientHandle * a_Client) :
m_Client(a_Client),
m_OutPacketBuffer(64 KiB),
m_OutPacketLenBuffer(20) // 20 bytes is more than enough for one VarInt
{
}
virtual ~cProtocol() {}
/** Logical types of outgoing packets.
These values get translated to on-wire packet IDs in GetPacketID(), specific for each protocol.
This is mainly useful for protocol sub-versions that re-number the packets while using mostly the same packet
layout. */
enum ePacketType
{
pktAttachEntity = 0,
pktBlockAction,
pktBlockBreakAnim,
pktBlockChange,
pktBlockChanges,
pktBossBar,
pktCameraSetTo,
pktChatRaw,
pktCollectEntity,
pktDestroyEntity,
pktDifficulty,
pktDisconnectDuringLogin,
pktDisconnectDuringGame,
pktDisplayObjective,
pktEditSign,
pktEncryptionRequest,
pktEntityAnimation,
pktEntityEffect,
pktEntityEquipment,
pktEntityHeadLook,
pktEntityLook,
pktEntityMeta,
pktEntityProperties,
pktEntityRelMove,
pktEntityRelMoveLook,
pktEntityStatus,
pktEntityVelocity,
pktExperience,
pktExplosion,
pktGameMode,
pktHeldItemChange,
pktHorseWindowOpen,
pktInventorySlot,
pktJoinGame,
pktKeepAlive,
pktLeashEntity,
pktLoginSuccess,
pktMapData,
pktParticleEffect,
pktPingResponse,
pktPlayerAbilities,
pktPlayerList,
pktPlayerListHeaderFooter,
pktPlayerMoveLook,
pktPluginMessage,
pktRemoveEntityEffect,
pktResourcePack,
pktRespawn,
pktScoreboardObjective,
pktSpawnObject,
pktSoundEffect,
pktSoundParticleEffect,
pktSpawnExperienceOrb,
pktSpawnGlobalEntity,
pktSpawnMob,
pktSpawnOtherPlayer,
pktSpawnPainting,
pktSpawnPosition,
pktStartCompression,
pktStatistics,
pktStatusResponse,
pktTabCompletionResults,
pktTeleportEntity,
pktTimeUpdate,
pktTitle,
pktUnloadChunk,
pktUnlockRecipe,
pktUpdateBlockEntity,
pktUpdateHealth,
pktUpdateScore,
pktUpdateSign,
pktUseBed,
pktWeather,
pktWindowItems,
pktWindowClose,
pktWindowOpen,
pktWindowProperty
};
enum class EntityMetadata
{
EntityFlags,
EntityAir,
EntityCustomName,
EntityCustomNameVisible,
EntitySilent,
EntityNoGravity,
EntityPose,
PotionThrown,
FallingBlockPosition,
AreaEffectCloudRadius,
AreaEffectCloudColor,
AreaEffectCloudSinglePointEffect,
AreaEffectCloudParticleId,
AreaEffectCloudParticleParameter1,
AreaEffectCloudParticleParameter2,
ArrowFlags,
TippedArrowColor,
PiercingLevel,
BoatLastHitTime,
BoatForwardDirection,
BoatDamageTaken,
BoatType,
BoatLeftPaddleTurning,
BoatRightPaddleTurning,
BoatSplashTimer,
EnderCrystalBeamTarget,
EnderCrystalShowBottom,
WitherSkullInvulnerable,
FireworkInfo,
FireworkBoostedEntityId,
FireworkFromCrossbow,
ItemFrameItem,
ItemFrameRotation,
ItemItem,
LivingActiveHand,
LivingHealth,
LivingPotionEffectColor,
LivingPotionEffectAmbient,
LivingNumberOfArrows,
PlayerAdditionalHearts,
PlayerScore,
PlayerDisplayedSkinParts,
PlayerMainHand,
ArmorStandStatus,
ArmorStandHeadRotation,
ArmorStandBodyRotation,
ArmorStandLeftArmRotation,
ArmorStandRightArmRotation,
ArmorStandLeftLegRotation,
ArmorStandRightLegRotation,
InsentientFlags,
BatHanging,
AgeableIsBaby,
AbstractHorseFlags,
AbstractHorseOwner,
HorseVariant,
HorseArmour,
ChestedHorseChested,
LlamaStrength,
LlamaCarpetColor,
LlamaVariant,
PigHasSaddle,
PigTotalCarrotOnAStickBoost,
RabbitType,
PolarBearStanding,
SheepFlags,
TameableAnimalFlags,
TameableAnimalOwner,
ThrowableItem,
TridentLoyaltyLevel,
OcelotType,
WolfDamageTaken,
WolfBegging,
WolfCollarColour,
VillagerProfession,
IronGolemPlayerCreated,
ShulkerFacingDirection,
ShulkerAttachmentFallingBlockPosition,
ShulkerShieldHeight,
BlazeOnFire,
CreeperState,
CreeperPowered,
CreeperIgnited,
GuardianStatus,
GuardianTarget,
IllagerFlags,
SpeIlagerSpell,
VexFlags,
AbstractSkeletonArmsSwinging,
SpiderClimbing,
WitchAggresive,
WitchDrinking,
WitherFirstHeadTarget,
WitherSecondHeadTarget,
WitherThirdHeadTarget,
WitherInvulnerableTimer,
ZombieIsBaby,
ZombieUnusedWasType,
ZombieHandsRisedUp,
ZombieVillagerConverting,
ZombieVillagerProfession,
EndermanCarriedBlock,
EndermanScreaming,
EnderDragonDragonPhase,
GhastAttacking,
SlimeSize,
MinecartShakingPower,
MinecartShakingDirection,
MinecartShakingMultiplier,
MinecartBlockIDMeta,
MinecartBlockY,
MinecartShowBlock,
MinecartCommandBlockCommand,
MinecartCommandBlockLastOutput,
MinecartFurnacePowered,
MooshroomType,
TNTPrimedFuseTime
};
enum class EntityMetadataType
{
Byte,
VarInt,
Float,
String,
Chat,
OptChat,
Item,
Boolean,
Rotation,
Position,
OptPosition,
Direction,
OptUUID,
OptBlockID,
NBT,
Particle,
VillagerData,
OptVarInt,
Pose
};
/** The protocol version number, received from the client in the Handshake packet. */
enum class Version
{
v1_8_0 = 47,
v1_9_0 = 107,
v1_9_1 = 108,
v1_9_2 = 109,
v1_9_4 = 110,
v1_10_0 = 210,
v1_11_0 = 315,
v1_11_1 = 316,
v1_12 = 335,
v1_12_1 = 338,
v1_12_2 = 340,
v1_13 = 393,
v1_13_1 = 401,
v1_13_2 = 404,
v1_14 = 477,
v1_14_1 = 480,
v1_14_2 = 485,
v1_14_3 = 490,
v1_14_4 = 498
};
enum State
{
Status = 1,
Login = 2,
Game = 3,
};
/** Called by cClientHandle to process data, when the client sends some.
The protocol uses the provided buffers for storage and processing, and must have exclusive access to them. */
virtual void DataReceived(cByteBuffer & a_Buffer, ContiguousByteBuffer & a_Data) = 0;
/** Called by cClientHandle to finalise a buffer of prepared data before they are sent to the client.
Descendants may for example, encrypt the data if needed.
The protocol modifies the provided buffer in-place. */
virtual void DataPrepared(ContiguousByteBuffer & a_Data) = 0;
// Sending stuff to clients (alphabetically sorted):
virtual void SendAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) = 0;
virtual void SendBlockAction(Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0;
virtual void SendBlockBreakAnim(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage) = 0;
virtual void SendBlockChange(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual void SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0;
virtual void SendBossBarAdd(
UInt32 a_UniqueID,
const cCompositeChat & a_Title,
float a_FractionFilled,
BossBarColor a_Color,
BossBarDivisionType a_DivisionType,
bool a_DarkenSky,
bool a_PlayEndMusic,
bool a_CreateFog
) = 0;
virtual void SendBossBarRemove(UInt32 a_UniqueID) = 0;
virtual void SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) = 0;
virtual void SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) = 0;
virtual void SendBossBarUpdateStyle(
UInt32 a_UniqueID,
BossBarColor a_Color,
BossBarDivisionType a_DivisionType
) = 0;
virtual void SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat & a_Title) = 0;
virtual void SendCameraSetTo(const cEntity & a_Entity) = 0;
virtual void SendChat(const AString & a_Message, eChatType a_Type) = 0;
virtual void SendChat(const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) = 0;
virtual void SendChatRaw(const AString & a_MessageRaw, eChatType a_Type) = 0;
virtual void SendChunkData(ContiguousByteBufferView a_ChunkData) = 0;
virtual void SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) = 0;
virtual void SendDestroyEntity(const cEntity & a_Entity) = 0;
virtual void SendDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) = 0;
virtual void SendDisconnect(const AString & a_Reason) = 0;
virtual void SendEditSign(Vector3i a_BlockPos
) = 0; ///< Request the client to open up the sign editor for the sign (1.6+)
virtual void SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) = 0;
virtual void SendEntityAnimation(const cEntity & a_Entity, EntityAnimation a_Animation) = 0;
virtual void SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0;
virtual void SendEntityHeadLook(const cEntity & a_Entity) = 0;
virtual void SendEntityLook(const cEntity & a_Entity) = 0;
virtual void SendEntityMetadata(const cEntity & a_Entity) = 0;
virtual void SendEntityPosition(const cEntity & a_Entity) = 0;
virtual void SendEntityProperties(const cEntity & a_Entity) = 0;
virtual void SendEntityVelocity(const cEntity & a_Entity) = 0;
virtual void SendExplosion(Vector3f a_Position, float a_Power) = 0;
virtual void SendGameMode(eGameMode a_GameMode) = 0;
virtual void SendHealth(void) = 0;
virtual void SendHeldItemChange(int a_ItemIndex) = 0;
virtual void SendHideTitle(void) = 0;
virtual void SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) = 0;
virtual void SendKeepAlive(UInt32 a_PingID) = 0;
virtual void SendLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) = 0;
virtual void SendLogin(const cPlayer & a_Player, const cWorld & a_World) = 0;
virtual void SendLoginSuccess(void) = 0;
virtual void SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY) = 0;
virtual void SendPaintingSpawn(const cPainting & a_Painting) = 0;
virtual void SendPlayerAbilities(void) = 0;
virtual void SendParticleEffect(
const AString & a_SoundName,
Vector3f a_Src,
Vector3f a_Offset,
float a_ParticleData,
int a_ParticleAmount
) = 0;
virtual void SendParticleEffect(
const AString & a_SoundName,
Vector3f a_Src,
Vector3f a_Offset,
float a_ParticleData,
int a_ParticleAmount,
std::array<int, 2> a_Data
) = 0;
virtual void SendPlayerListAddPlayer(const cPlayer & a_Player) = 0;
virtual void SendPlayerListHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) = 0;
virtual void SendPlayerListRemovePlayer(const cPlayer & a_Player) = 0;
virtual void SendPlayerListUpdateGameMode(const cPlayer & a_Player) = 0;
virtual void SendPlayerListUpdatePing() = 0;
virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) = 0;
virtual void SendPlayerMoveLook(Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative) = 0;
virtual void SendPlayerMoveLook(void) = 0;
virtual void SendPlayerPermissionLevel(void) = 0;
virtual void SendPlayerPosition(void) = 0;
virtual void SendPlayerSpawn(const cPlayer & a_Player) = 0;
virtual void SendPluginMessage(const AString & a_Channel, ContiguousByteBufferView a_Message) = 0;
virtual void SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) = 0;
virtual void SendResetTitle(void) = 0;
virtual void SendResourcePack(const AString & a_ResourcePackUrl) = 0;
virtual void SendRespawn(eDimension a_Dimension) = 0;
virtual void SendExperience(void) = 0;
virtual void SendExperienceOrb(const cExpOrb & a_ExpOrb) = 0;
virtual void SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;
virtual void SendScoreUpdate(
const AString & a_Objective,
const AString & a_Player,
cObjective::Score a_Score,
Byte a_Mode
) = 0;
virtual void SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0;
virtual void SendSetSubTitle(const cCompositeChat & a_SubTitle) = 0;
virtual void SendSetRawSubTitle(const AString & a_SubTitle) = 0;
virtual void SendSetTitle(const cCompositeChat & a_Title) = 0;
virtual void SendSetRawTitle(const AString & a_Title) = 0;
virtual void SendSoundEffect(const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) = 0;
virtual void SendSoundParticleEffect(const EffectID a_EffectID, Vector3i a_Origin, int a_Data) = 0;
virtual void SendSpawnEntity(const cEntity & a_Entity) = 0;
virtual void SendSpawnMob(const cMonster & a_Mob) = 0;
virtual void SendStatistics(const StatisticsManager & a_Manager) = 0;
virtual void SendTabCompletionResults(const AStringVector & a_Results) = 0;
virtual void SendThunderbolt(Vector3i a_Origin) = 0;
virtual void SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) = 0;
virtual void SendTimeUpdate(cTickTimeLong a_WorldAge, cTickTimeLong a_WorldDate, bool a_DoDaylightCycle) = 0;
virtual void SendUnleashEntity(const cEntity & a_Entity) = 0;
virtual void SendUnloadChunk(int a_ChunkX, int a_ChunkZ) = 0;
virtual void SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) = 0;
virtual void SendUpdateSign(
Vector3i a_BlockPos,
const AString & a_Line1,
const AString & a_Line2,
const AString & a_Line3,
const AString & a_Line4
) = 0;
virtual void SendUnlockRecipe(UInt32 a_RecipeID) = 0;
virtual void SendInitRecipes(UInt32 a_RecipeID) = 0;
virtual void SendWeather(eWeather a_Weather) = 0;
virtual void SendWholeInventory(const cWindow & a_Window) = 0;
virtual void SendWindowClose(const cWindow & a_Window) = 0;
virtual void SendWindowOpen(const cWindow & a_Window) = 0;
virtual void SendWindowProperty(const cWindow & a_Window, size_t a_Property, short a_Value) = 0;
/** Returns the ServerID used for authentication through session.minecraft.net */
virtual AString GetAuthServerID(void) = 0;
protected:
friend class cPacketizer;
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;
/** Returns the protocol-specific packet ID given the protocol-agnostic packet enum. */
virtual UInt32 GetPacketID(ePacketType a_Packet) const = 0;
/** Returns the current protocol's version, for handling status requests. */
virtual Version GetProtocolVersion() const = 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;
};
|