1
0
Fork 0

Unify multiprotocol entity animations

This commit is contained in:
Tiger Wang 2021-04-09 23:17:01 +01:00
parent 956f5bca28
commit 66c211c33a
29 changed files with 506 additions and 313 deletions

View File

@ -42,9 +42,8 @@ public:
virtual void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; 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 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 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 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 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, 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<int, 2> a_Data, 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<int, 2> 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 BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) = 0;
virtual void BroadcastTimeUpdate (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 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; virtual void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) = 0;
}; };

View File

@ -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) void cWorld::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{ {
ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) 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) 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) void cWorld::BroadcastWeather(eWeather a_Weather, const cClientHandle * a_Exclude)
{ {
ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client)

View File

@ -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) void cClientHandle::SendEntityVelocity(const cEntity & a_Entity)
{ {
m_Protocol->SendEntityVelocity(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); 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) void cClientHandle::SendUnlockRecipe(UInt32 a_RecipeId)
{ {
m_Protocol->SendUnlockRecipe(a_RecipeId); m_Protocol->SendUnlockRecipe(a_RecipeId);

View File

@ -162,7 +162,7 @@ public: // tolua_export
void SendDisconnect (const AString & a_Reason); void SendDisconnect (const AString & a_Reason);
void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display); void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ); 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 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 SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item);
void SendEntityHeadLook (const cEntity & a_Entity); void SendEntityHeadLook (const cEntity & a_Entity);
@ -170,7 +170,6 @@ public: // tolua_export
void SendEntityMetadata (const cEntity & a_Entity); void SendEntityMetadata (const cEntity & a_Entity);
void SendEntityPosition (const cEntity & a_Entity); void SendEntityPosition (const cEntity & a_Entity);
void SendEntityProperties (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 SendEntityVelocity (const cEntity & a_Entity);
void SendExperience (void); void SendExperience (void);
void SendExperienceOrb (const cExpOrb & a_ExpOrb); void SendExperienceOrb (const cExpOrb & a_ExpOrb);
@ -221,7 +220,6 @@ public: // tolua_export
void SendUnloadChunk (int a_ChunkX, int a_ChunkZ); void SendUnloadChunk (int a_ChunkX, int a_ChunkZ);
void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity); 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 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 */ /** Send a newly discovered recipe to show the notification and unlock in the recipe book */
void SendUnlockRecipe (UInt32 a_RecipeId); void SendUnlockRecipe (UInt32 a_RecipeId);

View File

@ -467,10 +467,92 @@ enum class BossBarDivisionType
TwentyNotches 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. */ /** Returns a textual representation of the click action. */
const char * ClickActionToString(int a_ClickAction); const char * ClickActionToString(int a_ClickAction);

View File

@ -525,7 +525,15 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
SetSpeed(a_TDI.Knockback); 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; 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 the victim is a player the hook is handled by the cPlayer class
if (!IsPlayer()) if (!IsPlayer())
{ {
AString emptystring = AString(""); AString emptystring;
cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_TDI, 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->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
} }
m_World->BroadcastEntityStatus(*this, esGenericDead); m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnDies);
} }

View File

@ -109,47 +109,6 @@ public:
// tolua_end // 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_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 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 static const int LAVA_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in lava

View File

@ -74,7 +74,7 @@ void cFireworkEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
if (m_TicksToExplosion <= 0) if (m_TicksToExplosion <= 0)
{ {
// TODO: Notify the plugins // TODO: Notify the plugins
m_World->BroadcastEntityStatus(*this, esFireworkExploding); m_World->BroadcastEntityAnimation(*this, EntityAnimation::FireworkRocketExplodes);
Destroy(); Destroy();
return; return;
} }

View File

@ -115,7 +115,7 @@ void cPawn::KilledBy(TakeDamageInfo & a_TDI)
// Is death eligible for totem reanimation? // Is death eligible for totem reanimation?
if (DeductTotem(a_TDI.DamageType)) if (DeductTotem(a_TDI.DamageType))
{ {
m_World->BroadcastEntityStatus(*this, esTotemOfUndying); m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnTotemActivates);
AddEntityEffect(cEntityEffect::effAbsorption, 100, 1); AddEntityEffect(cEntityEffect::effAbsorption, 100, 1);
AddEntityEffect(cEntityEffect::effRegeneration, 900, 1); AddEntityEffect(cEntityEffect::effRegeneration, 900, 1);

View File

@ -498,8 +498,7 @@ void cPlayer::StartEating(void)
// Set the timer: // Set the timer:
m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS; m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS;
// Send the packets: // Send the packet:
m_World->BroadcastEntityAnimation(*this, 3);
m_World->BroadcastEntityMetadata(*this); m_World->BroadcastEntityMetadata(*this);
} }
@ -513,7 +512,7 @@ void cPlayer::FinishEating(void)
m_EatingFinishTick = -1_tick; m_EatingFinishTick = -1_tick;
// Send the packets: // Send the packets:
m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted); m_ClientHandle->SendEntityAnimation(*this, EntityAnimation::PlayerFinishesEating);
m_World->BroadcastEntityMetadata(*this); m_World->BroadcastEntityMetadata(*this);
// consume the item: // consume the item:

View File

@ -1463,7 +1463,7 @@ void cMonster::RightClickFeed(cPlayer & a_Player)
a_Player.GetInventory().RemoveOneEquippedItem(); a_Player.GetInventory().RemoveOneEquippedItem();
} }
m_LoveTimer = TPS * 30; // half a minute 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 // If a player holding my spawn egg right-clicked me, spawn a new baby

View File

@ -166,14 +166,12 @@ void cOcelot::OnRightClicked(cPlayer & a_Player)
SetIsTame(true); SetIsTame(true);
SetOwner(a_Player.GetName(), a_Player.GetUUID()); SetOwner(a_Player.GetName(), a_Player.GetUUID());
SetCatType(static_cast<eCatType>(Random.RandInt<int>(1, 3))); SetCatType(static_cast<eCatType>(Random.RandInt<int>(1, 3)));
m_World->BroadcastEntityStatus(*this, esWolfTamed); m_World->BroadcastEntityAnimation(*this, EntityAnimation::OcelotTrusts);
m_World->BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
} }
else else
{ {
// Taming failed // Taming failed
m_World->BroadcastEntityStatus(*this, esWolfTaming); m_World->BroadcastEntityAnimation(*this, EntityAnimation::OcelotDistrusts);
m_World->BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
} }
} }
} }

View File

@ -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) if (m_World->GetBlock({ PosX, PosY, PosZ }) == E_BLOCK_GRASS)
{ {
m_World->BroadcastEntityStatus(*this, esSheepEating); m_World->BroadcastEntityAnimation(*this, EntityAnimation::SheepEatsGrass);
m_TimeToStopEating = 40; m_TimeToStopEating = 40;
} }
} }

View File

@ -34,7 +34,7 @@ bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
{ {
if (GetRandomProvider().RandBool(1.0 / 6.0)) if (GetRandomProvider().RandBool(1.0 / 6.0))
{ {
m_World->BroadcastEntityStatus(*this, esVillagerAngry); m_World->BroadcastEntityAnimation(*this, EntityAnimation::VillagerShowsAnger);
} }
} }

View File

@ -185,14 +185,12 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
SetMaxHealth(20); SetMaxHealth(20);
SetIsTame(true); SetIsTame(true);
SetOwner(a_Player.GetName(), a_Player.GetUUID()); SetOwner(a_Player.GetName(), a_Player.GetUUID());
m_World->BroadcastEntityStatus(*this, esWolfTamed); m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingSucceeds);
m_World->BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
} }
else else
{ {
// Taming failed // Taming failed
m_World->BroadcastEntityStatus(*this, esWolfTaming); m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingFails);
m_World->BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
} }
} }
} }

View File

@ -381,14 +381,13 @@ public:
virtual void SendDisconnect (const AString & a_Reason) = 0; 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 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 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 SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0;
virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0; virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0;
virtual void SendEntityLook (const cEntity & a_Entity) = 0; virtual void SendEntityLook (const cEntity & a_Entity) = 0;
virtual void SendEntityMetadata (const cEntity & a_Entity) = 0; virtual void SendEntityMetadata (const cEntity & a_Entity) = 0;
virtual void SendEntityPosition (const cEntity & a_Entity) = 0; virtual void SendEntityPosition (const cEntity & a_Entity) = 0;
virtual void SendEntityProperties (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 SendEntityVelocity (const cEntity & a_Entity) = 0;
virtual void SendExplosion (Vector3f a_Position, float a_Power) = 0; virtual void SendExplosion (Vector3f a_Position, float a_Power) = 0;
virtual void SendGameMode (eGameMode a_GameMode) = 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 SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 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 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 SendUnlockRecipe (UInt32 a_RecipeID) = 0;
virtual void SendInitRecipes (UInt32 a_RecipeID) = 0; virtual void SendInitRecipes (UInt32 a_RecipeID) = 0;
virtual void SendWeather (eWeather a_Weather) = 0; virtual void SendWeather (eWeather a_Weather) = 0;

View File

@ -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) void cProtocol_1_11_0::SendHideTitle(void)
{ {
ASSERT(m_State == 3); // In game mode? 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) void cProtocol_1_11_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
{ {
int BlockX, BlockY, BlockZ; 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, CursorX);
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorY);
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorZ); 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)); m_Client->HandleRightClick(BlockX, BlockY, BlockZ, FaceIntToBlockFace(Face), FloorC(CursorX * 16), FloorC(CursorY * 16), FloorC(CursorZ * 16), HandIntToEnum(Hand));
} }

View File

@ -33,6 +33,7 @@ public:
protected: protected:
virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override; 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 SendHideTitle (void) override;
virtual void SendResetTitle (void) override; virtual void SendResetTitle (void) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendSpawnMob (const cMonster & a_Mob) override;
@ -44,6 +45,7 @@ protected:
/** Converts eMonsterType to protocol-specific mob IDs */ /** Converts eMonsterType to protocol-specific mob IDs */
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override;
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer) override;

View File

@ -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) UInt32 cProtocol_1_12::GetProtocolMobType(const eMonsterType a_MobType)
{ {
switch (a_MobType) switch (a_MobType)

View File

@ -36,6 +36,7 @@ protected:
virtual UInt32 GetPacketID(ePacketType a_Packet) override; virtual UInt32 GetPacketID(ePacketType a_Packet) override;
virtual Version GetProtocolVersion() override; virtual Version GetProtocolVersion() override;
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override;
virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override;
virtual void HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer); virtual void HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer);

View File

@ -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) UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType)
{ {
switch (a_MobType) switch (a_MobType)

View File

@ -49,6 +49,8 @@ protected:
/** Translates outgoing packet types. */ /** Translates outgoing packet types. */
virtual UInt32 GetPacketID(ePacketType a_PacketType) override; virtual UInt32 GetPacketID(ePacketType a_PacketType) override;
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
/** Returns 1.13. */ /** Returns 1.13. */
virtual Version GetProtocolVersion() override; virtual Version GetProtocolVersion() override;

View File

@ -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) void cProtocol_1_14::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
{ {
// Send the Join Game packet: // 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) UInt32 cProtocol_1_14::GetPacketID(ePacketType a_PacketType)
{ {
switch (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) UInt32 cProtocol_1_14::GetProtocolItemType(short a_ItemID, short a_ItemDamage)
{ {
return Palette_1_14::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); return Palette_1_14::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage));

View File

@ -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 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 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 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 SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) 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 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 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 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 UInt32 GetPacketID(ePacketType a_PacketType) override;
virtual Version GetProtocolVersion() override; virtual Version GetProtocolVersion() override;
virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) override; virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) override;
virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) 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 GetProtocolItemType(short a_ItemID, short a_ItemDamage) override;
virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) override; virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) override;

View File

@ -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? ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktEntityAnimation); if (a_Animation == EntityAnimation::PlayerEntersBed)
Pkt.WriteVarInt32(a_Entity.GetUniqueID()); {
Pkt.WriteBEInt8(a_Animation); 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) void cProtocol_1_8_0::SendEntityVelocity(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode? 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) 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? ASSERT(m_State == 3); // In game mode?
int ParticleID = GetParticleID(a_ParticleName);
cPacketizer Pkt(*this, pktParticleEffect); cPacketizer Pkt(*this, pktParticleEffect);
Pkt.WriteBEInt32(ParticleID); Pkt.WriteBEInt32(GetProtocolParticleID(a_ParticleName));
Pkt.WriteBool(false); Pkt.WriteBool(false);
Pkt.WriteBEFloat(a_SrcX); Pkt.WriteBEFloat(a_SrcX);
Pkt.WriteBEFloat(a_SrcY); 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) 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? ASSERT(m_State == 3); // In game mode?
int ParticleID = GetParticleID(a_ParticleName);
const auto ParticleID = GetProtocolParticleID(a_ParticleName);
cPacketizer Pkt(*this, pktParticleEffect); cPacketizer Pkt(*this, pktParticleEffect);
Pkt.WriteBEInt32(ParticleID); 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_Offset.z);
Pkt.WriteBEFloat(a_ParticleData); Pkt.WriteBEFloat(a_ParticleData);
Pkt.WriteBEInt32(a_ParticleAmount); Pkt.WriteBEInt32(a_ParticleAmount);
switch (ParticleID) switch (ParticleID)
{ {
// iconcrack // 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) void cProtocol_1_8_0::SendUnlockRecipe(UInt32 a_RecipeID)
{ {
// Client doesn't support this feature // 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) UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType)
{ {
switch (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) bool cProtocol_1_8_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
{ {
switch (m_State) 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) const char * cProtocol_1_8_0::GetProtocolStatisticName(Statistic a_Statistic)
{ {
switch (a_Statistic) switch (a_Statistic)

View File

@ -62,7 +62,7 @@ public:
virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override;
virtual void SendDisconnect (const AString & a_Reason) 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 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 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 SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override; virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
@ -70,7 +70,6 @@ public:
virtual void SendEntityMetadata (const cEntity & a_Entity) override; virtual void SendEntityMetadata (const cEntity & a_Entity) override;
virtual void SendEntityPosition (const cEntity & a_Entity) override; virtual void SendEntityPosition (const cEntity & a_Entity) override;
virtual void SendEntityProperties (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 SendEntityVelocity (const cEntity & a_Entity) override;
virtual void SendExperience (void) override; virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) 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 SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) 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 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 SendUnlockRecipe (UInt32 a_RecipeID) override;
virtual void SendInitRecipes (UInt32 a_RecipeID) override; virtual void SendInitRecipes (UInt32 a_RecipeID) override;
virtual void SendWeather (eWeather a_Weather) 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. */ a_Compressed will be set to the compressed packet includes packet length and data length. */
static void CompressPacket(CircularBufferCompressor & a_Packet, ContiguousByteBuffer & a_Compressed); 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: protected:
/** State of the protocol. */ /** State of the protocol. */
State m_State; 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; virtual UInt32 GetPacketID(ePacketType a_Packet) override;
/** Returns 1.8. */ /** Returns 1.8. */
virtual Version GetProtocolVersion() override; 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 */ /** Converts eMonsterType to protocol-specific mob types */
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType); virtual UInt32 GetProtocolMobType(eMonsterType a_MobType);
/** Reads and handles the packet. The packet length and type have already been read. /** 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); virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType);
// Packet handlers while in the Status state (m_State == 1): // 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 */ Only entities that the Send Spawn Entity packet supports are valid inputs to this method */
static UInt8 GetProtocolEntityType(const cEntity & a_Entity); 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. /** 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. 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. */ Returns an empty string, handled correctly by the client, for newer, unsupported statistics. */

View File

@ -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) void cProtocol_1_9_0::SendExperienceOrb(const cExpOrb & a_ExpOrb)
{ {
ASSERT(m_State == 3); // In game mode? 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() cProtocol::Version cProtocol_1_9_0::GetProtocolVersion()
{ {
return Version::v1_9_0; return Version::v1_9_0;

View File

@ -51,7 +51,6 @@ public:
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; 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 SendEntityMetadata (const cEntity & a_Entity) override;
virtual void SendEntityPosition (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 SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendKeepAlive (UInt32 a_PingID) override; virtual void SendKeepAlive (UInt32 a_PingID) override;
virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) 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. */ /** Get the packet ID for a given packet. */
virtual UInt32 GetPacketID(ePacketType a_Packet) override; 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. */ /** Returns 1.9. */
virtual Version GetProtocolVersion() override; virtual Version GetProtocolVersion() override;

View File

@ -176,9 +176,8 @@ public:
virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; 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; virtual void BroadcastEntityPosition (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override;
void BroadcastEntityProperties (const cEntity & a_Entity); 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 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 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, 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<int, 2> a_Data, 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<int, 2> 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 BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) override;
virtual void BroadcastTimeUpdate (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 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 void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) override;
virtual cBroadcastInterface & GetBroadcastManager(void) override virtual cBroadcastInterface & GetBroadcastManager(void) override