2016-12-15 19:21:43 +00:00
// Protocol_1_11.cpp
/*
Implements the 1.11 protocol classes :
- cProtocol_1_11_0
- release 1.11 protocol ( # 315 )
2019-09-09 16:22:37 +00:00
- cProtocol_1_11_1
- release 1.11 .1 protocol ( # 316 )
2016-12-15 19:21:43 +00:00
*/
# include "Globals.h"
# include "Protocol_1_11.h"
# include "Packetizer.h"
2017-06-05 13:49:36 +00:00
# include "../WorldStorage/FastNBT.h"
2017-03-03 09:59:17 +00:00
# include "../Entities/Boat.h"
2020-10-29 20:47:20 +00:00
# include "../Entities/EnderCrystal.h"
2017-03-03 09:59:17 +00:00
# include "../Entities/ExpOrb.h"
# include "../Entities/Minecart.h"
# include "../Entities/FallingBlock.h"
# include "../Entities/Painting.h"
# include "../Entities/Pickup.h"
# include "../Entities/Player.h"
# include "../Entities/ItemFrame.h"
# include "../Entities/ArrowEntity.h"
# include "../Entities/FireworkEntity.h"
# include "../Entities/SplashPotionEntity.h"
# include "../Mobs/IncludeAllMonsters.h"
2017-07-07 07:31:45 +00:00
# include "../BlockEntities/BedEntity.h"
2017-06-05 13:49:36 +00:00
# include "../BlockEntities/MobSpawnerEntity.h"
2016-12-15 19:21:43 +00:00
# include "../Root.h"
# include "../Server.h"
# include "../ClientHandle.h"
# include "../CompositeChat.h"
2020-05-09 14:51:15 +00:00
# include "../JsonUtils.h"
2016-12-15 19:21:43 +00:00
# include "../Bindings/PluginManager.h"
2017-03-03 09:59:17 +00:00
// The disabled error is intended, since the Metadata have overlapping indexes
// based on the type of the Entity.
//
// IMPORTANT: The enum is used to automate the sequential counting of the
// Metadata indexes. Adding a new enum value causes the following values to
// increase their index. Therefore the ordering of the enum values is VERY important!
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wduplicate-enum"
# endif
2020-05-04 10:50:02 +00:00
namespace Metadata_1_11
2017-03-03 09:59:17 +00:00
{
2020-05-04 10:50:02 +00:00
enum MetadataIndex
2017-03-03 09:59:17 +00:00
{
// Entity
ENTITY_FLAGS ,
ENTITY_AIR ,
ENTITY_CUSTOM_NAME ,
ENTITY_CUSTOM_NAME_VISIBLE ,
ENTITY_SILENT ,
ENTITY_NO_GRAVITY ,
_ENTITY_NEXT , // Used by descendants
// Potion
POTION_THROWN = _ENTITY_NEXT ,
// FallingBlock
FALLING_BLOCK_POSITION = _ENTITY_NEXT ,
// AreaEffectCloud
AREA_EFFECT_CLOUD_RADIUS = _ENTITY_NEXT ,
AREA_EFFECT_CLOUD_COLOR ,
AREA_EFFECT_CLOUD_SINGLE_POINT_EFFECT ,
AREA_EFFECT_CLOUD_PARTICLE_ID ,
AREA_EFFECT_CLOUD_PARTICLE_PARAMETER1 ,
AREA_EFFECT_CLOUD_PARTICLE_PARAMETER2 ,
// Arrow
ARROW_CRITICAL = _ENTITY_NEXT ,
_ARROW_NEXT ,
// TippedArrow
TIPPED_ARROW_COLOR = _ARROW_NEXT ,
// Boat
BOAT_LAST_HIT_TIME = _ENTITY_NEXT ,
BOAT_FORWARD_DIRECTION ,
BOAT_DAMAGE_TAKEN ,
BOAT_TYPE ,
BOAT_RIGHT_PADDLE_TURNING ,
BOAT_LEFT_PADDLE_TURNING ,
// EnderCrystal
ENDER_CRYSTAL_BEAM_TARGET = _ENTITY_NEXT ,
ENDER_CRYSTAL_SHOW_BOTTOM ,
// Fireball
_FIREBALL_NEXT = _ENTITY_NEXT ,
// WitherSkull
WITHER_SKULL_INVULNERABLE = _FIREBALL_NEXT ,
// Fireworks
FIREWORK_INFO = _ENTITY_NEXT ,
FIREWORK_BOOSTED_ENTITY_ID , // 1.11.1 only
// Hanging
_HANGING_NEXT = _ENTITY_NEXT ,
// ItemFrame
ITEM_FRAME_ITEM = _HANGING_NEXT ,
ITEM_FRAME_ROTATION ,
// Item
ITEM_ITEM = _ENTITY_NEXT ,
// Living
LIVING_ACTIVE_HAND = _ENTITY_NEXT ,
LIVING_HEALTH ,
LIVING_POTION_EFFECT_COLOR ,
LIVING_POTION_EFFECT_AMBIENT ,
LIVING_NUMBER_OF_ARROWS ,
_LIVING_NEXT ,
// Player
PLAYER_ADDITIONAL_HEARTHS = _LIVING_NEXT ,
PLAYER_SCORE ,
PLAYER_DISPLAYED_SKIN_PARTS ,
PLAYER_MAIN_HAND ,
// ArmorStand
ARMOR_STAND_STATUS = _LIVING_NEXT ,
ARMOR_STAND_HEAD_ROTATION ,
ARMOR_STAND_BODY_ROTATION ,
ARMOR_STAND_LEFT_ARM_ROTATION ,
ARMOR_STAND_RIGHT_ARM_ROTATION ,
ARMOR_STAND_LEFT_LEG_ROTATION ,
ARMOR_STAND_RIGHT_LEG_ROTATION ,
// Insentient
INSENTIENT_STATUS = _LIVING_NEXT ,
_INSENTIENT_NEXT ,
// Ambient
_AMBIENT_NEXT = _INSENTIENT_NEXT ,
// Bat
BAT_HANGING = _AMBIENT_NEXT ,
// Creature
_CREATURE_NEXT = _INSENTIENT_NEXT ,
// Ageable
AGEABLE_BABY = _CREATURE_NEXT ,
_AGEABLE_NEXT ,
// PolarBear
POLAR_BEAR_STANDING = _AGEABLE_NEXT ,
// Animal
_ANIMAL_NEXT = _AGEABLE_NEXT ,
// Abstract horse
ABSTRACT_HORSE_STATUS = _ANIMAL_NEXT ,
ABSTRACT_HORSE_OWNER ,
_ABSTRACT_HORSE_NEXT ,
// Horse
HORSE_VARIANT = _ABSTRACT_HORSE_NEXT ,
HORSE_ARMOR ,
// Chested horse
CHESTED_HORSE_CHESTED = _ABSTRACT_HORSE_NEXT ,
_CHESTED_HORSE_NEXT ,
// Llama
LLAMA_STRENGTH = _CHESTED_HORSE_NEXT ,
LLAMA_CARPET_COLOR ,
LLAMA_VARIANT ,
// Pig
PIG_HAS_SADDLE = _ANIMAL_NEXT ,
PIG_TOTAL_CARROT_ON_A_STICK_BOOST , // 1.11.1 only
// Rabbit
RABBIT_TYPE = _ANIMAL_NEXT ,
// Sheep
SHEEP_STATUS = _ANIMAL_NEXT ,
// TameableAnimal
TAMEABLE_ANIMAL_STATUS = _ANIMAL_NEXT ,
TAMEABLE_ANIMAL_OWNER ,
_TAMEABLE_NEXT ,
// Ocelot
OCELOT_TYPE = _TAMEABLE_NEXT ,
// Wolf
WOLF_DAMAGE_TAKEN = _TAMEABLE_NEXT ,
WOLF_BEGGING ,
WOLF_COLLAR_COLOR ,
// Villager
VILLAGER_PROFESSION = _AGEABLE_NEXT ,
// Golem
_GOLEM_NEXT = _CREATURE_NEXT ,
// IronGolem
IRON_GOLEM_PLAYER_CREATED = _GOLEM_NEXT ,
// Shulker
SHULKER_FACING_DIRECTION = _GOLEM_NEXT ,
SHULKER_ATTACHMENT_FALLING_BLOCK_POSITION ,
SHULKER_SHIELD_HEIGHT ,
// Monster
_MONSTER_NEXT = _CREATURE_NEXT ,
// Blaze
BLAZE_ON_FIRE = _MONSTER_NEXT ,
// Creeper
CREEPER_STATE = _MONSTER_NEXT ,
CREEPER_POWERED ,
CREEPER_IGNITED ,
// Guardian
GUARDIAN_STATUS = _MONSTER_NEXT ,
GUARDIAN_TARGET ,
// Abstract Skeleton
ABSTRACT_SKELETON_ARMS_SWINGING = _MONSTER_NEXT ,
// Spider
SPIDER_CLIMBING = _MONSTER_NEXT ,
// Witch
WITCH_AGGRESIVE = _MONSTER_NEXT ,
// Wither
WITHER_FIRST_HEAD_TARGET = _MONSTER_NEXT ,
WITHER_SECOND_HEAD_TARGET ,
WITHER_THIRD_HEAD_TARGET ,
WITHER_INVULNERABLE_TIMER ,
// Zombie
ZOMBIE_IS_BABY = _MONSTER_NEXT ,
ZOMBIE_UNUSED , // Was type
ZOMBIE_HANDS_RISED_UP ,
_ZOMBIE_NEXT ,
// Zombie villager
ZOMBIE_VILLAGER_CONVERTING = _ZOMBIE_NEXT ,
ZOMBIE_VILLAGER_PROFESSION ,
// Enderman
ENDERMAN_CARRIED_BLOCK = _MONSTER_NEXT ,
ENDERMAN_SCREAMING ,
// Evocation illager
EVOKER_SPELL = _MONSTER_NEXT ,
// Vex
VEX_FLAGS = _MONSTER_NEXT ,
// Vindication illager
VINDICATOR_FLAGS = _MONSTER_NEXT ,
// EnderDragon
ENDER_DRAGON_DRAGON_PHASE = _INSENTIENT_NEXT ,
// Flying
_FLYING_NEXT = _INSENTIENT_NEXT ,
// Ghast
GHAST_ATTACKING = _FLYING_NEXT ,
// Slime
SLIME_SIZE = _INSENTIENT_NEXT ,
// Minecart
MINECART_SHAKING_POWER = _ENTITY_NEXT ,
MINECART_SHAKING_DIRECTION ,
MINECART_SHAKING_MULTIPLIER ,
MINECART_BLOCK_ID_META ,
MINECART_BLOCK_Y ,
MINECART_SHOW_BLOCK ,
_MINECART_NEXT ,
// MinecartCommandBlock
MINECART_COMMAND_BLOCK_COMMAND = _MINECART_NEXT ,
MINECART_COMMAND_BLOCK_LAST_OUTPUT ,
// MinecartFurnace
MINECART_FURNACE_POWERED = _MINECART_NEXT ,
// TNTPrimed
TNT_PRIMED_FUSE_TIME = _ENTITY_NEXT ,
} ;
}
# ifdef __clang__
# pragma clang diagnostic pop // Restore ignored clang errors
# endif
2016-12-15 19:21:43 +00:00
# define HANDLE_READ(ByteBuf, Proc, Type, Var) \
Type Var ; \
2019-08-11 09:39:43 +00:00
do { \
if ( ! ByteBuf . Proc ( Var ) ) \
{ \
return ; \
} \
} while ( false )
2016-12-15 19:21:43 +00:00
2020-07-19 19:49:29 +00:00
////////////////////////////////////////////////////////////////////////////////
// cProtocol_1_11_0:
2016-12-15 19:21:43 +00:00
2020-05-04 08:10:47 +00:00
void cProtocol_1_11_0 : : SendCollectEntity ( const cEntity & a_Collected , const cEntity & a_Collector , unsigned a_Count )
2016-12-15 19:21:43 +00:00
{
ASSERT ( m_State = = 3 ) ; // In game mode?
2019-09-09 16:22:37 +00:00
cPacketizer Pkt ( * this , pktCollectEntity ) ;
2020-05-04 08:10:47 +00:00
Pkt . WriteVarInt32 ( a_Collected . GetUniqueID ( ) ) ;
Pkt . WriteVarInt32 ( a_Collector . GetUniqueID ( ) ) ;
2016-12-15 19:21:43 +00:00
Pkt . WriteVarInt32 ( static_cast < UInt32 > ( a_Count ) ) ;
}
2021-04-09 22:17:01 +00:00
void cProtocol_1_11_0 : : SendEntityAnimation ( const cEntity & a_Entity , const EntityAnimation a_Animation )
{
switch ( a_Animation )
{
case EntityAnimation : : EggCracks :
case EntityAnimation : : SnowballPoofs :
{
// Vanilla stopped doing clientside prediction for thrown projectile particle effects (for some reason).
// But they're still doing motion prediction, and latency exists, hence re-send the server position to avoid particle effects happening inside a block:
SendEntityPosition ( a_Entity ) ;
break ;
}
case EntityAnimation : : PawnChestEquipmentBreaks :
case EntityAnimation : : PawnFeetEquipmentBreaks :
case EntityAnimation : : PawnHeadEquipmentBreaks :
case EntityAnimation : : PawnLegsEquipmentBreaks :
case EntityAnimation : : PawnMainHandEquipmentBreaks :
case EntityAnimation : : PawnOffHandEquipmentBreaks :
{
const auto Position = a_Entity . GetPosition ( ) ;
// 1.11 dropped the automatic particle effect + sound on item break. Emulate at least some of it:
SendSoundEffect ( " entity.item.break " , Position . x , Position . y , Position . z , 1 , 0.75f + ( ( a_Entity . GetUniqueID ( ) * 23 ) % 32 ) / 64.f ) ;
break ;
}
default : break ;
}
Super : : SendEntityAnimation ( a_Entity , a_Animation ) ;
}
2016-12-15 19:21:43 +00:00
void cProtocol_1_11_0 : : SendHideTitle ( void )
{
ASSERT ( m_State = = 3 ) ; // In game mode?
2019-09-09 16:22:37 +00:00
cPacketizer Pkt ( * this , pktTitle ) ;
2016-12-15 19:21:43 +00:00
Pkt . WriteVarInt32 ( 4 ) ; // Hide title
}
void cProtocol_1_11_0 : : SendResetTitle ( void )
{
ASSERT ( m_State = = 3 ) ; // In game mode?
2019-09-09 16:22:37 +00:00
cPacketizer Pkt ( * this , pktTitle ) ;
2016-12-15 19:21:43 +00:00
Pkt . WriteVarInt32 ( 5 ) ; // Reset title
}
void cProtocol_1_11_0 : : SendSpawnMob ( const cMonster & a_Mob )
{
ASSERT ( m_State = = 3 ) ; // In game mode?
2020-11-22 23:41:13 +00:00
const auto MobType = GetProtocolMobType ( a_Mob . GetMobType ( ) ) ;
// If the type is not valid in this protocol bail out:
if ( MobType = = 0 )
{
return ;
}
2019-09-09 16:22:37 +00:00
cPacketizer Pkt ( * this , pktSpawnMob ) ;
2016-12-15 19:21:43 +00:00
Pkt . WriteVarInt32 ( a_Mob . GetUniqueID ( ) ) ;
2017-02-21 15:11:28 +00:00
// TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
Pkt . WriteBEUInt64 ( 0 ) ;
Pkt . WriteBEUInt64 ( a_Mob . GetUniqueID ( ) ) ;
2020-11-22 23:41:13 +00:00
Pkt . WriteVarInt32 ( MobType ) ;
2020-05-04 08:10:47 +00:00
Vector3d LastSentPos = a_Mob . GetLastSentPosition ( ) ;
2020-03-05 10:58:46 +00:00
Pkt . WriteBEDouble ( LastSentPos . x ) ;
Pkt . WriteBEDouble ( LastSentPos . y ) ;
Pkt . WriteBEDouble ( LastSentPos . z ) ;
2020-04-21 22:12:55 +00:00
Pkt . WriteByteAngle ( a_Mob . GetHeadYaw ( ) ) ; // Doesn't seem to be used
2016-12-15 19:21:43 +00:00
Pkt . WriteByteAngle ( a_Mob . GetPitch ( ) ) ;
Pkt . WriteByteAngle ( a_Mob . GetYaw ( ) ) ;
Pkt . WriteBEInt16 ( static_cast < Int16 > ( a_Mob . GetSpeedX ( ) * 400 ) ) ;
Pkt . WriteBEInt16 ( static_cast < Int16 > ( a_Mob . GetSpeedY ( ) * 400 ) ) ;
Pkt . WriteBEInt16 ( static_cast < Int16 > ( a_Mob . GetSpeedZ ( ) * 400 ) ) ;
WriteEntityMetadata ( Pkt , a_Mob ) ;
2017-02-21 15:11:28 +00:00
Pkt . WriteBEUInt8 ( 0xff ) ; // Metadata terminator
2016-12-15 19:21:43 +00:00
}
2021-03-15 17:06:58 +00:00
void cProtocol_1_11_0 : : SendTitleTimes ( int a_FadeInTicks , int a_DisplayTicks , int a_FadeOutTicks )
2017-06-05 13:49:36 +00:00
{
2021-03-15 17:06:58 +00:00
ASSERT ( m_State = = 3 ) ; // In game mode?
2017-06-05 13:49:36 +00:00
2021-03-15 17:06:58 +00:00
cPacketizer Pkt ( * this , pktTitle ) ;
Pkt . WriteVarInt32 ( 3 ) ; // Set title display times
Pkt . WriteBEInt32 ( a_FadeInTicks ) ;
Pkt . WriteBEInt32 ( a_DisplayTicks ) ;
Pkt . WriteBEInt32 ( a_FadeOutTicks ) ;
}
2021-03-15 02:47:55 +00:00
2017-06-05 13:49:36 +00:00
2017-07-07 07:31:45 +00:00
2017-06-05 13:49:36 +00:00
2021-03-15 17:06:58 +00:00
void cProtocol_1_11_0 : : SendUpdateBlockEntity ( cBlockEntity & a_BlockEntity )
{
ASSERT ( m_State = = 3 ) ; // In game mode?
2017-06-05 13:49:36 +00:00
2021-03-15 17:06:58 +00:00
Byte Action ;
switch ( a_BlockEntity . GetBlockType ( ) )
{
2021-04-30 13:23:46 +00:00
case E_BLOCK_CHEST :
case E_BLOCK_ENCHANTMENT_TABLE :
case E_BLOCK_END_PORTAL :
case E_BLOCK_TRAPPED_CHEST :
{
// The ones with a action of 0 is just a workaround to send the block entities to a client.
// Todo: 18.09.2020 - remove this when block entities are transmitted in the ChunkData packet - 12xx12
Action = 0 ;
break ;
}
2021-03-15 17:06:58 +00:00
case E_BLOCK_MOB_SPAWNER : Action = 1 ; break ; // Update mob spawner spinny mob thing
case E_BLOCK_COMMAND_BLOCK : Action = 2 ; break ; // Update command block text
case E_BLOCK_BEACON : Action = 3 ; break ; // Update beacon entity
case E_BLOCK_HEAD : Action = 4 ; break ; // Update mobhead entity
case E_BLOCK_FLOWER_POT : Action = 5 ; break ; // Update flower pot
case E_BLOCK_WALL_BANNER :
case E_BLOCK_STANDING_BANNER : Action = 6 ; break ; // Update banner
case E_BLOCK_BED : Action = 11 ; break ; // Update bed color (new!)
2017-06-05 13:49:36 +00:00
2021-03-15 17:06:58 +00:00
default : return ; // Block entities change between versions
2017-06-05 13:49:36 +00:00
}
2021-03-15 17:06:58 +00:00
cPacketizer Pkt ( * this , pktUpdateBlockEntity ) ;
Pkt . WriteXYZPosition64 ( a_BlockEntity . GetPosX ( ) , a_BlockEntity . GetPosY ( ) , a_BlockEntity . GetPosZ ( ) ) ;
Pkt . WriteBEUInt8 ( Action ) ;
2017-06-05 13:49:36 +00:00
2021-03-15 17:06:58 +00:00
cFastNBTWriter Writer ;
WriteBlockEntity ( Writer , a_BlockEntity ) ;
Writer . Finish ( ) ;
Pkt . WriteBuf ( Writer . GetResult ( ) ) ;
2016-12-15 19:21:43 +00:00
}
2020-03-29 15:54:37 +00:00
2021-04-10 14:57:16 +00:00
signed char cProtocol_1_11_0 : : GetProtocolEntityStatus ( const EntityAnimation a_Animation ) const
2020-07-18 17:57:23 +00:00
{
2021-04-10 14:57:16 +00:00
switch ( a_Animation )
{
case EntityAnimation : : EggCracks : return 3 ;
case EntityAnimation : : EvokerFangsAttacks : return 4 ;
case EntityAnimation : : IronGolemStashesGift : return 34 ;
case EntityAnimation : : PawnTotemActivates : return 35 ;
case EntityAnimation : : SnowballPoofs : return 3 ;
default : return Super : : GetProtocolEntityStatus ( a_Animation ) ;
}
2020-07-18 17:57:23 +00:00
}
2021-04-10 14:57:16 +00:00
UInt32 cProtocol_1_11_0 : : GetProtocolMobType ( const eMonsterType a_MobType ) const
2020-03-29 15:54:37 +00:00
{
switch ( a_MobType )
{
// Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong)
2020-04-20 19:46:04 +00:00
case mtInvalidType : return 53 ;
2020-03-29 15:54:37 +00:00
case mtBat : return 65 ;
case mtBlaze : return 61 ;
case mtCaveSpider : return 59 ;
case mtChicken : return 93 ;
case mtCow : return 92 ;
case mtCreeper : return 50 ;
2020-11-22 23:41:13 +00:00
case mtDonkey : return 31 ;
2020-03-29 15:54:37 +00:00
case mtEnderDragon : return 63 ;
case mtEnderman : return 58 ;
2020-11-22 23:41:13 +00:00
case mtEndermite : return 67 ;
case mtEvoker : return 34 ;
2020-03-29 15:54:37 +00:00
case mtGhast : return 56 ;
case mtGiant : return 53 ;
case mtGuardian : return 68 ;
case mtHorse : return 100 ;
2020-11-22 23:41:13 +00:00
case mtHusk : return 23 ;
2020-03-29 15:54:37 +00:00
case mtIronGolem : return 99 ;
2020-11-22 23:41:13 +00:00
case mtLlama : return 103 ;
2020-03-29 15:54:37 +00:00
case mtMagmaCube : return 62 ;
case mtMooshroom : return 96 ;
2020-11-22 23:41:13 +00:00
case mtMule : return 32 ;
2020-03-29 15:54:37 +00:00
case mtOcelot : return 98 ;
case mtPig : return 90 ;
2020-11-22 23:41:13 +00:00
case mtPolarBear : return 102 ;
2020-03-29 15:54:37 +00:00
case mtRabbit : return 101 ;
case mtSheep : return 91 ;
2020-11-22 23:41:13 +00:00
case mtShulker : return 69 ;
2020-03-29 15:54:37 +00:00
case mtSilverfish : return 60 ;
case mtSkeleton : return 51 ;
case mtSlime : return 55 ;
case mtSnowGolem : return 97 ;
case mtSpider : return 52 ;
2020-11-22 23:41:13 +00:00
case mtStray : return 6 ;
case mtTraderLlama : return 103 ;
2020-03-29 15:54:37 +00:00
case mtSquid : return 94 ;
2020-11-22 23:41:13 +00:00
case mtVex : return 35 ;
2020-03-29 15:54:37 +00:00
case mtVillager : return 120 ;
2020-11-22 23:41:13 +00:00
case mtVindicator : return 36 ;
2020-03-29 15:54:37 +00:00
case mtWitch : return 66 ;
case mtWither : return 64 ;
2020-04-04 11:44:17 +00:00
case mtWitherSkeleton : return 5 ;
2020-03-29 15:54:37 +00:00
case mtWolf : return 95 ;
case mtZombie : return 54 ;
case mtZombiePigman : return 57 ;
2020-04-10 00:01:07 +00:00
case mtZombieVillager : return 27 ;
2020-11-22 23:41:13 +00:00
default : return 0 ;
2020-03-29 15:54:37 +00:00
}
}
2016-12-15 19:21:43 +00:00
2021-04-10 14:57:16 +00:00
cProtocol : : Version cProtocol_1_11_0 : : GetProtocolVersion ( ) const
2021-04-09 22:17:01 +00:00
{
2021-04-10 14:57:16 +00:00
return Version : : v1_11_0 ;
2021-04-09 22:17:01 +00:00
}
2016-12-15 19:21:43 +00:00
void cProtocol_1_11_0 : : HandlePacketBlockPlace ( cByteBuffer & a_ByteBuffer )
{
int BlockX , BlockY , BlockZ ;
2020-07-20 08:56:27 +00:00
if ( ! a_ByteBuffer . ReadXYZPosition64 ( BlockX , BlockY , BlockZ ) )
2016-12-15 19:21:43 +00:00
{
return ;
}
HANDLE_READ ( a_ByteBuffer , ReadVarInt , Int32 , Face ) ;
HANDLE_READ ( a_ByteBuffer , ReadVarInt , Int32 , Hand ) ;
HANDLE_READ ( a_ByteBuffer , ReadBEFloat , float , CursorX ) ;
HANDLE_READ ( a_ByteBuffer , ReadBEFloat , float , CursorY ) ;
HANDLE_READ ( a_ByteBuffer , ReadBEFloat , float , CursorZ ) ;
2021-04-09 22:17:01 +00:00
2021-04-10 14:57:16 +00:00
m_Client - > HandleRightClick ( BlockX , BlockY , BlockZ , FaceIntToBlockFace ( Face ) , FloorC ( CursorX * 16 ) , FloorC ( CursorY * 16 ) , FloorC ( CursorZ * 16 ) , Hand = = 0 ) ;
2016-12-15 19:21:43 +00:00
}
2021-04-10 14:57:16 +00:00
void cProtocol_1_11_0 : : WriteBlockEntity ( cFastNBTWriter & a_Writer , const cBlockEntity & a_BlockEntity ) const
2021-03-15 17:06:58 +00:00
{
a_Writer . AddInt ( " x " , a_BlockEntity . GetPosX ( ) ) ;
a_Writer . AddInt ( " y " , a_BlockEntity . GetPosY ( ) ) ;
a_Writer . AddInt ( " z " , a_BlockEntity . GetPosZ ( ) ) ;
switch ( a_BlockEntity . GetBlockType ( ) )
{
case E_BLOCK_BED :
{
auto & BedEntity = static_cast < const cBedEntity & > ( a_BlockEntity ) ;
a_Writer . AddInt ( " color " , BedEntity . GetColor ( ) ) ; // New: multicoloured beds
break ;
}
case E_BLOCK_MOB_SPAWNER :
{
auto & MobSpawnerEntity = static_cast < const cMobSpawnerEntity & > ( a_BlockEntity ) ;
a_Writer . BeginCompound ( " SpawnData " ) ;
a_Writer . AddString ( " id " , cMonster : : MobTypeToVanillaNBT ( MobSpawnerEntity . GetEntity ( ) ) ) ; // New: uses namespaced ID
a_Writer . EndCompound ( ) ;
a_Writer . AddShort ( " Delay " , MobSpawnerEntity . GetSpawnDelay ( ) ) ;
break ;
}
default : Super : : WriteBlockEntity ( a_Writer , a_BlockEntity ) ;
}
}
2021-04-10 14:57:16 +00:00
void cProtocol_1_11_0 : : WriteEntityMetadata ( cPacketizer & a_Pkt , const cEntity & a_Entity ) const
2017-03-03 09:59:17 +00:00
{
2020-05-04 10:50:02 +00:00
using namespace Metadata_1_11 ;
2017-03-03 09:59:17 +00:00
// Common metadata:
Int8 Flags = 0 ;
if ( a_Entity . IsOnFire ( ) )
{
Flags | = 0x01 ;
}
if ( a_Entity . IsCrouched ( ) )
{
Flags | = 0x02 ;
}
if ( a_Entity . IsSprinting ( ) )
{
Flags | = 0x08 ;
}
if ( a_Entity . IsRclking ( ) )
{
Flags | = 0x10 ;
}
if ( a_Entity . IsInvisible ( ) )
{
Flags | = 0x20 ;
}
a_Pkt . WriteBEUInt8 ( ENTITY_FLAGS ) ; // Index
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ; // Type
a_Pkt . WriteBEInt8 ( Flags ) ;
switch ( a_Entity . GetEntityType ( ) )
{
case cEntity : : etPlayer :
{
2018-05-02 07:50:36 +00:00
auto & Player = static_cast < const cPlayer & > ( a_Entity ) ;
2017-03-03 09:59:17 +00:00
// TODO Set player custom name to their name.
// Then it's possible to move the custom name of mobs to the entities
// and to remove the "special" player custom name.
a_Pkt . WriteBEUInt8 ( ENTITY_CUSTOM_NAME ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_STRING ) ;
a_Pkt . WriteString ( Player . GetName ( ) ) ;
a_Pkt . WriteBEUInt8 ( LIVING_HEALTH ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_FLOAT ) ;
a_Pkt . WriteBEFloat ( static_cast < float > ( Player . GetHealth ( ) ) ) ;
a_Pkt . WriteBEUInt8 ( PLAYER_DISPLAYED_SKIN_PARTS ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
a_Pkt . WriteBEUInt8 ( static_cast < UInt8 > ( Player . GetSkinParts ( ) ) ) ;
a_Pkt . WriteBEUInt8 ( PLAYER_MAIN_HAND ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
2021-04-10 14:57:16 +00:00
a_Pkt . WriteBEUInt8 ( Player . IsLeftHanded ( ) ? 0 : 1 ) ;
2017-03-03 09:59:17 +00:00
break ;
}
case cEntity : : etPickup :
{
a_Pkt . WriteBEUInt8 ( ITEM_ITEM ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_ITEM ) ;
2018-05-02 07:50:36 +00:00
WriteItem ( a_Pkt , static_cast < const cPickup & > ( a_Entity ) . GetItem ( ) ) ;
2017-03-03 09:59:17 +00:00
break ;
}
case cEntity : : etMinecart :
{
a_Pkt . WriteBEUInt8 ( MINECART_SHAKING_POWER ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
// The following expression makes Minecarts shake more with less health or higher damage taken
2018-05-02 07:50:36 +00:00
auto & Minecart = static_cast < const cMinecart & > ( a_Entity ) ;
2017-03-03 09:59:17 +00:00
auto maxHealth = a_Entity . GetMaxHealth ( ) ;
auto curHealth = a_Entity . GetHealth ( ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( ( maxHealth - curHealth ) * Minecart . LastDamage ( ) * 4 ) ) ;
a_Pkt . WriteBEUInt8 ( MINECART_SHAKING_DIRECTION ) ; // (doesn't seem to effect anything)
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( 1 ) ;
a_Pkt . WriteBEUInt8 ( MINECART_SHAKING_MULTIPLIER ) ; // or damage taken
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_FLOAT ) ;
a_Pkt . WriteBEFloat ( static_cast < float > ( Minecart . LastDamage ( ) + 10 ) ) ;
if ( Minecart . GetPayload ( ) = = cMinecart : : mpNone )
{
2018-05-02 07:50:36 +00:00
auto & RideableMinecart = static_cast < const cRideableMinecart & > ( Minecart ) ;
2017-03-03 09:59:17 +00:00
const cItem & MinecartContent = RideableMinecart . GetContent ( ) ;
if ( ! MinecartContent . IsEmpty ( ) )
{
a_Pkt . WriteBEUInt8 ( MINECART_BLOCK_ID_META ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
int Content = MinecartContent . m_ItemType ;
Content | = MinecartContent . m_ItemDamage < < 8 ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Content ) ) ;
a_Pkt . WriteBEUInt8 ( MINECART_BLOCK_Y ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( RideableMinecart . GetBlockHeight ( ) ) ) ;
a_Pkt . WriteBEUInt8 ( MINECART_SHOW_BLOCK ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( true ) ;
}
}
else if ( Minecart . GetPayload ( ) = = cMinecart : : mpFurnace )
{
a_Pkt . WriteBEUInt8 ( MINECART_FURNACE_POWERED ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
2018-05-02 07:50:36 +00:00
a_Pkt . WriteBool ( static_cast < const cMinecartWithFurnace & > ( Minecart ) . IsFueled ( ) ) ;
2017-03-03 09:59:17 +00:00
}
break ;
} // case etMinecart
case cEntity : : etProjectile :
{
2018-05-02 07:50:36 +00:00
auto & Projectile = static_cast < const cProjectileEntity & > ( a_Entity ) ;
2017-03-03 09:59:17 +00:00
switch ( Projectile . GetProjectileKind ( ) )
{
case cProjectileEntity : : pkArrow :
{
a_Pkt . WriteBEUInt8 ( ARROW_CRITICAL ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
2018-05-02 07:50:36 +00:00
a_Pkt . WriteBEInt8 ( static_cast < const cArrowEntity & > ( Projectile ) . IsCritical ( ) ? 1 : 0 ) ;
2017-03-03 09:59:17 +00:00
break ;
}
case cProjectileEntity : : pkFirework :
{
a_Pkt . WriteBEUInt8 ( FIREWORK_INFO ) ; // Firework item used for this firework
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_ITEM ) ;
2018-05-02 07:50:36 +00:00
WriteItem ( a_Pkt , static_cast < const cFireworkEntity & > ( Projectile ) . GetItem ( ) ) ;
2017-03-03 09:59:17 +00:00
// FIREWORK_BOOSTED_ENTITY_ID, in 1.11.1 only
break ;
}
case cProjectileEntity : : pkSplashPotion :
{
a_Pkt . WriteBEUInt8 ( POTION_THROWN ) ; // Potion item which was thrown
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_ITEM ) ;
2018-05-02 07:50:36 +00:00
WriteItem ( a_Pkt , static_cast < const cSplashPotionEntity & > ( Projectile ) . GetItem ( ) ) ;
2017-03-03 09:59:17 +00:00
}
default :
{
break ;
}
}
break ;
} // case etProjectile
case cEntity : : etMonster :
{
2018-05-02 07:50:36 +00:00
WriteMobMetadata ( a_Pkt , static_cast < const cMonster & > ( a_Entity ) ) ;
2017-03-03 09:59:17 +00:00
break ;
}
case cEntity : : etBoat :
{
2018-05-02 07:50:36 +00:00
auto & Boat = static_cast < const cBoat & > ( a_Entity ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEInt8 ( BOAT_LAST_HIT_TIME ) ;
a_Pkt . WriteBEInt8 ( METADATA_TYPE_VARINT ) ;
2017-05-15 16:04:53 +00:00
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Boat . GetLastDamage ( ) ) ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEInt8 ( BOAT_FORWARD_DIRECTION ) ;
a_Pkt . WriteBEInt8 ( METADATA_TYPE_VARINT ) ;
2017-05-15 16:04:53 +00:00
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Boat . GetForwardDirection ( ) ) ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEInt8 ( BOAT_DAMAGE_TAKEN ) ;
a_Pkt . WriteBEInt8 ( METADATA_TYPE_FLOAT ) ;
a_Pkt . WriteBEFloat ( Boat . GetDamageTaken ( ) ) ;
a_Pkt . WriteBEInt8 ( BOAT_TYPE ) ;
a_Pkt . WriteBEInt8 ( METADATA_TYPE_VARINT ) ;
2017-05-09 12:21:25 +00:00
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Boat . GetMaterial ( ) ) ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEInt8 ( BOAT_RIGHT_PADDLE_TURNING ) ;
a_Pkt . WriteBEInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Boat . IsRightPaddleUsed ( ) ) ;
a_Pkt . WriteBEInt8 ( BOAT_LEFT_PADDLE_TURNING ) ;
a_Pkt . WriteBEInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Boat . IsLeftPaddleUsed ( ) ) ;
break ;
} // case etBoat
case cEntity : : etItemFrame :
{
2018-05-02 07:50:36 +00:00
auto & Frame = static_cast < const cItemFrame & > ( a_Entity ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( ITEM_FRAME_ITEM ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_ITEM ) ;
WriteItem ( a_Pkt , Frame . GetItem ( ) ) ;
a_Pkt . WriteBEUInt8 ( ITEM_FRAME_ROTATION ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( Frame . GetItemRotation ( ) ) ;
break ;
} // case etItemFrame
2020-10-29 20:47:20 +00:00
case cEntity : : etEnderCrystal :
{
const auto & EnderCrystal = static_cast < const cEnderCrystal & > ( a_Entity ) ;
if ( EnderCrystal . DisplaysBeam ( ) )
{
2020-11-06 15:00:59 +00:00
a_Pkt . WriteBEUInt8 ( ENDER_CRYSTAL_BEAM_TARGET ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_OPTIONAL_POSITION ) ;
a_Pkt . WriteBool ( true ) ; // Dont do a second check if it should display the beam
2020-10-29 20:47:20 +00:00
a_Pkt . WriteXYZPosition64 ( EnderCrystal . GetBeamTarget ( ) ) ;
}
2020-11-06 15:00:59 +00:00
a_Pkt . WriteBEUInt8 ( ENDER_CRYSTAL_SHOW_BOTTOM ) ;
2020-10-29 20:47:20 +00:00
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( EnderCrystal . ShowsBottom ( ) ) ;
break ;
} // case etEnderCrystal
2017-03-03 09:59:17 +00:00
default :
{
break ;
}
}
}
2021-04-10 14:57:16 +00:00
void cProtocol_1_11_0 : : WriteMobMetadata ( cPacketizer & a_Pkt , const cMonster & a_Mob ) const
2017-03-03 09:59:17 +00:00
{
2020-05-04 10:50:02 +00:00
using namespace Metadata_1_11 ;
2017-03-03 09:59:17 +00:00
2020-11-22 23:41:13 +00:00
// Living entity Metadata
2017-03-03 09:59:17 +00:00
if ( a_Mob . HasCustomName ( ) )
{
// TODO: As of 1.9 _all_ entities can have custom names; should this be moved up?
a_Pkt . WriteBEUInt8 ( ENTITY_CUSTOM_NAME ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_STRING ) ;
a_Pkt . WriteString ( a_Mob . GetCustomName ( ) ) ;
a_Pkt . WriteBEUInt8 ( ENTITY_CUSTOM_NAME_VISIBLE ) ; // Custom name always visible
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( a_Mob . IsCustomNameAlwaysVisible ( ) ) ;
}
a_Pkt . WriteBEUInt8 ( LIVING_HEALTH ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_FLOAT ) ;
a_Pkt . WriteBEFloat ( static_cast < float > ( a_Mob . GetHealth ( ) ) ) ;
switch ( a_Mob . GetMobType ( ) )
{
case mtBat :
{
2018-05-02 07:50:36 +00:00
auto & Bat = static_cast < const cBat & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( BAT_HANGING ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
a_Pkt . WriteBEInt8 ( Bat . IsHanging ( ) ? 1 : 0 ) ;
break ;
} // case mtBat
2017-09-14 08:48:57 +00:00
case mtChicken :
{
2018-05-02 07:50:36 +00:00
auto & Chicken = static_cast < const cChicken & > ( a_Mob ) ;
2017-09-14 08:48:57 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Chicken . IsBaby ( ) ) ;
break ;
} // case mtChicken
case mtCow :
{
2018-05-02 07:50:36 +00:00
auto & Cow = static_cast < const cCow & > ( a_Mob ) ;
2017-09-14 08:48:57 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Cow . IsBaby ( ) ) ;
break ;
} // case mtCow
2017-03-03 09:59:17 +00:00
case mtCreeper :
{
2018-05-02 07:50:36 +00:00
auto & Creeper = static_cast < const cCreeper & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( CREEPER_STATE ) ; // (idle or "blowing")
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( Creeper . IsBlowing ( ) ? 1 : static_cast < UInt32 > ( - 1 ) ) ;
a_Pkt . WriteBEUInt8 ( CREEPER_POWERED ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Creeper . IsCharged ( ) ) ;
a_Pkt . WriteBEUInt8 ( CREEPER_IGNITED ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Creeper . IsBurnedWithFlintAndSteel ( ) ) ;
break ;
} // case mtCreeper
case mtEnderman :
{
2018-05-02 07:50:36 +00:00
auto & Enderman = static_cast < const cEnderman & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( ENDERMAN_CARRIED_BLOCK ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BLOCKID ) ;
UInt32 Carried = 0 ;
Carried | = static_cast < UInt32 > ( Enderman . GetCarriedBlock ( ) < < 4 ) ;
Carried | = Enderman . GetCarriedMeta ( ) ;
a_Pkt . WriteVarInt32 ( Carried ) ;
a_Pkt . WriteBEUInt8 ( ENDERMAN_SCREAMING ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Enderman . IsScreaming ( ) ) ;
break ;
} // case mtEnderman
case mtGhast :
{
2018-05-02 07:50:36 +00:00
auto & Ghast = static_cast < const cGhast & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( GHAST_ATTACKING ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Ghast . IsCharging ( ) ) ;
break ;
} // case mtGhast
case mtHorse :
{
2020-11-22 23:41:13 +00:00
// XXX This behaves incorrectly with different variants; horses have different entity IDs now
2017-03-03 09:59:17 +00:00
// Abstract horse
2018-05-02 07:50:36 +00:00
auto & Horse = static_cast < const cHorse & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
Int8 Flags = 0 ;
if ( Horse . IsTame ( ) )
{
Flags | = 0x02 ;
}
if ( Horse . IsSaddled ( ) )
{
Flags | = 0x04 ;
}
if ( Horse . IsChested ( ) )
{
Flags | = 0x08 ;
}
if ( Horse . IsEating ( ) )
{
Flags | = 0x20 ;
}
if ( Horse . IsRearing ( ) )
{
Flags | = 0x40 ;
}
if ( Horse . IsMthOpen ( ) )
{
Flags | = 0x80 ;
}
a_Pkt . WriteBEUInt8 ( ABSTRACT_HORSE_STATUS ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
a_Pkt . WriteBEInt8 ( Flags ) ;
// This doesn't exist any more; it'll cause horses to all be the normal type
// a_Pkt.WriteBEUInt8(HORSE_TYPE);
// a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
// a_Pkt.WriteVarInt32(static_cast<UInt32>(Horse.GetHorseType()));
// Regular horses
a_Pkt . WriteBEUInt8 ( HORSE_VARIANT ) ; // Color / style
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
int Appearance = 0 ;
Appearance = Horse . GetHorseColor ( ) ;
Appearance | = Horse . GetHorseStyle ( ) < < 8 ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Appearance ) ) ;
a_Pkt . WriteBEUInt8 ( HORSE_ARMOR ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Horse . GetHorseArmour ( ) ) ) ;
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Horse . IsBaby ( ) ) ;
break ;
} // case mtHorse
case mtMagmaCube :
{
2018-05-02 07:50:36 +00:00
auto & MagmaCube = static_cast < const cMagmaCube & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( SLIME_SIZE ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( MagmaCube . GetSize ( ) ) ) ;
break ;
} // case mtMagmaCube
case mtOcelot :
{
2020-11-22 23:41:13 +00:00
// Todo: move unnecessary to cat
2018-05-02 07:50:36 +00:00
auto & Ocelot = static_cast < const cOcelot & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Ocelot . IsBaby ( ) ) ;
2017-07-12 10:42:02 +00:00
Int8 OcelotStatus = 0 ;
if ( Ocelot . IsSitting ( ) )
{
OcelotStatus | = 0x1 ;
}
if ( Ocelot . IsTame ( ) )
{
OcelotStatus | = 0x4 ;
}
a_Pkt . WriteBEUInt8 ( TAMEABLE_ANIMAL_STATUS ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
a_Pkt . WriteBEInt8 ( OcelotStatus ) ;
a_Pkt . WriteBEUInt8 ( OCELOT_TYPE ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Ocelot . GetOcelotType ( ) ) ) ;
2017-03-03 09:59:17 +00:00
break ;
} // case mtOcelot
case mtPig :
{
2018-05-02 07:50:36 +00:00
auto & Pig = static_cast < const cPig & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Pig . IsBaby ( ) ) ;
a_Pkt . WriteBEUInt8 ( PIG_HAS_SADDLE ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Pig . IsSaddled ( ) ) ;
// PIG_TOTAL_CARROT_ON_A_STICK_BOOST in 1.11.1 only
break ;
} // case mtPig
2017-09-14 08:48:57 +00:00
case mtRabbit :
{
2018-05-02 07:50:36 +00:00
auto & Rabbit = static_cast < const cRabbit & > ( a_Mob ) ;
2017-09-14 08:48:57 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Rabbit . IsBaby ( ) ) ;
a_Pkt . WriteBEUInt8 ( RABBIT_TYPE ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Rabbit . GetRabbitType ( ) ) ) ;
break ;
} // case mtRabbit
2017-03-03 09:59:17 +00:00
case mtSheep :
{
2018-05-02 07:50:36 +00:00
auto & Sheep = static_cast < const cSheep & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Sheep . IsBaby ( ) ) ;
a_Pkt . WriteBEUInt8 ( SHEEP_STATUS ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
Int8 SheepMetadata = 0 ;
SheepMetadata = static_cast < Int8 > ( Sheep . GetFurColor ( ) ) ;
if ( Sheep . IsSheared ( ) )
{
SheepMetadata | = 0x10 ;
}
a_Pkt . WriteBEInt8 ( SheepMetadata ) ;
break ;
} // case mtSheep
case mtSlime :
{
2018-05-02 07:50:36 +00:00
auto & Slime = static_cast < const cSlime & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( SLIME_SIZE ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Slime . GetSize ( ) ) ) ;
break ;
} // case mtSlime
case mtVillager :
{
2018-05-02 07:50:36 +00:00
auto & Villager = static_cast < const cVillager & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Villager . IsBaby ( ) ) ;
a_Pkt . WriteBEUInt8 ( VILLAGER_PROFESSION ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Villager . GetVilType ( ) ) ) ;
break ;
} // case mtVillager
case mtWitch :
{
2018-05-02 07:50:36 +00:00
auto & Witch = static_cast < const cWitch & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( WITCH_AGGRESIVE ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Witch . IsAngry ( ) ) ;
break ;
} // case mtWitch
case mtWither :
{
2018-05-02 07:50:36 +00:00
auto & Wither = static_cast < const cWither & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( WITHER_INVULNERABLE_TIMER ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( Wither . GetWitherInvulnerableTicks ( ) ) ;
// TODO: Use boss bar packet for health
break ;
} // case mtWither
case mtWolf :
{
2018-05-02 07:50:36 +00:00
auto & Wolf = static_cast < const cWolf & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Wolf . IsBaby ( ) ) ;
Int8 WolfStatus = 0 ;
if ( Wolf . IsSitting ( ) )
{
WolfStatus | = 0x1 ;
}
if ( Wolf . IsAngry ( ) )
{
WolfStatus | = 0x2 ;
}
if ( Wolf . IsTame ( ) )
{
WolfStatus | = 0x4 ;
}
a_Pkt . WriteBEUInt8 ( TAMEABLE_ANIMAL_STATUS ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BYTE ) ;
a_Pkt . WriteBEInt8 ( WolfStatus ) ;
a_Pkt . WriteBEUInt8 ( WOLF_DAMAGE_TAKEN ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_FLOAT ) ;
a_Pkt . WriteBEFloat ( static_cast < float > ( a_Mob . GetHealth ( ) ) ) ; // TODO Not use the current health
a_Pkt . WriteBEUInt8 ( WOLF_BEGGING ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Wolf . IsBegging ( ) ) ;
a_Pkt . WriteBEUInt8 ( WOLF_COLLAR_COLOR ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( Wolf . GetCollarColor ( ) ) ) ;
break ;
} // case mtWolf
case mtZombie :
{
2020-11-22 23:41:13 +00:00
// XXX Zombies were also split into new subclasses; this doesn't handle that.
2018-05-02 07:50:36 +00:00
auto & Zombie = static_cast < const cZombie & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( ZOMBIE_IS_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( Zombie . IsBaby ( ) ) ;
break ;
} // case mtZombie
case mtZombiePigman :
{
2018-05-02 07:50:36 +00:00
auto & ZombiePigman = static_cast < const cZombiePigman & > ( a_Mob ) ;
2017-03-03 09:59:17 +00:00
a_Pkt . WriteBEUInt8 ( AGEABLE_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( ZombiePigman . IsBaby ( ) ) ;
break ;
} // case mtZombiePigman
2017-09-14 08:48:57 +00:00
2018-02-03 11:24:19 +00:00
case mtZombieVillager :
{
auto & ZombieVillager = reinterpret_cast < const cZombieVillager & > ( a_Mob ) ;
a_Pkt . WriteBEUInt8 ( ZOMBIE_IS_BABY ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_BOOL ) ;
a_Pkt . WriteBool ( ZombieVillager . IsBaby ( ) ) ;
a_Pkt . WriteBEUInt8 ( ZOMBIE_VILLAGER_CONVERTING ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( ZombieVillager . ConversionTime ( ) ) ) ;
a_Pkt . WriteBEUInt8 ( ZOMBIE_VILLAGER_PROFESSION ) ;
a_Pkt . WriteBEUInt8 ( METADATA_TYPE_VARINT ) ;
a_Pkt . WriteVarInt32 ( static_cast < UInt32 > ( ZombieVillager . GetProfession ( ) ) ) ;
break ;
} // case mtZombieVillager
2020-11-22 23:41:13 +00:00
case mtBlaze :
case mtElderGuardian :
case mtGuardian :
case mtSnowGolem :
{
// TODO: Mobs with extra fields that aren't implemented
break ;
}
case mtCat :
case mtDonkey :
case mtMule :
case mtEndermite :
case mtEvoker :
case mtLlama :
case mtPolarBear :
case mtShulker :
case mtSkeletonHorse :
case mtZombieHorse :
case mtVex :
case mtVindicator :
{
// Todo: Mobs not added yet. Grouped ones have the same metadata
2021-02-20 16:24:13 +00:00
ASSERT ( ! " cProtocol_1_11::WriteMobMetadata: received unimplemented type " ) ;
2020-11-22 23:41:13 +00:00
break ;
}
case mtCaveSpider :
case mtEnderDragon :
case mtGiant :
case mtIronGolem :
case mtMooshroom :
case mtSilverfish :
case mtSkeleton :
case mtStray :
case mtSpider :
case mtSquid :
case mtWitherSkeleton :
{
// Mobs without additional metadata
break ;
}
2021-02-20 16:24:13 +00:00
2020-11-22 23:41:13 +00:00
default : UNREACHABLE ( " cProtocol_1_11::WriteMobMetadata: received mob of invalid type " ) ;
2017-03-03 09:59:17 +00:00
} // switch (a_Mob.GetType())
}
2020-07-19 19:49:29 +00:00
////////////////////////////////////////////////////////////////////////////////
// cProtocol_1_11_1:
2017-02-21 15:11:28 +00:00
2021-04-10 14:57:16 +00:00
cProtocol : : Version cProtocol_1_11_1 : : GetProtocolVersion ( ) const
2017-02-21 15:11:28 +00:00
{
2020-08-20 20:34:46 +00:00
return Version : : v1_11_1 ;
2017-02-21 15:11:28 +00:00
}