summaryrefslogtreecommitdiffstats
path: root/src/Protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/Protocol')
-rw-r--r--src/Protocol/Protocol.h4
-rw-r--r--src/Protocol/Protocol_1_11.cpp53
-rw-r--r--src/Protocol/Protocol_1_11.h2
-rw-r--r--src/Protocol/Protocol_1_12.cpp14
-rw-r--r--src/Protocol/Protocol_1_12.h1
-rw-r--r--src/Protocol/Protocol_1_13.cpp13
-rw-r--r--src/Protocol/Protocol_1_13.h2
-rw-r--r--src/Protocol/Protocol_1_14.cpp51
-rw-r--r--src/Protocol/Protocol_1_14.h3
-rw-r--r--src/Protocol/Protocol_1_8.cpp381
-rw-r--r--src/Protocol/Protocol_1_8.h23
-rw-r--r--src/Protocol/Protocol_1_9.cpp44
-rw-r--r--src/Protocol/Protocol_1_9.h4
13 files changed, 397 insertions, 198 deletions
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 0f615f4dc..75ebb92d4 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -381,14 +381,13 @@ public:
virtual void SendDisconnect (const AString & a_Reason) = 0;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+)
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) = 0;
- virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0;
+ virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) = 0;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0;
virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0;
virtual void SendEntityLook (const cEntity & a_Entity) = 0;
virtual void SendEntityMetadata (const cEntity & a_Entity) = 0;
virtual void SendEntityPosition (const cEntity & a_Entity) = 0;
virtual void SendEntityProperties (const cEntity & a_Entity) = 0;
- virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0;
virtual void SendEntityVelocity (const cEntity & a_Entity) = 0;
virtual void SendExplosion (Vector3f a_Position, float a_Power) = 0;
virtual void SendGameMode (eGameMode a_GameMode) = 0;
@@ -441,7 +440,6 @@ public:
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0;
- virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
virtual void SendUnlockRecipe (UInt32 a_RecipeID) = 0;
virtual void SendInitRecipes (UInt32 a_RecipeID) = 0;
virtual void SendWeather (eWeather a_Weather) = 0;
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index db4ed5502..e2436e04c 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -346,6 +346,41 @@ void cProtocol_1_11_0::SendCollectEntity(const cEntity & a_Collected, const cEnt
+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);
+}
+
+
+
+
+
void cProtocol_1_11_0::SendHideTitle(void)
{
ASSERT(m_State == 3); // In game mode?
@@ -526,6 +561,23 @@ UInt32 cProtocol_1_11_0::GetProtocolMobType(const eMonsterType a_MobType)
+signed char cProtocol_1_11_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const
+{
+ 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);
+ }
+}
+
+
+
+
+
void cProtocol_1_11_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
{
int BlockX, BlockY, BlockZ;
@@ -539,6 +591,7 @@ void cProtocol_1_11_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorX);
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorY);
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorZ);
+
m_Client->HandleRightClick(BlockX, BlockY, BlockZ, FaceIntToBlockFace(Face), FloorC(CursorX * 16), FloorC(CursorY * 16), FloorC(CursorZ * 16), HandIntToEnum(Hand));
}
diff --git a/src/Protocol/Protocol_1_11.h b/src/Protocol/Protocol_1_11.h
index 6cd4d7607..f5ed73187 100644
--- a/src/Protocol/Protocol_1_11.h
+++ b/src/Protocol/Protocol_1_11.h
@@ -33,6 +33,7 @@ public:
protected:
virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override;
+ virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) override;
virtual void SendHideTitle (void) override;
virtual void SendResetTitle (void) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
@@ -44,6 +45,7 @@ protected:
/** Converts eMonsterType to protocol-specific mob IDs */
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override;
+ virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer) override;
diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp
index b340d87f5..31daa96f7 100644
--- a/src/Protocol/Protocol_1_12.cpp
+++ b/src/Protocol/Protocol_1_12.cpp
@@ -1070,6 +1070,20 @@ cProtocol::Version cProtocol_1_12::GetProtocolVersion()
+signed char cProtocol_1_12::GetProtocolEntityStatus(EntityAnimation a_Animation) const
+{
+ switch (a_Animation)
+ {
+ case EntityAnimation::PawnBurns: return 37;
+ case EntityAnimation::PawnDrowns: return 36;
+ default: return Super::GetProtocolEntityStatus(a_Animation);
+ }
+}
+
+
+
+
+
UInt32 cProtocol_1_12::GetProtocolMobType(const eMonsterType a_MobType)
{
switch (a_MobType)
diff --git a/src/Protocol/Protocol_1_12.h b/src/Protocol/Protocol_1_12.h
index 7a92c156f..65bc23bcd 100644
--- a/src/Protocol/Protocol_1_12.h
+++ b/src/Protocol/Protocol_1_12.h
@@ -36,6 +36,7 @@ protected:
virtual UInt32 GetPacketID(ePacketType a_Packet) override;
virtual Version GetProtocolVersion() override;
+ virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override;
virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override;
virtual void HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer);
diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp
index 28b6c26f9..a802f0074 100644
--- a/src/Protocol/Protocol_1_13.cpp
+++ b/src/Protocol/Protocol_1_13.cpp
@@ -403,6 +403,19 @@ UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType)
+signed char cProtocol_1_13::GetProtocolEntityStatus(const EntityAnimation a_Animation) const
+{
+ switch (a_Animation)
+ {
+ case EntityAnimation::DolphinShowsHappiness: return 38;
+ default: return Super::GetProtocolEntityStatus(a_Animation);
+ }
+}
+
+
+
+
+
UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType)
{
switch (a_MobType)
diff --git a/src/Protocol/Protocol_1_13.h b/src/Protocol/Protocol_1_13.h
index d515306e3..53de8bbc1 100644
--- a/src/Protocol/Protocol_1_13.h
+++ b/src/Protocol/Protocol_1_13.h
@@ -49,6 +49,8 @@ protected:
/** Translates outgoing packet types. */
virtual UInt32 GetPacketID(ePacketType a_PacketType) override;
+ virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
+
/** Returns 1.13. */
virtual Version GetProtocolVersion() override;
diff --git a/src/Protocol/Protocol_1_14.cpp b/src/Protocol/Protocol_1_14.cpp
index bc0e68d94..77918c7eb 100644
--- a/src/Protocol/Protocol_1_14.cpp
+++ b/src/Protocol/Protocol_1_14.cpp
@@ -48,6 +48,22 @@ void cProtocol_1_14::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cProtocol_1_14::SendEntityAnimation(const cEntity & a_Entity, EntityAnimation a_Animation)
+{
+ if (a_Animation == EntityAnimation::PlayerEntersBed)
+ {
+ // Use Bed packet removed, through metadata instead:
+ SendEntityMetadata(a_Entity);
+ return;
+ }
+
+ Super::SendEntityAnimation(a_Entity, a_Animation);
+}
+
+
+
+
+
void cProtocol_1_14::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
{
// Send the Join Game packet:
@@ -115,14 +131,6 @@ void cProtocol_1_14::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, co
-void cProtocol_1_14::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
-{
-}
-
-
-
-
-
UInt32 cProtocol_1_14::GetPacketID(ePacketType a_PacketType)
{
switch (a_PacketType)
@@ -203,6 +211,33 @@ UInt32 cProtocol_1_14::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_
+signed char cProtocol_1_14::GetProtocolEntityStatus(EntityAnimation a_Animation) const
+{
+ switch (a_Animation)
+ {
+ case EntityAnimation::FoxChews: return 45;
+ case EntityAnimation::OcelotTrusts: return 40;
+ case EntityAnimation::OcelotDistrusts: return 41;
+ case EntityAnimation::PawnBerryBushPricks: return 44;
+ case EntityAnimation::PawnChestEquipmentBreaks: return 50;
+ case EntityAnimation::PawnFeetEquipmentBreaks: return 52;
+ case EntityAnimation::PawnHeadEquipmentBreaks: return 49;
+ case EntityAnimation::PawnLegsEquipmentBreaks: return 51;
+ case EntityAnimation::PawnMainHandEquipmentBreaks: return 47;
+ case EntityAnimation::PawnOffHandEquipmentBreaks: return 48;
+ case EntityAnimation::PawnTeleports: return 46;
+ case EntityAnimation::PlayerBadOmenActivates: return 43;
+ case EntityAnimation::RavagerAttacks: return 4;
+ case EntityAnimation::RavagerBecomesStunned: return 39;
+ case EntityAnimation::VillagerSweats: return 42;
+ default: return Super::GetProtocolEntityStatus(a_Animation);
+ }
+}
+
+
+
+
+
UInt32 cProtocol_1_14::GetProtocolItemType(short a_ItemID, short a_ItemDamage)
{
return Palette_1_14::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage));
diff --git a/src/Protocol/Protocol_1_14.h b/src/Protocol/Protocol_1_14.h
index 3f328bbac..d1e5b5a4f 100644
--- a/src/Protocol/Protocol_1_14.h
+++ b/src/Protocol/Protocol_1_14.h
@@ -33,17 +33,18 @@ protected:
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) override;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
- virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual UInt32 GetPacketID(ePacketType a_PacketType) override;
virtual Version GetProtocolVersion() override;
virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) override;
virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) override;
+ virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) override;
virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) override;
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index 179e2b2ea..f815bbd29 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -472,13 +472,35 @@ void cProtocol_1_8_0::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
-void cProtocol_1_8_0::SendEntityAnimation(const cEntity & a_Entity, char a_Animation)
+void cProtocol_1_8_0::SendEntityAnimation(const cEntity & a_Entity, const EntityAnimation a_Animation)
{
ASSERT(m_State == 3); // In game mode?
- cPacketizer Pkt(*this, pktEntityAnimation);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEInt8(a_Animation);
+ if (a_Animation == EntityAnimation::PlayerEntersBed)
+ {
+ ASSERT(a_Entity.IsPlayer());
+ const auto BedPosition = static_cast<const cPlayer &>(a_Entity).GetLastBedPos();
+
+ cPacketizer Pkt(*this, pktUseBed);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteXYZPosition64(BedPosition.x, BedPosition.y, BedPosition.z);
+ return;
+ }
+
+ if (const auto AnimationID = GetProtocolEntityAnimation(a_Animation); AnimationID != static_cast<unsigned char>(-1))
+ {
+ cPacketizer Pkt(*this, pktEntityAnimation);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEUInt8(AnimationID);
+ return;
+ }
+
+ if (const auto StatusID = GetProtocolEntityStatus(a_Animation); StatusID != -1)
+ {
+ cPacketizer Pkt(*this, pktEntityStatus);
+ Pkt.WriteBEUInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEInt8(StatusID);
+ }
}
@@ -616,19 +638,6 @@ void cProtocol_1_8_0::SendEntityProperties(const cEntity & a_Entity)
-void cProtocol_1_8_0::SendEntityStatus(const cEntity & a_Entity, char a_Status)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktEntityStatus);
- Pkt.WriteBEUInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEInt8(a_Status);
-}
-
-
-
-
-
void cProtocol_1_8_0::SendEntityVelocity(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
@@ -942,10 +951,9 @@ void cProtocol_1_8_0::SendPlayerAbilities(void)
void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount)
{
ASSERT(m_State == 3); // In game mode?
- int ParticleID = GetParticleID(a_ParticleName);
cPacketizer Pkt(*this, pktParticleEffect);
- Pkt.WriteBEInt32(ParticleID);
+ Pkt.WriteBEInt32(GetProtocolParticleID(a_ParticleName));
Pkt.WriteBool(false);
Pkt.WriteBEFloat(a_SrcX);
Pkt.WriteBEFloat(a_SrcY);
@@ -964,7 +972,8 @@ void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, float a
void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data)
{
ASSERT(m_State == 3); // In game mode?
- int ParticleID = GetParticleID(a_ParticleName);
+
+ const auto ParticleID = GetProtocolParticleID(a_ParticleName);
cPacketizer Pkt(*this, pktParticleEffect);
Pkt.WriteBEInt32(ParticleID);
@@ -977,6 +986,7 @@ void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, Vector3
Pkt.WriteBEFloat(a_Offset.z);
Pkt.WriteBEFloat(a_ParticleData);
Pkt.WriteBEInt32(a_ParticleAmount);
+
switch (ParticleID)
{
// iconcrack
@@ -1624,19 +1634,6 @@ void cProtocol_1_8_0::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, c
-void cProtocol_1_8_0::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktUseBed);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
-}
-
-
-
-
-
void cProtocol_1_8_0::SendUnlockRecipe(UInt32 a_RecipeID)
{
// Client doesn't support this feature
@@ -1835,136 +1832,6 @@ void cProtocol_1_8_0::CompressPacket(CircularBufferCompressor & a_Packet, Contig
-int cProtocol_1_8_0::GetParticleID(const AString & a_ParticleName)
-{
- static const std::unordered_map<AString, int> ParticleMap
- {
- // Initialize the ParticleMap:
- { "explode", 0 },
- { "largeexplode", 1 },
- { "hugeexplosion", 2 },
- { "fireworksspark", 3 },
- { "bubble", 4 },
- { "splash", 5 },
- { "wake", 6 },
- { "suspended", 7 },
- { "depthsuspend", 8 },
- { "crit", 9 },
- { "magiccrit", 10 },
- { "smoke", 11 },
- { "largesmoke", 12 },
- { "spell", 13 },
- { "instantspell", 14 },
- { "mobspell", 15 },
- { "mobspellambient", 16 },
- { "witchmagic", 17 },
- { "dripwater", 18 },
- { "driplava", 19 },
- { "angryvillager", 20 },
- { "happyvillager", 21 },
- { "townaura", 22 },
- { "note", 23 },
- { "portal", 24 },
- { "enchantmenttable", 25 },
- { "flame", 26 },
- { "lava", 27 },
- { "footstep", 28 },
- { "cloud", 29 },
- { "reddust", 30 },
- { "snowballpoof", 31 },
- { "snowshovel", 32 },
- { "slime", 33 },
- { "heart", 34 },
- { "barrier", 35 },
- { "iconcrack", 36 },
- { "blockcrack", 37 },
- { "blockdust", 38 },
- { "droplet", 39 },
- { "take", 40 },
- { "mobappearance", 41 },
- { "dragonbreath", 42 },
- { "endrod", 43 },
- { "damageindicator", 44 },
- { "sweepattack", 45 },
- { "fallingdust", 46 },
- { "totem", 47 },
- { "spit", 48 }
- };
-
- const auto ParticleName = StrToLower(a_ParticleName);
- const auto FindResult = ParticleMap.find(ParticleName);
- if (FindResult == ParticleMap.end())
- {
- LOGWARNING("Unknown particle: %s", a_ParticleName.c_str());
- ASSERT(!"Unknown particle");
- return 0;
- }
-
- return FindResult->second;
-}
-
-
-
-
-
-UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType)
-{
- switch (a_MobType)
- {
- // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong)
- case mtInvalidType: return 53;
- case mtBat: return 65;
- case mtBlaze: return 61;
- case mtCaveSpider: return 59;
- case mtChicken: return 93;
- case mtCow: return 92;
- case mtCreeper: return 50;
- case mtEnderDragon: return 63;
- case mtEnderman: return 58;
- case mtEndermite: return 67;
- case mtGhast: return 56;
- case mtGiant: return 53;
- case mtGuardian: return 68;
- case mtHorse: return 100;
- case mtIronGolem: return 99;
- case mtMagmaCube: return 62;
- case mtMooshroom: return 96;
- case mtOcelot: return 98;
- case mtPig: return 90;
- case mtRabbit: return 101;
- case mtSheep: return 91;
- case mtSilverfish: return 60;
- case mtSkeleton: return 51;
- case mtSlime: return 55;
- case mtSnowGolem: return 97;
- case mtSpider: return 52;
- case mtSquid: return 94;
- case mtVillager: return 120;
- case mtWitch: return 66;
- case mtWither: return 64;
- case mtWitherSkeleton: return 51;
- case mtWolf: return 95;
- case mtZombie: return 54;
- case mtZombiePigman: return 57;
- case mtZombieVillager: return 27;
-
- // Mobs that get replaced with another because they were added later
- case mtCat: return GetProtocolMobType(mtOcelot);
- case mtDonkey: return GetProtocolMobType(mtHorse);
- case mtMule: return GetProtocolMobType(mtHorse);
- case mtSkeletonHorse: return GetProtocolMobType(mtHorse);
- case mtZombieHorse: return GetProtocolMobType(mtHorse);
- case mtStray: return GetProtocolMobType(mtSkeleton);
- case mtHusk: return GetProtocolMobType(mtZombie);
-
- default: return 0;
- }
-}
-
-
-
-
-
UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType)
{
switch (a_PacketType)
@@ -2065,6 +1932,122 @@ cProtocol::Version cProtocol_1_8_0::GetProtocolVersion()
+unsigned char cProtocol_1_8_0::GetProtocolEntityAnimation(const EntityAnimation a_Animation) const
+{
+ switch (a_Animation)
+ {
+ case EntityAnimation::EntityGetsCriticalHit: return 4;
+ case EntityAnimation::EntityGetsMagicalCriticalHit: return 5;
+ case EntityAnimation::PlayerLeavesBed: return 2;
+ case EntityAnimation::PlayerMainHandSwings: return 0;
+ case EntityAnimation::PlayerOffHandSwings: return 0;
+ default: return static_cast<unsigned char>(-1);
+ }
+}
+
+
+
+
+
+signed char cProtocol_1_8_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const
+{
+ switch (a_Animation)
+ {
+ case EntityAnimation::AnimalFallsInLove: return 18;
+ case EntityAnimation::FireworkRocketExplodes: return 17;
+ case EntityAnimation::GuardianAttacks: return 21;
+ case EntityAnimation::HorseTamingFails: return 6;
+ case EntityAnimation::HorseTamingSucceeds: return 7;
+ case EntityAnimation::IronGolemAttacks: return 4;
+ case EntityAnimation::IronGolemOffersGift: return 11;
+ case EntityAnimation::MinecartSpawnerDelayResets: return 1;
+ case EntityAnimation::MinecartTNTIgnites: return 10;
+ case EntityAnimation::MobSpawns: return 20;
+ case EntityAnimation::OcelotTrusts: return 6;
+ case EntityAnimation::OcelotDistrusts: return 7;
+ case EntityAnimation::PawnBerryBushPricks: return 2;
+ case EntityAnimation::PawnBurns: return 2;
+ case EntityAnimation::PawnDies: return 3;
+ case EntityAnimation::PawnDrowns: return 2;
+ case EntityAnimation::PawnHurts: return 2;
+ case EntityAnimation::PawnThornsPricks: return 2;
+ case EntityAnimation::PlayerFinishesEating: return 9;
+ case EntityAnimation::RabbitJumps: return 1;
+ case EntityAnimation::SheepEatsGrass: return 10;
+ case EntityAnimation::VillagerKisses: return 12;
+ case EntityAnimation::VillagerShowsAnger: return 13;
+ case EntityAnimation::VillagerShowsHappiness: return 14;
+ case EntityAnimation::WitchMagicks: return 15;
+ case EntityAnimation::WolfShakesWater: return 8;
+ case EntityAnimation::WolfTamingFails: return 6;
+ case EntityAnimation::WolfTamingSucceeds: return 7;
+ case EntityAnimation::ZombieVillagerCureFinishes: return 16;
+ default: return -1;
+ }
+}
+
+
+
+
+
+UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType)
+{
+ switch (a_MobType)
+ {
+ // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong)
+ case mtInvalidType: return 53;
+ case mtBat: return 65;
+ case mtBlaze: return 61;
+ case mtCaveSpider: return 59;
+ case mtChicken: return 93;
+ case mtCow: return 92;
+ case mtCreeper: return 50;
+ case mtEnderDragon: return 63;
+ case mtEnderman: return 58;
+ case mtEndermite: return 67;
+ case mtGhast: return 56;
+ case mtGiant: return 53;
+ case mtGuardian: return 68;
+ case mtHorse: return 100;
+ case mtIronGolem: return 99;
+ case mtMagmaCube: return 62;
+ case mtMooshroom: return 96;
+ case mtOcelot: return 98;
+ case mtPig: return 90;
+ case mtRabbit: return 101;
+ case mtSheep: return 91;
+ case mtSilverfish: return 60;
+ case mtSkeleton: return 51;
+ case mtSlime: return 55;
+ case mtSnowGolem: return 97;
+ case mtSpider: return 52;
+ case mtSquid: return 94;
+ case mtVillager: return 120;
+ case mtWitch: return 66;
+ case mtWither: return 64;
+ case mtWitherSkeleton: return 51;
+ case mtWolf: return 95;
+ case mtZombie: return 54;
+ case mtZombiePigman: return 57;
+ case mtZombieVillager: return 27;
+
+ // Mobs that get replaced with another because they were added later
+ case mtCat: return GetProtocolMobType(mtOcelot);
+ case mtDonkey: return GetProtocolMobType(mtHorse);
+ case mtMule: return GetProtocolMobType(mtHorse);
+ case mtSkeletonHorse: return GetProtocolMobType(mtHorse);
+ case mtZombieHorse: return GetProtocolMobType(mtHorse);
+ case mtStray: return GetProtocolMobType(mtSkeleton);
+ case mtHusk: return GetProtocolMobType(mtZombie);
+
+ default: return 0;
+ }
+}
+
+
+
+
+
bool cProtocol_1_8_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
{
switch (m_State)
@@ -4079,6 +4062,78 @@ UInt8 cProtocol_1_8_0::GetProtocolEntityType(const cEntity & a_Entity)
+int cProtocol_1_8_0::GetProtocolParticleID(const AString & a_ParticleName)
+{
+ static const std::unordered_map<AString, int> ParticleMap
+ {
+ // Initialize the ParticleMap:
+ { "explode", 0 },
+ { "largeexplode", 1 },
+ { "hugeexplosion", 2 },
+ { "fireworksspark", 3 },
+ { "bubble", 4 },
+ { "splash", 5 },
+ { "wake", 6 },
+ { "suspended", 7 },
+ { "depthsuspend", 8 },
+ { "crit", 9 },
+ { "magiccrit", 10 },
+ { "smoke", 11 },
+ { "largesmoke", 12 },
+ { "spell", 13 },
+ { "instantspell", 14 },
+ { "mobspell", 15 },
+ { "mobspellambient", 16 },
+ { "witchmagic", 17 },
+ { "dripwater", 18 },
+ { "driplava", 19 },
+ { "angryvillager", 20 },
+ { "happyvillager", 21 },
+ { "townaura", 22 },
+ { "note", 23 },
+ { "portal", 24 },
+ { "enchantmenttable", 25 },
+ { "flame", 26 },
+ { "lava", 27 },
+ { "footstep", 28 },
+ { "cloud", 29 },
+ { "reddust", 30 },
+ { "snowballpoof", 31 },
+ { "snowshovel", 32 },
+ { "slime", 33 },
+ { "heart", 34 },
+ { "barrier", 35 },
+ { "iconcrack", 36 },
+ { "blockcrack", 37 },
+ { "blockdust", 38 },
+ { "droplet", 39 },
+ { "take", 40 },
+ { "mobappearance", 41 },
+ { "dragonbreath", 42 },
+ { "endrod", 43 },
+ { "damageindicator", 44 },
+ { "sweepattack", 45 },
+ { "fallingdust", 46 },
+ { "totem", 47 },
+ { "spit", 48 }
+ };
+
+ const auto ParticleName = StrToLower(a_ParticleName);
+ const auto FindResult = ParticleMap.find(ParticleName);
+ if (FindResult == ParticleMap.end())
+ {
+ LOGWARNING("Unknown particle: %s", a_ParticleName.c_str());
+ ASSERT(!"Unknown particle");
+ return 0;
+ }
+
+ return FindResult->second;
+}
+
+
+
+
+
const char * cProtocol_1_8_0::GetProtocolStatisticName(Statistic a_Statistic)
{
switch (a_Statistic)
diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h
index 44168e499..d4aa0c899 100644
--- a/src/Protocol/Protocol_1_8.h
+++ b/src/Protocol/Protocol_1_8.h
@@ -62,7 +62,7 @@ public:
virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
- virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
+ virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) override;
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
@@ -70,7 +70,6 @@ public:
virtual void SendEntityMetadata (const cEntity & a_Entity) override;
virtual void SendEntityPosition (const cEntity & a_Entity) override;
virtual void SendEntityProperties (const cEntity & a_Entity) override;
- virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendEntityVelocity (const cEntity & a_Entity) override;
virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
@@ -123,7 +122,6 @@ public:
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
- virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendUnlockRecipe (UInt32 a_RecipeID) override;
virtual void SendInitRecipes (UInt32 a_RecipeID) override;
virtual void SendWeather (eWeather a_Weather) override;
@@ -138,26 +136,30 @@ public:
a_Compressed will be set to the compressed packet includes packet length and data length. */
static void CompressPacket(CircularBufferCompressor & a_Packet, ContiguousByteBuffer & a_Compressed);
- /** The 1.8 protocol use a particle id instead of a string. This function converts the name to the id. If the name is incorrect, it returns 0. */
- static int GetParticleID(const AString & a_ParticleName);
-
protected:
/** State of the protocol. */
State m_State;
- /** Nobody inherits 1.8, so it doesn't use this method */
+ /** Get the packet ID for a given packet. */
virtual UInt32 GetPacketID(ePacketType a_Packet) override;
/** Returns 1.8. */
virtual Version GetProtocolVersion() override;
+ /** Converts an animation into an ID suitable for use with the Entity Animation packet.
+ Returns (uchar)-1 if the protocol version doesn't support this animation. */
+ virtual unsigned char GetProtocolEntityAnimation(EntityAnimation a_Animation) const;
+
+ /** Converts an animation into an ID suitable for use with the Entity Status packet.
+ Returns -1 if the protocol version doesn't support this animation. */
+ virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const;
+
/** Converts eMonsterType to protocol-specific mob types */
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType);
/** Reads and handles the packet. The packet length and type have already been read.
- Returns true if the packet was understood, false if it was an unknown packet
- */
+ Returns true if the packet was understood, false if it was an unknown packet. */
virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType);
// Packet handlers while in the Status state (m_State == 1):
@@ -269,6 +271,9 @@ private:
Only entities that the Send Spawn Entity packet supports are valid inputs to this method */
static UInt8 GetProtocolEntityType(const cEntity & a_Entity);
+ /** The 1.8 protocol use a particle id instead of a string. This function converts the name to the id. If the name is incorrect, it returns 0. */
+ static int GetProtocolParticleID(const AString & a_ParticleName);
+
/** Converts a statistic to a protocol-specific string.
Protocols <= 1.12 use strings, hence this is a static as the string-mapping was append-only for the versions that used it.
Returns an empty string, handled correctly by the client, for newer, unsupported statistics. */
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index 0ae451117..6b240b235 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -367,19 +367,6 @@ void cProtocol_1_9_0::SendEntityPosition(const cEntity & a_Entity)
-void cProtocol_1_9_0::SendEntityStatus(const cEntity & a_Entity, char a_Status)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktEntityStatus);
- Pkt.WriteBEUInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEInt8(a_Status);
-}
-
-
-
-
-
void cProtocol_1_9_0::SendExperienceOrb(const cExpOrb & a_ExpOrb)
{
ASSERT(m_State == 3); // In game mode?
@@ -708,6 +695,37 @@ UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet)
+unsigned char cProtocol_1_9_0::GetProtocolEntityAnimation(const EntityAnimation a_Animation) const
+{
+ if (a_Animation == EntityAnimation::PlayerOffHandSwings)
+ {
+ return 3;
+ }
+
+ return Super::GetProtocolEntityAnimation(a_Animation);
+}
+
+
+
+
+
+signed char cProtocol_1_9_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const
+{
+ switch (a_Animation)
+ {
+ case EntityAnimation::ArmorStandGetsHit: return 32;
+ case EntityAnimation::ArrowTipSparkles: return 0;
+ case EntityAnimation::PawnShieldBlocks: return 29;
+ case EntityAnimation::PawnShieldBreaks: return 30;
+ case EntityAnimation::PawnThornsPricks: return 33;
+ default: return Super::GetProtocolEntityStatus(a_Animation);
+ }
+}
+
+
+
+
+
cProtocol::Version cProtocol_1_9_0::GetProtocolVersion()
{
return Version::v1_9_0;
diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h
index 190b20005..00d6c477a 100644
--- a/src/Protocol/Protocol_1_9.h
+++ b/src/Protocol/Protocol_1_9.h
@@ -51,7 +51,6 @@ public:
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityMetadata (const cEntity & a_Entity) override;
virtual void SendEntityPosition (const cEntity & a_Entity) override;
- virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendKeepAlive (UInt32 a_PingID) override;
virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override;
@@ -74,6 +73,9 @@ protected:
/** Get the packet ID for a given packet. */
virtual UInt32 GetPacketID(ePacketType a_Packet) override;
+ virtual unsigned char GetProtocolEntityAnimation(EntityAnimation a_Animation) const override;
+ virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
+
/** Returns 1.9. */
virtual Version GetProtocolVersion() override;