From 8405b8969f205ffae219361dfc03f3b4c680ce73 Mon Sep 17 00:00:00 2001 From: 12xx12 <44411062+12xx12@users.noreply.github.com> Date: Fri, 5 Mar 2021 16:08:30 +0100 Subject: [PATCH] Adding Boss bar (#5025) + Add boss bar Co-authored-by: Tiger Wang --- Server/Plugins/APIDump/APIDesc.lua | 189 +++++++++++++++++++++++++++++ src/Blocks/BroadcastInterface.h | 3 +- src/Broadcaster.cpp | 39 ++++-- src/ClientHandle.cpp | 72 +++++++++-- src/ClientHandle.h | 6 + src/Defines.h | 29 +++++ src/Mobs/EnderDragon.cpp | 25 ++++ src/Mobs/EnderDragon.h | 6 +- src/Mobs/Wither.cpp | 78 +++++++----- src/Mobs/Wither.h | 12 +- src/Protocol/Packetizer.cpp | 1 + src/Protocol/Protocol.h | 7 ++ src/Protocol/Protocol_1_10.h | 2 +- src/Protocol/Protocol_1_11.h | 4 +- src/Protocol/Protocol_1_12.h | 6 +- src/Protocol/Protocol_1_13.cpp | 90 +++++++++++++- src/Protocol/Protocol_1_13.h | 7 +- src/Protocol/Protocol_1_14.h | 2 +- src/Protocol/Protocol_1_8.cpp | 121 +++++++++++++----- src/Protocol/Protocol_1_8.h | 8 +- src/Protocol/Protocol_1_9.cpp | 167 +++++++++++++++++++++++++ src/Protocol/Protocol_1_9.h | 12 +- src/World.h | 3 +- 23 files changed, 781 insertions(+), 108 deletions(-) diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index c84260903..411ee95f4 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -1569,6 +1569,128 @@ end }, Notes = "Sends a BlockChange packet to the client. This can be used to create fake blocks only for that player.", }, + SendBossBarAdd = + { + Params = + { + { + Name = "UniqueID", + Type = "number", + }, + { + Name = "Title", + Type = "cCompositeChat", + }, + { + Name = "FractionFilled", + Type = "number", + }, + { + Name = "Colour", + Type = "BossBarColor", + }, + { + Name = "DivisionType", + Type = "BossBarDivisionType", + }, + { + Name = "DarkenSky", + Type = "boolean", + }, + { + Name = "PlayEndMusic", + Type = "boolean", + }, + { + Name = "CreateFog", + Type = "boolean", + }, + }, + Notes = "Creates a boss bar on the client's UI. The boss bar is independent of any entity and has a lifetime and properties fully controlled by the plugin. Plugins are responsible for assigning a unique ID and removal.", + }, + SendBossBarUpdateFlags = + { + Params = + { + { + Name = "UniqueID", + Type = "number", + }, + { + Name = "DarkenSky", + Type = "boolean", + }, + { + Name = "PlayEndMusic", + Type = "boolean", + }, + { + Name = "CreateFog", + Type = "boolean", + }, + }, + Notes = "Updates a boss bar on the client's UI. Only updates some meta flags for additional effects.", + }, + SendBossBarUpdateStyle = + { + Params = + { + { + Name = "UniqueID", + Type = "number", + }, + { + Name = "Color", + Type = "BossBarColor", + }, + { + Name = "DivisionType", + Type = "BossBarDivisionType", + }, + }, + Notes = "Updates a boss bar on the client's UI. Only updates the visuals of the Boss Bar.", + }, + SendBossBarUpdateTitle = + { + Params = + { + { + Name = "UniqueID", + Type = "number", + }, + { + Name = "Title", + Type = "cCompositeChat", + }, + }, + Notes = "Updates a boss bar on the client's UI. Only Updates the text at the top.", + }, + SendBossBarRemove = + { + Params = + { + { + Name = "UniqueID", + Type = "number", + }, + }, + Notes = "Removes the boss bar with the given ID from the client's UI.", + }, + SendBossBarUpdateHealth = + { + Params = + { + { + Name = "UniqueID", + Type = "number", + }, + { + Name = "FractionFilled", + Type = "number", + }, + }, + Notes = "Updates the health displayed by the boss bar with the given ID.", + }, SendEntityAnimation = { Params = @@ -13120,6 +13242,73 @@ end }, -- ConstantGroups }, -- cWindow + BossBarColor = + { + Desc = [[ + An enumeration of boss bar display colours which can be used with {{cClientHandle#SendBossBarAdd|SendBossBarAdd}}. + ]], + Constants = + { + Pink = + { + Notes = "A pink boss bar." + }, + Blue = + { + Notes = "A blue boss bar." + }, + Red = + { + Notes = "A red boss bar." + }, + Green = + { + Notes = "A green boss bar." + }, + Yellow = + { + Notes = "A yellow boss bar." + }, + Purple = + { + Notes = "A purple boss bar." + }, + White = + { + Notes = "A white boss bar." + }, + }, + }, + BossBarDivisionType = + { + Desc = [[ + An enumeration of boss bar division types which can be used with {{cClientHandle#SendBossBarAdd|SendBossBarAdd}}. + These constants control the number of notches the bar itself renders with. + ]], + Constants = + { + None = + { + Notes = "A completely smooth boss bar." + }, + SixNotches = + { + Notes = "A six-notch'd boss bar." + }, + TenNotches = + { + Notes = "A ten-notch'd boss bar." + }, + TwelveNotches = + { + Notes = "A twelve notch'd boss bar." + }, + TwentyNotches = + { + Notes = "A twenty notch'd boss bar." + }, + }, + }, EffectID = { Desc = [[ diff --git a/src/Blocks/BroadcastInterface.h b/src/Blocks/BroadcastInterface.h index 93dbe4961..552686cf8 100644 --- a/src/Blocks/BroadcastInterface.h +++ b/src/Blocks/BroadcastInterface.h @@ -24,6 +24,7 @@ public: virtual void BroadcastBlockAction (Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastBlockBreakAnimation (UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastBossBarUpdateHealth (const cEntity & a_Entity, UInt32 a_UniqueID, float a_FractionFilled) = 0; virtual void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = nullptr, eMessageType a_ChatPrefix = mtCustom) = 0; virtual void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastChatFailure (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; @@ -50,9 +51,9 @@ public: virtual void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) = 0; virtual void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; - virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; virtual void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_PlayerName, cObjective::Score a_Score, Byte a_Mode) = 0; diff --git a/src/Broadcaster.cpp b/src/Broadcaster.cpp index 98759a58b..c8d2de615 100644 --- a/src/Broadcaster.cpp +++ b/src/Broadcaster.cpp @@ -171,6 +171,19 @@ void cWorld::BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle * a_E +void cWorld::BroadcastBossBarUpdateHealth(const cEntity & a_Entity, UInt32 a_UniqueID, float a_FractionFilled) +{ + ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendBossBarUpdateHealth(a_UniqueID, a_FractionFilled); + } + ); +} + + + + + void cWorld::BroadcastChat(const AString & a_Message, const cClientHandle * a_Exclude, eMessageType a_ChatPrefix) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) @@ -444,6 +457,19 @@ void cWorld::BroadcastPlayerListRemovePlayer(const cPlayer & a_Player, const cCl +void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendPlayerListUpdateDisplayName(a_Player, a_CustomName); + } + ); +} + + + + + void cWorld::BroadcastPlayerListUpdateGameMode(const cPlayer & a_Player, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) @@ -470,19 +496,6 @@ void cWorld::BroadcastPlayerListUpdatePing(const cPlayer & a_Player, const cClie -void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude) -{ - ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) - { - a_Client.SendPlayerListUpdateDisplayName(a_Player, a_CustomName); - } - ); -} - - - - - void cWorld::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 3c003e132..683a243fe 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2188,6 +2188,60 @@ void cClientHandle::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlock +void cClientHandle::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + m_Protocol->SendBossBarAdd(a_UniqueID, a_Title, a_FractionFilled, a_Color, a_DivisionType, a_DarkenSky, a_PlayEndMusic, a_CreateFog); +} + + + + + +void cClientHandle::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + m_Protocol->SendBossBarUpdateFlags(a_UniqueID, a_DarkenSky, a_PlayEndMusic, a_CreateFog); +} + + + + + +void cClientHandle::SendBossBarUpdateStyle(UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) +{ + m_Protocol->SendBossBarUpdateStyle(a_UniqueID, a_Color, a_DivisionType); +} + + + + + +void cClientHandle::SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat & a_Title) +{ + m_Protocol->SendBossBarUpdateTitle(a_UniqueID, a_Title); +} + + + + + +void cClientHandle::SendBossBarRemove(UInt32 a_UniqueID) +{ + m_Protocol->SendBossBarRemove(a_UniqueID); +} + + + + + +void cClientHandle::SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) +{ + m_Protocol->SendBossBarUpdateHealth(a_UniqueID, a_FractionFilled); +} + + + + + void cClientHandle::SendCameraSetTo(const cEntity & a_Entity) { m_Protocol->SendCameraSetTo(a_Entity); @@ -2643,6 +2697,15 @@ void cClientHandle::SendPlayerListRemovePlayer(const cPlayer & a_Player) +void cClientHandle::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) +{ + m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_CustomName); +} + + + + + void cClientHandle::SendPlayerListUpdateGameMode(const cPlayer & a_Player) { m_Protocol->SendPlayerListUpdateGameMode(a_Player); @@ -2661,15 +2724,6 @@ void cClientHandle::SendPlayerListUpdatePing(const cPlayer & a_Player) -void cClientHandle::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) -{ - m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_CustomName); -} - - - - - void cClientHandle::SendPlayerMaxSpeed(void) { m_Protocol->SendPlayerMaxSpeed(); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index f3e0e7f25..2e1e09a06 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -144,6 +144,12 @@ public: // tolua_export void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage); void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes); + void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog); // tolua_export + void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog); // tolua_export + void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType); // tolua_export + void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title); // tolua_export + void SendBossBarRemove (UInt32 a_UniqueID); // tolua_export + void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled); // tolua_export void SendCameraSetTo (const cEntity & a_Entity); void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); void SendChat (const cCompositeChat & a_Message); diff --git a/src/Defines.h b/src/Defines.h index fb3231ff2..cf030bdd7 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -394,6 +394,35 @@ enum eMessageType + +enum class BossBarColor +{ + Pink, + Blue, + Red, + Green, + Yellow, + Purple, + White +}; + + + + + +enum class BossBarDivisionType +{ + None, + SixNotches, + TenNotches, + TwelveNotches, + TwentyNotches +}; + + + + + /** Returns a textual representation of the click action. */ const char * ClickActionToString(int a_ClickAction); diff --git a/src/Mobs/EnderDragon.cpp b/src/Mobs/EnderDragon.cpp index a3ba5f937..e33fb21f1 100644 --- a/src/Mobs/EnderDragon.cpp +++ b/src/Mobs/EnderDragon.cpp @@ -2,6 +2,8 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EnderDragon.h" +#include "../ClientHandle.h" +#include "../CompositeChat.h" @@ -17,6 +19,21 @@ cEnderDragon::cEnderDragon(void) : +bool cEnderDragon::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (!Super::DoTakeDamage(a_TDI)) + { + return false; + } + + m_World->BroadcastBossBarUpdateHealth(*this, GetUniqueID(), GetHealth() / GetMaxHealth()); + return true; +} + + + + + void cEnderDragon::GetDrops(cItems & a_Drops, cEntity * a_Killer) { // No drops @@ -25,3 +42,11 @@ void cEnderDragon::GetDrops(cItems & a_Drops, cEntity * a_Killer) + +void cEnderDragon::SpawnOn(cClientHandle & a_Client) +{ + Super::SpawnOn(a_Client); + + // Red boss bar with no divisions that plays boss music and creates fog: + a_Client.SendBossBarAdd(GetUniqueID(), cCompositeChat("Ender Dragon"), GetHealth() / GetMaxHealth(), BossBarColor::Red, BossBarDivisionType::None, false, true, true); +} diff --git a/src/Mobs/EnderDragon.h b/src/Mobs/EnderDragon.h index 1856d165c..ffc39218c 100644 --- a/src/Mobs/EnderDragon.h +++ b/src/Mobs/EnderDragon.h @@ -18,9 +18,7 @@ public: CLASS_PROTODEF(cEnderDragon) + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + virtual void SpawnOn(cClientHandle & a_Client) override; } ; - - - - diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp index fc02b2971..bdbbfcadb 100644 --- a/src/Mobs/Wither.cpp +++ b/src/Mobs/Wither.cpp @@ -5,6 +5,8 @@ #include "../World.h" #include "../Entities/Player.h" +#include "../ClientHandle.h" +#include "../CompositeChat.h" @@ -48,40 +50,13 @@ bool cWither::DoTakeDamage(TakeDamageInfo & a_TDI) return false; } - return Super::DoTakeDamage(a_TDI); -} - - - - - -void cWither::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) -{ - Super::Tick(a_Dt, a_Chunk); - if (!IsTicking()) + if (!Super::DoTakeDamage(a_TDI)) { - // The base class tick destroyed us - return; + return false; } - if (m_WitherInvulnerableTicks > 0) - { - unsigned int NewTicks = m_WitherInvulnerableTicks - 1; - - if (NewTicks == 0) - { - m_World->DoExplosionAt(7.0, GetPosX(), GetPosY(), GetPosZ(), false, esWitherBirth, this); - } - - m_WitherInvulnerableTicks = NewTicks; - - if ((NewTicks % 10) == 0) - { - Heal(10); - } - } - - m_World->BroadcastEntityMetadata(*this); + m_World->BroadcastBossBarUpdateHealth(*this, GetUniqueID(), GetHealth() / GetMaxHealth()); + return true; } @@ -119,3 +94,44 @@ void cWither::KilledBy(TakeDamageInfo & a_TDI) + +void cWither::SpawnOn(cClientHandle & a_Client) +{ + Super::SpawnOn(a_Client); + + // Purple boss bar with no divisions that darkens the sky: + a_Client.SendBossBarAdd(GetUniqueID(), cCompositeChat("Wither"), GetHealth() / GetMaxHealth(), BossBarColor::Purple, BossBarDivisionType::None, true, false, false); +} + + + + + +void cWither::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +{ + Super::Tick(a_Dt, a_Chunk); + if (!IsTicking()) + { + // The base class tick destroyed us + return; + } + + if (m_WitherInvulnerableTicks > 0) + { + unsigned int NewTicks = m_WitherInvulnerableTicks - 1; + + if (NewTicks == 0) + { + m_World->DoExplosionAt(7.0, GetPosX(), GetPosY(), GetPosZ(), false, esWitherBirth, this); + } + + m_WitherInvulnerableTicks = NewTicks; + + if ((NewTicks % 10) == 0) + { + Heal(10); + } + } + + m_World->BroadcastEntityMetadata(*this); +} diff --git a/src/Mobs/Wither.h b/src/Mobs/Wither.h index 21e6aecf8..f6afb1e6d 100644 --- a/src/Mobs/Wither.h +++ b/src/Mobs/Wither.h @@ -26,12 +26,12 @@ public: bool IsArmored(void) const; // cEntity overrides - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; - virtual void KilledBy(TakeDamageInfo & a_TDI) override; - + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsUndead(void) override { return true; } + virtual void KilledBy(TakeDamageInfo & a_TDI) override; + virtual void SpawnOn(cClientHandle & a_Client) override; + virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; private: @@ -39,7 +39,3 @@ private: unsigned int m_WitherInvulnerableTicks; } ; - - - - diff --git a/src/Protocol/Packetizer.cpp b/src/Protocol/Packetizer.cpp index 9f0fd28b1..e71cba086 100644 --- a/src/Protocol/Packetizer.cpp +++ b/src/Protocol/Packetizer.cpp @@ -62,6 +62,7 @@ AString cPacketizer::PacketTypeToStr(cProtocol::ePacketType a_PacketType) case cProtocol::pktBlockBreakAnim: return "pktBlockBreakAnim"; case cProtocol::pktBlockChange: return "pktBlockChange"; case cProtocol::pktBlockChanges: return "pktBlockChanges"; + case cProtocol::pktBossBar: return "pktBossBar"; case cProtocol::pktCameraSetTo: return "pktCameraSetTo"; case cProtocol::pktChatRaw: return "pktChatRaw"; case cProtocol::pktCollectEntity: return "pktCollectEntity"; diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 7b5ad7a51..41c461e76 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -67,6 +67,7 @@ public: pktBlockBreakAnim, pktBlockChange, pktBlockChanges, + pktBossBar, pktCameraSetTo, pktChatRaw, pktCollectEntity, @@ -362,6 +363,12 @@ public: virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) = 0; virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0; + virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) = 0; + virtual void SendBossBarRemove (UInt32 a_UniqueID) = 0; + virtual void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled) = 0; + virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) = 0; + virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) = 0; + virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) = 0; virtual void SendCameraSetTo (const cEntity & a_Entity) = 0; virtual void SendChat (const AString & a_Message, eChatType a_Type) = 0; virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) = 0; diff --git a/src/Protocol/Protocol_1_10.h b/src/Protocol/Protocol_1_10.h index 3d78e7079..6c27b25b5 100644 --- a/src/Protocol/Protocol_1_10.h +++ b/src/Protocol/Protocol_1_10.h @@ -26,7 +26,7 @@ class cProtocol_1_10_0: public: - using Super::cProtocol_1_9_4; + using Super::Super; protected: diff --git a/src/Protocol/Protocol_1_11.h b/src/Protocol/Protocol_1_11.h index 4c0d8a22a..731426396 100644 --- a/src/Protocol/Protocol_1_11.h +++ b/src/Protocol/Protocol_1_11.h @@ -28,7 +28,7 @@ class cProtocol_1_11_0: public: - using Super::cProtocol_1_10_0; + using Super::Super; protected: @@ -62,7 +62,7 @@ class cProtocol_1_11_1: public: - using Super::cProtocol_1_11_0; + using Super::Super; protected: diff --git a/src/Protocol/Protocol_1_12.h b/src/Protocol/Protocol_1_12.h index 24e0eca60..7a92c156f 100644 --- a/src/Protocol/Protocol_1_12.h +++ b/src/Protocol/Protocol_1_12.h @@ -30,7 +30,7 @@ class cProtocol_1_12: public: - using Super::cProtocol_1_11_1; + using Super::Super; protected: @@ -56,7 +56,7 @@ class cProtocol_1_12_1: public: - using Super::cProtocol_1_12; + using Super::Super; protected: @@ -76,7 +76,7 @@ class cProtocol_1_12_2: public: - using Super::cProtocol_1_12_1; + using Super::Super; protected: diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp index afb0a9cc9..77cf86333 100644 --- a/src/Protocol/Protocol_1_13.cpp +++ b/src/Protocol/Protocol_1_13.cpp @@ -23,6 +23,7 @@ Implements the 1.13 protocol classes: #include "../Mobs/IncludeAllMonsters.h" +#include "../CompositeChat.h" #include "../ClientHandle.h" #include "../Root.h" #include "../Server.h" @@ -465,7 +466,6 @@ UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) case mtZombieVillager: return 89; default: return 0; } - UNREACHABLE("Unsupported mob type"); } @@ -1338,6 +1338,94 @@ void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_13_1: +void cProtocol_1_13_1::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(0); // Add + Pkt.WriteString(a_Title.CreateJsonString()); + Pkt.WriteBEFloat(a_FractionFilled); + Pkt.WriteVarInt32([a_Color] + { + switch (a_Color) + { + case BossBarColor::Pink: return 0U; + case BossBarColor::Blue: return 1U; + case BossBarColor::Red: return 2U; + case BossBarColor::Green: return 3U; + case BossBarColor::Yellow: return 4U; + case BossBarColor::Purple: return 5U; + case BossBarColor::White: return 6U; + } + }()); + Pkt.WriteVarInt32([a_DivisionType] + { + switch (a_DivisionType) + { + case BossBarDivisionType::None: return 0U; + case BossBarDivisionType::SixNotches: return 1U; + case BossBarDivisionType::TenNotches: return 2U; + case BossBarDivisionType::TwelveNotches: return 3U; + case BossBarDivisionType::TwentyNotches: return 4U; + } + }()); + { + UInt8 Flags = 0x00; + if (a_DarkenSky) + { + Flags |= 0x01; + } + if (a_PlayEndMusic) + { + Flags |= 0x02; + } + if (a_CreateFog) + { + Flags |= 0x04; // Only difference to 1.9 is fog now a separate flag + } + Pkt.WriteBEUInt8(Flags); + } +} + + + + + +void cProtocol_1_13_1::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(5); // Update Flags + { + UInt8 Flags = 0x00; + if (a_DarkenSky) + { + Flags |= 0x01; + } + if (a_PlayEndMusic) + { + Flags |= 0x02; + } + if (a_CreateFog) + { + Flags |= 0x04; // Only difference to 1.9 is fog now a separate flag + } + Pkt.WriteBEUInt8(Flags); + } +} + + + + + cProtocol::Version cProtocol_1_13_1::GetProtocolVersion() { return Version::v1_13_1; diff --git a/src/Protocol/Protocol_1_13.h b/src/Protocol/Protocol_1_13.h index 483ee88a0..d515306e3 100644 --- a/src/Protocol/Protocol_1_13.h +++ b/src/Protocol/Protocol_1_13.h @@ -32,7 +32,7 @@ class cProtocol_1_13: public: - using Super::cProtocol_1_12_2; + using Super::Super; protected: @@ -84,10 +84,13 @@ class cProtocol_1_13_1 : public: - using Super::cProtocol_1_13; + using Super::Super; protected: + virtual void SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual void SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual Version GetProtocolVersion() override; virtual std::pair GetItemFromProtocolID(UInt32 a_ProtocolID) override; virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) override; diff --git a/src/Protocol/Protocol_1_14.h b/src/Protocol/Protocol_1_14.h index e9bbca6eb..3f328bbac 100644 --- a/src/Protocol/Protocol_1_14.h +++ b/src/Protocol/Protocol_1_14.h @@ -26,7 +26,7 @@ class cProtocol_1_14: public: - using Super::cProtocol_1_13_2; + using Super::Super; protected: diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index 91c132c8b..e3bb7e5a3 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -280,6 +280,60 @@ void cProtocol_1_8_0::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlo +void cProtocol_1_8_0::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + // No such packet here +} + + + + + +void cProtocol_1_8_0::SendBossBarRemove(UInt32 a_UniqueID) +{ + // No such packet here +} + + + + + +void cProtocol_1_8_0::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + // No such packet here +} + + + + + +void cProtocol_1_8_0::SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) +{ + // No such packet here +} + + + + + +void cProtocol_1_8_0::SendBossBarUpdateStyle(UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) +{ + // No such packet here +} + + + + + +void cProtocol_1_8_0::SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat & a_Title) +{ + // No such packet here +} + + + + + void cProtocol_1_8_0::SendCameraSetTo(const cEntity & a_Entity) { cPacketizer Pkt(*this, pktCameraSetTo); @@ -356,9 +410,22 @@ void cProtocol_1_8_0::SendDestroyEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, pktDestroyEntity); - Pkt.WriteVarInt32(1); - Pkt.WriteVarInt32(a_Entity.GetUniqueID()); + { + cPacketizer Pkt(*this, pktDestroyEntity); + Pkt.WriteVarInt32(1); + Pkt.WriteVarInt32(a_Entity.GetUniqueID()); + } + + if (!a_Entity.IsMob()) + { + return; + } + + const auto & Mob = static_cast(a_Entity); + if ((Mob.GetMobType() == mtEnderDragon) || (Mob.GetMobType() == mtWither)) + { + SendBossBarRemove(Mob.GetUniqueID()); + } } @@ -1021,6 +1088,30 @@ void cProtocol_1_8_0::SendPlayerListRemovePlayer(const cPlayer & a_Player) +void cProtocol_1_8_0::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktPlayerList); + Pkt.WriteVarInt32(3); + Pkt.WriteVarInt32(1); + Pkt.WriteUUID(a_Player.GetUUID()); + + if (a_CustomName.empty()) + { + Pkt.WriteBool(false); + } + else + { + Pkt.WriteBool(true); + Pkt.WriteString(Printf("{\"text\":\"%s\"}", a_CustomName.c_str())); + } +} + + + + + void cProtocol_1_8_0::SendPlayerListUpdateGameMode(const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? @@ -1051,30 +1142,6 @@ void cProtocol_1_8_0::SendPlayerListUpdatePing(const cPlayer & a_Player) -void cProtocol_1_8_0::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) -{ - ASSERT(m_State == 3); // In game mode? - - cPacketizer Pkt(*this, pktPlayerList); - Pkt.WriteVarInt32(3); - Pkt.WriteVarInt32(1); - Pkt.WriteUUID(a_Player.GetUUID()); - - if (a_CustomName.empty()) - { - Pkt.WriteBool(false); - } - else - { - Pkt.WriteBool(true); - Pkt.WriteString(Printf("{\"text\":\"%s\"}", a_CustomName.c_str())); - } -} - - - - - void cProtocol_1_8_0::SendPlayerMaxSpeed(void) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index 4e4f2fa47..e2aadf147 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -45,6 +45,12 @@ public: virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; + virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual void SendBossBarRemove (UInt32 a_UniqueID) override; + virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled) override; + virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) override; + virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) override; virtual void SendCameraSetTo (const cEntity & a_Entity) override; virtual void SendChat (const AString & a_Message, eChatType a_Type) override; virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) override; @@ -85,9 +91,9 @@ public: virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override; virtual void SendPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) override; virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; - virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 5506aec1a..88f8933be 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -104,6 +104,172 @@ void cProtocol_1_9_0::SendAttachEntity(const cEntity & a_Entity, const cEntity & +void cProtocol_1_9_0::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(0); // Add + Pkt.WriteString(a_Title.CreateJsonString()); + Pkt.WriteBEFloat(a_FractionFilled); + Pkt.WriteVarInt32([a_Color] + { + switch (a_Color) + { + case BossBarColor::Pink: return 0U; + case BossBarColor::Blue: return 1U; + case BossBarColor::Red: return 2U; + case BossBarColor::Green: return 3U; + case BossBarColor::Yellow: return 4U; + case BossBarColor::Purple: return 5U; + case BossBarColor::White: return 6U; + } + }()); + Pkt.WriteVarInt32([a_DivisionType] + { + switch (a_DivisionType) + { + case BossBarDivisionType::None: return 0U; + case BossBarDivisionType::SixNotches: return 1U; + case BossBarDivisionType::TenNotches: return 2U; + case BossBarDivisionType::TwelveNotches: return 3U; + case BossBarDivisionType::TwentyNotches: return 4U; + } + }()); + { + UInt8 Flags = 0x00; + if (a_DarkenSky) + { + Flags |= 0x01; + } + if (a_PlayEndMusic || a_CreateFog) + { + Flags |= 0x02; + } + Pkt.WriteBEUInt8(Flags); + } +} + + + + + +void cProtocol_1_9_0::SendBossBarRemove(UInt32 a_UniqueID) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(1); // Remove +} + + + + + +void cProtocol_1_9_0::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(5); // Update Flags + { + UInt8 Flags = 0x00; + if (a_DarkenSky) + { + Flags |= 0x01; + } + if (a_PlayEndMusic || a_CreateFog) + { + Flags |= 0x02; + } + Pkt.WriteBEUInt8(Flags); + } +} + + + + + +void cProtocol_1_9_0::SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(2); // Update health + Pkt.WriteBEFloat(a_FractionFilled); +} + + + + + +void cProtocol_1_9_0::SendBossBarUpdateStyle(UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(4); // Update health + Pkt.WriteVarInt32([a_Color] + { + switch (a_Color) + { + case BossBarColor::Pink: return 0U; + case BossBarColor::Blue: return 1U; + case BossBarColor::Red: return 2U; + case BossBarColor::Green: return 3U; + case BossBarColor::Yellow: return 4U; + case BossBarColor::Purple: return 5U; + case BossBarColor::White: return 6U; + } + }()); + Pkt.WriteVarInt32([a_DivisionType] + { + switch (a_DivisionType) + { + case BossBarDivisionType::None: return 0U; + case BossBarDivisionType::SixNotches: return 1U; + case BossBarDivisionType::TenNotches: return 2U; + case BossBarDivisionType::TwelveNotches: return 3U; + case BossBarDivisionType::TwentyNotches: return 4U; + } + }()); +} + + + + + +void cProtocol_1_9_0::SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat & a_Title) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktBossBar); + // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. + Pkt.WriteBEUInt64(0); + Pkt.WriteBEUInt64(a_UniqueID); + Pkt.WriteVarInt32(3); // Update title + Pkt.WriteString(a_Title.CreateJsonString()); +} + + + + + void cProtocol_1_9_0::SendDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) { ASSERT(m_State == 3); // In game mode? @@ -488,6 +654,7 @@ UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet) case pktBlockBreakAnim: return 0x08; case pktBlockChange: return 0x0b; case pktBlockChanges: return 0x10; + case pktBossBar: return 0x0c; case pktCameraSetTo: return 0x36; case pktChatRaw: return 0x0f; case pktCollectEntity: return 0x49; diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h index 27b005bd4..cdaeaeed9 100644 --- a/src/Protocol/Protocol_1_9.h +++ b/src/Protocol/Protocol_1_9.h @@ -41,6 +41,12 @@ public: /** Sending stuff to clients (alphabetically sorted): */ virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; + virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual void SendBossBarRemove (UInt32 a_UniqueID) override; + virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled) override; + virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) override; + virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) override; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityMetadata (const cEntity & a_Entity) override; @@ -153,7 +159,7 @@ class cProtocol_1_9_1: public: - using Super::cProtocol_1_9_0; + using Super::Super; protected: @@ -175,7 +181,7 @@ class cProtocol_1_9_2: public: - using Super::cProtocol_1_9_1; + using Super::Super; protected: @@ -195,7 +201,7 @@ class cProtocol_1_9_4: public: - using Super::cProtocol_1_9_2; + using Super::Super; protected: diff --git a/src/World.h b/src/World.h index ec114cedc..e43f481a6 100644 --- a/src/World.h +++ b/src/World.h @@ -179,6 +179,7 @@ public: virtual void BroadcastBlockAction (Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) override; ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude + virtual void BroadcastBossBarUpdateHealth(const cEntity & a_Entity, UInt32 a_UniqueID, float a_FractionFilled) override; // tolua_begin virtual void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = nullptr, eMessageType a_ChatPrefix = mtCustom) override; @@ -209,9 +210,9 @@ public: virtual void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) override; // tolua_export virtual void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; - virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override;