void cProtocol125::SendSpawnMob(const cMonster & a_Mob) { cCSLock Lock(m_CSPacket); WriteByte (PACKET_SPAWN_MOB); WriteInt (a_Mob.GetUniqueID()); WriteByte (a_Mob.GetMobType()); WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32)); WriteByte (0); WriteByte (0); WriteByte (0); AString MetaData = GetEntityMetaData(a_Mob); SendData (MetaData.data(), MetaData.size()); Flush(); }
void cProtocol125::SendSpawnMob(const cMonster & a_Mob) { cCSLock Lock(m_CSPacket); WriteByte (PACKET_SPAWN_MOB); WriteInt (a_Mob.GetUniqueID()); WriteByte ((Byte)a_Mob.GetMobType()); WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32)); WriteByte (0); WriteByte (0); WriteByte (0); WriteCommonMetadata(a_Mob); WriteMobMetadata(a_Mob); WriteByte(0x7f); Flush(); }
void cProtocol132::SendSpawnMob(const cMonster & a_Mob) { cCSLock Lock(m_CSPacket); WriteByte (PACKET_SPAWN_MOB); WriteInt (a_Mob.GetUniqueID()); WriteByte (a_Mob.GetMobType()); WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32)); WriteByte ((Byte)((a_Mob.GetRotation() / 360.f) * 256)); WriteByte ((Byte)((a_Mob.GetPitch() / 360.f) * 256)); WriteByte ((Byte)((a_Mob.GetHeadYaw() / 360.f) * 256)); WriteShort ((short)(a_Mob.GetSpeedX() * 400)); WriteShort ((short)(a_Mob.GetSpeedY() * 400)); WriteShort ((short)(a_Mob.GetSpeedZ() * 400)); AString MetaData = GetEntityMetaData(a_Mob); SendData (MetaData.data(), MetaData.size()); Flush(); }
void cProtocol132::SendSpawnMob(const cMonster & a_Mob) { cCSLock Lock(m_CSPacket); WriteByte (PACKET_SPAWN_MOB); WriteInt (a_Mob.GetUniqueID()); WriteByte ((Byte)a_Mob.GetMobType()); WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32)); WriteByte ((Byte)((a_Mob.GetYaw() / 360.f) * 256)); WriteByte ((Byte)((a_Mob.GetPitch() / 360.f) * 256)); WriteByte ((Byte)((a_Mob.GetHeadYaw() / 360.f) * 256)); WriteShort ((short)(a_Mob.GetSpeedX() * 400)); WriteShort ((short)(a_Mob.GetSpeedY() * 400)); WriteShort ((short)(a_Mob.GetSpeedZ() * 400)); WriteCommonMetadata(a_Mob); WriteMobMetadata(a_Mob); WriteByte(0x7f); Flush(); }
void cProtocol_1_11_0::SendSpawnMob(const cMonster & a_Mob) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, GetPacketId(sendSpawnMob)); // Spawn Mob packet Pkt.WriteVarInt32(a_Mob.GetUniqueID()); // 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()); Pkt.WriteVarInt32(static_cast<UInt32>(a_Mob.GetMobType())); Pkt.WriteBEDouble(a_Mob.GetPosX()); Pkt.WriteBEDouble(a_Mob.GetPosY()); Pkt.WriteBEDouble(a_Mob.GetPosZ()); Pkt.WriteByteAngle(a_Mob.GetPitch()); Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); 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); Pkt.WriteBEUInt8(0xff); // Metadata terminator }
void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) { using namespace Metadata; // Living Enitiy Metadata 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: { auto & Bat = reinterpret_cast<const cBat &>(a_Mob); a_Pkt.WriteBEUInt8(BAT_HANGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtCreeper: { auto & Creeper = reinterpret_cast<const cCreeper &>(a_Mob); 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: { auto & Enderman = reinterpret_cast<const cEnderman &>(a_Mob); 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: { auto & Ghast = reinterpret_cast<const cGhast &>(a_Mob); a_Pkt.WriteBEUInt8(GHAST_ATTACKING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { // XXX This behaves incorrectly with different varients; horses have different entity IDs now // Abstract horse auto & Horse = reinterpret_cast<const cHorse &>(a_Mob); 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: { auto & MagmaCube = reinterpret_cast<const cMagmaCube &>(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast<UInt32>(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { auto & Ocelot = reinterpret_cast<const cOcelot &>(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ocelot.IsBaby()); 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())); break; } // case mtOcelot case mtCow: { auto & Cow = reinterpret_cast<const cCow &>(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Cow.IsBaby()); break; } // case mtCow case mtChicken: { auto & Chicken = reinterpret_cast<const cChicken &>(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Chicken.IsBaby()); break; } // case mtChicken case mtPig: { auto & Pig = reinterpret_cast<const cPig &>(a_Mob); 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 case mtSheep: { auto & Sheep = reinterpret_cast<const cSheep &>(a_Mob); 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 mtRabbit: { auto & Rabbit = reinterpret_cast<const cRabbit &>(a_Mob); 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 case mtSkeleton: { // XXX Skeletons are separate entities; all skeletons are currently treated as regular ones // auto & Skeleton = reinterpret_cast<const cSkeleton &>(a_Mob); // a_Pkt.WriteBEUInt8(SKELETON_TYPE); // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0); break; } // case mtSkeleton case mtSlime: { auto & Slime = reinterpret_cast<const cSlime &>(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast<UInt32>(Slime.GetSize())); break; } // case mtSlime case mtVillager: { auto & Villager = reinterpret_cast<const cVillager &>(a_Mob); 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: { auto & Witch = reinterpret_cast<const cWitch &>(a_Mob); a_Pkt.WriteBEUInt8(WITCH_AGGRESIVE); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Witch.IsAngry()); break; } // case mtWitch case mtWither: { auto & Wither = reinterpret_cast<const cWither &>(a_Mob); 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: { auto & Wolf = reinterpret_cast<const cWolf &>(a_Mob); 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: { // XXX Zombies were also split into new sublcasses; this doesn't handle that. auto & Zombie = reinterpret_cast<const cZombie &>(a_Mob); a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Zombie.IsBaby()); // These don't exist // a_Pkt.WriteBEUInt8(ZOMBIE_TYPE); // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0); // a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING); // a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); // a_Pkt.WriteBool(Zombie.IsConverting()); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = reinterpret_cast<const cZombiePigman &>(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombiePigman.IsBaby()); break; } // case mtZombiePigman } // switch (a_Mob.GetType()) }
void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) { switch (a_Mob.GetMobType()) { case cMonster::mtCreeper: { WriteByte(0x10); WriteChar(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up? WriteByte(0x11); WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged? break; } case cMonster::mtBat: { WriteByte(0x10); WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? break; } case cMonster::mtPig: { WriteByte(0x10); WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? break; } case cMonster::mtVillager: { WriteByte(0x50); WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? break; } case cMonster::mtZombie: { WriteByte(0xC); WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie? WriteByte(0xD); WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie? WriteByte(0xE); WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? break; } case cMonster::mtGhast: { WriteByte(0x10); WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P break; } case cMonster::mtWolf: { Byte WolfStatus = 0; if (((const cWolf &)a_Mob).IsSitting()) { WolfStatus |= 0x1; } if (((const cWolf &)a_Mob).IsAngry()) { WolfStatus |= 0x2; } if (((const cWolf &)a_Mob).IsTame()) { WolfStatus |= 0x4; } WriteByte(0x10); WriteByte(WolfStatus); WriteByte(0x72); WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way) WriteByte(0x13); WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode? break; } case cMonster::mtSheep: { // [1](1111) // [] = Is sheared? () = Color, from 0 to 15 WriteByte(0x10); Byte SheepMetadata = 0; SheepMetadata = (Byte)((const cSheep &)a_Mob).GetFurColor(); if (((const cSheep &)a_Mob).IsSheared()) { SheepMetadata |= 0x16; } WriteByte(SheepMetadata); break; } case cMonster::mtEnderman: { WriteByte(0x10); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house WriteByte(0x11); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house WriteByte(0x12); WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face? break; } case cMonster::mtSkeleton: { WriteByte(0xD); WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not break; } case cMonster::mtWitch: { WriteByte(0x15); WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything break; } case cMonster::mtWither: { WriteByte(0x54); // Int at index 20 WriteInt((Int32)((const cWither &)a_Mob).GetWitherInvulnerableTicks()); WriteByte(0x66); // Float at index 6 WriteFloat((float)(a_Mob.GetHealth())); break; } case cMonster::mtSlime: case cMonster::mtMagmaCube: { WriteByte(0x10); if (a_Mob.GetMobType() == cMonster::mtSlime) { WriteByte((Byte)((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME } else { WriteByte((Byte)((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME } break; } case cMonster::mtHorse: { int Flags = 0; if (((const cHorse &)a_Mob).IsTame()) { Flags |= 0x2; } if (((const cHorse &)a_Mob).IsSaddled()) { Flags |= 0x4; } if (((const cHorse &)a_Mob).IsChested()) { Flags |= 0x8; } if (((const cHorse &)a_Mob).IsBaby()) { Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer } if (((const cHorse &)a_Mob).IsEating()) { Flags |= 0x20; } if (((const cHorse &)a_Mob).IsRearing()) { Flags |= 0x40; } if (((const cHorse &)a_Mob).IsMthOpen()) { Flags |= 0x80; } WriteByte(0x50); WriteInt(Flags); WriteByte(0x13); WriteByte((Byte)((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.) WriteByte(0x54); int Appearance = 0; Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256 WriteInt(Appearance); WriteByte(0x56); WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour break; } default: { break; } } }