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 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<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 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;
};

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)
{
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)

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)
{
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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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:

View File

@ -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

View File

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

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)
{
m_World->BroadcastEntityStatus(*this, esSheepEating);
m_World->BroadcastEntityAnimation(*this, EntityAnimation::SheepEatsGrass);
m_TimeToStopEating = 40;
}
}

View File

@ -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);
}
}

View File

@ -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<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingSucceeds);
}
else
{
// Taming failed
m_World->BroadcastEntityStatus(*this, esWolfTaming);
m_World->BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingFails);
}
}
}

View File

@ -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;

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)
{
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));
}

View File

@ -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;

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)
{
switch (a_MobType)

View File

@ -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);

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)
{
switch (a_MobType)

View File

@ -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;

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)
{
// 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));

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 SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) override;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual UInt32 GetPacketID(ePacketType a_PacketType) override;
virtual Version GetProtocolVersion() override;
virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) override;
virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) override;
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) override;
virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) override;

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?
cPacketizer Pkt(*this, pktEntityAnimation);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
Pkt.WriteBEInt8(a_Animation);
if (a_Animation == EntityAnimation::PlayerEntersBed)
{
ASSERT(a_Entity.IsPlayer());
const auto BedPosition = static_cast<const cPlayer &>(a_Entity).GetLastBedPos();
cPacketizer Pkt(*this, pktUseBed);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
Pkt.WriteXYZPosition64(BedPosition.x, BedPosition.y, BedPosition.z);
return;
}
if (const auto AnimationID = GetProtocolEntityAnimation(a_Animation); AnimationID != static_cast<unsigned char>(-1))
{
cPacketizer Pkt(*this, pktEntityAnimation);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
Pkt.WriteBEUInt8(AnimationID);
return;
}
if (const auto StatusID = GetProtocolEntityStatus(a_Animation); StatusID != -1)
{
cPacketizer Pkt(*this, pktEntityStatus);
Pkt.WriteBEUInt32(a_Entity.GetUniqueID());
Pkt.WriteBEInt8(StatusID);
}
}
@ -616,19 +638,6 @@ void cProtocol_1_8_0::SendEntityProperties(const cEntity & a_Entity)
void cProtocol_1_8_0::SendEntityStatus(const cEntity & a_Entity, char a_Status)
{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktEntityStatus);
Pkt.WriteBEUInt32(a_Entity.GetUniqueID());
Pkt.WriteBEInt8(a_Status);
}
void cProtocol_1_8_0::SendEntityVelocity(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
@ -942,10 +951,9 @@ void cProtocol_1_8_0::SendPlayerAbilities(void)
void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount)
{
ASSERT(m_State == 3); // In game mode?
int ParticleID = GetParticleID(a_ParticleName);
cPacketizer Pkt(*this, pktParticleEffect);
Pkt.WriteBEInt32(ParticleID);
Pkt.WriteBEInt32(GetProtocolParticleID(a_ParticleName));
Pkt.WriteBool(false);
Pkt.WriteBEFloat(a_SrcX);
Pkt.WriteBEFloat(a_SrcY);
@ -964,7 +972,8 @@ void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, float a
void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data)
{
ASSERT(m_State == 3); // In game mode?
int ParticleID = GetParticleID(a_ParticleName);
const auto ParticleID = GetProtocolParticleID(a_ParticleName);
cPacketizer Pkt(*this, pktParticleEffect);
Pkt.WriteBEInt32(ParticleID);
@ -977,6 +986,7 @@ void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, Vector3
Pkt.WriteBEFloat(a_Offset.z);
Pkt.WriteBEFloat(a_ParticleData);
Pkt.WriteBEInt32(a_ParticleAmount);
switch (ParticleID)
{
// iconcrack
@ -1624,19 +1634,6 @@ void cProtocol_1_8_0::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, c
void cProtocol_1_8_0::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktUseBed);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
Pkt.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ);
}
void cProtocol_1_8_0::SendUnlockRecipe(UInt32 a_RecipeID)
{
// Client doesn't support this feature
@ -1835,136 +1832,6 @@ void cProtocol_1_8_0::CompressPacket(CircularBufferCompressor & a_Packet, Contig
int cProtocol_1_8_0::GetParticleID(const AString & a_ParticleName)
{
static const std::unordered_map<AString, int> ParticleMap
{
// Initialize the ParticleMap:
{ "explode", 0 },
{ "largeexplode", 1 },
{ "hugeexplosion", 2 },
{ "fireworksspark", 3 },
{ "bubble", 4 },
{ "splash", 5 },
{ "wake", 6 },
{ "suspended", 7 },
{ "depthsuspend", 8 },
{ "crit", 9 },
{ "magiccrit", 10 },
{ "smoke", 11 },
{ "largesmoke", 12 },
{ "spell", 13 },
{ "instantspell", 14 },
{ "mobspell", 15 },
{ "mobspellambient", 16 },
{ "witchmagic", 17 },
{ "dripwater", 18 },
{ "driplava", 19 },
{ "angryvillager", 20 },
{ "happyvillager", 21 },
{ "townaura", 22 },
{ "note", 23 },
{ "portal", 24 },
{ "enchantmenttable", 25 },
{ "flame", 26 },
{ "lava", 27 },
{ "footstep", 28 },
{ "cloud", 29 },
{ "reddust", 30 },
{ "snowballpoof", 31 },
{ "snowshovel", 32 },
{ "slime", 33 },
{ "heart", 34 },
{ "barrier", 35 },
{ "iconcrack", 36 },
{ "blockcrack", 37 },
{ "blockdust", 38 },
{ "droplet", 39 },
{ "take", 40 },
{ "mobappearance", 41 },
{ "dragonbreath", 42 },
{ "endrod", 43 },
{ "damageindicator", 44 },
{ "sweepattack", 45 },
{ "fallingdust", 46 },
{ "totem", 47 },
{ "spit", 48 }
};
const auto ParticleName = StrToLower(a_ParticleName);
const auto FindResult = ParticleMap.find(ParticleName);
if (FindResult == ParticleMap.end())
{
LOGWARNING("Unknown particle: %s", a_ParticleName.c_str());
ASSERT(!"Unknown particle");
return 0;
}
return FindResult->second;
}
UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType)
{
switch (a_MobType)
{
// Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong)
case mtInvalidType: return 53;
case mtBat: return 65;
case mtBlaze: return 61;
case mtCaveSpider: return 59;
case mtChicken: return 93;
case mtCow: return 92;
case mtCreeper: return 50;
case mtEnderDragon: return 63;
case mtEnderman: return 58;
case mtEndermite: return 67;
case mtGhast: return 56;
case mtGiant: return 53;
case mtGuardian: return 68;
case mtHorse: return 100;
case mtIronGolem: return 99;
case mtMagmaCube: return 62;
case mtMooshroom: return 96;
case mtOcelot: return 98;
case mtPig: return 90;
case mtRabbit: return 101;
case mtSheep: return 91;
case mtSilverfish: return 60;
case mtSkeleton: return 51;
case mtSlime: return 55;
case mtSnowGolem: return 97;
case mtSpider: return 52;
case mtSquid: return 94;
case mtVillager: return 120;
case mtWitch: return 66;
case mtWither: return 64;
case mtWitherSkeleton: return 51;
case mtWolf: return 95;
case mtZombie: return 54;
case mtZombiePigman: return 57;
case mtZombieVillager: return 27;
// Mobs that get replaced with another because they were added later
case mtCat: return GetProtocolMobType(mtOcelot);
case mtDonkey: return GetProtocolMobType(mtHorse);
case mtMule: return GetProtocolMobType(mtHorse);
case mtSkeletonHorse: return GetProtocolMobType(mtHorse);
case mtZombieHorse: return GetProtocolMobType(mtHorse);
case mtStray: return GetProtocolMobType(mtSkeleton);
case mtHusk: return GetProtocolMobType(mtZombie);
default: return 0;
}
}
UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType)
{
switch (a_PacketType)
@ -2065,6 +1932,122 @@ cProtocol::Version cProtocol_1_8_0::GetProtocolVersion()
unsigned char cProtocol_1_8_0::GetProtocolEntityAnimation(const EntityAnimation a_Animation) const
{
switch (a_Animation)
{
case EntityAnimation::EntityGetsCriticalHit: return 4;
case EntityAnimation::EntityGetsMagicalCriticalHit: return 5;
case EntityAnimation::PlayerLeavesBed: return 2;
case EntityAnimation::PlayerMainHandSwings: return 0;
case EntityAnimation::PlayerOffHandSwings: return 0;
default: return static_cast<unsigned char>(-1);
}
}
signed char cProtocol_1_8_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const
{
switch (a_Animation)
{
case EntityAnimation::AnimalFallsInLove: return 18;
case EntityAnimation::FireworkRocketExplodes: return 17;
case EntityAnimation::GuardianAttacks: return 21;
case EntityAnimation::HorseTamingFails: return 6;
case EntityAnimation::HorseTamingSucceeds: return 7;
case EntityAnimation::IronGolemAttacks: return 4;
case EntityAnimation::IronGolemOffersGift: return 11;
case EntityAnimation::MinecartSpawnerDelayResets: return 1;
case EntityAnimation::MinecartTNTIgnites: return 10;
case EntityAnimation::MobSpawns: return 20;
case EntityAnimation::OcelotTrusts: return 6;
case EntityAnimation::OcelotDistrusts: return 7;
case EntityAnimation::PawnBerryBushPricks: return 2;
case EntityAnimation::PawnBurns: return 2;
case EntityAnimation::PawnDies: return 3;
case EntityAnimation::PawnDrowns: return 2;
case EntityAnimation::PawnHurts: return 2;
case EntityAnimation::PawnThornsPricks: return 2;
case EntityAnimation::PlayerFinishesEating: return 9;
case EntityAnimation::RabbitJumps: return 1;
case EntityAnimation::SheepEatsGrass: return 10;
case EntityAnimation::VillagerKisses: return 12;
case EntityAnimation::VillagerShowsAnger: return 13;
case EntityAnimation::VillagerShowsHappiness: return 14;
case EntityAnimation::WitchMagicks: return 15;
case EntityAnimation::WolfShakesWater: return 8;
case EntityAnimation::WolfTamingFails: return 6;
case EntityAnimation::WolfTamingSucceeds: return 7;
case EntityAnimation::ZombieVillagerCureFinishes: return 16;
default: return -1;
}
}
UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType)
{
switch (a_MobType)
{
// Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong)
case mtInvalidType: return 53;
case mtBat: return 65;
case mtBlaze: return 61;
case mtCaveSpider: return 59;
case mtChicken: return 93;
case mtCow: return 92;
case mtCreeper: return 50;
case mtEnderDragon: return 63;
case mtEnderman: return 58;
case mtEndermite: return 67;
case mtGhast: return 56;
case mtGiant: return 53;
case mtGuardian: return 68;
case mtHorse: return 100;
case mtIronGolem: return 99;
case mtMagmaCube: return 62;
case mtMooshroom: return 96;
case mtOcelot: return 98;
case mtPig: return 90;
case mtRabbit: return 101;
case mtSheep: return 91;
case mtSilverfish: return 60;
case mtSkeleton: return 51;
case mtSlime: return 55;
case mtSnowGolem: return 97;
case mtSpider: return 52;
case mtSquid: return 94;
case mtVillager: return 120;
case mtWitch: return 66;
case mtWither: return 64;
case mtWitherSkeleton: return 51;
case mtWolf: return 95;
case mtZombie: return 54;
case mtZombiePigman: return 57;
case mtZombieVillager: return 27;
// Mobs that get replaced with another because they were added later
case mtCat: return GetProtocolMobType(mtOcelot);
case mtDonkey: return GetProtocolMobType(mtHorse);
case mtMule: return GetProtocolMobType(mtHorse);
case mtSkeletonHorse: return GetProtocolMobType(mtHorse);
case mtZombieHorse: return GetProtocolMobType(mtHorse);
case mtStray: return GetProtocolMobType(mtSkeleton);
case mtHusk: return GetProtocolMobType(mtZombie);
default: return 0;
}
}
bool cProtocol_1_8_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
{
switch (m_State)
@ -4079,6 +4062,78 @@ UInt8 cProtocol_1_8_0::GetProtocolEntityType(const cEntity & a_Entity)
int cProtocol_1_8_0::GetProtocolParticleID(const AString & a_ParticleName)
{
static const std::unordered_map<AString, int> ParticleMap
{
// Initialize the ParticleMap:
{ "explode", 0 },
{ "largeexplode", 1 },
{ "hugeexplosion", 2 },
{ "fireworksspark", 3 },
{ "bubble", 4 },
{ "splash", 5 },
{ "wake", 6 },
{ "suspended", 7 },
{ "depthsuspend", 8 },
{ "crit", 9 },
{ "magiccrit", 10 },
{ "smoke", 11 },
{ "largesmoke", 12 },
{ "spell", 13 },
{ "instantspell", 14 },
{ "mobspell", 15 },
{ "mobspellambient", 16 },
{ "witchmagic", 17 },
{ "dripwater", 18 },
{ "driplava", 19 },
{ "angryvillager", 20 },
{ "happyvillager", 21 },
{ "townaura", 22 },
{ "note", 23 },
{ "portal", 24 },
{ "enchantmenttable", 25 },
{ "flame", 26 },
{ "lava", 27 },
{ "footstep", 28 },
{ "cloud", 29 },
{ "reddust", 30 },
{ "snowballpoof", 31 },
{ "snowshovel", 32 },
{ "slime", 33 },
{ "heart", 34 },
{ "barrier", 35 },
{ "iconcrack", 36 },
{ "blockcrack", 37 },
{ "blockdust", 38 },
{ "droplet", 39 },
{ "take", 40 },
{ "mobappearance", 41 },
{ "dragonbreath", 42 },
{ "endrod", 43 },
{ "damageindicator", 44 },
{ "sweepattack", 45 },
{ "fallingdust", 46 },
{ "totem", 47 },
{ "spit", 48 }
};
const auto ParticleName = StrToLower(a_ParticleName);
const auto FindResult = ParticleMap.find(ParticleName);
if (FindResult == ParticleMap.end())
{
LOGWARNING("Unknown particle: %s", a_ParticleName.c_str());
ASSERT(!"Unknown particle");
return 0;
}
return FindResult->second;
}
const char * cProtocol_1_8_0::GetProtocolStatisticName(Statistic a_Statistic)
{
switch (a_Statistic)

View File

@ -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. */

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)
{
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;

View File

@ -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;

View File

@ -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<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 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