Cuberite
A lightweight, fast and extensible game server for Minecraft
Protocol_1_10.cpp
Go to the documentation of this file.
1 
2 // Protocol_1_10.cpp
3 
4 /*
5 Implements the 1.10 protocol classes:
6  - cProtocol_1_10_0
7  - release 1.10 protocol (#210), also used by 1.10.1 and 1.10.2
8 */
9 
10 #include "Globals.h"
11 #include "Protocol_1_10.h"
12 #include "Packetizer.h"
13 
14 #include "json/json.h"
15 
16 #include "../Root.h"
17 #include "../Server.h"
18 #include "../ClientHandle.h"
19 #include "../JsonUtils.h"
20 
21 #include "../WorldStorage/FastNBT.h"
22 
23 #include "../Entities/Boat.h"
24 #include "../Entities/EnderCrystal.h"
25 #include "../Entities/ExpOrb.h"
26 #include "../Entities/Minecart.h"
27 #include "../Entities/FallingBlock.h"
28 #include "../Entities/Painting.h"
29 #include "../Entities/Pickup.h"
30 #include "../Entities/Player.h"
31 #include "../Entities/ItemFrame.h"
32 #include "../Entities/ArrowEntity.h"
33 #include "../Entities/FireworkEntity.h"
34 #include "../Entities/SplashPotionEntity.h"
35 
36 #include "../Mobs/IncludeAllMonsters.h"
37 
38 #include "../BlockEntities/BannerEntity.h"
39 #include "../BlockEntities/BeaconEntity.h"
40 #include "../BlockEntities/CommandBlockEntity.h"
41 #include "../BlockEntities/MobHeadEntity.h"
42 #include "../BlockEntities/MobSpawnerEntity.h"
43 #include "../BlockEntities/FlowerPotEntity.h"
44 
45 #include "../Bindings/PluginManager.h"
46 
47 
48 
49 
50 
51 // The disabled error is intended, since the Metadata have overlapping indexes
52 // based on the type of the Entity.
53 //
54 // IMPORTANT: The enum is used to automate the sequential counting of the
55 // Metadata indexes. Adding a new enum value causes the following values to
56 // increase their index. Therefore the ordering of the enum values is VERY important!
57 #ifdef __clang__
58  #pragma clang diagnostic push
59  #pragma clang diagnostic ignored "-Wduplicate-enum"
60 #endif
61 
62 namespace Metadata
63 {
65  {
66  // Entity
73  _ENTITY_NEXT, // Used by descendants
74 
75  // Potion
76  POTION_THROWN = _ENTITY_NEXT,
77 
78  // FallingBlock
79  FALLING_BLOCK_POSITION = _ENTITY_NEXT,
80 
81  // AreaEffectCloud
82  AREA_EFFECT_CLOUD_RADIUS = _ENTITY_NEXT,
88 
89  // Arrow
90  ARROW_CRITICAL = _ENTITY_NEXT,
91  _ARROW_NEXT,
92 
93  // TippedArrow
94  TIPPED_ARROW_COLOR = _ARROW_NEXT,
95 
96  // Boat
97  BOAT_LAST_HIT_TIME = _ENTITY_NEXT,
103 
104  // EnderCrystal
107 
108  // Fireball
109  _FIREBALL_NEXT = _ENTITY_NEXT,
110 
111  // WitherSkull
112  WITHER_SKULL_INVULNERABLE = _FIREBALL_NEXT,
113 
114  // Fireworks
115  FIREWORK_INFO = _ENTITY_NEXT,
116 
117  // Hanging
118  _HANGING_NEXT = _ENTITY_NEXT,
119 
120  // ItemFrame
121  ITEM_FRAME_ITEM = _HANGING_NEXT,
123 
124  // Item
125  ITEM_ITEM = _ENTITY_NEXT,
126 
127  // Living
128  LIVING_ACTIVE_HAND = _ENTITY_NEXT,
133  _LIVING_NEXT,
134 
135  // Player
140 
141  // ArmorStand
142  ARMOR_STAND_STATUS = _LIVING_NEXT,
149 
150  // Insentient
151  INSENTIENT_STATUS = _LIVING_NEXT,
152  _INSENTIENT_NEXT,
153 
154  // Ambient
155  _AMBIENT_NEXT = _INSENTIENT_NEXT,
156 
157  // Bat
158  BAT_HANGING = _AMBIENT_NEXT,
159 
160  // Creature
161  _CREATURE_NEXT = _INSENTIENT_NEXT,
162 
163  // Ageable
164  AGEABLE_BABY = _CREATURE_NEXT,
165  _AGEABLE_NEXT,
166 
167  // PolarBear
168  POLAR_BEAR_STANDING = _AGEABLE_NEXT,
169 
170  // Animal
171  _ANIMAL_NEXT = _AGEABLE_NEXT,
172 
173  // Horse
174  HORSE_STATUS = _ANIMAL_NEXT,
179 
180  // Pig
181  PIG_HAS_SADDLE = _ANIMAL_NEXT,
182 
183  // Rabbit
184  RABBIT_TYPE = _ANIMAL_NEXT,
185 
186  // Sheep
187  SHEEP_STATUS = _ANIMAL_NEXT,
188 
189  // TameableAnimal
190  TAMEABLE_ANIMAL_STATUS = _ANIMAL_NEXT,
192  _TAMEABLE_NEXT,
193 
194  // Ocelot
195  OCELOT_TYPE = _TAMEABLE_NEXT,
196 
197  // Wolf
198  WOLF_DAMAGE_TAKEN = _TAMEABLE_NEXT,
201 
202  // Villager
203  VILLAGER_PROFESSION = _AGEABLE_NEXT,
204 
205  // Golem
206  _GOLEM_NEXT = _CREATURE_NEXT,
207 
208  // IronGolem
210 
211  // Shulker
215 
216  // Monster
217  _MONSTER_NEXT = _CREATURE_NEXT,
218 
219  // Blaze
220  BLAZE_ON_FIRE = _MONSTER_NEXT,
221 
222  // Creeper
223  CREEPER_STATE = _MONSTER_NEXT,
226 
227  // Guardian
228  GUARDIAN_STATUS = _MONSTER_NEXT,
230 
231  // Skeleton
232  SKELETON_TYPE = _MONSTER_NEXT,
234 
235  // Spider
236  SPIDER_CLIMBING = _MONSTER_NEXT,
237 
238  // Witch
239  WITCH_AGGRESIVE = _MONSTER_NEXT,
240 
241  // Wither
242  WITHER_FIRST_HEAD_TARGET = _MONSTER_NEXT,
246 
247  // Zombie
248  ZOMBIE_IS_BABY = _MONSTER_NEXT,
252 
253  // Enderman
254  ENDERMAN_CARRIED_BLOCK = _MONSTER_NEXT,
256 
257  // EnderDragon
258  ENDER_DRAGON_DRAGON_PHASE = _INSENTIENT_NEXT,
259 
260  // Flying
261  _FLYING_NEXT = _INSENTIENT_NEXT,
262 
263  // Ghast
264  GHAST_ATTACKING = _FLYING_NEXT,
265 
266  // Slime
267  SLIME_SIZE = _INSENTIENT_NEXT,
268 
269  // Minecart
270  MINECART_SHAKING_POWER = _ENTITY_NEXT,
276  _MINECART_NEXT,
277 
278  // MinecartCommandBlock
281 
282  // MinecartFurnace
283  MINECART_FURNACE_POWERED = _MINECART_NEXT,
284 
285  // TNTPrimed
286  TNT_PRIMED_FUSE_TIME = _ENTITY_NEXT,
287  };
288 }
289 
290 #ifdef __clang__
291  #pragma clang diagnostic pop // Restore ignored clang errors
292 #endif
293 
294 
295 
296 
297 
299 // cProtocol_1_10_0:
300 
301 void cProtocol_1_10_0::SendSoundEffect(const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch)
302 {
303  ASSERT(m_State == 3); // In game mode?
304 
305  cPacketizer Pkt(*this, pktSoundEffect);
306  Pkt.WriteString(a_SoundName);
307  Pkt.WriteVarInt32(0); // Master sound category (may want to be changed to a parameter later)
308  Pkt.WriteBEInt32(FloorC(a_Origin.x * 8.0));
309  Pkt.WriteBEInt32(FloorC(a_Origin.y * 8.0));
310  Pkt.WriteBEInt32(FloorC(a_Origin.z * 8.0));
311  Pkt.WriteBEFloat(a_Volume);
312  Pkt.WriteBEFloat(a_Pitch);
313 }
314 
315 
316 
317 
318 
320 {
321  switch (a_MobType)
322  {
323  case mtPolarBear: return 102;
324  default: return Super::GetProtocolMobType(a_MobType);
325  }
326 }
327 
328 
329 
330 
331 
333 {
334  return Version::v1_10_0;
335 }
336 
337 
338 
339 
340 
342 {
343  HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status);
345 }
346 
347 
348 
349 
350 
351 void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const
352 {
353  using namespace Metadata;
354 
355  // Common metadata:
356  Int8 Flags = 0;
357  if (a_Entity.IsOnFire())
358  {
359  Flags |= 0x01;
360  }
361  if (a_Entity.IsCrouched())
362  {
363  Flags |= 0x02;
364  }
365  if (a_Entity.IsSprinting())
366  {
367  Flags |= 0x08;
368  }
369  if (a_Entity.IsRclking())
370  {
371  Flags |= 0x10;
372  }
373  if (a_Entity.IsInvisible())
374  {
375  Flags |= 0x20;
376  }
377  a_Pkt.WriteBEUInt8(ENTITY_FLAGS); // Index
378  a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type
379  a_Pkt.WriteBEInt8(Flags);
380 
381  switch (a_Entity.GetEntityType())
382  {
383  case cEntity::etPlayer:
384  {
385  auto & Player = static_cast<const cPlayer &>(a_Entity);
386 
387  // TODO Set player custom name to their name.
388  // Then it's possible to move the custom name of mobs to the entities
389  // and to remove the "special" player custom name.
392  a_Pkt.WriteString(Player.GetName());
393 
396  a_Pkt.WriteBEFloat(static_cast<float>(Player.GetHealth()));
397 
400  a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetSkinParts()));
401 
404  a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1);
405  break;
406  }
407  case cEntity::etPickup:
408  {
409  a_Pkt.WriteBEUInt8(ITEM_ITEM);
411  WriteItem(a_Pkt, static_cast<const cPickup &>(a_Entity).GetItem());
412  break;
413  }
414  case cEntity::etMinecart:
415  {
418 
419  // The following expression makes Minecarts shake more with less health or higher damage taken
420  auto & Minecart = static_cast<const cMinecart &>(a_Entity);
421  auto maxHealth = a_Entity.GetMaxHealth();
422  auto curHealth = a_Entity.GetHealth();
423  a_Pkt.WriteVarInt32(static_cast<UInt32>((maxHealth - curHealth) * Minecart.LastDamage() * 4));
424 
425  a_Pkt.WriteBEUInt8(MINECART_SHAKING_DIRECTION); // (doesn't seem to effect anything)
427  a_Pkt.WriteVarInt32(1);
428 
429  a_Pkt.WriteBEUInt8(MINECART_SHAKING_MULTIPLIER); // or damage taken
431  a_Pkt.WriteBEFloat(static_cast<float>(Minecart.LastDamage() + 10));
432 
433  if (Minecart.GetPayload() == cMinecart::mpNone)
434  {
435  auto & RideableMinecart = static_cast<const cRideableMinecart &>(Minecart);
436  const cItem & MinecartContent = RideableMinecart.GetContent();
437  if (!MinecartContent.IsEmpty())
438  {
441  int Content = MinecartContent.m_ItemType;
442  Content |= MinecartContent.m_ItemDamage << 8;
443  a_Pkt.WriteVarInt32(static_cast<UInt32>(Content));
444 
447  a_Pkt.WriteVarInt32(static_cast<UInt32>(RideableMinecart.GetBlockHeight()));
448 
451  a_Pkt.WriteBool(true);
452  }
453  }
454  else if (Minecart.GetPayload() == cMinecart::mpFurnace)
455  {
458  a_Pkt.WriteBool(static_cast<const cMinecartWithFurnace &>(Minecart).IsFueled());
459  }
460  break;
461  } // case etMinecart
462 
464  {
465  auto & Projectile = static_cast<const cProjectileEntity &>(a_Entity);
466  switch (Projectile.GetProjectileKind())
467  {
469  {
472  a_Pkt.WriteBEInt8(static_cast<const cArrowEntity &>(Projectile).IsCritical() ? 1 : 0);
473  break;
474  }
476  {
477  a_Pkt.WriteBEUInt8(FIREWORK_INFO); // Firework item used for this firework
479  WriteItem(a_Pkt, static_cast<const cFireworkEntity &>(Projectile).GetItem());
480  break;
481  }
483  {
484  a_Pkt.WriteBEUInt8(POTION_THROWN); // Potion item which was thrown
486  WriteItem(a_Pkt, static_cast<const cSplashPotionEntity &>(Projectile).GetItem());
487  }
488  default:
489  {
490  break;
491  }
492  }
493  break;
494  } // case etProjectile
495 
496  case cEntity::etMonster:
497  {
498  WriteMobMetadata(a_Pkt, static_cast<const cMonster &>(a_Entity));
499  break;
500  }
501 
502  case cEntity::etBoat:
503  {
504  auto & Boat = static_cast<const cBoat &>(a_Entity);
505 
508  a_Pkt.WriteVarInt32(static_cast<UInt32>(Boat.GetLastDamage()));
509 
512  a_Pkt.WriteVarInt32(static_cast<UInt32>(Boat.GetForwardDirection()));
513 
516  a_Pkt.WriteBEFloat(Boat.GetDamageTaken());
517 
518  a_Pkt.WriteBEInt8(BOAT_TYPE);
520  a_Pkt.WriteVarInt32(static_cast<UInt32>(Boat.GetMaterial()));
521 
524  a_Pkt.WriteBool(Boat.IsRightPaddleUsed());
525 
528  a_Pkt.WriteBool(Boat.IsLeftPaddleUsed());
529 
530  break;
531  } // case etBoat
532 
534  {
535  auto & Frame = static_cast<const cItemFrame &>(a_Entity);
538  WriteItem(a_Pkt, Frame.GetItem());
541  a_Pkt.WriteVarInt32(Frame.GetItemRotation());
542  break;
543  } // case etItemFrame
544 
546  {
547  const auto & EnderCrystal = static_cast<const cEnderCrystal &>(a_Entity);
550  a_Pkt.WriteBool(EnderCrystal.DisplaysBeam());
551  if (EnderCrystal.DisplaysBeam())
552  {
553  a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget());
554  }
557  a_Pkt.WriteBool(EnderCrystal.ShowsBottom());
558  break;
559  } // case etEnderCrystal
560 
561  default:
562  {
563  break;
564  }
565  }
566 }
567 
568 
569 
570 
571 
572 void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const
573 {
574  using namespace Metadata;
575 
576  // Living entity metadata
577  if (a_Mob.HasCustomName())
578  {
579  // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up?
582  a_Pkt.WriteString(a_Mob.GetCustomName());
583 
584  a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME_VISIBLE); // Custom name always visible
586  a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible());
587  }
588 
591  a_Pkt.WriteBEFloat(static_cast<float>(a_Mob.GetHealth()));
592 
593  switch (a_Mob.GetMobType())
594  {
595  case mtBat:
596  {
597  auto & Bat = static_cast<const cBat &>(a_Mob);
598  a_Pkt.WriteBEUInt8(BAT_HANGING);
600  a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0);
601  break;
602  } // case mtBat
603 
604  case mtChicken:
605  {
606  auto & Chicken = static_cast<const cChicken &>(a_Mob);
607 
608  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
610  a_Pkt.WriteBool(Chicken.IsBaby());
611  break;
612  } // case mtChicken
613 
614  case mtCow:
615  {
616  auto & Cow = static_cast<const cCow &>(a_Mob);
617 
618  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
620  a_Pkt.WriteBool(Cow.IsBaby());
621  break;
622  } // case mtCow
623 
624  case mtCreeper:
625  {
626  auto & Creeper = static_cast<const cCreeper &>(a_Mob);
627  a_Pkt.WriteBEUInt8(CREEPER_STATE); // (idle or "blowing")
629  a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : static_cast<UInt32>(-1));
630 
633  a_Pkt.WriteBool(Creeper.IsCharged());
634 
637  a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel());
638  break;
639  } // case mtCreeper
640 
641  case mtEnderman:
642  {
643  auto & Enderman = static_cast<const cEnderman &>(a_Mob);
646  UInt32 Carried = 0;
647  Carried |= static_cast<UInt32>(Enderman.GetCarriedBlock() << 4);
648  Carried |= Enderman.GetCarriedMeta();
649  a_Pkt.WriteVarInt32(Carried);
650 
653  a_Pkt.WriteBool(Enderman.IsScreaming());
654  break;
655  } // case mtEnderman
656 
657  case mtGhast:
658  {
659  auto & Ghast = static_cast<const cGhast &>(a_Mob);
662  a_Pkt.WriteBool(Ghast.IsCharging());
663  break;
664  } // case mtGhast
665 
666  case mtHorse:
667  {
668  auto & Horse = static_cast<const cHorse &>(a_Mob);
669  Int8 Flags = 0;
670  if (Horse.IsTame())
671  {
672  Flags |= 0x02;
673  }
674  if (Horse.IsSaddled())
675  {
676  Flags |= 0x04;
677  }
678  if (Horse.IsChested())
679  {
680  Flags |= 0x08;
681  }
682  if (Horse.IsEating())
683  {
684  Flags |= 0x20;
685  }
686  if (Horse.IsRearing())
687  {
688  Flags |= 0x40;
689  }
690  if (Horse.IsMthOpen())
691  {
692  Flags |= 0x80;
693  }
694  a_Pkt.WriteBEUInt8(HORSE_STATUS);
696  a_Pkt.WriteBEInt8(Flags);
697 
698  a_Pkt.WriteBEUInt8(HORSE_TYPE);
700  a_Pkt.WriteVarInt32(static_cast<UInt32>(Horse.GetHorseType()));
701 
702  a_Pkt.WriteBEUInt8(HORSE_VARIANT); // Color / style
704  int Appearance = 0;
705  Appearance = Horse.GetHorseColor();
706  Appearance |= Horse.GetHorseStyle() << 8;
707  a_Pkt.WriteVarInt32(static_cast<UInt32>(Appearance));
708 
709  a_Pkt.WriteBEUInt8(HORSE_ARMOR);
711  a_Pkt.WriteVarInt32(static_cast<UInt32>(Horse.GetHorseArmour()));
712 
713  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
715  a_Pkt.WriteBool(Horse.IsBaby());
716  break;
717  } // case mtHorse
718 
719  case mtMagmaCube:
720  {
721  auto & MagmaCube = static_cast<const cMagmaCube &>(a_Mob);
722  a_Pkt.WriteBEUInt8(SLIME_SIZE);
724  a_Pkt.WriteVarInt32(static_cast<UInt32>(MagmaCube.GetSize()));
725  break;
726  } // case mtMagmaCube
727 
728  case mtOcelot:
729  {
730  auto & Ocelot = static_cast<const cOcelot &>(a_Mob);
731 
732  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
734  a_Pkt.WriteBool(Ocelot.IsBaby());
735  break;
736  } // case mtOcelot
737 
738  case mtPig:
739  {
740  auto & Pig = static_cast<const cPig &>(a_Mob);
741 
742  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
744  a_Pkt.WriteBool(Pig.IsBaby());
745 
748  a_Pkt.WriteBool(Pig.IsSaddled());
749 
750  break;
751  } // case mtPig
752 
753  case mtRabbit:
754  {
755  auto & Rabbit = static_cast<const cRabbit &>(a_Mob);
756  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
758  a_Pkt.WriteBool(Rabbit.IsBaby());
759 
760  a_Pkt.WriteBEUInt8(RABBIT_TYPE);
762  a_Pkt.WriteVarInt32(static_cast<UInt32>(Rabbit.GetRabbitType()));
763  break;
764  } // case mtRabbit
765 
766  case mtSheep:
767  {
768  auto & Sheep = static_cast<const cSheep &>(a_Mob);
769 
770  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
772  a_Pkt.WriteBool(Sheep.IsBaby());
773 
774  a_Pkt.WriteBEUInt8(SHEEP_STATUS);
776  Int8 SheepMetadata = 0;
777  SheepMetadata = static_cast<Int8>(Sheep.GetFurColor());
778  if (Sheep.IsSheared())
779  {
780  SheepMetadata |= 0x10;
781  }
782  a_Pkt.WriteBEInt8(SheepMetadata);
783  break;
784  } // case mtSheep
785 
786  case mtSkeleton:
787  {
788  auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
791  a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00);
792 
795  a_Pkt.WriteBool(Skeleton.IsChargingBow());
796  break;
797  } // case mtSkeleton
798 
799  case mtSlime:
800  {
801  auto & Slime = static_cast<const cSlime &>(a_Mob);
802  a_Pkt.WriteBEUInt8(SLIME_SIZE);
804  a_Pkt.WriteVarInt32(static_cast<UInt32>(Slime.GetSize()));
805  break;
806  } // case mtSlime
807 
808  case mtVillager:
809  {
810  auto & Villager = static_cast<const cVillager &>(a_Mob);
811  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
813  a_Pkt.WriteBool(Villager.IsBaby());
814 
817  a_Pkt.WriteVarInt32(static_cast<UInt32>(Villager.GetVilType()));
818  break;
819  } // case mtVillager
820 
821  case mtWitch:
822  {
823  auto & Witch = static_cast<const cWitch &>(a_Mob);
826  a_Pkt.WriteBool(Witch.IsAngry());
827  break;
828  } // case mtWitch
829 
830  case mtWither:
831  {
832  auto & Wither = static_cast<const cWither &>(a_Mob);
835  a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks());
836 
837  // TODO: Use boss bar packet for health
838  break;
839  } // case mtWither
840 
841  case mtWitherSkeleton:
842  {
845  a_Pkt.WriteVarInt32(1); // Is wither skeleton
846  break;
847  } // case mtWitherSkeleton
848 
849  case mtWolf:
850  {
851  auto & Wolf = static_cast<const cWolf &>(a_Mob);
852  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
854  a_Pkt.WriteBool(Wolf.IsBaby());
855 
856  Int8 WolfStatus = 0;
857  if (Wolf.IsSitting())
858  {
859  WolfStatus |= 0x1;
860  }
861  if (Wolf.IsAngry())
862  {
863  WolfStatus |= 0x2;
864  }
865  if (Wolf.IsTame())
866  {
867  WolfStatus |= 0x4;
868  }
871  a_Pkt.WriteBEInt8(WolfStatus);
872 
875  a_Pkt.WriteBEFloat(static_cast<float>(a_Mob.GetHealth())); // TODO Not use the current health
876 
877  a_Pkt.WriteBEUInt8(WOLF_BEGGING);
879  a_Pkt.WriteBool(Wolf.IsBegging());
880 
883  a_Pkt.WriteVarInt32(static_cast<UInt32>(Wolf.GetCollarColor()));
884  break;
885  } // case mtWolf
886 
887  case mtHusk:
888  case mtZombie:
889  {
890  auto & Zombie = static_cast<const cZombie &>(a_Mob);
893  a_Pkt.WriteBool(Zombie.IsBaby());
894 
895  a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
897  a_Pkt.WriteVarInt32(0);
898 
901  a_Pkt.WriteBool(false);
902  break;
903  } // case mtZombie
904 
905  case mtZombiePigman:
906  {
907  auto & ZombiePigman = static_cast<const cZombiePigman &>(a_Mob);
908  a_Pkt.WriteBEUInt8(AGEABLE_BABY);
910  a_Pkt.WriteBool(ZombiePigman.IsBaby());
911  break;
912  } // case mtZombiePigman
913 
914  case mtZombieVillager:
915  {
916  auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
919  a_Pkt.WriteBool(ZombieVillager.IsBaby());
920 
921  a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
923  a_Pkt.WriteVarInt32(ZombieVillager.GetProfession());
924 
927  a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1);
928  break;
929  } // case mtZombieVillager
930 
931  case mtBlaze:
932  case mtElderGuardian:
933  case mtGuardian:
934  {
935  // TODO: Mobs with extra fields that aren't implemented
936  break;
937  }
938  case mtCat:
939 
940  case mtPolarBear:
941 
942  case mtShulker:
943 
944  case mtDonkey:
945  case mtMule:
946  case mtSkeletonHorse:
947  case mtZombieHorse:
948  {
949  // Todo: Mobs not added yet. Grouped ones have the same metadata
950  ASSERT(!"cProtocol_1_10::WriteMobMetadata: received unimplemented type");
951  break;
952  }
953 
954  case mtCaveSpider:
955  case mtEnderDragon:
956  case mtEndermite:
957  case mtGiant:
958  case mtIronGolem:
959  case mtMooshroom:
960  case mtSilverfish:
961  case mtSnowGolem:
962  case mtStray:
963  case mtSpider:
964  case mtSquid:
965  {
966  // Entities without additional metadata
967  break;
968  }
969 
970  default: UNREACHABLE("cProtocol_1_10::WriteMobMetadata: received mob of invalid type");
971  } // switch (a_Mob.GetType())
972 }
#define UNREACHABLE(x)
Definition: Globals.h:288
unsigned int UInt32
Definition: Globals.h:157
signed char Int8
Definition: Globals.h:154
unsigned char UInt8
Definition: Globals.h:159
#define ASSERT(x)
Definition: Globals.h:276
std::enable_if< std::is_arithmetic< T >::value, C >::type FloorC(T a_Value)
Floors a value, then casts it to C (an int by default).
Definition: Globals.h:347
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
@ mtPolarBear
Definition: MonsterTypes.h:51
@ 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
@ mtHusk
Definition: MonsterTypes.h:36
@ 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
@ 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
@ Rabbit
@ Chicken
@ Minecart
std::string AString
Definition: StringUtils.h:11
@ ENDER_CRYSTAL_SHOW_BOTTOM
@ ARMOR_STAND_LEFT_LEG_ROTATION
@ ARMOR_STAND_BODY_ROTATION
@ MINECART_COMMAND_BLOCK_COMMAND
@ WITHER_SECOND_HEAD_TARGET
@ ARMOR_STAND_RIGHT_LEG_ROTATION
@ AREA_EFFECT_CLOUD_RADIUS
@ LIVING_NUMBER_OF_ARROWS
@ LIVING_POTION_EFFECT_COLOR
@ ENDERMAN_CARRIED_BLOCK
@ MINECART_FURNACE_POWERED
@ PLAYER_DISPLAYED_SKIN_PARTS
@ TAMEABLE_ANIMAL_OWNER
@ WITHER_INVULNERABLE_TIMER
@ ARMOR_STAND_LEFT_ARM_ROTATION
@ LIVING_POTION_EFFECT_AMBIENT
@ IRON_GOLEM_PLAYER_CREATED
@ ARMOR_STAND_HEAD_ROTATION
@ BOAT_LEFT_PADDLE_TURNING
@ MINECART_SHAKING_POWER
@ SKELETON_ARMS_SWINGING
@ MINECART_SHAKING_DIRECTION
@ ENTITY_CUSTOM_NAME
@ AREA_EFFECT_CLOUD_COLOR
@ AREA_EFFECT_CLOUD_PARTICLE_ID
@ PLAYER_ADDITIONAL_HEARTHS
@ TIPPED_ARROW_COLOR
@ ENDER_CRYSTAL_BEAM_TARGET
@ ARMOR_STAND_RIGHT_ARM_ROTATION
@ SHULKER_FACING_DIRECTION
@ AREA_EFFECT_CLOUD_PARTICLE_PARAMETER1
@ TNT_PRIMED_FUSE_TIME
@ TAMEABLE_ANIMAL_STATUS
@ WITHER_FIRST_HEAD_TARGET
@ MINECART_BLOCK_ID_META
@ ENDER_DRAGON_DRAGON_PHASE
@ ENTITY_CUSTOM_NAME_VISIBLE
@ BOAT_FORWARD_DIRECTION
@ BOAT_RIGHT_PADDLE_TURNING
@ AREA_EFFECT_CLOUD_PARTICLE_PARAMETER2
@ AREA_EFFECT_CLOUD_SINGLE_POINT_EFFECT
@ ZOMBIE_HANDS_RISED_UP
@ SHULKER_SHIELD_HEIGHT
@ FALLING_BLOCK_POSITION
@ WITHER_THIRD_HEAD_TARGET
@ SHULKER_ATTACHMENT_FALLING_BLOCK_POSITION
@ WITHER_SKULL_INVULNERABLE
@ BOAT_LAST_HIT_TIME
@ MINECART_COMMAND_BLOCK_LAST_OUTPUT
@ MINECART_SHAKING_MULTIPLIER
An object that can store incoming bytes and lets its clients read the bytes sequentially The bytes ar...
Definition: ByteBuffer.h:32
void HandleResourcePack(UInt8 a_Status)
bool IsCritical(void) const
Returns true if the arrow is set as critical.
Definition: ArrowEntity.h:70
Definition: Boat.h:20
Definition: Entity.h:76
virtual bool IsRclking(void) const
Definition: Entity.h:490
virtual bool IsCrouched(void) const
Definition: Entity.h:486
float GetMaxHealth(void) const
Definition: Entity.h:407
eEntityType GetEntityType(void) const
Definition: Entity.h:156
virtual bool IsOnFire(void) const
Definition: Entity.h:489
virtual bool IsInvisible(void) const
Definition: Entity.h:488
float GetHealth(void) const
Returns the health of this entity.
Definition: Entity.h:367
@ 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
@ mpNone
Definition: Minecart.h:31
@ mpFurnace
Definition: Minecart.h:33
bool IsFueled(void) const
Definition: Minecart.h:201
Definition: Pickup.h:20
Definition: Player.h:29
Definition: Item.h:37
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
short m_ItemType
Definition: Item.h:163
short m_ItemDamage
Definition: Item.h:165
Definition: Bat.h:12
Definition: Cow.h:12
Definition: Ghast.h:12
Definition: Horse.h:14
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
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 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 WriteBEFloat(float a_Value)
Definition: Packetizer.h:129
void WriteString(const AString &a_Value)
Definition: Packetizer.h:147
void WriteBEUInt8(UInt8 a_Value)
Definition: Packetizer.h:81
void WriteBEInt8(Int8 a_Value)
Definition: Packetizer.h:87
@ pktSoundEffect
Definition: Protocol.h:108
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 WriteEntityMetadata(cPacketizer &a_Pkt, const cEntity &a_Entity) const override
Writes the metadata for the specified entity, not including the terminating 0x7f.
virtual Version GetProtocolVersion() const override
Returns the protocol version.
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override
Converts eMonsterType to protocol-specific mob types.
virtual void HandlePacketResourcePackStatus(cByteBuffer &a_ByteBuffer) override
virtual void SendSoundEffect(const AString &a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) override
virtual void WriteMobMetadata(cPacketizer &a_Pkt, const cMonster &a_Mob) const override
Writes the mob-specific metadata for the specified mob.
State m_State
State of the protocol.
Definition: Protocol_1_8.h:143
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override
Converts eMonsterType to protocol-specific mob types.
virtual void WriteItem(cPacketizer &a_Pkt, const cItem &a_Item) const override
Writes the item data into a packet.
@ METADATA_TYPE_OPTIONAL_POSITION
Definition: Protocol_1_9.h:116
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17