diff --git a/src/Blocks/BroadcastInterface.h b/src/Blocks/BroadcastInterface.h index ab756fe88..6c52a5156 100644 --- a/src/Blocks/BroadcastInterface.h +++ b/src/Blocks/BroadcastInterface.h @@ -42,9 +42,8 @@ public: virtual void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityPosition (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; - virtual void BroadcastEntityStatus (const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; - virtual void BroadcastEntityAnimation (const cEntity & a_Entity, Int8 a_Animation, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) = 0; virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data, const cClientHandle * a_Exclude = nullptr) = 0; @@ -64,6 +63,5 @@ public: virtual void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastTimeUpdate (const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastUnleashEntity (const cEntity & a_Entity) = 0; - virtual void BroadcastUseBed (const cEntity & a_Entity, Vector3i a_BedPos) = 0; virtual void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) = 0; }; diff --git a/src/Broadcaster.cpp b/src/Broadcaster.cpp index 770a3987c..0a8f17930 100644 --- a/src/Broadcaster.cpp +++ b/src/Broadcaster.cpp @@ -358,19 +358,6 @@ void cWorld::BroadcastEntityProperties(const cEntity & a_Entity) -void cWorld::BroadcastEntityStatus(const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude) -{ - ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) - { - a_Client.SendEntityStatus(a_Entity, a_Status); - } - ); -} - - - - - void cWorld::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) @@ -384,7 +371,7 @@ void cWorld::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHand -void cWorld::BroadcastEntityAnimation(const cEntity & a_Entity, Int8 a_Animation, const cClientHandle * a_Exclude) +void cWorld::BroadcastEntityAnimation(const cEntity & a_Entity, EntityAnimation a_Animation, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { @@ -631,19 +618,6 @@ void cWorld::BroadcastUnleashEntity(const cEntity & a_Entity) -void cWorld::BroadcastUseBed(const cEntity & a_Entity, Vector3i a_BedPos) -{ - ForClientsWithChunkAtPos(a_BedPos, *this, nullptr, [&](cClientHandle & a_Client) - { - a_Client.SendUseBed(a_Entity, a_BedPos.x, a_BedPos.y, a_BedPos.z); - } - ); -} - - - - - void cWorld::BroadcastWeather(eWeather a_Weather, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 2050fd1ed..d356b524a 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2537,15 +2537,6 @@ void cClientHandle::SendEntityProperties(const cEntity & a_Entity) -void cClientHandle::SendEntityStatus(const cEntity & a_Entity, char a_Status) -{ - m_Protocol->SendEntityStatus(a_Entity, a_Status); -} - - - - - void cClientHandle::SendEntityVelocity(const cEntity & a_Entity) { m_Protocol->SendEntityVelocity(a_Entity); @@ -2674,7 +2665,7 @@ void cClientHandle::SendPaintingSpawn(const cPainting & a_Painting) -void cClientHandle::SendEntityAnimation(const cEntity & a_Entity, char a_Animation) +void cClientHandle::SendEntityAnimation(const cEntity & a_Entity, EntityAnimation a_Animation) { m_Protocol->SendEntityAnimation(a_Entity, a_Animation); } @@ -3064,15 +3055,6 @@ void cClientHandle::SendUpdateSign( -void cClientHandle::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) -{ - m_Protocol->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); -} - - - - - void cClientHandle::SendUnlockRecipe(UInt32 a_RecipeId) { m_Protocol->SendUnlockRecipe(a_RecipeId); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 971edfb8a..cb0ea508a 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -162,7 +162,7 @@ public: // tolua_export void SendDisconnect (const AString & a_Reason); void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display); void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ); - void SendEntityAnimation (const cEntity & a_Entity, char a_Animation); // tolua_export + void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation); // tolua_export void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration); void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item); void SendEntityHeadLook (const cEntity & a_Entity); @@ -170,7 +170,6 @@ public: // tolua_export void SendEntityMetadata (const cEntity & a_Entity); void SendEntityPosition (const cEntity & a_Entity); void SendEntityProperties (const cEntity & a_Entity); - void SendEntityStatus (const cEntity & a_Entity, char a_Status); void SendEntityVelocity (const cEntity & a_Entity); void SendExperience (void); void SendExperienceOrb (const cExpOrb & a_ExpOrb); @@ -221,7 +220,6 @@ public: // tolua_export void SendUnloadChunk (int a_ChunkX, int a_ChunkZ); void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity); 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); - void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ); /** Send a newly discovered recipe to show the notification and unlock in the recipe book */ void SendUnlockRecipe (UInt32 a_RecipeId); diff --git a/src/Defines.h b/src/Defines.h index 417f28a42..a1c1d1cf8 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -467,10 +467,92 @@ enum class BossBarDivisionType TwentyNotches }; +// tolua_end + +enum class EntityAnimation +{ + AnimalFallsInLove, + ArmorStandGetsHit, + ArrowTipSparkles, + DolphinShowsHappiness, + EggCracks, + EntityGetsCriticalHit, + EntityGetsMagicalCriticalHit, + EntityTrailsHoney, + EvokerFangsAttacks, + FireworkRocketExplodes, + // FishingHookReels, + FoxChews, + GuardianAttacks, + HoglinAttacks, + HorseTamingFails, + HorseTamingSucceeds, + IronGolemAttacks, + IronGolemOffersGift, + IronGolemStashesGift, + MinecartSpawnerDelayResets, + MinecartTNTIgnites, + MobSpawns, + OcelotTrusts, + OcelotDistrusts, + PawnBerryBushPricks, + PawnBurns, + PawnChestEquipmentBreaks, + PawnDies, + PawnDrowns, + PawnFeetEquipmentBreaks, + PawnHandItemSwaps, + PawnHeadEquipmentBreaks, + PawnHurts, + PawnLegsEquipmentBreaks, + PawnMainHandEquipmentBreaks, + PawnOffHandEquipmentBreaks, + PawnShieldBlocks, + PawnShieldBreaks, + PawnTeleports, + PawnThornsPricks, + PawnTotemActivates, + PlayerBadOmenActivates, + PlayerEntersBed, + PlayerFinishesEating, + PlayerLeavesBed, + PlayerMainHandSwings, + // PlayerReducedDebugScreenDisables, + // PlayerReducedDebugScreenEnables, + // PlayerSetsOperatorLevelFour, + // PlayerSetsOperatorLevelOne, + // PlayerSetsOperatorLevelThree, + // PlayerSetsOperatorLevelTwo, + // PlayerSetsOperatorLevelZero, + PlayerOffHandSwings, + RabbitJumps, + RavagerAttacks, + RavagerBecomesStunned, + SheepEatsGrass, + SnowballPoofs, + // SquidResetsRotation, + VillagerKisses, + VillagerShowsAnger, + VillagerShowsHappiness, + VillagerSweats, + WitchMagicks, + WolfShakesWater, + WolfTamingFails, + WolfTamingSucceeds, + ZoglinAttacks, + ZombieVillagerCureFinishes +}; + + + + + +// tolua_begin + /** Returns a textual representation of the click action. */ const char * ClickActionToString(int a_ClickAction); diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index c8a6b8ef9..7bb53bd2a 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -525,7 +525,15 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) SetSpeed(a_TDI.Knockback); } - m_World->BroadcastEntityStatus(*this, esGenericHurt); + m_World->BroadcastEntityAnimation(*this, [&a_TDI] + { + switch (a_TDI.DamageType) + { + case eDamageType::dtBurning: return EntityAnimation::PawnBurns; + case eDamageType::dtDrowning: return EntityAnimation::PawnDrowns; + default: return EntityAnimation::PawnHurts; + } + }()); m_InvulnerableTicks = 10; @@ -797,7 +805,7 @@ void cEntity::KilledBy(TakeDamageInfo & a_TDI) // If the victim is a player the hook is handled by the cPlayer class if (!IsPlayer()) { - AString emptystring = AString(""); + AString emptystring; cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_TDI, emptystring); } @@ -813,7 +821,7 @@ void cEntity::KilledBy(TakeDamageInfo & a_TDI) m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ()); } - m_World->BroadcastEntityStatus(*this, esGenericDead); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnDies); } diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index c3ccaa228..db526045e 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -109,47 +109,6 @@ public: // tolua_end - enum eEntityStatus - { - // TODO: Investigate 0, 1, and 5 as Wiki.vg is not certain - - // Entity becomes coloured red - esGenericHurt = 2, - // Entity plays death animation (entity falls to ground) - esGenericDead = 3, - // Iron Golem plays attack animation (arms lift and fall) - esIronGolemAttacking = 4, - // Wolf taming particles spawn (smoke) - esWolfTaming = 6, - // Wolf tamed particles spawn (hearts) - esWolfTamed = 7, - // Wolf plays water removal animation (shaking and water particles) - esWolfDryingWater = 8, - // Informs client that eating was accepted - esPlayerEatingAccepted = 9, - // Sheep plays eating animation (head lowers to ground) - esSheepEating = 10, - // Iron Golem holds gift to villager children - esIronGolemGivingPlant = 11, - // Villager spawns heart particles - esVillagerBreeding = 12, - // Villager spawns thunderclound particles - esVillagerAngry = 13, - // Villager spawns green crosses - esVillagerHappy = 14, - // Witch spawns magic particle (TODO: investigation into what this is) - esWitchMagicking = 15, - - // It seems 16 (zombie conversion) is now done with metadata - - // Informs client to explode a firework based on its metadata - esFireworkExploding = 17, - // Passive mob is in "love mode" - esMobInLove = 18, - // Plays totem of undying animation and sound - esTotemOfUndying = 35, - } ; - static const int FIRE_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in fire static const int FIRE_DAMAGE = 1; ///< Damage to deal when standing in fire static const int LAVA_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in lava diff --git a/src/Entities/FireworkEntity.cpp b/src/Entities/FireworkEntity.cpp index eb386cdfc..03db96d91 100644 --- a/src/Entities/FireworkEntity.cpp +++ b/src/Entities/FireworkEntity.cpp @@ -74,7 +74,7 @@ void cFireworkEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) if (m_TicksToExplosion <= 0) { // TODO: Notify the plugins - m_World->BroadcastEntityStatus(*this, esFireworkExploding); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::FireworkRocketExplodes); Destroy(); return; } diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp index cc11323e1..5476db468 100644 --- a/src/Entities/Pawn.cpp +++ b/src/Entities/Pawn.cpp @@ -115,7 +115,7 @@ void cPawn::KilledBy(TakeDamageInfo & a_TDI) // Is death eligible for totem reanimation? if (DeductTotem(a_TDI.DamageType)) { - m_World->BroadcastEntityStatus(*this, esTotemOfUndying); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnTotemActivates); AddEntityEffect(cEntityEffect::effAbsorption, 100, 1); AddEntityEffect(cEntityEffect::effRegeneration, 900, 1); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 8c047c533..563a1cb97 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -498,8 +498,7 @@ void cPlayer::StartEating(void) // Set the timer: m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS; - // Send the packets: - m_World->BroadcastEntityAnimation(*this, 3); + // Send the packet: m_World->BroadcastEntityMetadata(*this); } @@ -513,7 +512,7 @@ void cPlayer::FinishEating(void) m_EatingFinishTick = -1_tick; // Send the packets: - m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted); + m_ClientHandle->SendEntityAnimation(*this, EntityAnimation::PlayerFinishesEating); m_World->BroadcastEntityMetadata(*this); // consume the item: diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 1537a8a74..c1a244a9f 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -1463,7 +1463,7 @@ void cMonster::RightClickFeed(cPlayer & a_Player) a_Player.GetInventory().RemoveOneEquippedItem(); } m_LoveTimer = TPS * 30; // half a minute - m_World->BroadcastEntityStatus(*this, esMobInLove); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::AnimalFallsInLove); } } // If a player holding my spawn egg right-clicked me, spawn a new baby diff --git a/src/Mobs/Ocelot.cpp b/src/Mobs/Ocelot.cpp index 329c17527..4b731154d 100644 --- a/src/Mobs/Ocelot.cpp +++ b/src/Mobs/Ocelot.cpp @@ -166,14 +166,12 @@ void cOcelot::OnRightClicked(cPlayer & a_Player) SetIsTame(true); SetOwner(a_Player.GetName(), a_Player.GetUUID()); SetCatType(static_cast(Random.RandInt(1, 3))); - m_World->BroadcastEntityStatus(*this, esWolfTamed); - m_World->BroadcastParticleEffect("heart", static_cast(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::OcelotTrusts); } else { // Taming failed - m_World->BroadcastEntityStatus(*this, esWolfTaming); - m_World->BroadcastParticleEffect("smoke", static_cast(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::OcelotDistrusts); } } } diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 7808d3181..156046c74 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -129,7 +129,7 @@ void cSheep::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { if (m_World->GetBlock({ PosX, PosY, PosZ }) == E_BLOCK_GRASS) { - m_World->BroadcastEntityStatus(*this, esSheepEating); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::SheepEatsGrass); m_TimeToStopEating = 40; } } diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 156515880..46dd613f1 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -34,7 +34,7 @@ bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) { if (GetRandomProvider().RandBool(1.0 / 6.0)) { - m_World->BroadcastEntityStatus(*this, esVillagerAngry); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::VillagerShowsAnger); } } diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 85d2a5a1b..0a3a12ea7 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -185,14 +185,12 @@ void cWolf::OnRightClicked(cPlayer & a_Player) SetMaxHealth(20); SetIsTame(true); SetOwner(a_Player.GetName(), a_Player.GetUUID()); - m_World->BroadcastEntityStatus(*this, esWolfTamed); - m_World->BroadcastParticleEffect("heart", static_cast(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingSucceeds); } else { // Taming failed - m_World->BroadcastEntityStatus(*this, esWolfTaming); - m_World->BroadcastParticleEffect("smoke", static_cast(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingFails); } } } 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 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(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(-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 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 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(-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 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; diff --git a/src/World.h b/src/World.h index 8db9a9e9d..958154bf0 100644 --- a/src/World.h +++ b/src/World.h @@ -176,9 +176,8 @@ public: virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityPosition (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; void BroadcastEntityProperties (const cEntity & a_Entity); - virtual void BroadcastEntityStatus (const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; - virtual void BroadcastEntityAnimation (const cEntity & a_Entity, Int8 a_Animation, const cClientHandle * a_Exclude = nullptr) override; // tolua_export + virtual void BroadcastEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation, const cClientHandle * a_Exclude = nullptr) override; // tolua_export virtual void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp @@ -198,7 +197,6 @@ public: virtual void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastTimeUpdate (const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastUnleashEntity (const cEntity & a_Entity) override; - virtual void BroadcastUseBed (const cEntity & a_Entity, Vector3i a_BlockPos) override; virtual void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) override; virtual cBroadcastInterface & GetBroadcastManager(void) override