Cuberite
A lightweight, fast and extensible game server for Minecraft
Protocol_1_9.cpp
Go to the documentation of this file.
1 
2 // Protocol_1_9.cpp
3 
4 /*
5 Implements the 1.9 protocol classes:
6  - cProtocol_1_9_0
7  - release 1.9 protocol (#107)
8  - cProtocol_1_9_1
9  - release 1.9.1 protocol (#108)
10  - cProtocol_1_9_2
11  - release 1.9.2 protocol (#109)
12  - cProtocol_1_9_4
13  - release 1.9.4 protocol (#110)
14 */
15 
16 #include "Globals.h"
17 #include "Protocol_1_9.h"
18 #include "../mbedTLS++/Sha1Checksum.h"
19 #include "Packetizer.h"
20 
21 #include "../ClientHandle.h"
22 #include "../Root.h"
23 #include "../Server.h"
24 #include "../World.h"
25 #include "../StringCompression.h"
26 #include "../CompositeChat.h"
27 #include "../JsonUtils.h"
28 
29 #include "../WorldStorage/FastNBT.h"
30 
31 #include "../Entities/EnderCrystal.h"
32 #include "../Entities/ExpOrb.h"
33 #include "../Entities/Minecart.h"
34 #include "../Entities/FallingBlock.h"
35 #include "../Entities/Painting.h"
36 #include "../Entities/Pickup.h"
37 #include "../Entities/Player.h"
38 #include "../Entities/ItemFrame.h"
39 #include "../Entities/ArrowEntity.h"
40 #include "../Entities/FireworkEntity.h"
41 #include "../Entities/SplashPotionEntity.h"
42 
43 #include "../Items/ItemSpawnEgg.h"
44 
45 #include "../Mobs/IncludeAllMonsters.h"
46 #include "../UI/HorseWindow.h"
47 
48 #include "../BlockEntities/MobSpawnerEntity.h"
49 
50 
51 
52 
53 
54 // Value for main hand in Hand parameter for Protocol 1.9.
55 #define MAIN_HAND 0
56 
57 // Value for left hand in MainHand parameter for Protocol 1.9.
58 #define LEFT_HAND 0
59 
60 
61 
62 
63 
65 // cProtocol_1_9_0:
66 
67 cProtocol_1_9_0::cProtocol_1_9_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State) :
68  Super(a_Client, a_ServerAddress, a_State),
69  m_IsTeleportIdConfirmed(true),
70  m_OutstandingTeleportId(0)
71 {
72 }
73 
74 
75 
76 
77 
78 void cProtocol_1_9_0::SendAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle)
79 {
80  ASSERT(m_State == 3); // In game mode?
81  cPacketizer Pkt(*this, pktAttachEntity);
82  Pkt.WriteVarInt32(a_Vehicle.GetUniqueID());
83  Pkt.WriteVarInt32(1); // 1 passenger
84  Pkt.WriteVarInt32(a_Entity.GetUniqueID());
85 }
86 
87 
88 
89 
90 
91 void cProtocol_1_9_0::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)
92 {
93  ASSERT(m_State == 3); // In game mode?
94 
95  cPacketizer Pkt(*this, pktBossBar);
96  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
97  Pkt.WriteBEUInt64(0);
98  Pkt.WriteBEUInt64(a_UniqueID);
99  Pkt.WriteVarInt32(0); // Add
100  Pkt.WriteString(a_Title.CreateJsonString());
101  Pkt.WriteBEFloat(a_FractionFilled);
102  Pkt.WriteVarInt32([a_Color]
103  {
104  switch (a_Color)
105  {
106  case BossBarColor::Pink: return 0U;
107  case BossBarColor::Blue: return 1U;
108  case BossBarColor::Red: return 2U;
109  case BossBarColor::Green: return 3U;
110  case BossBarColor::Yellow: return 4U;
111  case BossBarColor::Purple: return 5U;
112  case BossBarColor::White: return 6U;
113  }
114  UNREACHABLE("Unsupported boss bar property");
115  }());
116  Pkt.WriteVarInt32([a_DivisionType]
117  {
118  switch (a_DivisionType)
119  {
120  case BossBarDivisionType::None: return 0U;
121  case BossBarDivisionType::SixNotches: return 1U;
122  case BossBarDivisionType::TenNotches: return 2U;
123  case BossBarDivisionType::TwelveNotches: return 3U;
124  case BossBarDivisionType::TwentyNotches: return 4U;
125  }
126  UNREACHABLE("Unsupported boss bar property");
127  }());
128  {
129  UInt8 Flags = 0x00;
130  if (a_DarkenSky)
131  {
132  Flags |= 0x01;
133  }
134  if (a_PlayEndMusic || a_CreateFog)
135  {
136  Flags |= 0x02;
137  }
138  Pkt.WriteBEUInt8(Flags);
139  }
140 }
141 
142 
143 
144 
145 
147 {
148  ASSERT(m_State == 3); // In game mode?
149 
150  cPacketizer Pkt(*this, pktBossBar);
151  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
152  Pkt.WriteBEUInt64(0);
153  Pkt.WriteBEUInt64(a_UniqueID);
154  Pkt.WriteVarInt32(1); // Remove
155 }
156 
157 
158 
159 
160 
161 void cProtocol_1_9_0::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog)
162 {
163  ASSERT(m_State == 3); // In game mode?
164 
165  cPacketizer Pkt(*this, pktBossBar);
166  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
167  Pkt.WriteBEUInt64(0);
168  Pkt.WriteBEUInt64(a_UniqueID);
169  Pkt.WriteVarInt32(5); // Update Flags
170  {
171  UInt8 Flags = 0x00;
172  if (a_DarkenSky)
173  {
174  Flags |= 0x01;
175  }
176  if (a_PlayEndMusic || a_CreateFog)
177  {
178  Flags |= 0x02;
179  }
180  Pkt.WriteBEUInt8(Flags);
181  }
182 }
183 
184 
185 
186 
187 
188 void cProtocol_1_9_0::SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled)
189 {
190  ASSERT(m_State == 3); // In game mode?
191 
192  cPacketizer Pkt(*this, pktBossBar);
193  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
194  Pkt.WriteBEUInt64(0);
195  Pkt.WriteBEUInt64(a_UniqueID);
196  Pkt.WriteVarInt32(2); // Update health
197  Pkt.WriteBEFloat(a_FractionFilled);
198 }
199 
200 
201 
202 
203 
205 {
206  ASSERT(m_State == 3); // In game mode?
207 
208  cPacketizer Pkt(*this, pktBossBar);
209  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
210  Pkt.WriteBEUInt64(0);
211  Pkt.WriteBEUInt64(a_UniqueID);
212  Pkt.WriteVarInt32(4); // Update health
213  Pkt.WriteVarInt32([a_Color]
214  {
215  switch (a_Color)
216  {
217  case BossBarColor::Pink: return 0U;
218  case BossBarColor::Blue: return 1U;
219  case BossBarColor::Red: return 2U;
220  case BossBarColor::Green: return 3U;
221  case BossBarColor::Yellow: return 4U;
222  case BossBarColor::Purple: return 5U;
223  case BossBarColor::White: return 6U;
224  }
225  UNREACHABLE("Unsupported boss bar property");
226  }());
227  Pkt.WriteVarInt32([a_DivisionType]
228  {
229  switch (a_DivisionType)
230  {
231  case BossBarDivisionType::None: return 0U;
232  case BossBarDivisionType::SixNotches: return 1U;
233  case BossBarDivisionType::TenNotches: return 2U;
234  case BossBarDivisionType::TwelveNotches: return 3U;
235  case BossBarDivisionType::TwentyNotches: return 4U;
236  }
237  UNREACHABLE("Unsupported boss bar property");
238  }());
239 }
240 
241 
242 
243 
244 
246 {
247  ASSERT(m_State == 3); // In game mode?
248 
249  cPacketizer Pkt(*this, pktBossBar);
250  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
251  Pkt.WriteBEUInt64(0);
252  Pkt.WriteBEUInt64(a_UniqueID);
253  Pkt.WriteVarInt32(3); // Update title
254  Pkt.WriteString(a_Title.CreateJsonString());
255 }
256 
257 
258 
259 
260 
261 void cProtocol_1_9_0::SendDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle)
262 {
263  ASSERT(m_State == 3); // In game mode?
264  cPacketizer Pkt(*this, pktAttachEntity);
265  Pkt.WriteVarInt32(a_PreviousVehicle.GetUniqueID());
266  Pkt.WriteVarInt32(0); // No passangers
267 }
268 
269 
270 
271 
272 
273 void cProtocol_1_9_0::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item)
274 {
275  ASSERT(m_State == 3); // In game mode?
276 
277  cPacketizer Pkt(*this, pktEntityEquipment);
278  Pkt.WriteVarInt32(a_Entity.GetUniqueID());
279  // Needs to be adjusted due to the insertion of offhand at slot 1
280  if (a_SlotNum > 0)
281  {
282  a_SlotNum++;
283  }
284  Pkt.WriteVarInt32(static_cast<UInt32>(a_SlotNum));
285  WriteItem(Pkt, a_Item);
286 }
287 
288 
289 
290 
291 
293 {
294  ASSERT(m_State == 3); // In game mode?
295 
296  cPacketizer Pkt(*this, pktEntityMeta);
297  Pkt.WriteVarInt32(a_Entity.GetUniqueID());
298  WriteEntityMetadata(Pkt, a_Entity);
299  Pkt.WriteBEUInt8(0xff); // The termination byte
300 }
301 
302 
303 
304 
305 
307 {
308  ASSERT(m_State == 3); // In game mode?
309 
310  const auto Delta = (a_Entity.GetPosition() * 32 * 128).Floor() - (a_Entity.GetLastSentPosition() * 32 * 128).Floor();
311 
312  // Ensure that the delta has enough precision and is within range of a BEInt16:
313  if (
314  Delta.HasNonZeroLength() &&
318  )
319  {
320  const auto Move = static_cast<Vector3<Int16>>(Delta);
321 
322  // Difference within limitations, use a relative move packet
323  if (a_Entity.IsOrientationDirty())
324  {
325  cPacketizer Pkt(*this, pktEntityRelMoveLook);
326  Pkt.WriteVarInt32(a_Entity.GetUniqueID());
327  Pkt.WriteBEInt16(Move.x);
328  Pkt.WriteBEInt16(Move.y);
329  Pkt.WriteBEInt16(Move.z);
330  Pkt.WriteByteAngle(a_Entity.GetYaw());
331  Pkt.WriteByteAngle(a_Entity.GetPitch());
332  Pkt.WriteBool(a_Entity.IsOnGround());
333  }
334  else
335  {
336  cPacketizer Pkt(*this, pktEntityRelMove);
337  Pkt.WriteVarInt32(a_Entity.GetUniqueID());
338  Pkt.WriteBEInt16(Move.x);
339  Pkt.WriteBEInt16(Move.y);
340  Pkt.WriteBEInt16(Move.z);
341  Pkt.WriteBool(a_Entity.IsOnGround());
342  }
343 
344  return;
345  }
346 
347  // Too big or small a movement, do a teleport.
348 
349  cPacketizer Pkt(*this, pktTeleportEntity);
350  Pkt.WriteVarInt32(a_Entity.GetUniqueID());
351  Pkt.WriteBEDouble(a_Entity.GetPosX());
352  Pkt.WriteBEDouble(a_Entity.GetPosY());
353  Pkt.WriteBEDouble(a_Entity.GetPosZ());
354  Pkt.WriteByteAngle(a_Entity.GetYaw());
355  Pkt.WriteByteAngle(a_Entity.GetPitch());
356  Pkt.WriteBool(a_Entity.IsOnGround());
357 }
358 
359 
360 
361 
362 
364 {
365  ASSERT(m_State == 3); // In game mode?
366 
368  Pkt.WriteVarInt32(a_ExpOrb.GetUniqueID());
369  Pkt.WriteBEDouble(a_ExpOrb.GetPosX());
370  Pkt.WriteBEDouble(a_ExpOrb.GetPosY());
371  Pkt.WriteBEDouble(a_ExpOrb.GetPosZ());
372  Pkt.WriteBEInt16(static_cast<Int16>(a_ExpOrb.GetReward()));
373 }
374 
375 
376 
377 
378 
380 {
381  // Drop the packet if the protocol is not in the Game state yet (caused a client crash):
382  if (m_State != 3)
383  {
384  LOG("Trying to send a KeepAlive packet to a player who's not yet fully logged in (%d). The protocol class prevented the packet.", m_State);
385  return;
386  }
387 
388  cPacketizer Pkt(*this, pktKeepAlive);
389  Pkt.WriteVarInt32(a_PingID);
390 }
391 
392 
393 
394 
395 
396 void cProtocol_1_9_0::SendLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo)
397 {
398  ASSERT(m_State == 3); // In game mode?
399  cPacketizer Pkt(*this, pktLeashEntity);
400  Pkt.WriteBEUInt32(a_Entity.GetUniqueID());
401  Pkt.WriteBEUInt32(a_EntityLeashedTo.GetUniqueID());
402 }
403 
404 
405 
406 
407 
409 {
410  ASSERT(m_State == 3); // In game mode?
411  cPacketizer Pkt(*this, pktLeashEntity);
412  Pkt.WriteBEUInt32(a_Entity.GetUniqueID());
413  Pkt.WriteBEInt32(-1); // Unleash a_Entity
414 }
415 
416 
417 
418 
419 
421 {
422  ASSERT(m_State == 3); // In game mode?
423  double PosX = a_Painting.GetPosX();
424  double PosY = a_Painting.GetPosY();
425  double PosZ = a_Painting.GetPosZ();
426 
427  cPacketizer Pkt(*this, pktSpawnPainting);
428  Pkt.WriteVarInt32(a_Painting.GetUniqueID());
429  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
430  Pkt.WriteBEUInt64(0);
431  Pkt.WriteBEUInt64(a_Painting.GetUniqueID());
432  Pkt.WriteString(a_Painting.GetName());
433  Pkt.WriteXYZPosition64(static_cast<Int32>(PosX), static_cast<Int32>(PosY), static_cast<Int32>(PosZ));
434  Pkt.WriteBEInt8(static_cast<Int8>(a_Painting.GetProtocolFacing()));
435 }
436 
437 
438 
439 
440 
441 void cProtocol_1_9_0::SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY)
442 {
443  ASSERT(m_State == 3); // In game mode?
444 
445  cPacketizer Pkt(*this, pktMapData);
446  Pkt.WriteVarInt32(a_Map.GetID());
447  Pkt.WriteBEUInt8(static_cast<UInt8>(a_Map.GetScale()));
448 
449  Pkt.WriteBool(true);
450  Pkt.WriteVarInt32(static_cast<UInt32>(a_Map.GetDecorators().size()));
451  for (const auto & Decorator : a_Map.GetDecorators())
452  {
453  Pkt.WriteBEUInt8(static_cast<Byte>((static_cast<Int32>(Decorator.GetType()) << 4) | (Decorator.GetRot() & 0xF)));
454  Pkt.WriteBEUInt8(static_cast<UInt8>(Decorator.GetPixelX()));
455  Pkt.WriteBEUInt8(static_cast<UInt8>(Decorator.GetPixelZ()));
456  }
457 
458  Pkt.WriteBEUInt8(128);
459  Pkt.WriteBEUInt8(128);
460  Pkt.WriteBEUInt8(static_cast<UInt8>(a_DataStartX));
461  Pkt.WriteBEUInt8(static_cast<UInt8>(a_DataStartY));
462  Pkt.WriteVarInt32(static_cast<UInt32>(a_Map.GetData().size()));
463  for (auto itr = a_Map.GetData().cbegin(); itr != a_Map.GetData().cend(); ++itr)
464  {
465  Pkt.WriteBEUInt8(*itr);
466  }
467 }
468 
469 
470 
471 
472 
473 void cProtocol_1_9_0::SendPlayerMoveLook (const Vector3d a_Pos, const float a_Yaw, const float a_Pitch, const bool a_IsRelative)
474 {
475  ASSERT(m_State == 3); // In game mode?
476 
477  cPacketizer Pkt(*this, pktPlayerMoveLook);
478  Pkt.WriteBEDouble(a_Pos.x);
479  Pkt.WriteBEDouble(a_Pos.y);
480  Pkt.WriteBEDouble(a_Pos.z);
481  Pkt.WriteBEFloat(a_Yaw);
482  Pkt.WriteBEFloat(a_Pitch);
483 
484  if (a_IsRelative)
485  {
486  // Set all bits to 1 - makes everything relative
487  Pkt.WriteBEUInt8(static_cast<UInt8>(-1));
488  }
489  else
490  {
491  // Set all bits to 0 - make everything absolute
492  Pkt.WriteBEUInt8(0);
493  }
494 
496 
497  // This teleport ID hasn't been confirmed yet
498  m_IsTeleportIdConfirmed = false;
499 }
500 
501 
502 
503 
504 
506 {
507  cPlayer * Player = m_Client->GetPlayer();
508  SendPlayerMoveLook(Player->GetPosition(), static_cast<float>(Player->GetYaw()), static_cast<float>(Player->GetPitch()), false);
509 }
510 
511 
512 
513 
514 
516 {
517  const cPlayer & Player = *m_Client->GetPlayer();
518 
519  cPacketizer Pkt(*this, pktEntityStatus);
520  Pkt.WriteBEUInt32(Player.GetUniqueID());
521  Pkt.WriteBEInt8([&Player]() -> signed char
522  {
523  if (Player.HasPermission("core.stop") || Player.HasPermission("core.reload") || Player.HasPermission("core.save-all"))
524  {
525  return 28;
526  }
527 
528  if (Player.HasPermission("core.ban") || Player.HasPermission("core.deop") || Player.HasPermission("core.kick") || Player.HasPermission("core.op"))
529  {
530  return 27;
531  }
532 
533  if (Player.HasPermission("cuberite.comandblock.set") || Player.HasPermission("core.clear") || Player.HasPermission("core.difficulty") || Player.HasPermission("core.effect") || Player.HasPermission("core.gamemode") || Player.HasPermission("core.tp") || Player.HasPermission("core.give"))
534  {
535  return 26;
536  }
537 
538  if (Player.HasPermission("core.spawnprotect.bypass"))
539  {
540  return 25;
541  }
542 
543  return 24;
544  }());
545 }
546 
547 
548 
549 
550 
552 {
553  // Called to spawn another player for the client
554  cPacketizer Pkt(*this, pktSpawnOtherPlayer);
555  Pkt.WriteVarInt32(a_Player.GetUniqueID());
556  Pkt.WriteUUID(a_Player.GetUUID());
557  Vector3d LastSentPos = a_Player.GetLastSentPosition();
558  Pkt.WriteBEDouble(LastSentPos.x);
559  Pkt.WriteBEDouble(LastSentPos.y + 0.001); // The "+ 0.001" is there because otherwise the player falls through the block they were standing on.
560  Pkt.WriteBEDouble(LastSentPos.z);
561  Pkt.WriteByteAngle(a_Player.GetYaw());
562  Pkt.WriteByteAngle(a_Player.GetPitch());
563  WriteEntityMetadata(Pkt, a_Player);
564  Pkt.WriteBEUInt8(0xff); // Metadata: end
565 }
566 
567 
568 
569 
570 
571 void cProtocol_1_9_0::SendSoundEffect(const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch)
572 {
573  ASSERT(m_State == 3); // In game mode?
574 
575  cPacketizer Pkt(*this, pktSoundEffect);
576  Pkt.WriteString(a_SoundName);
577  Pkt.WriteVarInt32(0); // Master sound category (may want to be changed to a parameter later)
578  Pkt.WriteBEInt32(static_cast<Int32>(a_Origin.x * 8.0));
579  Pkt.WriteBEInt32(static_cast<Int32>(a_Origin.y * 8.0));
580  Pkt.WriteBEInt32(static_cast<Int32>(a_Origin.z * 8.0));
581  Pkt.WriteBEFloat(a_Volume);
582  Pkt.WriteBEUInt8(static_cast<Byte>(a_Pitch * 63));
583 }
584 
585 
586 
587 
588 
590 {
591  ASSERT(m_State == 3); // In game mode?
592 
593  const auto MobType = GetProtocolMobType(a_Mob.GetMobType());
594 
595  // If the type is not valid in this protocol bail out:
596  if (MobType == 0)
597  {
598  return;
599  }
600 
601  cPacketizer Pkt(*this, pktSpawnMob);
602  Pkt.WriteVarInt32(a_Mob.GetUniqueID());
603  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
604  Pkt.WriteBEUInt64(0);
605  Pkt.WriteBEUInt64(a_Mob.GetUniqueID());
606  Pkt.WriteBEUInt8(static_cast<Byte>(MobType));
607  Vector3d LastSentPos = a_Mob.GetLastSentPosition();
608  Pkt.WriteBEDouble(LastSentPos.x);
609  Pkt.WriteBEDouble(LastSentPos.y);
610  Pkt.WriteBEDouble(LastSentPos.z);
611  Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); // Doesn't seem to be used
612  Pkt.WriteByteAngle(a_Mob.GetPitch());
613  Pkt.WriteByteAngle(a_Mob.GetYaw());
614  Pkt.WriteBEInt16(static_cast<Int16>(a_Mob.GetSpeedX() * 400));
615  Pkt.WriteBEInt16(static_cast<Int16>(a_Mob.GetSpeedY() * 400));
616  Pkt.WriteBEInt16(static_cast<Int16>(a_Mob.GetSpeedZ() * 400));
617  WriteEntityMetadata(Pkt, a_Mob);
618  Pkt.WriteBEUInt8(0xff); // Metadata terminator
619 }
620 
621 
622 
623 
624 
626 {
627  ASSERT(m_State == 3); // In game mode?
628 
629  cPacketizer Pkt(*this, pktSpawnGlobalEntity);
630  Pkt.WriteVarInt32(0); // EntityID = 0, always
631  Pkt.WriteBEUInt8(1); // Type = Thunderbolt
632  Pkt.WriteBEDouble(a_Origin.x);
633  Pkt.WriteBEDouble(a_Origin.y);
634  Pkt.WriteBEDouble(a_Origin.z);
635 }
636 
637 
638 
639 
640 
641 void cProtocol_1_9_0::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
642 {
643  ASSERT(m_State == 3); // In game mode?
644 
645  cPacketizer Pkt(*this, pktUnloadChunk);
646  Pkt.WriteBEInt32(a_ChunkX);
647  Pkt.WriteBEInt32(a_ChunkZ);
648 }
649 
650 
651 
652 
653 
655 {
656  switch (a_Packet)
657  {
658  case pktAttachEntity: return 0x40;
659  case pktBlockAction: return 0x0a;
660  case pktBlockBreakAnim: return 0x08;
661  case pktBlockChange: return 0x0b;
662  case pktBlockChanges: return 0x10;
663  case pktBossBar: return 0x0c;
664  case pktCameraSetTo: return 0x36;
665  case pktChatRaw: return 0x0f;
666  case pktCollectEntity: return 0x49;
667  case pktDestroyEntity: return 0x30;
668  case pktDifficulty: return 0x0d;
669  case pktDisconnectDuringGame: return 0x1a;
670  case pktDisconnectDuringLogin: return 0x0;
671  case pktDisplayObjective: return 0x38;
672  case pktEditSign: return 0x2a;
673  case pktEncryptionRequest: return 0x01;
674  case pktEntityAnimation: return 0x06;
675  case pktEntityEffect: return 0x4c;
676  case pktEntityEquipment: return 0x3c;
677  case pktEntityHeadLook: return 0x34;
678  case pktEntityLook: return 0x27;
679  case pktEntityMeta: return 0x39;
680  case pktEntityProperties: return 0x4b;
681  case pktEntityRelMove: return 0x25;
682  case pktEntityRelMoveLook: return 0x26;
683  case pktEntityStatus: return 0x1b;
684  case pktEntityVelocity: return 0x3b;
685  case pktExperience: return 0x3d;
686  case pktExplosion: return 0x1c;
687  case pktGameMode: return 0x1e;
688  case pktHeldItemChange: return 0x37;
689  case pktInventorySlot: return 0x16;
690  case pktJoinGame: return 0x23;
691  case pktKeepAlive: return 0x1f;
692  case pktLeashEntity: return 0x3a;
693  case pktLoginSuccess: return 0x02;
694  case pktMapData: return 0x24;
695  case pktParticleEffect: return 0x22;
696  case pktPingResponse: return 0x01;
697  case pktPlayerAbilities: return 0x2b;
698  case pktPlayerList: return 0x2d;
699  case pktPlayerListHeaderFooter: return 0x48;
700  case pktPlayerMoveLook: return 0x2e;
701  case pktPluginMessage: return 0x18;
702  case pktRemoveEntityEffect: return 0x31;
703  case pktResourcePack: return 0x32;
704  case pktRespawn: return 0x33;
705  case pktScoreboardObjective: return 0x3f;
706  case pktSpawnExperienceOrb: return 0x01;
707  case pktSpawnGlobalEntity: return 0x02;
708  case pktSpawnObject: return 0x00;
709  case pktSpawnOtherPlayer: return 0x05;
710  case pktSpawnPainting: return 0x04;
711  case pktSpawnPosition: return 0x43;
712  case pktSoundEffect: return 0x19;
713  case pktSoundParticleEffect: return 0x21;
714  case pktSpawnMob: return 0x03;
715  case pktStartCompression: return 0x03;
716  case pktStatistics: return 0x07;
717  case pktStatusResponse: return 0x00;
718  case pktTabCompletionResults: return 0x0e;
719  case pktTeleportEntity: return 0x4a;
720  case pktTimeUpdate: return 0x44;
721  case pktTitle: return 0x45;
722  case pktUnloadChunk: return 0x1d;
723  case pktUpdateBlockEntity: return 0x09;
724  case pktUpdateHealth: return 0x3e;
725  case pktUpdateScore: return 0x42;
726  case pktUpdateSign: return 0x46;
727  case pktUseBed: return 0x2f;
728  case pktWeather: return 0x1e;
729  case pktWindowClose: return 0x12;
730  case pktWindowItems: return 0x14;
731  case pktWindowOpen: return 0x13;
732  case pktWindowProperty: return 0x15;
733 
734  // Unsupported packets
735  case pktUnlockRecipe:
736  {
737  break;
738  }
739 
740  default:
741  break;
742  }
743  UNREACHABLE("Unsupported outgoing packet type");
744 }
745 
746 
747 
748 
749 
750 unsigned char cProtocol_1_9_0::GetProtocolEntityAnimation(const EntityAnimation a_Animation) const
751 {
752  if (a_Animation == EntityAnimation::PlayerOffHandSwings)
753  {
754  return 3;
755  }
756 
757  return Super::GetProtocolEntityAnimation(a_Animation);
758 }
759 
760 
761 
762 
763 
764 signed char cProtocol_1_9_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const
765 {
766  switch (a_Animation)
767  {
768  case EntityAnimation::ArmorStandGetsHit: return 32;
769  case EntityAnimation::ArrowTipSparkles: return 0;
770  case EntityAnimation::PawnShieldBlocks: return 29;
771  case EntityAnimation::PawnShieldBreaks: return 30;
772  case EntityAnimation::PawnThornsPricks: return 33;
773  default: return Super::GetProtocolEntityStatus(a_Animation);
774  }
775 }
776 
777 
778 
779 
780 
782 {
783  switch (a_MobType)
784  {
785  case mtShulker: return 69;
786  default: return Super::GetProtocolMobType(a_MobType);
787  }
788 }
789 
790 
791 
792 
793 
795 {
796  return Version::v1_9_0;
797 }
798 
799 
800 
801 
802 
803 bool cProtocol_1_9_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
804 {
805  switch (m_State)
806  {
807  case State::Status:
808  {
809  switch (a_PacketType)
810  {
811  case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true;
812  case 0x01: HandlePacketStatusPing (a_ByteBuffer); return true;
813  }
814  break;
815  }
816 
817  case State::Login:
818  {
819  switch (a_PacketType)
820  {
821  case 0x00: HandlePacketLoginStart (a_ByteBuffer); return true;
822  case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true;
823  }
824  break;
825  }
826 
827  case State::Game:
828  {
829  switch (a_PacketType)
830  {
831  case 0x00: HandleConfirmTeleport (a_ByteBuffer); return true;
832  case 0x01: HandlePacketTabComplete (a_ByteBuffer); return true;
833  case 0x02: HandlePacketChatMessage (a_ByteBuffer); return true;
834  case 0x03: HandlePacketClientStatus (a_ByteBuffer); return true;
835  case 0x04: HandlePacketClientSettings (a_ByteBuffer); return true;
836  case 0x05: break; // Confirm transaction - not used in MCS
837  case 0x06: HandlePacketEnchantItem (a_ByteBuffer); return true;
838  case 0x07: HandlePacketWindowClick (a_ByteBuffer); return true;
839  case 0x08: HandlePacketWindowClose (a_ByteBuffer); return true;
840  case 0x09: HandlePacketPluginMessage (a_ByteBuffer); return true;
841  case 0x0a: HandlePacketUseEntity (a_ByteBuffer); return true;
842  case 0x0b: HandlePacketKeepAlive (a_ByteBuffer); return true;
843  case 0x0c: HandlePacketPlayerPos (a_ByteBuffer); return true;
844  case 0x0d: HandlePacketPlayerPosLook (a_ByteBuffer); return true;
845  case 0x0e: HandlePacketPlayerLook (a_ByteBuffer); return true;
846  case 0x0f: HandlePacketPlayer (a_ByteBuffer); return true;
847  case 0x10: HandlePacketVehicleMove (a_ByteBuffer); return true;
848  case 0x11: HandlePacketBoatSteer (a_ByteBuffer); return true;
849  case 0x12: HandlePacketPlayerAbilities (a_ByteBuffer); return true;
850  case 0x13: HandlePacketBlockDig (a_ByteBuffer); return true;
851  case 0x14: HandlePacketEntityAction (a_ByteBuffer); return true;
852  case 0x15: HandlePacketSteerVehicle (a_ByteBuffer); return true;
853  case 0x16: HandlePacketResourcePackStatus (a_ByteBuffer); return true;
854  case 0x17: HandlePacketSlotSelect (a_ByteBuffer); return true;
855  case 0x18: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
856  case 0x19: HandlePacketUpdateSign (a_ByteBuffer); return true;
857  case 0x1a: HandlePacketAnimation (a_ByteBuffer); return true;
858  case 0x1b: HandlePacketSpectate (a_ByteBuffer); return true;
859  case 0x1c: HandlePacketBlockPlace (a_ByteBuffer); return true;
860  case 0x1d: HandlePacketUseItem (a_ByteBuffer); return true;
861  }
862  break;
863  }
864  } // switch (m_State)
865 
866  // Unknown packet type, report to the ClientHandle:
867  m_Client->PacketUnknown(a_PacketType);
868  return false;
869 }
870 
871 
872 
873 
874 
876 {
877  HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand);
878 
879  m_Client->HandleAnimation(Hand == MAIN_HAND); // Packet exists solely for arm-swing notification (main and off-hand).
880 }
881 
882 
883 
884 
885 
887 {
888  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status);
889 
890  Vector3i Position;
891  if (!a_ByteBuffer.ReadXYZPosition64(Position))
892  {
893  return;
894  }
895 
896  HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Face);
898 }
899 
900 
901 
902 
903 
905 {
906  Vector3i Position;
907  if (!a_ByteBuffer.ReadXYZPosition64(Position))
908  {
909  return;
910  }
911 
912  HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Face);
913  HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand);
914  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorX);
915  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorY);
916  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorZ);
917 
918  m_Client->HandleRightClick(Position, FaceIntToBlockFace(Face), {CursorX, CursorY, CursorZ}, Hand == MAIN_HAND);
919 }
920 
921 
922 
923 
924 
926 {
927  HANDLE_READ(a_ByteBuffer, ReadBool, bool, RightPaddle);
928  HANDLE_READ(a_ByteBuffer, ReadBool, bool, LeftPaddle);
929 
930  // Get the players vehicle
931  cPlayer * Player = m_Client->GetPlayer();
932  cEntity * Vehicle = Player->GetAttached();
933 
934  if (Vehicle)
935  {
936  if (Vehicle->GetEntityType() == cEntity::etBoat)
937  {
938  auto * Boat = static_cast<cBoat *>(Vehicle);
939  Boat->UpdatePaddles(RightPaddle, LeftPaddle);
940  }
941  }
942 }
943 
944 
945 
946 
947 
949 {
950  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Locale);
951  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ViewDistance);
952  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ChatFlags);
953  HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors);
954  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinParts);
955  HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, MainHand);
956 
957  m_Client->SetLocale(Locale);
958  m_Client->SetViewDistance(ViewDistance);
959  m_Client->GetPlayer()->SetSkinParts(SkinParts);
960  m_Client->GetPlayer()->SetLeftHanded(MainHand == LEFT_HAND);
961  // TODO: Handle chat flags and chat colors
962 }
963 
964 
965 
966 
967 
969 {
970  HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, TeleportID);
971 
972  // Can we stop throwing away incoming player position packets?
973  if (TeleportID == m_OutstandingTeleportId)
974  {
976  }
977 }
978 
979 
980 
981 
982 
984 {
985  HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, PlayerID);
986  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Action);
987  HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, JumpBoost);
988 
989  if (PlayerID != m_Client->GetPlayer()->GetUniqueID())
990  {
991  LOGD("Player \"%s\" attempted to action another entity - hacked client?", m_Client->GetUsername().c_str());
992  return;
993  }
994 
995  switch (Action)
996  {
997  case 0: return m_Client->HandleCrouch(true);
998  case 1: return m_Client->HandleCrouch(false);
999  case 2: return m_Client->HandleLeaveBed();
1000  case 3: return m_Client->HandleSprint(true);
1001  case 4: return m_Client->HandleSprint(false);
1002  case 7: return m_Client->HandleOpenHorseInventory();
1003  case 8: return m_Client->HandleStartElytraFlight();
1004  }
1005 }
1006 
1007 
1008 
1009 
1010 
1012 {
1013  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX);
1014  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY);
1015  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ);
1016  HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround);
1017 
1019  {
1020  m_Client->HandlePlayerMove({PosX, PosY, PosZ}, IsOnGround);
1021  }
1022 }
1023 
1024 
1025 
1026 
1027 
1029 {
1030  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX);
1031  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY);
1032  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ);
1033  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw);
1034  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch);
1035  HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround);
1036 
1038  {
1039  m_Client->HandlePlayerMoveLook({PosX, PosY, PosZ}, Yaw, Pitch, IsOnGround);
1040  }
1041 }
1042 
1043 
1044 
1045 
1046 
1048 {
1049  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Sideways);
1050  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Forward);
1051  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Flags);
1052 
1053  if ((Flags & 0x2) != 0)
1054  {
1056  }
1057  else if ((Flags & 0x1) != 0)
1058  {
1059  // TODO: Handle vehicle jump (for animals)
1060  }
1061  else
1062  {
1063  m_Client->HandleSteerVehicle(Forward, Sideways);
1064  }
1065 }
1066 
1067 
1068 
1069 
1070 
1072 {
1073  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Text);
1074  HANDLE_READ(a_ByteBuffer, ReadBool, bool, AssumeCommand);
1075  HANDLE_READ(a_ByteBuffer, ReadBool, bool, HasPosition);
1076 
1077  if (HasPosition)
1078  {
1079  HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Position);
1080  }
1081 
1083 }
1084 
1085 
1086 
1087 
1088 
1090 {
1091  Vector3i Position;
1092  if (!a_ByteBuffer.ReadXYZPosition64(Position))
1093  {
1094  return;
1095  }
1096 
1097  AString Lines[4];
1098  for (int i = 0; i < 4; i++)
1099  {
1100  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line);
1101  Lines[i] = Line;
1102  }
1103 
1104  m_Client->HandleUpdateSign(Position, Lines[0], Lines[1], Lines[2], Lines[3]);
1105 }
1106 
1107 
1108 
1109 
1110 
1112 {
1113  HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, EntityID);
1114  HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Type);
1115 
1116  switch (Type)
1117  {
1118  case 0:
1119  {
1120  HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Hand);
1121 
1122  if (Hand == MAIN_HAND) // TODO: implement handling of off-hand actions; ignore them for now to avoid processing actions twice
1123  {
1124  m_Client->HandleUseEntity(EntityID, false);
1125  }
1126  break;
1127  }
1128  case 1:
1129  {
1130  m_Client->HandleUseEntity(EntityID, true);
1131  break;
1132  }
1133  case 2:
1134  {
1135  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetX);
1136  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetY);
1137  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetZ);
1138  HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Hand);
1139 
1140  // TODO: Do anything
1141  break;
1142  }
1143  default:
1144  {
1145  ASSERT(!"Unhandled use entity type!");
1146  return;
1147  }
1148  }
1149 }
1150 
1151 
1152 
1153 
1154 
1156 {
1157  HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand);
1158 
1159  m_Client->HandleUseItem(Hand == MAIN_HAND);
1160 }
1161 
1162 
1163 
1164 
1165 
1167 {
1168  // This handles updating the vehicles location server side
1169  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, xPos);
1170  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, yPos);
1171  HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, zPos);
1172  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, yaw);
1173  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, pitch);
1174 
1175  // Get the players vehicle
1176  cEntity * Vehicle = m_Client->GetPlayer()->GetAttached();
1177 
1178  if (Vehicle)
1179  {
1180  Vehicle->SetPosX(xPos);
1181  Vehicle->SetPosY(yPos);
1182  Vehicle->SetPosZ(zPos);
1183  Vehicle->SetYaw(yaw);
1184  Vehicle->SetPitch(pitch);
1185  }
1186 }
1187 
1188 
1189 
1190 
1191 
1193 {
1194  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID);
1195  HANDLE_READ(a_ByteBuffer, ReadBEInt16, Int16, SlotNum);
1196  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Button);
1197  HANDLE_READ(a_ByteBuffer, ReadBEUInt16, UInt16, TransactionID);
1198  HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Mode);
1199  cItem Item;
1200  ReadItem(a_ByteBuffer, Item);
1201 
1203  static const Int16 SLOT_NUM_OUTSIDE = -999;
1204 
1205  // Convert Button, Mode, SlotNum and HeldItem into eClickAction:
1206  eClickAction Action;
1207  switch ((Mode << 8) | Button)
1208  {
1209  case 0x0000: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caLeftClick : caLeftClickOutside; break;
1210  case 0x0001: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caRightClick : caRightClickOutside; break;
1211  case 0x0100: Action = caShiftLeftClick; break;
1212  case 0x0101: Action = caShiftRightClick; break;
1213  case 0x0200: Action = caNumber1; break;
1214  case 0x0201: Action = caNumber2; break;
1215  case 0x0202: Action = caNumber3; break;
1216  case 0x0203: Action = caNumber4; break;
1217  case 0x0204: Action = caNumber5; break;
1218  case 0x0205: Action = caNumber6; break;
1219  case 0x0206: Action = caNumber7; break;
1220  case 0x0207: Action = caNumber8; break;
1221  case 0x0208: Action = caNumber9; break;
1222  case 0x0302: Action = caMiddleClick; break;
1223  case 0x0400: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftClickOutsideHoldNothing : caDropKey; break;
1224  case 0x0401: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightClickOutsideHoldNothing : caCtrlDropKey; break;
1225  case 0x0500: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftPaintBegin : caUnknown; break;
1226  case 0x0501: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caLeftPaintProgress : caUnknown; break;
1227  case 0x0502: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftPaintEnd : caUnknown; break;
1228  case 0x0504: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightPaintBegin : caUnknown; break;
1229  case 0x0505: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caRightPaintProgress : caUnknown; break;
1230  case 0x0506: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightPaintEnd : caUnknown; break;
1231  case 0x0508: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caMiddlePaintBegin : caUnknown; break;
1232  case 0x0509: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caMiddlePaintProgress : caUnknown; break;
1233  case 0x050a: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caMiddlePaintEnd : caUnknown; break;
1234  case 0x0600: Action = caDblClick; break;
1235  default:
1236  {
1237  LOGWARNING("Unhandled window click mode / button combination: %d (0x%x)", (Mode << 8) | Button, (Mode << 8) | Button);
1238  Action = caUnknown;
1239  break;
1240  }
1241  }
1242 
1243  m_Client->HandleWindowClick(WindowID, SlotNum, Action, Item);
1244 }
1245 
1246 
1247 
1248 
1249 
1250 void cProtocol_1_9_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, std::string_view a_Channel)
1251 {
1252  if (a_Channel == "AutoCmd")
1253  {
1254  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockX);
1255  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockY);
1256  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockZ);
1257  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Command);
1258  HANDLE_READ(a_ByteBuffer, ReadBool, bool, TrackOutput);
1259  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Mode);
1260  HANDLE_READ(a_ByteBuffer, ReadBool, bool, Conditional);
1261  HANDLE_READ(a_ByteBuffer, ReadBool, bool, Automatic);
1262 
1263  m_Client->HandleCommandBlockBlockChange({BlockX, BlockY, BlockZ}, Command);
1264  }
1265  else if (a_Channel == "PickItem")
1266  {
1267  HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, InventorySlotIndex);
1268  }
1269  else if (a_Channel == "Struct")
1270  {
1271  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockX);
1272  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockY);
1273  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockZ);
1274  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Action);
1275  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Mode);
1276  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Name);
1277  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, OffsetX);
1278  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, OffsetY);
1279  HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, OffsetZ);
1280  HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, SizeX);
1281  HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, SizeY);
1282  HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, SizeZ);
1283  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Mirror);
1284  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Rotation);
1285  HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Metadata);
1286  HANDLE_READ(a_ByteBuffer, ReadBool, bool, IgnoreEntities);
1287  HANDLE_READ(a_ByteBuffer, ReadBool, bool, ShowAir);
1288  HANDLE_READ(a_ByteBuffer, ReadBool, bool, ShowBoundingBox);
1289  HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Integrity);
1290  HANDLE_READ(a_ByteBuffer, ReadVarInt64, UInt64, Seed);
1291  }
1292  else
1293  {
1294  Super::HandleVanillaPluginMessage(a_ByteBuffer, a_Channel);
1295  }
1296 }
1297 
1298 
1299 
1300 
1301 
1303 {
1304  // Parse into NBT:
1305  cParsedNBT NBT(a_Metadata);
1306  if (!NBT.IsValid())
1307  {
1308  AString HexDump;
1309  CreateHexDump(HexDump, a_Metadata.data(), std::max<size_t>(a_Metadata.size(), 1024), 16);
1310  LOGWARNING("Cannot parse NBT item metadata: %s at (%zu / %zu bytes)\n%s",
1311  NBT.GetErrorCode().message().c_str(), NBT.GetErrorPos(), a_Metadata.size(), HexDump.c_str()
1312  );
1313  return;
1314  }
1315 
1316  // Load enchantments and custom display names from the NBT data:
1317  for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag))
1318  {
1319  AString TagName = NBT.GetName(tag);
1320  switch (NBT.GetType(tag))
1321  {
1322  case TAG_List:
1323  {
1324  if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
1325  {
1327  }
1328  break;
1329  }
1330  case TAG_Compound:
1331  {
1332  if (TagName == "display") // Custom name and lore tag
1333  {
1334  for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag))
1335  {
1336  if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag
1337  {
1338  a_Item.m_CustomName = NBT.GetString(displaytag);
1339  }
1340  else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag
1341  {
1342  a_Item.m_LoreTable.clear();
1343  for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
1344  {
1345  a_Item.m_LoreTable.push_back(NBT.GetString(loretag));
1346  }
1347  }
1348  else if ((NBT.GetType(displaytag) == TAG_Int) && (NBT.GetName(displaytag) == "color"))
1349  {
1350  a_Item.m_ItemColor.m_Color = static_cast<unsigned int>(NBT.GetInt(displaytag));
1351  }
1352  }
1353  }
1354  else if ((TagName == "Fireworks") || (TagName == "Explosion"))
1355  {
1356  cFireworkItem::ParseFromNBT(a_Item.m_FireworkItem, NBT, tag, static_cast<ENUM_ITEM_TYPE>(a_Item.m_ItemType));
1357  }
1358  else if (TagName == "EntityTag")
1359  {
1360  for (int entitytag = NBT.GetFirstChild(tag); entitytag >= 0; entitytag = NBT.GetNextSibling(entitytag))
1361  {
1362  if ((NBT.GetType(entitytag) == TAG_String) && (NBT.GetName(entitytag) == "id"))
1363  {
1364  AString NBTName = NBT.GetString(entitytag);
1365  ReplaceString(NBTName, "minecraft:", "");
1366  eMonsterType MonsterType = cMonster::StringToMobType(NBTName);
1367  a_Item.m_ItemDamage = static_cast<short>(GetProtocolMobType(MonsterType));
1368 
1369  }
1370  }
1371  }
1372  break;
1373  }
1374  case TAG_Int:
1375  {
1376  if (TagName == "RepairCost")
1377  {
1378  a_Item.m_RepairCost = NBT.GetInt(tag);
1379  }
1380  break;
1381  }
1382  case TAG_String:
1383  {
1384  if (TagName == "Potion")
1385  {
1386  AString PotionEffect = NBT.GetString(tag);
1387  if (PotionEffect.find("minecraft:") == AString::npos)
1388  {
1389  LOGD("Unknown or missing domain on potion effect name %s!", PotionEffect.c_str());
1390  continue;
1391  }
1392 
1393  if (PotionEffect.find("empty") != AString::npos)
1394  {
1395  a_Item.m_ItemDamage = 0;
1396  }
1397  else if (PotionEffect.find("mundane") != AString::npos)
1398  {
1399  a_Item.m_ItemDamage = 64;
1400  }
1401  else if (PotionEffect.find("thick") != AString::npos)
1402  {
1403  a_Item.m_ItemDamage = 32;
1404  }
1405  else if (PotionEffect.find("awkward") != AString::npos)
1406  {
1407  a_Item.m_ItemDamage = 16;
1408  }
1409  else if (PotionEffect.find("regeneration") != AString::npos)
1410  {
1411  a_Item.m_ItemDamage = 1;
1412  }
1413  else if (PotionEffect.find("swiftness") != AString::npos)
1414  {
1415  a_Item.m_ItemDamage = 2;
1416  }
1417  else if (PotionEffect.find("fire_resistance") != AString::npos)
1418  {
1419  a_Item.m_ItemDamage = 3;
1420  }
1421  else if (PotionEffect.find("poison") != AString::npos)
1422  {
1423  a_Item.m_ItemDamage = 4;
1424  }
1425  else if (PotionEffect.find("healing") != AString::npos)
1426  {
1427  a_Item.m_ItemDamage = 5;
1428  }
1429  else if (PotionEffect.find("night_vision") != AString::npos)
1430  {
1431  a_Item.m_ItemDamage = 6;
1432  }
1433  else if (PotionEffect.find("weakness") != AString::npos)
1434  {
1435  a_Item.m_ItemDamage = 8;
1436  }
1437  else if (PotionEffect.find("strength") != AString::npos)
1438  {
1439  a_Item.m_ItemDamage = 9;
1440  }
1441  else if (PotionEffect.find("slowness") != AString::npos)
1442  {
1443  a_Item.m_ItemDamage = 10;
1444  }
1445  else if (PotionEffect.find("leaping") != AString::npos)
1446  {
1447  a_Item.m_ItemDamage = 11;
1448  }
1449  else if (PotionEffect.find("harming") != AString::npos)
1450  {
1451  a_Item.m_ItemDamage = 12;
1452  }
1453  else if (PotionEffect.find("water_breathing") != AString::npos)
1454  {
1455  a_Item.m_ItemDamage = 13;
1456  }
1457  else if (PotionEffect.find("invisibility") != AString::npos)
1458  {
1459  a_Item.m_ItemDamage = 14;
1460  }
1461  else if (PotionEffect.find("water") != AString::npos)
1462  {
1463  a_Item.m_ItemDamage = 0;
1464  // Water bottles shouldn't have other bits set on them; exit early.
1465  continue;
1466  }
1467  else
1468  {
1469  // Note: luck potions are not handled and will reach this location
1470  LOGD("Unknown potion type for effect name %s!", PotionEffect.c_str());
1471  continue;
1472  }
1473 
1474  if (PotionEffect.find("strong") != AString::npos)
1475  {
1476  a_Item.m_ItemDamage |= 0x20;
1477  }
1478  if (PotionEffect.find("long") != AString::npos)
1479  {
1480  a_Item.m_ItemDamage |= 0x40;
1481  }
1482 
1483  // Ugly special case with the changed splash potion ID in 1.9
1484  if ((a_Item.m_ItemType == 438) || (a_Item.m_ItemType == 441))
1485  {
1486  // Splash or lingering potions - change the ID to the normal one and mark as splash potions
1487  a_Item.m_ItemType = E_ITEM_POTION;
1488  a_Item.m_ItemDamage |= 0x4000; // Is splash potion
1489  }
1490  else
1491  {
1492  a_Item.m_ItemDamage |= 0x2000; // Is drinkable
1493  }
1494  }
1495  break;
1496  }
1497  default: LOGD("Unimplemented NBT data when parsing!"); break;
1498  }
1499  }
1500 }
1501 
1502 
1503 
1504 
1505 
1506 void cProtocol_1_9_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData)
1507 {
1508  ASSERT(m_State == 3); // In game mode?
1509 
1510  cPacketizer Pkt(*this, pktSpawnObject);
1511  Pkt.WriteVarInt32(a_Entity.GetUniqueID());
1512 
1513  // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
1514  Pkt.WriteBEUInt64(0);
1515  Pkt.WriteBEUInt64(a_Entity.GetUniqueID());
1516 
1517  Pkt.WriteBEUInt8(a_ObjectType);
1518  Pkt.WriteBEDouble(a_Entity.GetPosX());
1519  Pkt.WriteBEDouble(a_Entity.GetPosY());
1520  Pkt.WriteBEDouble(a_Entity.GetPosZ());
1521  Pkt.WriteByteAngle(a_Entity.GetPitch());
1522  Pkt.WriteByteAngle(a_Entity.GetYaw());
1523  Pkt.WriteBEInt32(a_ObjectData);
1524  Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedX() * 400));
1525  Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedY() * 400));
1526  Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedZ() * 400));
1527 }
1528 
1529 
1530 
1531 
1532 
1533 void cProtocol_1_9_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const
1534 {
1535  if (a_BlockEntity.GetBlockType() == E_BLOCK_MOB_SPAWNER)
1536  {
1537  auto & MobSpawnerEntity = static_cast<const cMobSpawnerEntity &>(a_BlockEntity);
1538  a_Writer.AddInt("x", a_BlockEntity.GetPosX());
1539  a_Writer.AddInt("y", a_BlockEntity.GetPosY());
1540  a_Writer.AddInt("z", a_BlockEntity.GetPosZ());
1541  a_Writer.BeginCompound("SpawnData"); // New: SpawnData compound
1542  a_Writer.AddString("id", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity()));
1543  a_Writer.EndCompound();
1544  a_Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay());
1545  }
1546  else
1547  {
1548  Super::WriteBlockEntity(a_Writer, a_BlockEntity);
1549  }
1550 }
1551 
1552 
1553 
1554 
1555 
1556 void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const
1557 {
1558  // Common metadata:
1559  Int8 Flags = 0;
1560  if (a_Entity.IsOnFire())
1561  {
1562  Flags |= 0x01;
1563  }
1564  if (a_Entity.IsCrouched())
1565  {
1566  Flags |= 0x02;
1567  }
1568  if (a_Entity.IsSprinting())
1569  {
1570  Flags |= 0x08;
1571  }
1572  if (a_Entity.IsRclking())
1573  {
1574  Flags |= 0x10;
1575  }
1576  if (a_Entity.IsInvisible())
1577  {
1578  Flags |= 0x20;
1579  }
1580  if (a_Entity.IsElytraFlying())
1581  {
1582  Flags |= 0x80;
1583  }
1584  a_Pkt.WriteBEUInt8(0); // Index 0
1585  a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type
1586  a_Pkt.WriteBEInt8(Flags);
1587 
1588  switch (a_Entity.GetEntityType())
1589  {
1590  case cEntity::etPlayer:
1591  {
1592  auto & Player = static_cast<const cPlayer &>(a_Entity);
1593 
1594  // TODO Set player custom name to their name.
1595  // Then it's possible to move the custom name of mobs to the entities
1596  // and to remove the "special" player custom name.
1597  a_Pkt.WriteBEUInt8(2); // Index 2: Custom name
1599  a_Pkt.WriteString(Player.GetName());
1600 
1601  a_Pkt.WriteBEUInt8(6); // Index 6: Health
1603  a_Pkt.WriteBEFloat(static_cast<float>(Player.GetHealth()));
1604 
1605  a_Pkt.WriteBEUInt8(12);
1607  a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetSkinParts()));
1608 
1609  a_Pkt.WriteBEUInt8(13);
1611  a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1);
1612  break;
1613  }
1614  case cEntity::etPickup:
1615  {
1616  a_Pkt.WriteBEUInt8(5); // Index 5: Item
1618  WriteItem(a_Pkt, static_cast<const cPickup &>(a_Entity).GetItem());
1619  break;
1620  }
1621  case cEntity::etMinecart:
1622  {
1623  a_Pkt.WriteBEUInt8(5); // Index 5: Shaking power
1625 
1626  // The following expression makes Minecarts shake more with less health or higher damage taken
1627  auto & Minecart = static_cast<const cMinecart &>(a_Entity);
1628  auto maxHealth = a_Entity.GetMaxHealth();
1629  auto curHealth = a_Entity.GetHealth();
1630  a_Pkt.WriteVarInt32(static_cast<UInt32>((maxHealth - curHealth) * Minecart.LastDamage() * 4));
1631 
1632  a_Pkt.WriteBEUInt8(6); // Index 6: Shaking direction (doesn't seem to effect anything)
1634  a_Pkt.WriteVarInt32(1);
1635 
1636  a_Pkt.WriteBEUInt8(7); // Index 7: Shake multiplier / damage taken
1638  a_Pkt.WriteBEFloat(static_cast<float>(Minecart.LastDamage() + 10));
1639 
1640  if (Minecart.GetPayload() == cMinecart::mpNone)
1641  {
1642  auto & RideableMinecart = static_cast<const cRideableMinecart &>(Minecart);
1643  const cItem & MinecartContent = RideableMinecart.GetContent();
1644  if (!MinecartContent.IsEmpty())
1645  {
1646  a_Pkt.WriteBEUInt8(8); // Index 8: Block ID and damage
1648  int Content = MinecartContent.m_ItemType;
1649  Content |= MinecartContent.m_ItemDamage << 8;
1650  a_Pkt.WriteVarInt32(static_cast<UInt32>(Content));
1651 
1652  a_Pkt.WriteBEUInt8(9); // Index 9: Block ID and damage
1654  a_Pkt.WriteVarInt32(static_cast<UInt32>(RideableMinecart.GetBlockHeight()));
1655 
1656  a_Pkt.WriteBEUInt8(10); // Index 10: Show block
1658  a_Pkt.WriteBool(true);
1659  }
1660  }
1661  else if (Minecart.GetPayload() == cMinecart::mpFurnace)
1662  {
1663  a_Pkt.WriteBEUInt8(11); // Index 11: Is powered
1665  a_Pkt.WriteBool(static_cast<const cMinecartWithFurnace &>(Minecart).IsFueled());
1666  }
1667  break;
1668  } // case etMinecart
1669 
1670  case cEntity::etProjectile:
1671  {
1672  auto & Projectile = static_cast<const cProjectileEntity &>(a_Entity);
1673  switch (Projectile.GetProjectileKind())
1674  {
1676  {
1677  a_Pkt.WriteBEUInt8(5); // Index 5: Is critical
1679  a_Pkt.WriteBEInt8(static_cast<const cArrowEntity &>(Projectile).IsCritical() ? 1 : 0);
1680  break;
1681  }
1683  {
1684  a_Pkt.WriteBEUInt8(5); // Index 5: Firework item used for this firework
1686  WriteItem(a_Pkt, static_cast<const cFireworkEntity &>(Projectile).GetItem());
1687  break;
1688  }
1690  {
1691  a_Pkt.WriteBEUInt8(5); // Index 5: Potion item which was thrown
1693  WriteItem(a_Pkt, static_cast<const cSplashPotionEntity &>(Projectile).GetItem());
1694  }
1695  default:
1696  {
1697  break;
1698  }
1699  }
1700  break;
1701  } // case etProjectile
1702 
1703  case cEntity::etMonster:
1704  {
1705  WriteMobMetadata(a_Pkt, static_cast<const cMonster &>(a_Entity));
1706  break;
1707  }
1708 
1709  case cEntity::etBoat:
1710  {
1711  auto & Boat = static_cast<const cBoat &>(a_Entity);
1712 
1713  a_Pkt.WriteBEInt8(5); // Index 6: Time since last hit
1715  a_Pkt.WriteVarInt32(static_cast<UInt32>(Boat.GetLastDamage()));
1716 
1717  a_Pkt.WriteBEInt8(6); // Index 7: Forward direction
1719  a_Pkt.WriteVarInt32(static_cast<UInt32>(Boat.GetForwardDirection()));
1720 
1721  a_Pkt.WriteBEInt8(7); // Index 8: Damage taken
1723  a_Pkt.WriteBEFloat(Boat.GetDamageTaken());
1724 
1725  a_Pkt.WriteBEInt8(8); // Index 9: Type
1727  a_Pkt.WriteVarInt32(static_cast<UInt32>(Boat.GetMaterial()));
1728 
1729  a_Pkt.WriteBEInt8(9); // Index 10: Right paddle turning
1731  a_Pkt.WriteBool(Boat.IsRightPaddleUsed());
1732 
1733  a_Pkt.WriteBEInt8(10); // Index 11: Left paddle turning
1735  a_Pkt.WriteBool(Boat.IsLeftPaddleUsed());
1736 
1737  break;
1738  } // case etBoat
1739 
1740  case cEntity::etItemFrame:
1741  {
1742  auto & Frame = static_cast<const cItemFrame &>(a_Entity);
1743  a_Pkt.WriteBEUInt8(5); // Index 5: Item
1745  WriteItem(a_Pkt, Frame.GetItem());
1746  a_Pkt.WriteBEUInt8(6); // Index 6: Rotation
1748  a_Pkt.WriteVarInt32(Frame.GetItemRotation());
1749  break;
1750  } // case etItemFrame
1751 
1753  {
1754  const auto & EnderCrystal = static_cast<const cEnderCrystal &>(a_Entity);
1755  a_Pkt.WriteBEUInt8(5);
1757  a_Pkt.WriteBool(EnderCrystal.DisplaysBeam());
1758  if (EnderCrystal.DisplaysBeam())
1759  {
1760  a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget());
1761  }
1762  a_Pkt.WriteBEUInt8(6);
1764  a_Pkt.WriteBool(EnderCrystal.ShowsBottom());
1765  break;
1766  } // case etEnderCrystal
1767  default:
1768  {
1769  break;
1770  }
1771  }
1772 }
1773 
1774 
1775 
1776 
1777 
1778 void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const
1779 {
1780  short ItemType = a_Item.m_ItemType;
1781  ASSERT(ItemType >= -1); // Check validity of packets in debug runtime
1782  if (ItemType <= 0)
1783  {
1784  // Fix, to make sure no invalid values are sent.
1785  ItemType = -1;
1786  }
1787 
1788  if (a_Item.IsEmpty())
1789  {
1790  a_Pkt.WriteBEInt16(-1);
1791  return;
1792  }
1793 
1794  if ((ItemType == E_ITEM_POTION) && ((a_Item.m_ItemDamage & 0x4000) != 0))
1795  {
1796  // Ugly special case for splash potion ids which changed in 1.9; this can be removed when the new 1.9 ids are implemented
1797  a_Pkt.WriteBEInt16(438); // minecraft:splash_potion
1798  }
1799  else
1800  {
1801  // Normal item
1802  a_Pkt.WriteBEInt16(ItemType);
1803  }
1804  a_Pkt.WriteBEInt8(a_Item.m_ItemCount);
1805  if ((ItemType == E_ITEM_POTION) || (ItemType == E_ITEM_SPAWN_EGG))
1806  {
1807  // These items lost their metadata; if it is sent they don't render correctly.
1808  a_Pkt.WriteBEInt16(0);
1809  }
1810  else
1811  {
1812  a_Pkt.WriteBEInt16(a_Item.m_ItemDamage);
1813  }
1814 
1815  if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (ItemType != E_ITEM_FIREWORK_ROCKET) && (ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid() && (ItemType != E_ITEM_POTION) && (ItemType != E_ITEM_SPAWN_EGG))
1816  {
1817  a_Pkt.WriteBEInt8(0);
1818  return;
1819  }
1820 
1821 
1822  // Send the enchantments and custom names:
1823  cFastNBTWriter Writer;
1824  if (a_Item.m_RepairCost != 0)
1825  {
1826  Writer.AddInt("RepairCost", a_Item.m_RepairCost);
1827  }
1828  if (!a_Item.m_Enchantments.IsEmpty())
1829  {
1830  const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
1832  }
1833  if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid())
1834  {
1835  Writer.BeginCompound("display");
1836  if (a_Item.m_ItemColor.IsValid())
1837  {
1838  Writer.AddInt("color", static_cast<Int32>(a_Item.m_ItemColor.m_Color));
1839  }
1840 
1841  if (!a_Item.IsCustomNameEmpty())
1842  {
1843  Writer.AddString("Name", a_Item.m_CustomName);
1844  }
1845  if (!a_Item.IsLoreEmpty())
1846  {
1847  Writer.BeginList("Lore", TAG_String);
1848 
1849  for (const auto & Line : a_Item.m_LoreTable)
1850  {
1851  Writer.AddString("", Line);
1852  }
1853 
1854  Writer.EndList();
1855  }
1856  Writer.EndCompound();
1857  }
1858  if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR))
1859  {
1860  cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast<ENUM_ITEM_TYPE>(a_Item.m_ItemType));
1861  }
1862  if (a_Item.m_ItemType == E_ITEM_POTION)
1863  {
1864  // 1.9 potions use a different format. In the future (when only 1.9+ is supported) this should be its own class
1865  AString PotionID = "empty"; // Fallback of "Uncraftable potion" for unhandled cases
1866 
1869  {
1870  switch (Type)
1871  {
1872  case cEntityEffect::effRegeneration: PotionID = "regeneration"; break;
1873  case cEntityEffect::effSpeed: PotionID = "swiftness"; break;
1874  case cEntityEffect::effFireResistance: PotionID = "fire_resistance"; break;
1875  case cEntityEffect::effPoison: PotionID = "poison"; break;
1876  case cEntityEffect::effInstantHealth: PotionID = "healing"; break;
1877  case cEntityEffect::effNightVision: PotionID = "night_vision"; break;
1878  case cEntityEffect::effWeakness: PotionID = "weakness"; break;
1879  case cEntityEffect::effStrength: PotionID = "strength"; break;
1880  case cEntityEffect::effSlowness: PotionID = "slowness"; break;
1881  case cEntityEffect::effJumpBoost: PotionID = "leaping"; break;
1882  case cEntityEffect::effInstantDamage: PotionID = "harming"; break;
1883  case cEntityEffect::effWaterBreathing: PotionID = "water_breathing"; break;
1884  case cEntityEffect::effInvisibility: PotionID = "invisibility"; break;
1885  default: ASSERT(!"Unknown potion effect"); break;
1886  }
1888  {
1889  PotionID = "strong_" + PotionID;
1890  }
1891  else if (a_Item.m_ItemDamage & 0x40)
1892  {
1893  // Extended potion bit
1894  PotionID = "long_" + PotionID;
1895  }
1896  }
1897  else
1898  {
1899  // Empty potions: Water bottles and other base ones
1900  if (a_Item.m_ItemDamage == 0)
1901  {
1902  // No other bits set; thus it's a water bottle
1903  PotionID = "water";
1904  }
1905  else
1906  {
1907  switch (a_Item.m_ItemDamage & 0x3f)
1908  {
1909  case 0x00: PotionID = "mundane"; break;
1910  case 0x10: PotionID = "awkward"; break;
1911  case 0x20: PotionID = "thick"; break;
1912  }
1913  // Default cases will use "empty" from before.
1914  }
1915  }
1916 
1917  PotionID = "minecraft:" + PotionID;
1918 
1919  Writer.AddString("Potion", PotionID);
1920  }
1921  if (a_Item.m_ItemType == E_ITEM_SPAWN_EGG)
1922  {
1923  // Convert entity ID to the name.
1925  if (MonsterType != eMonsterType::mtInvalidType)
1926  {
1927  Writer.BeginCompound("EntityTag");
1928  Writer.AddString("id", "minecraft:" + cMonster::MobTypeToVanillaNBT(MonsterType));
1929  Writer.EndCompound();
1930  }
1931  }
1932 
1933  Writer.Finish();
1934 
1935  const auto Result = Writer.GetResult();
1936  if (Result.empty())
1937  {
1938  a_Pkt.WriteBEInt8(0);
1939  return;
1940  }
1941  a_Pkt.WriteBuf(Result);
1942 }
1943 
1944 
1945 
1946 
1947 
1948 void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const
1949 {
1950  // Living entity metadata
1951  if (a_Mob.HasCustomName())
1952  {
1953  // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up?
1954  a_Pkt.WriteBEUInt8(2); // Index 2: Custom name
1956  a_Pkt.WriteString(a_Mob.GetCustomName());
1957 
1958  a_Pkt.WriteBEUInt8(3); // Index 3: Custom name always visible
1960  a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible());
1961  }
1962 
1963  a_Pkt.WriteBEUInt8(6); // Index 6: Health
1965  a_Pkt.WriteBEFloat(static_cast<float>(a_Mob.GetHealth()));
1966 
1967  switch (a_Mob.GetMobType())
1968  {
1969  case mtBat:
1970  {
1971  auto & Bat = static_cast<const cBat &>(a_Mob);
1972  a_Pkt.WriteBEUInt8(11); // Index 11: Bat flags - currently only hanging
1974  a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0);
1975  break;
1976  } // case mtBat
1977 
1978  case mtChicken:
1979  {
1980  auto & Chicken = static_cast<const cChicken &>(a_Mob);
1981 
1982  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
1984  a_Pkt.WriteBool(Chicken.IsBaby());
1985  break;
1986  } // case mtChicken
1987 
1988  case mtCow:
1989  {
1990  auto & Cow = static_cast<const cCow &>(a_Mob);
1991 
1992  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
1994  a_Pkt.WriteBool(Cow.IsBaby());
1995  break;
1996  } // case mtCow
1997 
1998  case mtCreeper:
1999  {
2000  auto & Creeper = static_cast<const cCreeper &>(a_Mob);
2001  a_Pkt.WriteBEUInt8(11); // Index 11: State (idle or "blowing")
2003  a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : 0xffffffff);
2004 
2005  a_Pkt.WriteBEUInt8(12); // Index 12: Is charged
2007  a_Pkt.WriteBool(Creeper.IsCharged());
2008 
2009  a_Pkt.WriteBEUInt8(13); // Index 13: Is ignited
2011  a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel());
2012  break;
2013  } // case mtCreeper
2014 
2015  case mtEnderman:
2016  {
2017  auto & Enderman = static_cast<const cEnderman &>(a_Mob);
2018  a_Pkt.WriteBEUInt8(11); // Index 11: Carried block
2020  UInt32 Carried = 0;
2021  Carried |= static_cast<UInt32>(Enderman.GetCarriedBlock() << 4);
2022  Carried |= Enderman.GetCarriedMeta();
2023  a_Pkt.WriteVarInt32(Carried);
2024 
2025  a_Pkt.WriteBEUInt8(12); // Index 12: Is screaming
2027  a_Pkt.WriteBool(Enderman.IsScreaming());
2028  break;
2029  } // case mtEnderman
2030 
2031  case mtGhast:
2032  {
2033  auto & Ghast = static_cast<const cGhast &>(a_Mob);
2034  a_Pkt.WriteBEUInt8(11); // Is attacking
2036  a_Pkt.WriteBool(Ghast.IsCharging());
2037  break;
2038  } // case mtGhast
2039 
2040  case mtHorse:
2041  {
2042  auto & Horse = static_cast<const cHorse &>(a_Mob);
2043  Int8 Flags = 0;
2044  if (Horse.IsTame())
2045  {
2046  Flags |= 0x02;
2047  }
2048  if (Horse.IsSaddled())
2049  {
2050  Flags |= 0x04;
2051  }
2052  if (Horse.IsChested())
2053  {
2054  Flags |= 0x08;
2055  }
2056  if (Horse.IsEating())
2057  {
2058  Flags |= 0x20;
2059  }
2060  if (Horse.IsRearing())
2061  {
2062  Flags |= 0x40;
2063  }
2064  if (Horse.IsMthOpen())
2065  {
2066  Flags |= 0x80;
2067  }
2068  a_Pkt.WriteBEUInt8(12); // Index 12: flags
2070  a_Pkt.WriteBEInt8(Flags);
2071 
2072  a_Pkt.WriteBEUInt8(13); // Index 13: Variant / type
2074  a_Pkt.WriteVarInt32(static_cast<UInt32>(Horse.GetHorseType()));
2075 
2076  a_Pkt.WriteBEUInt8(14); // Index 14: Color / style
2078  int Appearance = 0;
2079  Appearance = Horse.GetHorseColor();
2080  Appearance |= Horse.GetHorseStyle() << 8;
2081  a_Pkt.WriteVarInt32(static_cast<UInt32>(Appearance));
2082 
2083  a_Pkt.WriteBEUInt8(16); // Index 16: Armor
2085  a_Pkt.WriteVarInt32(static_cast<UInt32>(Horse.GetHorseArmour()));
2086 
2087  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2089  a_Pkt.WriteBool(Horse.IsBaby());
2090  break;
2091  } // case mtHorse
2092 
2093  case mtMagmaCube:
2094  {
2095  auto & MagmaCube = static_cast<const cMagmaCube &>(a_Mob);
2096  a_Pkt.WriteBEUInt8(11); // Index 11: Size
2098  a_Pkt.WriteVarInt32(static_cast<UInt32>(MagmaCube.GetSize()));
2099  break;
2100  } // case mtMagmaCube
2101 
2102  case mtOcelot:
2103  {
2104  auto & Ocelot = static_cast<const cOcelot &>(a_Mob);
2105 
2106  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2108  a_Pkt.WriteBool(Ocelot.IsBaby());
2109  break;
2110  } // case mtOcelot
2111 
2112  case mtPig:
2113  {
2114  auto & Pig = static_cast<const cPig &>(a_Mob);
2115 
2116  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2118  a_Pkt.WriteBool(Pig.IsBaby());
2119 
2120  a_Pkt.WriteBEUInt8(12); // Index 12: Is saddled
2122  a_Pkt.WriteBool(Pig.IsSaddled());
2123 
2124  break;
2125  } // case mtPig
2126 
2127  case mtRabbit:
2128  {
2129  auto & Rabbit = static_cast<const cRabbit &>(a_Mob);
2130  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2132  a_Pkt.WriteBool(Rabbit.IsBaby());
2133 
2134  a_Pkt.WriteBEUInt8(12); // Index 12: Type
2136  a_Pkt.WriteVarInt32(static_cast<UInt32>(Rabbit.GetRabbitType()));
2137  break;
2138  } // case mtRabbit
2139 
2140  case mtSheep:
2141  {
2142  auto & Sheep = static_cast<const cSheep &>(a_Mob);
2143 
2144  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2146  a_Pkt.WriteBool(Sheep.IsBaby());
2147 
2148  a_Pkt.WriteBEUInt8(12); // Index 12: sheared, color
2150  Int8 SheepMetadata = 0;
2151  SheepMetadata = static_cast<Int8>(Sheep.GetFurColor());
2152  if (Sheep.IsSheared())
2153  {
2154  SheepMetadata |= 0x10;
2155  }
2156  a_Pkt.WriteBEInt8(SheepMetadata);
2157  break;
2158  } // case mtSheep
2159 
2160  case mtSkeleton:
2161  {
2162  auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
2163  a_Pkt.WriteBEUInt8(11);
2165  a_Pkt.WriteVarInt32(0);
2166 
2167  // Index 5 and 12 used for charging bow client animation.
2168  a_Pkt.WriteBEUInt8(5);
2170  a_Pkt.WriteBEInt8(0x02 | (Skeleton.IsChargingBow() ? 0x01 : 0x00));
2171 
2172  a_Pkt.WriteBEUInt8(12);
2174  a_Pkt.WriteBool(Skeleton.IsChargingBow());
2175  break;
2176  }
2177 
2178  case mtSlime:
2179  {
2180  auto & Slime = static_cast<const cSlime &>(a_Mob);
2181  a_Pkt.WriteBEUInt8(11); // Index 11: Size
2183  a_Pkt.WriteVarInt32(static_cast<UInt32>(Slime.GetSize()));
2184  break;
2185  } // case mtSlime
2186 
2187  case mtVillager:
2188  {
2189  auto & Villager = static_cast<const cVillager &>(a_Mob);
2190  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2192  a_Pkt.WriteBool(Villager.IsBaby());
2193 
2194  a_Pkt.WriteBEUInt8(12); // Index 12: Type
2196  a_Pkt.WriteVarInt32(static_cast<UInt32>(Villager.GetVilType()));
2197  break;
2198  } // case mtVillager
2199 
2200  case mtWitch:
2201  {
2202  auto & Witch = static_cast<const cWitch &>(a_Mob);
2203  a_Pkt.WriteBEUInt8(11); // Index 11: Is angry
2205  a_Pkt.WriteBool(Witch.IsAngry());
2206  break;
2207  } // case mtWitch
2208 
2209  case mtWither:
2210  {
2211  auto & Wither = static_cast<const cWither &>(a_Mob);
2212  a_Pkt.WriteBEUInt8(14); // Index 14: Invulnerable ticks
2214  a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks());
2215 
2216  // TODO: Use boss bar packet for health
2217  break;
2218  } // case mtWither
2219 
2220  case mtWitherSkeleton:
2221  {
2222  a_Pkt.WriteBEUInt8(11); // Index 11: Type
2224  a_Pkt.WriteVarInt32(1); // Is wither skeleton
2225  break;
2226  } // case mtWitherSkeleton
2227 
2228  case mtWolf:
2229  {
2230  auto & Wolf = static_cast<const cWolf &>(a_Mob);
2231  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2233  a_Pkt.WriteBool(Wolf.IsBaby());
2234 
2235  Int8 WolfStatus = 0;
2236  if (Wolf.IsSitting())
2237  {
2238  WolfStatus |= 0x1;
2239  }
2240  if (Wolf.IsAngry())
2241  {
2242  WolfStatus |= 0x2;
2243  }
2244  if (Wolf.IsTame())
2245  {
2246  WolfStatus |= 0x4;
2247  }
2248  a_Pkt.WriteBEUInt8(12); // Index 12: status
2250  a_Pkt.WriteBEInt8(WolfStatus);
2251 
2252  a_Pkt.WriteBEUInt8(14); // Index 14: Health
2254  a_Pkt.WriteBEFloat(static_cast<float>(a_Mob.GetHealth()));
2255 
2256  a_Pkt.WriteBEUInt8(15); // Index 15: Is begging
2258  a_Pkt.WriteBool(Wolf.IsBegging());
2259 
2260  a_Pkt.WriteBEUInt8(16); // Index 16: Collar color
2262  a_Pkt.WriteVarInt32(static_cast<UInt32>(Wolf.GetCollarColor()));
2263  break;
2264  } // case mtWolf
2265 
2266  case mtZombie:
2267  {
2268  auto & Zombie = static_cast<const cZombie &>(a_Mob);
2269  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2271  a_Pkt.WriteBool(Zombie.IsBaby());
2272 
2273  a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager
2275  a_Pkt.WriteVarInt32(0);
2276 
2277  a_Pkt.WriteBEUInt8(13); // Index 13: Is converting
2279  a_Pkt.WriteBool(false);
2280  break;
2281  } // case mtZombie
2282 
2283  case mtZombiePigman:
2284  {
2285  auto & ZombiePigman = static_cast<const cZombiePigman &>(a_Mob);
2286  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2288  a_Pkt.WriteBool(ZombiePigman.IsBaby());
2289  break;
2290  } // case mtZombiePigman
2291 
2292  case mtZombieVillager:
2293  {
2294  auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
2295  a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
2297  a_Pkt.WriteBool(ZombieVillager.IsBaby());
2298 
2299  a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager
2301  a_Pkt.WriteVarInt32(ZombieVillager.GetProfession());
2302 
2303  a_Pkt.WriteBEUInt8(13); // Index 13: Is converting
2305  a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1);
2306  break;
2307  } // case mtZombieVillager
2308 
2309  case mtBlaze:
2310  case mtElderGuardian:
2311  case mtGuardian:
2312  {
2313  // TODO: Mobs with extra fields that aren't implemented
2314  break;
2315  }
2316 
2317  case mtCat:
2318 
2319  case mtDonkey:
2320 
2321  case mtMule:
2322 
2323  case mtStray:
2324 
2325  case mtSkeletonHorse:
2326  case mtZombieHorse:
2327 
2328  case mtShulker:
2329  {
2330  // Todo: Mobs not added yet. Grouped ones have the same metadata
2331  ASSERT(!"cProtocol_1_9::WriteMobMetadata: received unimplemented type");
2332  break;
2333  }
2334 
2335  case mtCaveSpider:
2336  case mtEnderDragon:
2337  case mtEndermite:
2338  case mtGiant:
2339  case mtIronGolem:
2340  case mtMooshroom:
2341  case mtSilverfish:
2342  case mtSnowGolem:
2343  case mtSpider:
2344  case mtSquid:
2345  {
2346  // Entities without additional metadata
2347  break;
2348  }
2349 
2350  default: UNREACHABLE("cProtocol_1_9::WriteMobMetadata: received mob of invalid type");
2351  } // switch (a_Mob.GetType())
2352 }
2353 
2354 
2355 
2356 
2357 
2359 // cProtocol_1_9_1:
2360 
2361 void cProtocol_1_9_1::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
2362 {
2363  // Send the Join Game packet:
2364  {
2365  cServer * Server = cRoot::Get()->GetServer();
2366  cPacketizer Pkt(*this, pktJoinGame);
2367  Pkt.WriteBEUInt32(a_Player.GetUniqueID());
2368  Pkt.WriteBEUInt8(static_cast<UInt8>(a_Player.GetEffectiveGameMode()) | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4
2369  Pkt.WriteBEInt32(static_cast<Int32>(a_World.GetDimension())); // This is the change from 1.9.0 (Int8 to Int32)
2370  Pkt.WriteBEUInt8(2); // TODO: Difficulty (set to Normal)
2371  Pkt.WriteBEUInt8(static_cast<UInt8>(Clamp<size_t>(Server->GetMaxPlayers(), 0, 255)));
2372  Pkt.WriteString("default"); // Level type - wtf?
2373  Pkt.WriteBool(false); // Reduced Debug Info - wtf?
2374  }
2375 
2376  // Send the spawn position:
2377  {
2378  cPacketizer Pkt(*this, pktSpawnPosition);
2379  Pkt.WriteXYZPosition64(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ());
2380  }
2381 
2382  // Send the server difficulty:
2383  {
2384  cPacketizer Pkt(*this, pktDifficulty);
2385  Pkt.WriteBEInt8(1);
2386  }
2387 }
2388 
2389 
2390 
2391 
2392 
2394 {
2395  return Version::v1_9_1;
2396 }
2397 
2398 
2399 
2400 
2401 
2403 // cProtocol_1_9_2:
2404 
2406 {
2407  return Version::v1_9_2;
2408 }
2409 
2410 
2411 
2412 
2413 
2415 // cProtocol_1_9_4:
2416 
2417 void cProtocol_1_9_4::SendUpdateSign(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
2418 {
2419  ASSERT(m_State == 3); // In game mode?
2420 
2421  // 1.9.4 removed the update sign packet and now uses Update Block Entity
2422  cPacketizer Pkt(*this, pktUpdateBlockEntity);
2423  Pkt.WriteXYZPosition64(a_BlockPos);
2424  Pkt.WriteBEUInt8(9); // Action 9 - update sign
2425 
2426  cFastNBTWriter Writer;
2427  Writer.AddInt("x", a_BlockPos.x);
2428  Writer.AddInt("y", a_BlockPos.y);
2429  Writer.AddInt("z", a_BlockPos.z);
2430  Writer.AddString("id", "Sign");
2431 
2432  Json::Value Line1;
2433  Line1["text"] = a_Line1;
2434  Writer.AddString("Text1", JsonUtils::WriteFastString(Line1));
2435  Json::Value Line2;
2436  Line2["text"] = a_Line2;
2437  Writer.AddString("Text2", JsonUtils::WriteFastString(Line2));
2438  Json::Value Line3;
2439  Line3["text"] = a_Line3;
2440  Writer.AddString("Text3", JsonUtils::WriteFastString(Line3));
2441  Json::Value Line4;
2442  Line4["text"] = a_Line4;
2443  Writer.AddString("Text4", JsonUtils::WriteFastString(Line4));
2444 
2445  Writer.Finish();
2446  Pkt.WriteBuf(Writer.GetResult());
2447 }
2448 
2449 
2450 
2451 
2452 
2454 {
2455  switch (a_Packet)
2456  {
2457  case pktCollectEntity: return 0x48;
2458  case pktEntityEffect: return 0x4b;
2459  case pktEntityProperties: return 0x4a;
2460  case pktPlayerListHeaderFooter: return 0x47;
2461  case pktTeleportEntity: return 0x49;
2462 
2463  default: return Super::GetPacketID(a_Packet);
2464  }
2465 }
2466 
2467 
2468 
2469 
2470 
2472 {
2473  return Version::v1_9_4;
2474 }
@ E_BLOCK_MOB_SPAWNER
Definition: BlockType.h:62
ENUM_ITEM_TYPE
Definition: BlockType.h:295
@ E_ITEM_POTION
Definition: BlockType.h:418
@ E_ITEM_FIREWORK_STAR
Definition: BlockType.h:448
@ E_ITEM_SPAWN_EGG
Definition: BlockType.h:429
@ E_ITEM_FIREWORK_ROCKET
Definition: BlockType.h:447
@ E_ITEM_BOOK
Definition: BlockType.h:385
BossBarDivisionType
Definition: Defines.h:443
EntityAnimation
Definition: Defines.h:458
eClickAction
Individual actions sent in the WindowClick packet.
Definition: Defines.h:82
@ caRightPaintProgress
Definition: Defines.h:108
@ caDblClick
Definition: Defines.h:113
@ caLeftPaintProgress
Definition: Defines.h:107
@ caNumber6
Definition: Defines.h:93
@ caNumber8
Definition: Defines.h:95
@ caMiddleClick
Definition: Defines.h:97
@ caCtrlDropKey
Definition: Defines.h:99
@ caLeftPaintEnd
Definition: Defines.h:110
@ caLeftClickOutside
Definition: Defines.h:100
@ caMiddlePaintEnd
Definition: Defines.h:112
@ caLeftClickOutsideHoldNothing
Definition: Defines.h:102
@ caDropKey
Definition: Defines.h:98
@ caShiftRightClick
Definition: Defines.h:87
@ caNumber7
Definition: Defines.h:94
@ caRightClick
Definition: Defines.h:85
@ caNumber4
Definition: Defines.h:91
@ caNumber1
Definition: Defines.h:88
@ caMiddlePaintBegin
Definition: Defines.h:106
@ caMiddlePaintProgress
Definition: Defines.h:109
@ caNumber3
Definition: Defines.h:90
@ caLeftPaintBegin
Definition: Defines.h:104
@ caRightClickOutsideHoldNothing
Definition: Defines.h:103
@ caNumber9
Definition: Defines.h:96
@ caNumber2
Definition: Defines.h:89
@ caRightPaintEnd
Definition: Defines.h:111
@ caRightClickOutside
Definition: Defines.h:101
@ caUnknown
Definition: Defines.h:115
@ caShiftLeftClick
Definition: Defines.h:86
@ caNumber5
Definition: Defines.h:92
@ caRightPaintBegin
Definition: Defines.h:105
@ caLeftClick
Definition: Defines.h:84
BossBarColor
Definition: Defines.h:428
#define UNREACHABLE(x)
Definition: Globals.h:288
unsigned int UInt32
Definition: Globals.h:157
signed long long Int64
Definition: Globals.h:151
signed short Int16
Definition: Globals.h:153
std::basic_string_view< std::byte > ContiguousByteBufferView
Definition: Globals.h:376
signed char Int8
Definition: Globals.h:154
signed int Int32
Definition: Globals.h:152
unsigned char UInt8
Definition: Globals.h:159
unsigned long long UInt64
Definition: Globals.h:156
#define ASSERT(x)
Definition: Globals.h:276
unsigned short UInt16
Definition: Globals.h:158
unsigned char Byte
Definition: Globals.h:161
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
void LOG(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:55
#define LOGD
Definition: LoggerSimple.h:83
eMonsterType
Identifies individual monster type.
Definition: MonsterTypes.h:11
@ mtZombieVillager
Definition: MonsterTypes.h:82
@ mtElderGuardian
Definition: MonsterTypes.h:25
@ mtSkeleton
Definition: MonsterTypes.h:59
@ mtSheep
Definition: MonsterTypes.h:56
@ mtEndermite
Definition: MonsterTypes.h:28
@ mtMagmaCube
Definition: MonsterTypes.h:40
@ mtWolf
Definition: MonsterTypes.h:77
@ mtStray
Definition: MonsterTypes.h:65
@ mtRabbit
Definition: MonsterTypes.h:53
@ mtCat
Definition: MonsterTypes.h:16
@ mtZombie
Definition: MonsterTypes.h:79
@ mtOcelot
Definition: MonsterTypes.h:43
@ mtDonkey
Definition: MonsterTypes.h:23
@ mtEnderman
Definition: MonsterTypes.h:27
@ mtCaveSpider
Definition: MonsterTypes.h:17
@ mtShulker
Definition: MonsterTypes.h:57
@ mtWither
Definition: MonsterTypes.h:75
@ mtSkeletonHorse
Definition: MonsterTypes.h:60
@ mtPig
Definition: MonsterTypes.h:47
@ mtVillager
Definition: MonsterTypes.h:71
@ mtHorse
Definition: MonsterTypes.h:34
@ mtZombieHorse
Definition: MonsterTypes.h:80
@ mtWitch
Definition: MonsterTypes.h:74
@ mtCow
Definition: MonsterTypes.h:20
@ mtEnderDragon
Definition: MonsterTypes.h:26
@ mtMooshroom
Definition: MonsterTypes.h:41
@ mtSquid
Definition: MonsterTypes.h:64
@ mtInvalidType
Definition: MonsterTypes.h:12
@ mtBat
Definition: MonsterTypes.h:14
@ mtChicken
Definition: MonsterTypes.h:18
@ mtGiant
Definition: MonsterTypes.h:32
@ mtSnowGolem
Definition: MonsterTypes.h:62
@ mtBlaze
Definition: MonsterTypes.h:15
@ mtIronGolem
Definition: MonsterTypes.h:38
@ mtCreeper
Definition: MonsterTypes.h:21
@ mtSpider
Definition: MonsterTypes.h:63
@ mtMule
Definition: MonsterTypes.h:42
@ mtGhast
Definition: MonsterTypes.h:31
@ mtSilverfish
Definition: MonsterTypes.h:58
@ mtZombiePigman
Definition: MonsterTypes.h:85
@ mtSlime
Definition: MonsterTypes.h:61
@ mtWitherSkeleton
Definition: MonsterTypes.h:76
@ mtGuardian
Definition: MonsterTypes.h:33
#define HANDLE_READ(ByteBuf, Proc, Type, Var)
Macros used to read packets more easily.
Definition: Packetizer.h:28
#define LEFT_HAND
#define MAIN_HAND
Item
Definition: Items.h:4
@ Rabbit
@ Chicken
@ Minecart
void ReplaceString(AString &iHayStack, const AString &iNeedle, const AString &iReplaceWith)
Replaces each occurence of iNeedle in iHayStack with iReplaceWith.
AString & CreateHexDump(AString &a_Out, const void *a_Data, size_t a_Size, size_t a_BytesPerLine)
format binary data this way: 00001234: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 1234567890abcd...
std::string AString
Definition: StringUtils.h:11
@ TAG_List
Definition: FastNBT.h:41
@ TAG_String
Definition: FastNBT.h:40
@ TAG_Compound
Definition: FastNBT.h:42
@ TAG_Int
Definition: FastNBT.h:35
AString WriteFastString(const Json::Value &a_Root)
Definition: JsonUtils.cpp:12
bool Conditional(const BlockState Block)
void ParseFromNBT(cEnchantments &a_Enchantments, const cParsedNBT &a_NBT, int a_EnchListTagIdx)
Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments)
void WriteToNBTCompound(const cEnchantments &a_Enchantments, cFastNBTWriter &a_Writer, const AString &a_ListTagName)
Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name...
int GetPosZ() const
Definition: BlockEntity.h:93
int GetPosY() const
Definition: BlockEntity.h:92
int GetPosX() const
Definition: BlockEntity.h:91
BLOCKTYPE GetBlockType() const
Definition: BlockEntity.h:97
An object that can store incoming bytes and lets its clients read the bytes sequentially The bytes ar...
Definition: ByteBuffer.h:32
static bool CanBEInt16Represent(int a_Value)
Returns if the given value can fit in a protocol big-endian 16 bit integer.
Definition: ByteBuffer.cpp:226
bool ReadXYZPosition64(int &a_BlockX, int &a_BlockY, int &a_BlockZ)
Definition: ByteBuffer.cpp:505
void HandleUnmount(void)
void HandleCommandBlockBlockChange(Vector3i a_BlockPos, const AString &a_NewCommand)
Called when the protocol receives a message, indicating that the player set a new command in the comm...
void SetLocale(const AString &a_Locale)
Definition: ClientHandle.h:267
void HandleLeftClick(Vector3i a_BlockPos, eBlockFace a_BlockFace, UInt8 a_Status)
void SetViewDistance(int a_ViewDistance)
Sets the maximal view distance.
void PacketUnknown(UInt32 a_PacketType)
void HandleWindowClick(UInt8 a_WindowID, Int16 a_SlotNum, eClickAction a_ClickAction, const cItem &a_HeldItem)
void HandleLeaveBed()
Handles a player exiting his bed.
void HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_Cursor, bool a_UsedMainHand)
void HandleUseEntity(UInt32 a_TargetEntityID, bool a_IsLeftClick)
void HandleUpdateSign(Vector3i a_BlockPos, const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4)
void HandleSteerVehicle(float Forward, float Sideways)
void HandleStartElytraFlight()
Handles a player starting elytra flight while falling.
void HandleUseItem(bool a_UsedMainHand)
void HandleSprint(bool a_IsSprinting)
Handles a player sprinting or slowing back down.
const AString & GetUsername(void) const
void HandlePlayerMove(Vector3d a_Pos, bool a_IsOnGround)
Verifies and sets player position, performing relevant checks.
void HandleTabCompletion(const AString &a_Text)
void HandleCrouch(bool a_IsCrouching)
Handles a player sneaking or unsneaking.
cPlayer * GetPlayer(void)
Definition: ClientHandle.h:78
void HandlePlayerMoveLook(Vector3d a_Pos, float a_Rotation, float a_Pitch, bool a_IsOnGround)
void HandleOpenHorseInventory()
Handles a player opening his inventory while riding a horse.
void HandleAnimation(bool a_SwingMainHand)
Called when the protocol receives a (hand swing) animation packet.
unsigned int m_Color
Definition: Color.h:56
bool IsValid() const
Returns whether the color is a valid color.
Definition: Color.h:28
Container for a single chat message composed of multiple functional parts.
Definition: CompositeChat.h:34
AString CreateJsonString(bool a_ShouldUseChatPrefixes=true) const
bool IsEmpty(void) const
Returns true if there are no enchantments.
bool IsCritical(void) const
Returns true if the arrow is set as critical.
Definition: ArrowEntity.h:70
Definition: Boat.h:20
void UpdatePaddles(bool rightPaddleUsed, bool leftPaddleUsed)
Definition: Boat.cpp:235
Definition: Entity.h:76
virtual bool IsElytraFlying(void) const
Definition: Entity.h:487
virtual bool IsRclking(void) const
Definition: Entity.h:490
void SetPitch(double a_Pitch)
Definition: Entity.cpp:2136
double GetSpeedZ(void) const
Definition: Entity.h:204
void SetYaw(double a_Yaw)
Definition: Entity.cpp:2125
virtual bool IsCrouched(void) const
Definition: Entity.h:486
float GetMaxHealth(void) const
Definition: Entity.h:407
double GetSpeedY(void) const
Definition: Entity.h:203
Vector3d GetLastSentPosition(void) const
Returns the last position we sent to all the clients.
Definition: Entity.h:304
double GetPosX(void) const
Definition: Entity.h:195
void SetPosY(double a_PosY)
Definition: Entity.h:216
double GetPosZ(void) const
Definition: Entity.h:197
UInt32 GetUniqueID(void) const
Definition: Entity.h:253
eEntityType GetEntityType(void) const
Definition: Entity.h:156
double GetPitch(void) const
Definition: Entity.h:199
virtual bool IsOnFire(void) const
Definition: Entity.h:489
bool IsOrientationDirty() const
Returns whether the entity's orientation has been set manually.
Definition: Entity.cpp:2093
double GetPosY(void) const
Definition: Entity.h:196
double GetHeadYaw(void) const
Definition: Entity.h:192
virtual bool IsOnGround(void) const
Returns whether the entity is on ground or not.
Definition: Entity.h:519
void SetPosZ(double a_PosZ)
Definition: Entity.h:217
void SetPosX(double a_PosX)
Definition: Entity.h:215
cEntity * GetAttached()
Gets entity (vehicle) attached to this entity.
Definition: Entity.cpp:2018
virtual bool IsInvisible(void) const
Definition: Entity.h:488
double GetYaw(void) const
Definition: Entity.h:198
float GetHealth(void) const
Returns the health of this entity.
Definition: Entity.h:367
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
@ etPickup
Definition: Entity.h:93
@ etProjectile
Definition: Entity.h:99
@ etItemFrame
Definition: Entity.h:102
@ etMinecart
Definition: Entity.h:96
@ etEnderCrystal
Definition: Entity.h:91
@ etMonster
Definition: Entity.h:94
@ etBoat
Definition: Entity.h:97
@ etPlayer
Definition: Entity.h:92
virtual bool IsSprinting(void) const
Definition: Entity.h:492
double GetSpeedX(void) const
Definition: Entity.h:202
eType
All types of entity effects (numbers correspond to protocol / storage types)
Definition: EntityEffect.h:12
static short GetPotionEffectIntensity(short a_ItemDamage)
Retrieves the intensity level from the potion's damage value.
static cEntityEffect::eType GetPotionEffectType(short a_ItemDamage)
Translates the potion's damage value into the entity effect that the potion gives.
Definition: ExpOrb.h:13
int GetReward(void) const
Get the exp amount.
Definition: ExpOrb.h:40
Byte GetProtocolFacing() const
Returns the direction in which the entity is facing.
Definition: HangingEntity.h:28
@ mpNone
Definition: Minecart.h:31
@ mpFurnace
Definition: Minecart.h:33
bool IsFueled(void) const
Definition: Minecart.h:201
const AString & GetName(void) const
Returns the protocol name of the painting.
Definition: Painting.h:25
Definition: Pickup.h:20
Definition: Player.h:29
const cUUID & GetUUID(void) const
Returns the UUID that has been read from the client, or nil if not available.
Definition: Player.cpp:2431
void SetSkinParts(int a_Parts)
Definition: Player.cpp:2504
void SetLeftHanded(bool a_IsLeftHanded)
Sets the dominant hand of the player.
Definition: Player.cpp:719
bool HasPermission(const AString &a_Permission) const
Definition: Player.cpp:1586
eGameMode GetEffectiveGameMode(void) const
Returns the current effective gamemode (inherited gamemode is resolved before returning)
Definition: Player.cpp:1531
Definition: Item.h:37
bool IsBothNameAndLoreEmpty(void) const
Definition: Item.h:95
cEnchantments m_Enchantments
Definition: Item.h:166
bool IsCustomNameEmpty(void) const
Definition: Item.h:101
char m_ItemCount
Definition: Item.h:164
AString m_CustomName
Definition: Item.h:167
bool IsEmpty(void) const
Returns true if the item represents an empty stack - either the type is invalid, or count is zero.
Definition: Item.h:69
cColor m_ItemColor
Definition: Item.h:202
bool IsLoreEmpty(void) const
Definition: Item.h:102
AStringVector m_LoreTable
Definition: Item.h:171
short m_ItemType
Definition: Item.h:163
int m_RepairCost
Definition: Item.h:200
cFireworkItem m_FireworkItem
Definition: Item.h:201
short m_ItemDamage
Definition: Item.h:165
static eMonsterType ItemDamageToMonsterType(short a_ItemDamage)
Converts the Spawn egg item damage to the monster type to spawn.
Definition: ItemSpawnEgg.h:64
Encapsulates an in-game world map.
Definition: Map.h:83
const cMapDecoratorList GetDecorators(void) const
Definition: Map.h:168
const cColorList & GetData(void) const
Definition: Map.h:170
unsigned int GetScale(void) const
Definition: Map.h:147
unsigned int GetID(void) const
Definition: Map.h:152
Definition: Bat.h:12
Definition: Cow.h:12
Definition: Ghast.h:12
Definition: Horse.h:14
static AString MobTypeToVanillaName(eMonsterType a_MobType)
Translates MobType enum to the vanilla name of the mob, empty string if unknown.
Definition: Monster.cpp:1025
bool HasCustomName(void) const
Returns true if the monster has a custom name.
Definition: Monster.h:165
const AString & GetCustomName(void) const
Gets the custom name of the monster.
Definition: Monster.h:168
bool IsCustomNameAlwaysVisible(void) const
Is the custom name of this monster always visible? If not, you only see the name when you sight the m...
Definition: Monster.h:175
eMonsterType GetMobType(void) const
Definition: Monster.h:70
static AString MobTypeToVanillaNBT(eMonsterType a_MobType)
Translates the MobType enum to the vanilla nbt name.
Definition: Monster.cpp:1044
static eMonsterType StringToMobType(const AString &a_MobTypeName)
Translates MobType string to the enum, mtInvalidType if not recognized.
Definition: Monster.cpp:1063
Definition: Ocelot.h:13
Definition: Pig.h:12
Definition: Rabbit.h:27
Definition: Sheep.h:12
Definition: Slime.h:12
Definition: Witch.h:12
Definition: Wither.h:12
Definition: Wolf.h:14
Definition: Zombie.h:11
Composes an individual packet in the protocol's m_OutPacketBuffer; sends it just before being destruc...
Definition: Packetizer.h:60
void WriteVarInt32(UInt32 a_Value)
Definition: Packetizer.h:141
void WriteUUID(const cUUID &a_UUID)
Writes the specified UUID as a 128-bit BigEndian integer.
Definition: Packetizer.cpp:44
void WriteBEUInt32(UInt32 a_Value)
Definition: Packetizer.h:111
void WriteBEInt32(Int32 a_Value)
Definition: Packetizer.h:105
void WriteBool(bool a_Value)
Definition: Packetizer.h:76
void WriteXYZPosition64(int a_BlockX, int a_BlockY, int a_BlockZ)
Writes the specified block position as a single encoded 64-bit BigEndian integer.
Definition: Packetizer.h:161
void WriteBEUInt64(UInt64 a_Value)
Definition: Packetizer.h:123
void WriteBEFloat(float a_Value)
Definition: Packetizer.h:129
void WriteBEInt16(Int16 a_Value)
Definition: Packetizer.h:93
void WriteString(const AString &a_Value)
Definition: Packetizer.h:147
void WriteBEUInt8(UInt8 a_Value)
Definition: Packetizer.h:81
void WriteBEDouble(double a_Value)
Definition: Packetizer.h:135
void WriteBuf(const ContiguousByteBufferView a_Data)
Definition: Packetizer.h:153
void WriteByteAngle(double a_Angle)
Writes the specified angle using a single byte.
Definition: Packetizer.cpp:26
void WriteBEInt8(Int8 a_Value)
Definition: Packetizer.h:87
ePacketType
Logical types of outgoing packets.
Definition: Protocol.h:57
@ pktUnloadChunk
Definition: Protocol.h:123
@ pktEntityHeadLook
Definition: Protocol.h:77
@ pktSoundEffect
Definition: Protocol.h:108
@ pktEntityRelMove
Definition: Protocol.h:81
@ pktSoundParticleEffect
Definition: Protocol.h:109
@ pktEntityVelocity
Definition: Protocol.h:84
@ pktEntityMeta
Definition: Protocol.h:79
@ pktAttachEntity
Definition: Protocol.h:58
@ pktBlockChanges
Definition: Protocol.h:62
@ pktDisplayObjective
Definition: Protocol.h:71
@ pktChatRaw
Definition: Protocol.h:65
@ pktUseBed
Definition: Protocol.h:129
@ pktMapData
Definition: Protocol.h:95
@ pktResourcePack
Definition: Protocol.h:104
@ pktSpawnGlobalEntity
Definition: Protocol.h:111
@ pktKeepAlive
Definition: Protocol.h:92
@ pktInventorySlot
Definition: Protocol.h:90
@ pktSpawnPainting
Definition: Protocol.h:114
@ pktParticleEffect
Definition: Protocol.h:96
@ pktSpawnOtherPlayer
Definition: Protocol.h:113
@ pktCameraSetTo
Definition: Protocol.h:64
@ pktEntityEffect
Definition: Protocol.h:75
@ pktTeleportEntity
Definition: Protocol.h:120
@ pktUpdateBlockEntity
Definition: Protocol.h:125
@ pktPluginMessage
Definition: Protocol.h:102
@ pktSpawnExperienceOrb
Definition: Protocol.h:110
@ pktSpawnObject
Definition: Protocol.h:107
@ pktPlayerMoveLook
Definition: Protocol.h:101
@ pktEditSign
Definition: Protocol.h:72
@ pktStatistics
Definition: Protocol.h:117
@ pktSpawnPosition
Definition: Protocol.h:115
@ pktTimeUpdate
Definition: Protocol.h:121
@ pktStatusResponse
Definition: Protocol.h:118
@ pktBossBar
Definition: Protocol.h:63
@ pktPlayerList
Definition: Protocol.h:99
@ pktEntityRelMoveLook
Definition: Protocol.h:82
@ pktJoinGame
Definition: Protocol.h:91
@ pktExplosion
Definition: Protocol.h:86
@ pktDifficulty
Definition: Protocol.h:68
@ pktDestroyEntity
Definition: Protocol.h:67
@ pktUpdateHealth
Definition: Protocol.h:126
@ pktUpdateScore
Definition: Protocol.h:127
@ pktPingResponse
Definition: Protocol.h:97
@ pktEntityEquipment
Definition: Protocol.h:76
@ pktWindowOpen
Definition: Protocol.h:133
@ pktUpdateSign
Definition: Protocol.h:128
@ pktRespawn
Definition: Protocol.h:105
@ pktWindowProperty
Definition: Protocol.h:134
@ pktEntityProperties
Definition: Protocol.h:80
@ pktEntityStatus
Definition: Protocol.h:83
@ pktEncryptionRequest
Definition: Protocol.h:73
@ pktScoreboardObjective
Definition: Protocol.h:106
@ pktCollectEntity
Definition: Protocol.h:66
@ pktBlockChange
Definition: Protocol.h:61
@ pktRemoveEntityEffect
Definition: Protocol.h:103
@ pktUnlockRecipe
Definition: Protocol.h:124
@ pktBlockBreakAnim
Definition: Protocol.h:60
@ pktTabCompletionResults
Definition: Protocol.h:119
@ pktHeldItemChange
Definition: Protocol.h:88
@ pktEntityAnimation
Definition: Protocol.h:74
@ pktWindowClose
Definition: Protocol.h:132
@ pktSpawnMob
Definition: Protocol.h:112
@ pktStartCompression
Definition: Protocol.h:116
@ pktLoginSuccess
Definition: Protocol.h:94
@ pktPlayerListHeaderFooter
Definition: Protocol.h:100
@ pktEntityLook
Definition: Protocol.h:78
@ pktDisconnectDuringGame
Definition: Protocol.h:70
@ pktTitle
Definition: Protocol.h:122
@ pktPlayerAbilities
Definition: Protocol.h:98
@ pktWeather
Definition: Protocol.h:130
@ pktExperience
Definition: Protocol.h:85
@ pktGameMode
Definition: Protocol.h:87
@ pktLeashEntity
Definition: Protocol.h:93
@ pktDisconnectDuringLogin
Definition: Protocol.h:69
@ pktBlockAction
Definition: Protocol.h:59
@ pktWindowItems
Definition: Protocol.h:131
Version
The protocol version number, received from the client in the Handshake packet.
Definition: Protocol.h:335
cClientHandle * m_Client
Definition: Protocol.h:472
virtual void HandlePacketPlayer(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketStatusPing(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketLoginEncryptionResponse(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketEnchantItem(cByteBuffer &a_ByteBuffer)
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const
Converts eMonsterType to protocol-specific mob types.
virtual unsigned char GetProtocolEntityAnimation(EntityAnimation a_Animation) const
Converts an animation into an ID suitable for use with the Entity Animation packet.
virtual void WriteBlockEntity(cFastNBTWriter &a_Writer, const cBlockEntity &a_BlockEntity) const
Writes the block entity data for the specified block entity into the packet.
virtual void HandlePacketLoginStart(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketCreativeInventoryAction(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketWindowClose(cByteBuffer &a_ByteBuffer)
virtual void HandleVanillaPluginMessage(cByteBuffer &a_ByteBuffer, std::string_view a_Channel)
Parses Vanilla plugin messages into specific ClientHandle calls.
virtual void HandlePacketStatusRequest(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketPluginMessage(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketPlayerAbilities(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketChatMessage(cByteBuffer &a_ByteBuffer)
State m_State
State of the protocol.
Definition: Protocol_1_8.h:143
virtual void HandlePacketKeepAlive(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketResourcePackStatus(cByteBuffer &a_ByteBuffer)
virtual bool ReadItem(cByteBuffer &a_ByteBuffer, cItem &a_Item, size_t a_KeepRemainingBytes=0) const
Reads an item out of the received data, sets a_Item to the values read.
static eBlockFace FaceIntToBlockFace(Int32 a_FaceInt)
Converts the BlockFace received by the protocol into eBlockFace constants.
virtual void HandlePacketPlayerLook(cByteBuffer &a_ByteBuffer)
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const
Converts an animation into an ID suitable for use with the Entity Status packet.
virtual void HandlePacketClientStatus(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketSlotSelect(cByteBuffer &a_ByteBuffer)
virtual void HandlePacketSpectate(cByteBuffer &a_ByteBuffer)
virtual void SendSpawnMob(const cMonster &a_Mob) override
virtual void HandlePacketSteerVehicle(cByteBuffer &a_ByteBuffer) override
virtual void SendEntitySpawn(const cEntity &a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) override
Sends the entity type and entity-dependent data required for the entity to initially spawn.
virtual Version GetProtocolVersion() const override
Returns the protocol version.
virtual void WriteMobMetadata(cPacketizer &a_Pkt, const cMonster &a_Mob) const override
Writes the mob-specific metadata for the specified mob.
virtual void HandlePacketUseEntity(cByteBuffer &a_ByteBuffer) override
cProtocol_1_9_0(cClientHandle *a_Client, const AString &a_ServerAddress, State a_State)
virtual void SendKeepAlive(UInt32 a_PingID) override
virtual unsigned char GetProtocolEntityAnimation(EntityAnimation a_Animation) const override
Converts an animation into an ID suitable for use with the Entity Animation packet.
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override
Converts eMonsterType to protocol-specific mob types.
virtual void SendEntityEquipment(const cEntity &a_Entity, short a_SlotNum, const cItem &a_Item) override
virtual void HandlePacketBlockPlace(cByteBuffer &a_ByteBuffer) override
virtual void WriteItem(cPacketizer &a_Pkt, const cItem &a_Item) const override
Writes the item data into a packet.
virtual void SendPaintingSpawn(const cPainting &a_Painting) override
virtual void HandlePacketPlayerPos(cByteBuffer &a_ByteBuffer) override
virtual void SendDetachEntity(const cEntity &a_Entity, const cEntity &a_PreviousVehicle) override
virtual void SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat &a_Title) override
virtual void SendEntityMetadata(const cEntity &a_Entity) override
virtual void HandlePacketUseItem(cByteBuffer &a_ByteBuffer)
virtual void WriteBlockEntity(cFastNBTWriter &a_Writer, const cBlockEntity &a_BlockEntity) const override
Writes the block entity data for the specified block entity into the packet.
UInt32 m_OutstandingTeleportId
Whether the current teleport ID has been confirmed by the client.
Definition: Protocol_1_9.h:70
virtual void SendUnloadChunk(int a_ChunkX, int a_ChunkZ) override
virtual void SendPlayerSpawn(const cPlayer &a_Player) override
virtual void SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override
virtual void SendMapData(const cMap &a_Map, int a_DataStartX, int a_DataStartY) override
virtual UInt32 GetPacketID(ePacketType a_Packet) const override
Get the packet ID for a given packet.
virtual void HandlePacketWindowClick(cByteBuffer &a_ByteBuffer) override
virtual void HandlePacketClientSettings(cByteBuffer &a_ByteBuffer) override
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) override
virtual void SendPlayerPermissionLevel() override
virtual void ParseItemMetadata(cItem &a_Item, ContiguousByteBufferView a_Metadata) const override
Parses item metadata as read by ReadItem(), into the item enchantments.
virtual void SendEntityPosition(const cEntity &a_Entity) override
virtual void WriteEntityMetadata(cPacketizer &a_Pkt, const cEntity &a_Entity) const override
Writes the metadata for the specified entity, not including the terminating 0x7f.
virtual void HandlePacketEntityAction(cByteBuffer &a_ByteBuffer) override
virtual void SendBossBarUpdateStyle(UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) override
virtual void SendSoundEffect(const AString &a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) override
virtual void HandlePacketPlayerPosLook(cByteBuffer &a_ByteBuffer) override
virtual void SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) override
virtual void SendBossBarRemove(UInt32 a_UniqueID) override
virtual bool HandlePacket(cByteBuffer &a_ByteBuffer, UInt32 a_PacketType) override
Reads and handles the packet.
virtual void SendUnleashEntity(const cEntity &a_Entity) override
virtual void SendPlayerMoveLook(void) override
virtual void HandlePacketBoatSteer(cByteBuffer &a_ByteBuffer)
virtual void HandleConfirmTeleport(cByteBuffer &a_ByteBuffer)
@ METADATA_TYPE_OPTIONAL_POSITION
Definition: Protocol_1_9.h:116
virtual void HandleVanillaPluginMessage(cByteBuffer &a_ByteBuffer, std::string_view a_Channel) override
Parses Vanilla plugin messages into specific ClientHandle calls.
virtual void SendThunderbolt(Vector3i a_Origin) override
virtual void HandlePacketUpdateSign(cByteBuffer &a_ByteBuffer) override
virtual void HandlePacketBlockDig(cByteBuffer &a_ByteBuffer) override
virtual void SendLeashEntity(const cEntity &a_Entity, const cEntity &a_EntityLeashedTo) override
virtual void HandlePacketAnimation(cByteBuffer &a_ByteBuffer) override
virtual void SendAttachEntity(const cEntity &a_Entity, const cEntity &a_Vehicle) override
virtual void HandlePacketVehicleMove(cByteBuffer &a_ByteBuffer)
virtual void SendExperienceOrb(const cExpOrb &a_ExpOrb) override
virtual void HandlePacketTabComplete(cByteBuffer &a_ByteBuffer) override
bool m_IsTeleportIdConfirmed
The current teleport ID.
Definition: Protocol_1_9.h:67
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override
Converts an animation into an ID suitable for use with the Entity Status packet.
virtual Version GetProtocolVersion() const override
Returns the protocol version.
virtual void SendLogin(const cPlayer &a_Player, const cWorld &a_World) override
virtual Version GetProtocolVersion() const override
Returns the protocol version.
virtual UInt32 GetPacketID(ePacketType a_Packet) const override
Get the packet ID for a given packet.
virtual Version GetProtocolVersion() const override
Returns the protocol version.
virtual void SendUpdateSign(Vector3i a_BlockPos, const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4) override
cServer * GetServer(void)
Definition: Root.h:71
static cRoot * Get()
Definition: Root.h:52
Definition: Server.h:56
size_t GetMaxPlayers(void) const
Definition: Server.h:70
bool IsHardcore(void) const
Definition: Server.h:93
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
Definition: World.h:53
int GetSpawnX(void) const
Definition: World.h:585
int GetSpawnZ(void) const
Definition: World.h:587
virtual eDimension GetDimension(void) const override
Definition: World.h:133
int GetSpawnY(void) const
Definition: World.h:586
Parses and contains the parsed data Also implements data accessor functions for tree traversal and va...
Definition: FastNBT.h:153
int GetNextSibling(int a_Tag) const
Returns the next sibling of the specified tag, or -1 if none.
Definition: FastNBT.h:175
size_t GetErrorPos() const
Returns the position where an error occurred while parsing.
Definition: FastNBT.h:163
std::error_code GetErrorCode() const
Returns the error code for the parsing of the NBT data.
Definition: FastNBT.h:160
int GetFirstChild(int a_Tag) const
Returns the first child of the specified tag, or -1 if none / not applicable.
Definition: FastNBT.h:169
bool IsValid(void) const
Definition: FastNBT.h:157
AString GetName(int a_Tag) const
Returns the tag's name.
Definition: FastNBT.h:293
eTagType GetType(int a_Tag) const
Definition: FastNBT.h:210
int GetRoot(void) const
Returns the root tag of the hierarchy.
Definition: FastNBT.h:166
Int32 GetInt(int a_Tag) const
Returns the value stored in an Int tag.
Definition: FastNBT.h:234
AString GetString(int a_Tag) const
Returns the value stored in a String tag.
Definition: FastNBT.h:280
void AddShort(const AString &a_Name, Int16 a_Value)
Definition: FastNBT.cpp:561
void AddInt(const AString &a_Name, Int32 a_Value)
Definition: FastNBT.cpp:572
void Finish(void)
Definition: FastNBT.cpp:674
void AddString(const AString &a_Name, std::string_view a_Value)
Definition: FastNBT.cpp:616
void EndList(void)
Definition: FastNBT.cpp:536
void BeginList(const AString &a_Name, eTagType a_ChildrenType)
Definition: FastNBT.cpp:512
void EndCompound(void)
Definition: FastNBT.cpp:499
void BeginCompound(const AString &a_Name)
Definition: FastNBT.cpp:481
ContiguousByteBufferView GetResult(void) const
Definition: FastNBT.h:351
static void WriteToNBTCompound(const cFireworkItem &a_FireworkItem, cFastNBTWriter &a_Writer, const ENUM_ITEM_TYPE a_Type)
Writes firework NBT data to a Writer object.
static void ParseFromNBT(cFireworkItem &a_FireworkItem, const cParsedNBT &a_NBT, int a_TagIdx, const ENUM_ITEM_TYPE a_Type)
Reads NBT data from a NBT object and populates a FireworkItem with it.