From 925f960ea2aeeea8eaeae94a8ef6602690b215c2 Mon Sep 17 00:00:00 2001 From: dImrich Date: Thu, 4 Feb 2021 00:33:17 +0100 Subject: [PATCH] Adds playerlist header and footer broadcasting (1.8-1.13) --- Server/Plugins/APIDump/APIDesc.lua | 30 +++++ Server/Plugins/APIDump/Classes/World.lua | 15 +++ src/Blocks/BroadcastInterface.h | 1 + src/Broadcaster.cpp | 13 ++ src/ClientHandle.cpp | 9 ++ src/ClientHandle.h | 1 + src/Protocol/Packetizer.cpp | 151 ++++++++++----------- src/Protocol/Protocol.h | 2 + src/Protocol/Protocol_1_12.cpp | 61 ++++----- src/Protocol/Protocol_1_13.cpp | 107 +++++++-------- src/Protocol/Protocol_1_8.cpp | 160 ++++++++++++----------- src/Protocol/Protocol_1_8.h | 1 + src/Protocol/Protocol_1_9.cpp | 160 ++++++++++++----------- src/Root.cpp | 12 ++ src/Root.h | 3 + src/World.h | 1 + 16 files changed, 417 insertions(+), 310 deletions(-) diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index 88e999bd3..430e43df6 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -1584,6 +1584,21 @@ end }, Notes = "Sends the specified animation of the specified entity to the client. The AnimationNumber is protocol-specific.", }, + SendPlayerListHeaderFooter = + { + Params = + { + { + Type = "cCompositeChat", + Name = "Header", + }, + { + Type = "cCompositeChat", + Name = "Footer", + }, + }, + Desc = "Sends the header and footer of the player list to the client.", + }, SendHideTitle = { Notes = "Hides the title. This makes the title and subtitle disappear, but if you call SendTitleTimes() the same title and subtitle will appear again." @@ -11388,6 +11403,21 @@ a_Player:OpenWindow(Window); }, Notes = "Broadcasts the specified message to all players, with its message type set to mtWarning. Use for concerning events, such as plugin reload etc.", }, + BroadcastPlayerListsHeaderFooter = + { + Params = + { + { + Type = "cCompositeChat", + Name = "Header", + }, + { + Type = "cCompositeChat", + Name = "Footer", + }, + }, + Desc = "Broadcasts the header and footer of the player list to all players.", + }, DoWithPlayerByUUID = { Params = diff --git a/Server/Plugins/APIDump/Classes/World.lua b/Server/Plugins/APIDump/Classes/World.lua index a1f2bc979..8792e7651 100644 --- a/Server/Plugins/APIDump/Classes/World.lua +++ b/Server/Plugins/APIDump/Classes/World.lua @@ -327,6 +327,21 @@ return }, Notes = "Spawns the specified particles to all players in the world exept the optional ExeptClient. A list of available particles by thinkofdeath can be found {{https://gist.github.com/thinkofdeath/5110835|Here}}", }, + BroadcastPlayerListHeaderFooter = + { + Params = + { + { + Type = "cCompositeChat", + Name = "Header", + }, + { + Type = "cCompositeChat", + Name = "Footer", + }, + }, + Desc = "Broadcasts the header and footer of the player list to all players in the world.", + }, BroadcastSoundEffect = { Params = diff --git a/src/Blocks/BroadcastInterface.h b/src/Blocks/BroadcastInterface.h index ee903f461..93dbe4961 100644 --- a/src/Blocks/BroadcastInterface.h +++ b/src/Blocks/BroadcastInterface.h @@ -48,6 +48,7 @@ public: virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data, const cClientHandle * a_Exclude = nullptr) = 0; 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 BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; diff --git a/src/Broadcaster.cpp b/src/Broadcaster.cpp index e7a29cb5d..98759a58b 100644 --- a/src/Broadcaster.cpp +++ b/src/Broadcaster.cpp @@ -418,6 +418,19 @@ void cWorld::BroadcastPlayerListAddPlayer(const cPlayer & a_Player, const cClien +void cWorld::BroadcastPlayerListHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) +{ + ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendPlayerListHeaderFooter(a_Header, a_Footer); + } + ); +} + + + + + void cWorld::BroadcastPlayerListRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 9d236e4d5..3c003e132 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2625,6 +2625,15 @@ void cClientHandle::SendPlayerListAddPlayer(const cPlayer & a_Player) +void cClientHandle::SendPlayerListHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) +{ + m_Protocol->SendPlayerListHeaderFooter(a_Header, a_Footer); +} + + + + + void cClientHandle::SendPlayerListRemovePlayer(const cPlayer & a_Player) { m_Protocol->SendPlayerListRemovePlayer(a_Player); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 2662f20d6..f3e0e7f25 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -183,6 +183,7 @@ public: // tolua_export void SendParticleEffect (const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data); void SendPlayerAbilities (void); void SendPlayerListAddPlayer (const cPlayer & a_Player); + void SendPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer); // tolua_export void SendPlayerListRemovePlayer (const cPlayer & a_Player); void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName); void SendPlayerListUpdateGameMode (const cPlayer & a_Player); diff --git a/src/Protocol/Packetizer.cpp b/src/Protocol/Packetizer.cpp index 12bfcc0dd..9f0fd28b1 100644 --- a/src/Protocol/Packetizer.cpp +++ b/src/Protocol/Packetizer.cpp @@ -57,81 +57,82 @@ AString cPacketizer::PacketTypeToStr(cProtocol::ePacketType a_PacketType) { switch (a_PacketType) { - case cProtocol::pktAttachEntity: return "pktAttachEntity"; - case cProtocol::pktBlockAction: return "pktBlockAction"; - case cProtocol::pktBlockBreakAnim: return "pktBlockBreakAnim"; - case cProtocol::pktBlockChange: return "pktBlockChange"; - case cProtocol::pktBlockChanges: return "pktBlockChanges"; - case cProtocol::pktCameraSetTo: return "pktCameraSetTo"; - case cProtocol::pktChatRaw: return "pktChatRaw"; - case cProtocol::pktCollectEntity: return "pktCollectEntity"; - case cProtocol::pktDestroyEntity: return "pktDestroyEntity"; - case cProtocol::pktDifficulty: return "pktDifficulty"; - case cProtocol::pktDisconnectDuringLogin: return "pktDisconnectDuringLogin"; - case cProtocol::pktDisconnectDuringGame: return "pktDisconnectDuringGame"; - case cProtocol::pktDisplayObjective: return "pktDisplayObjective"; - case cProtocol::pktEditSign: return "pktEditSign"; - case cProtocol::pktEncryptionRequest: return "pktEncryptionRequest"; - case cProtocol::pktEntityAnimation: return "pktEntityAnimation"; - case cProtocol::pktEntityEffect: return "pktEntityEffect"; - case cProtocol::pktEntityEquipment: return "pktEntityEquipment"; - case cProtocol::pktEntityHeadLook: return "pktEntityHeadLook"; - case cProtocol::pktEntityLook: return "pktEntityLook"; - case cProtocol::pktEntityMeta: return "pktEntityMeta"; - case cProtocol::pktEntityProperties: return "pktEntityProperties"; - case cProtocol::pktEntityRelMove: return "pktEntityRelMove"; - case cProtocol::pktEntityRelMoveLook: return "pktEntityRelMoveLook"; - case cProtocol::pktEntityStatus: return "pktEntityStatus"; - case cProtocol::pktEntityVelocity: return "pktEntityVelocity"; - case cProtocol::pktExperience: return "pktExperience"; - case cProtocol::pktExplosion: return "pktExplosion"; - case cProtocol::pktGameMode: return "pktGameMode"; - case cProtocol::pktHeldItemChange: return "pktHeldItemChange"; - case cProtocol::pktInventorySlot: return "pktInventorySlot"; - case cProtocol::pktJoinGame: return "pktJoinGame"; - case cProtocol::pktKeepAlive: return "pktKeepAlive"; - case cProtocol::pktLeashEntity: return "pktLeashEntity"; - case cProtocol::pktLoginSuccess: return "pktLoginSuccess"; - case cProtocol::pktMapData: return "pktMapData"; - case cProtocol::pktParticleEffect: return "pktParticleEffect"; - case cProtocol::pktPingResponse: return "pktPingResponse"; - case cProtocol::pktPlayerAbilities: return "pktPlayerAbilities"; - case cProtocol::pktPlayerList: return "pktPlayerList"; - case cProtocol::pktPlayerMaxSpeed: return "pktPlayerMaxSpeed"; - case cProtocol::pktPlayerMoveLook: return "pktPlayerMoveLook"; - case cProtocol::pktPluginMessage: return "pktPluginMessage"; - case cProtocol::pktRemoveEntityEffect: return "pktRemoveEntityEffect"; - case cProtocol::pktResourcePack: return "pktResourcePack"; - case cProtocol::pktRespawn: return "pktRespawn"; - case cProtocol::pktScoreboardObjective: return "pktScoreboardObjective"; - case cProtocol::pktSpawnObject: return "pktSpawnObject"; - case cProtocol::pktSoundEffect: return "pktSoundEffect"; - case cProtocol::pktSoundParticleEffect: return "pktSoundParticleEffect"; - case cProtocol::pktSpawnExperienceOrb: return "pktSpawnExperienceOrb"; - case cProtocol::pktSpawnGlobalEntity: return "pktSpawnGlobalEntity"; - case cProtocol::pktSpawnMob: return "pktSpawnMob"; - case cProtocol::pktSpawnOtherPlayer: return "pktSpawnOtherPlayer"; - case cProtocol::pktSpawnPainting: return "pktSpawnPainting"; - case cProtocol::pktSpawnPosition: return "pktSpawnPosition"; - case cProtocol::pktStartCompression: return "pktStartCompression"; - case cProtocol::pktStatistics: return "pktStatistics"; - case cProtocol::pktStatusResponse: return "pktStatusResponse"; - case cProtocol::pktTabCompletionResults: return "pktTabCompletionResults"; - case cProtocol::pktTeleportEntity: return "pktTeleportEntity"; - case cProtocol::pktTimeUpdate: return "pktTimeUpdate"; - case cProtocol::pktTitle: return "pktTitle"; - case cProtocol::pktUnloadChunk: return "pktUnloadChunk"; - case cProtocol::pktUnlockRecipe: return "pktUnlockRecipe"; - case cProtocol::pktUpdateBlockEntity: return "pktUpdateBlockEntity"; - case cProtocol::pktUpdateHealth: return "pktUpdateHealth"; - case cProtocol::pktUpdateScore: return "pktUpdateScore"; - case cProtocol::pktUpdateSign: return "pktUpdateSign"; - case cProtocol::pktUseBed: return "pktUseBed"; - case cProtocol::pktWeather: return "pktWeather"; - case cProtocol::pktWindowItems: return "pktWindowItems"; - case cProtocol::pktWindowClose: return "pktWindowClose"; - case cProtocol::pktWindowOpen: return "pktWindowOpen"; - case cProtocol::pktWindowProperty: return "pktWindowProperty"; + case cProtocol::pktAttachEntity: return "pktAttachEntity"; + case cProtocol::pktBlockAction: return "pktBlockAction"; + case cProtocol::pktBlockBreakAnim: return "pktBlockBreakAnim"; + case cProtocol::pktBlockChange: return "pktBlockChange"; + case cProtocol::pktBlockChanges: return "pktBlockChanges"; + case cProtocol::pktCameraSetTo: return "pktCameraSetTo"; + case cProtocol::pktChatRaw: return "pktChatRaw"; + case cProtocol::pktCollectEntity: return "pktCollectEntity"; + case cProtocol::pktDestroyEntity: return "pktDestroyEntity"; + case cProtocol::pktDifficulty: return "pktDifficulty"; + case cProtocol::pktDisconnectDuringLogin: return "pktDisconnectDuringLogin"; + case cProtocol::pktDisconnectDuringGame: return "pktDisconnectDuringGame"; + case cProtocol::pktDisplayObjective: return "pktDisplayObjective"; + case cProtocol::pktEditSign: return "pktEditSign"; + case cProtocol::pktEncryptionRequest: return "pktEncryptionRequest"; + case cProtocol::pktEntityAnimation: return "pktEntityAnimation"; + case cProtocol::pktEntityEffect: return "pktEntityEffect"; + case cProtocol::pktEntityEquipment: return "pktEntityEquipment"; + case cProtocol::pktEntityHeadLook: return "pktEntityHeadLook"; + case cProtocol::pktEntityLook: return "pktEntityLook"; + case cProtocol::pktEntityMeta: return "pktEntityMeta"; + case cProtocol::pktEntityProperties: return "pktEntityProperties"; + case cProtocol::pktEntityRelMove: return "pktEntityRelMove"; + case cProtocol::pktEntityRelMoveLook: return "pktEntityRelMoveLook"; + case cProtocol::pktEntityStatus: return "pktEntityStatus"; + case cProtocol::pktEntityVelocity: return "pktEntityVelocity"; + case cProtocol::pktExperience: return "pktExperience"; + case cProtocol::pktExplosion: return "pktExplosion"; + case cProtocol::pktGameMode: return "pktGameMode"; + case cProtocol::pktHeldItemChange: return "pktHeldItemChange"; + case cProtocol::pktInventorySlot: return "pktInventorySlot"; + case cProtocol::pktJoinGame: return "pktJoinGame"; + case cProtocol::pktKeepAlive: return "pktKeepAlive"; + case cProtocol::pktLeashEntity: return "pktLeashEntity"; + case cProtocol::pktLoginSuccess: return "pktLoginSuccess"; + case cProtocol::pktMapData: return "pktMapData"; + case cProtocol::pktParticleEffect: return "pktParticleEffect"; + case cProtocol::pktPingResponse: return "pktPingResponse"; + case cProtocol::pktPlayerAbilities: return "pktPlayerAbilities"; + case cProtocol::pktPlayerList: return "pktPlayerList"; + case cProtocol::pktPlayerListHeaderFooter: return "pktPlayerListHeaderFooter"; + case cProtocol::pktPlayerMaxSpeed: return "pktPlayerMaxSpeed"; + case cProtocol::pktPlayerMoveLook: return "pktPlayerMoveLook"; + case cProtocol::pktPluginMessage: return "pktPluginMessage"; + case cProtocol::pktRemoveEntityEffect: return "pktRemoveEntityEffect"; + case cProtocol::pktResourcePack: return "pktResourcePack"; + case cProtocol::pktRespawn: return "pktRespawn"; + case cProtocol::pktScoreboardObjective: return "pktScoreboardObjective"; + case cProtocol::pktSpawnObject: return "pktSpawnObject"; + case cProtocol::pktSoundEffect: return "pktSoundEffect"; + case cProtocol::pktSoundParticleEffect: return "pktSoundParticleEffect"; + case cProtocol::pktSpawnExperienceOrb: return "pktSpawnExperienceOrb"; + case cProtocol::pktSpawnGlobalEntity: return "pktSpawnGlobalEntity"; + case cProtocol::pktSpawnMob: return "pktSpawnMob"; + case cProtocol::pktSpawnOtherPlayer: return "pktSpawnOtherPlayer"; + case cProtocol::pktSpawnPainting: return "pktSpawnPainting"; + case cProtocol::pktSpawnPosition: return "pktSpawnPosition"; + case cProtocol::pktStartCompression: return "pktStartCompression"; + case cProtocol::pktStatistics: return "pktStatistics"; + case cProtocol::pktStatusResponse: return "pktStatusResponse"; + case cProtocol::pktTabCompletionResults: return "pktTabCompletionResults"; + case cProtocol::pktTeleportEntity: return "pktTeleportEntity"; + case cProtocol::pktTimeUpdate: return "pktTimeUpdate"; + case cProtocol::pktTitle: return "pktTitle"; + case cProtocol::pktUnloadChunk: return "pktUnloadChunk"; + case cProtocol::pktUnlockRecipe: return "pktUnlockRecipe"; + case cProtocol::pktUpdateBlockEntity: return "pktUpdateBlockEntity"; + case cProtocol::pktUpdateHealth: return "pktUpdateHealth"; + case cProtocol::pktUpdateScore: return "pktUpdateScore"; + case cProtocol::pktUpdateSign: return "pktUpdateSign"; + case cProtocol::pktUseBed: return "pktUseBed"; + case cProtocol::pktWeather: return "pktWeather"; + case cProtocol::pktWindowItems: return "pktWindowItems"; + case cProtocol::pktWindowClose: return "pktWindowClose"; + case cProtocol::pktWindowOpen: return "pktWindowOpen"; + case cProtocol::pktWindowProperty: return "pktWindowProperty"; } return Printf("Unknown packet type: 0x%02x", a_PacketType); } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 341e0b0f4..7b5ad7a51 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -102,6 +102,7 @@ public: pktPingResponse, pktPlayerAbilities, pktPlayerList, + pktPlayerListHeaderFooter, pktPlayerMaxSpeed, pktPlayerMoveLook, pktPluginMessage, @@ -397,6 +398,7 @@ public: virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) = 0; virtual void SendParticleEffect (const AString & a_SoundName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) = 0; virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) = 0; + virtual void SendPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) = 0; virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) = 0; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) = 0; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) = 0; diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp index 30a975d18..e4ce9a942 100644 --- a/src/Protocol/Protocol_1_12.cpp +++ b/src/Protocol/Protocol_1_12.cpp @@ -1167,36 +1167,37 @@ UInt32 cProtocol_1_12_1::GetPacketID(ePacketType a_Packet) { switch (a_Packet) { - case pktAttachEntity: return 0x43; - case pktCameraSetTo: return 0x39; - case pktCollectEntity: return 0x4b; - case pktDestroyEntity: return 0x32; - case pktDisplayObjective: return 0x3b; - case pktEntityEffect: return 0x4f; - case pktEntityEquipment: return 0x3f; - case pktEntityHeadLook: return 0x36; - case pktEntityMeta: return 0x3c; - case pktEntityProperties: return 0x4e; - case pktEntityVelocity: return 0x3e; - case pktExperience: return 0x40; - case pktHeldItemChange: return 0x3a; - case pktLeashEntity: return 0x3d; - case pktPlayerList: return 0x2e; - case pktPlayerAbilities: return 0x2c; - case pktPlayerMaxSpeed: return 0x4e; - case pktPlayerMoveLook: return 0x2f; - case pktRemoveEntityEffect: return 0x33; - case pktResourcePack: return 0x34; - case pktRespawn: return 0x35; - case pktScoreboardObjective: return 0x42; - case pktSpawnPosition: return 0x46; - case pktUnlockRecipe: return 0x31; - case pktUpdateHealth: return 0x41; - case pktUpdateScore: return 0x45; - case pktUseBed: return 0x30; - case pktTeleportEntity: return 0x4c; - case pktTimeUpdate: return 0x47; - case pktTitle: return 0x48; + case pktAttachEntity: return 0x43; + case pktCameraSetTo: return 0x39; + case pktCollectEntity: return 0x4b; + case pktDestroyEntity: return 0x32; + case pktDisplayObjective: return 0x3b; + case pktEntityEffect: return 0x4f; + case pktEntityEquipment: return 0x3f; + case pktEntityHeadLook: return 0x36; + case pktEntityMeta: return 0x3c; + case pktEntityProperties: return 0x4e; + case pktEntityVelocity: return 0x3e; + case pktExperience: return 0x40; + case pktHeldItemChange: return 0x3a; + case pktLeashEntity: return 0x3d; + case pktPlayerList: return 0x2e; + case pktPlayerListHeaderFooter: return 0x4a; + case pktPlayerAbilities: return 0x2c; + case pktPlayerMaxSpeed: return 0x4e; + case pktPlayerMoveLook: return 0x2f; + case pktRemoveEntityEffect: return 0x33; + case pktResourcePack: return 0x34; + case pktRespawn: return 0x35; + case pktScoreboardObjective: return 0x42; + case pktSpawnPosition: return 0x46; + case pktUnlockRecipe: return 0x31; + case pktUpdateHealth: return 0x41; + case pktUpdateScore: return 0x45; + case pktUseBed: return 0x30; + case pktTeleportEntity: return 0x4c; + case pktTimeUpdate: return 0x47; + case pktTitle: return 0x48; default: return Super::GetPacketID(a_Packet); } diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp index 4da065af7..dbfd51d59 100644 --- a/src/Protocol/Protocol_1_13.cpp +++ b/src/Protocol/Protocol_1_13.cpp @@ -337,59 +337,60 @@ UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) { switch (a_PacketType) { - case pktAttachEntity: return 0x46; - case pktBlockChanges: return 0x0f; - case pktCameraSetTo: return 0x3c; - case pktChatRaw: return 0x0e; - case pktCollectEntity: return 0x4f; - case pktDestroyEntity: return 0x35; - case pktDisconnectDuringGame: return 0x1b; - case pktEditSign: return 0x2c; - case pktEntityEffect: return 0x53; - case pktEntityEquipment: return 0x42; - case pktEntityHeadLook: return 0x39; - case pktEntityLook: return 0x2a; - case pktEntityMeta: return 0x3f; - case pktEntityProperties: return 0x52; - case pktEntityRelMove: return 0x28; - case pktEntityRelMoveLook: return 0x29; - case pktEntityStatus: return 0x1c; - case pktEntityVelocity: return 0x41; - case pktExperience: return 0x43; - case pktExplosion: return 0x1e; - case pktGameMode: return 0x20; - case pktHeldItemChange: return 0x3d; - case pktInventorySlot: return 0x17; - case pktJoinGame: return 0x25; - case pktKeepAlive: return 0x21; - case pktLeashEntity: return 0x40; - case pktMapData: return 0x26; - case pktParticleEffect: return 0x24; - case pktPlayerAbilities: return 0x2e; - case pktPlayerList: return 0x30; - case pktPlayerMaxSpeed: return 0x52; - case pktPlayerMoveLook: return 0x32; - case pktPluginMessage: return 0x19; - case pktRemoveEntityEffect: return 0x36; - case pktRespawn: return 0x38; - case pktScoreboardObjective: return 0x45; - case pktSoundEffect: return 0x1a; - case pktSoundParticleEffect: return 0x23; - case pktSpawnPosition: return 0x49; - case pktTabCompletionResults: return 0x10; - case pktTeleportEntity: return 0x50; - case pktTimeUpdate: return 0x4a; - case pktTitle: return 0x4b; - case pktUnloadChunk: return 0x1f; - case pktUnlockRecipe: return 0x32; - case pktUpdateHealth: return 0x44; - case pktUpdateScore: return 0x48; - case pktUpdateSign: return GetPacketID(pktUpdateBlockEntity); - case pktUseBed: return 0x33; - case pktWindowClose: return 0x13; - case pktWindowItems: return 0x15; - case pktWindowOpen: return 0x14; - case pktWindowProperty: return 0x16; + case pktAttachEntity: return 0x46; + case pktBlockChanges: return 0x0f; + case pktCameraSetTo: return 0x3c; + case pktChatRaw: return 0x0e; + case pktCollectEntity: return 0x4f; + case pktDestroyEntity: return 0x35; + case pktDisconnectDuringGame: return 0x1b; + case pktEditSign: return 0x2c; + case pktEntityEffect: return 0x53; + case pktEntityEquipment: return 0x42; + case pktEntityHeadLook: return 0x39; + case pktEntityLook: return 0x2a; + case pktEntityMeta: return 0x3f; + case pktEntityProperties: return 0x52; + case pktEntityRelMove: return 0x28; + case pktEntityRelMoveLook: return 0x29; + case pktEntityStatus: return 0x1c; + case pktEntityVelocity: return 0x41; + case pktExperience: return 0x43; + case pktExplosion: return 0x1e; + case pktGameMode: return 0x20; + case pktHeldItemChange: return 0x3d; + case pktInventorySlot: return 0x17; + case pktJoinGame: return 0x25; + case pktKeepAlive: return 0x21; + case pktLeashEntity: return 0x40; + case pktMapData: return 0x26; + case pktParticleEffect: return 0x24; + case pktPlayerAbilities: return 0x2e; + case pktPlayerList: return 0x30; + case pktPlayerListHeaderFooter: return 0x4E; + case pktPlayerMaxSpeed: return 0x52; + case pktPlayerMoveLook: return 0x32; + case pktPluginMessage: return 0x19; + case pktRemoveEntityEffect: return 0x36; + case pktRespawn: return 0x38; + case pktScoreboardObjective: return 0x45; + case pktSoundEffect: return 0x1a; + case pktSoundParticleEffect: return 0x23; + case pktSpawnPosition: return 0x49; + case pktTabCompletionResults: return 0x10; + case pktTeleportEntity: return 0x50; + case pktTimeUpdate: return 0x4a; + case pktTitle: return 0x4b; + case pktUnloadChunk: return 0x1f; + case pktUnlockRecipe: return 0x32; + case pktUpdateHealth: return 0x44; + case pktUpdateScore: return 0x48; + case pktUpdateSign: return GetPacketID(pktUpdateBlockEntity); + case pktUseBed: return 0x33; + case pktWindowClose: return 0x13; + case pktWindowItems: return 0x15; + case pktWindowOpen: return 0x14; + case pktWindowProperty: return 0x16; default: return Super::GetPacketID(a_PacketType); } } diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index cafcfb0ff..003fc75e2 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -994,6 +994,19 @@ void cProtocol_1_8_0::SendPlayerListAddPlayer(const cPlayer & a_Player) +void cProtocol_1_8_0::SendPlayerListHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, pktPlayerListHeaderFooter); + Pkt.WriteString(a_Header.CreateJsonString(false)); + Pkt.WriteString(a_Footer.CreateJsonString(false)); +} + + + + + void cProtocol_1_8_0::SendPlayerListRemovePlayer(const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? @@ -2043,79 +2056,80 @@ UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType) { switch (a_PacketType) { - case pktAttachEntity: return 0x1b; - case pktBlockAction: return 0x24; - case pktBlockBreakAnim: return 0x25; - case pktBlockChange: return 0x23; - case pktBlockChanges: return 0x22; - case pktCameraSetTo: return 0x43; - case pktChatRaw: return 0x02; - case pktCollectEntity: return 0x0d; - case pktDestroyEntity: return 0x13; - case pktDifficulty: return 0x41; - case pktDisconnectDuringGame: return 0x40; - case pktDisconnectDuringLogin: return 0x00; - case pktDisplayObjective: return 0x3d; - case pktEditSign: return 0x36; - case pktEncryptionRequest: return 0x01; - case pktEntityAnimation: return 0x0b; - case pktEntityEffect: return 0x1d; - case pktEntityEquipment: return 0x04; - case pktEntityHeadLook: return 0x19; - case pktEntityLook: return 0x16; - case pktEntityMeta: return 0x1c; - case pktEntityProperties: return 0x20; - case pktEntityRelMove: return 0x15; - case pktEntityRelMoveLook: return 0x17; - case pktEntityStatus: return 0x1a; - case pktEntityVelocity: return 0x12; - case pktExperience: return 0x1f; - case pktExplosion: return 0x27; - case pktGameMode: return 0x2b; - case pktHeldItemChange: return 0x09; - case pktInventorySlot: return 0x2f; - case pktJoinGame: return 0x01; - case pktKeepAlive: return 0x00; - case pktLeashEntity: return 0x1b; - case pktLoginSuccess: return 0x02; - case pktMapData: return 0x34; - case pktParticleEffect: return 0x2a; - case pktPingResponse: return 0x01; - case pktPlayerAbilities: return 0x39; - case pktPlayerList: return 0x38; - case pktPlayerMoveLook: return 0x08; - case pktPluginMessage: return 0x3f; - case pktRemoveEntityEffect: return 0x1e; - case pktResourcePack: return 0x48; - case pktRespawn: return 0x07; - case pktScoreboardObjective: return 0x3b; - case pktSoundEffect: return 0x29; - case pktSoundParticleEffect: return 0x28; - case pktSpawnExperienceOrb: return 0x11; - case pktSpawnGlobalEntity: return 0x2c; - case pktSpawnMob: return 0x0f; - case pktSpawnObject: return 0x0e; - case pktSpawnOtherPlayer: return 0x0c; - case pktSpawnPainting: return 0x10; - case pktSpawnPosition: return 0x05; - case pktStartCompression: return 0x03; - case pktStatistics: return 0x37; - case pktStatusResponse: return 0x00; - case pktTabCompletionResults: return 0x3a; - case pktTeleportEntity: return 0x18; - case pktTimeUpdate: return 0x03; - case pktTitle: return 0x45; - case pktUnloadChunk: return 0x21; - case pktUpdateBlockEntity: return 0x35; - case pktUpdateHealth: return 0x06; - case pktUpdateScore: return 0x3c; - case pktUpdateSign: return 0x33; - case pktUseBed: return 0x0a; - case pktWeather: return 0x2b; - case pktWindowClose: return 0x2e; - case pktWindowItems: return 0x30; - case pktWindowOpen: return 0x2d; - case pktWindowProperty: return 0x31; + case pktAttachEntity: return 0x1b; + case pktBlockAction: return 0x24; + case pktBlockBreakAnim: return 0x25; + case pktBlockChange: return 0x23; + case pktBlockChanges: return 0x22; + case pktCameraSetTo: return 0x43; + case pktChatRaw: return 0x02; + case pktCollectEntity: return 0x0d; + case pktDestroyEntity: return 0x13; + case pktDifficulty: return 0x41; + case pktDisconnectDuringGame: return 0x40; + case pktDisconnectDuringLogin: return 0x00; + case pktDisplayObjective: return 0x3d; + case pktEditSign: return 0x36; + case pktEncryptionRequest: return 0x01; + case pktEntityAnimation: return 0x0b; + case pktEntityEffect: return 0x1d; + case pktEntityEquipment: return 0x04; + case pktEntityHeadLook: return 0x19; + case pktEntityLook: return 0x16; + case pktEntityMeta: return 0x1c; + case pktEntityProperties: return 0x20; + case pktEntityRelMove: return 0x15; + case pktEntityRelMoveLook: return 0x17; + case pktEntityStatus: return 0x1a; + case pktEntityVelocity: return 0x12; + case pktExperience: return 0x1f; + case pktExplosion: return 0x27; + case pktGameMode: return 0x2b; + case pktHeldItemChange: return 0x09; + case pktInventorySlot: return 0x2f; + case pktJoinGame: return 0x01; + case pktKeepAlive: return 0x00; + case pktLeashEntity: return 0x1b; + case pktLoginSuccess: return 0x02; + case pktMapData: return 0x34; + case pktParticleEffect: return 0x2a; + case pktPingResponse: return 0x01; + case pktPlayerAbilities: return 0x39; + case pktPlayerList: return 0x38; + case pktPlayerListHeaderFooter: return 0x47; + case pktPlayerMoveLook: return 0x08; + case pktPluginMessage: return 0x3f; + case pktRemoveEntityEffect: return 0x1e; + case pktResourcePack: return 0x48; + case pktRespawn: return 0x07; + case pktScoreboardObjective: return 0x3b; + case pktSoundEffect: return 0x29; + case pktSoundParticleEffect: return 0x28; + case pktSpawnExperienceOrb: return 0x11; + case pktSpawnGlobalEntity: return 0x2c; + case pktSpawnMob: return 0x0f; + case pktSpawnObject: return 0x0e; + case pktSpawnOtherPlayer: return 0x0c; + case pktSpawnPainting: return 0x10; + case pktSpawnPosition: return 0x05; + case pktStartCompression: return 0x03; + case pktStatistics: return 0x37; + case pktStatusResponse: return 0x00; + case pktTabCompletionResults: return 0x3a; + case pktTeleportEntity: return 0x18; + case pktTimeUpdate: return 0x03; + case pktTitle: return 0x45; + case pktUnloadChunk: return 0x21; + case pktUpdateBlockEntity: return 0x35; + case pktUpdateHealth: return 0x06; + case pktUpdateScore: return 0x3c; + case pktUpdateSign: return 0x33; + case pktUseBed: return 0x0a; + case pktWeather: return 0x2b; + case pktWindowClose: return 0x2e; + case pktWindowItems: return 0x30; + case pktWindowOpen: return 0x2d; + case pktWindowProperty: return 0x31; default: { LOG("Unhandled outgoing packet type: %s (0x%02x)", cPacketizer::PacketTypeToStr(a_PacketType), a_PacketType); diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index f5800cb21..4e4f2fa47 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -83,6 +83,7 @@ public: virtual void 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) override; virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) override; 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 SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 67e920925..e2396ce0e 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -483,80 +483,81 @@ UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet) { switch (a_Packet) { - case pktAttachEntity: return 0x40; - case pktBlockAction: return 0x0a; - case pktBlockBreakAnim: return 0x08; - case pktBlockChange: return 0x0b; - case pktBlockChanges: return 0x10; - case pktCameraSetTo: return 0x36; - case pktChatRaw: return 0x0f; - case pktCollectEntity: return 0x49; - case pktDestroyEntity: return 0x30; - case pktDifficulty: return 0x0d; - case pktDisconnectDuringGame: return 0x1a; - case pktDisconnectDuringLogin: return 0x0; - case pktDisplayObjective: return 0x38; - case pktEditSign: return 0x2a; - case pktEncryptionRequest: return 0x01; - case pktEntityAnimation: return 0x06; - case pktEntityEffect: return 0x4c; - case pktEntityEquipment: return 0x3c; - case pktEntityHeadLook: return 0x34; - case pktEntityLook: return 0x27; - case pktEntityMeta: return 0x39; - case pktEntityProperties: return 0x4b; - case pktEntityRelMove: return 0x25; - case pktEntityRelMoveLook: return 0x26; - case pktEntityStatus: return 0x1b; - case pktEntityVelocity: return 0x3b; - case pktExperience: return 0x3d; - case pktExplosion: return 0x1c; - case pktGameMode: return 0x1e; - case pktHeldItemChange: return 0x37; - case pktInventorySlot: return 0x16; - case pktJoinGame: return 0x23; - case pktKeepAlive: return 0x1f; - case pktLeashEntity: return 0x3a; - case pktLoginSuccess: return 0x02; - case pktMapData: return 0x24; - case pktParticleEffect: return 0x22; - case pktPingResponse: return 0x01; - case pktPlayerAbilities: return 0x2b; - case pktPlayerList: return 0x2d; - case pktPlayerMaxSpeed: return 0x4b; - case pktPlayerMoveLook: return 0x2e; - case pktPluginMessage: return 0x18; - case pktRemoveEntityEffect: return 0x31; - case pktResourcePack: return 0x32; - case pktRespawn: return 0x33; - case pktScoreboardObjective: return 0x3f; - case pktSpawnExperienceOrb: return 0x01; - case pktSpawnGlobalEntity: return 0x02; - case pktSpawnObject: return 0x00; - case pktSpawnOtherPlayer: return 0x05; - case pktSpawnPainting: return 0x04; - case pktSpawnPosition: return 0x43; - case pktSoundEffect: return 0x19; - case pktSoundParticleEffect: return 0x21; - case pktSpawnMob: return 0x03; - case pktStartCompression: return 0x03; - case pktStatistics: return 0x07; - case pktStatusResponse: return 0x00; - case pktTabCompletionResults: return 0x0e; - case pktTeleportEntity: return 0x4a; - case pktTimeUpdate: return 0x44; - case pktTitle: return 0x45; - case pktUnloadChunk: return 0x1d; - case pktUpdateBlockEntity: return 0x09; - case pktUpdateHealth: return 0x3e; - case pktUpdateScore: return 0x42; - case pktUpdateSign: return 0x46; - case pktUseBed: return 0x2f; - case pktWeather: return 0x1e; - case pktWindowClose: return 0x12; - case pktWindowItems: return 0x14; - case pktWindowOpen: return 0x13; - case pktWindowProperty: return 0x15; + case pktAttachEntity: return 0x40; + case pktBlockAction: return 0x0a; + case pktBlockBreakAnim: return 0x08; + case pktBlockChange: return 0x0b; + case pktBlockChanges: return 0x10; + case pktCameraSetTo: return 0x36; + case pktChatRaw: return 0x0f; + case pktCollectEntity: return 0x49; + case pktDestroyEntity: return 0x30; + case pktDifficulty: return 0x0d; + case pktDisconnectDuringGame: return 0x1a; + case pktDisconnectDuringLogin: return 0x0; + case pktDisplayObjective: return 0x38; + case pktEditSign: return 0x2a; + case pktEncryptionRequest: return 0x01; + case pktEntityAnimation: return 0x06; + case pktEntityEffect: return 0x4c; + case pktEntityEquipment: return 0x3c; + case pktEntityHeadLook: return 0x34; + case pktEntityLook: return 0x27; + case pktEntityMeta: return 0x39; + case pktEntityProperties: return 0x4b; + case pktEntityRelMove: return 0x25; + case pktEntityRelMoveLook: return 0x26; + case pktEntityStatus: return 0x1b; + case pktEntityVelocity: return 0x3b; + case pktExperience: return 0x3d; + case pktExplosion: return 0x1c; + case pktGameMode: return 0x1e; + case pktHeldItemChange: return 0x37; + case pktInventorySlot: return 0x16; + case pktJoinGame: return 0x23; + case pktKeepAlive: return 0x1f; + case pktLeashEntity: return 0x3a; + case pktLoginSuccess: return 0x02; + case pktMapData: return 0x24; + case pktParticleEffect: return 0x22; + case pktPingResponse: return 0x01; + case pktPlayerAbilities: return 0x2b; + case pktPlayerList: return 0x2d; + case pktPlayerListHeaderFooter: return 0x48; + case pktPlayerMaxSpeed: return 0x4b; + case pktPlayerMoveLook: return 0x2e; + case pktPluginMessage: return 0x18; + case pktRemoveEntityEffect: return 0x31; + case pktResourcePack: return 0x32; + case pktRespawn: return 0x33; + case pktScoreboardObjective: return 0x3f; + case pktSpawnExperienceOrb: return 0x01; + case pktSpawnGlobalEntity: return 0x02; + case pktSpawnObject: return 0x00; + case pktSpawnOtherPlayer: return 0x05; + case pktSpawnPainting: return 0x04; + case pktSpawnPosition: return 0x43; + case pktSoundEffect: return 0x19; + case pktSoundParticleEffect: return 0x21; + case pktSpawnMob: return 0x03; + case pktStartCompression: return 0x03; + case pktStatistics: return 0x07; + case pktStatusResponse: return 0x00; + case pktTabCompletionResults: return 0x0e; + case pktTeleportEntity: return 0x4a; + case pktTimeUpdate: return 0x44; + case pktTitle: return 0x45; + case pktUnloadChunk: return 0x1d; + case pktUpdateBlockEntity: return 0x09; + case pktUpdateHealth: return 0x3e; + case pktUpdateScore: return 0x42; + case pktUpdateSign: return 0x46; + case pktUseBed: return 0x2f; + case pktWeather: return 0x1e; + case pktWindowClose: return 0x12; + case pktWindowItems: return 0x14; + case pktWindowOpen: return 0x13; + case pktWindowProperty: return 0x15; // Unsupported packets case pktUnlockRecipe: @@ -2309,11 +2310,12 @@ UInt32 cProtocol_1_9_4::GetPacketID(cProtocol::ePacketType a_Packet) { switch (a_Packet) { - case pktCollectEntity: return 0x48; - case pktEntityEffect: return 0x4b; - case pktEntityProperties: return 0x4a; - case pktPlayerMaxSpeed: return 0x4a; - case pktTeleportEntity: return 0x49; + case pktCollectEntity: return 0x48; + case pktEntityEffect: return 0x4b; + case pktEntityProperties: return 0x4a; + case pktPlayerMaxSpeed: return 0x4a; + case pktPlayerListHeaderFooter: return 0x47; + case pktTeleportEntity: return 0x49; default: return Super::GetPacketID(a_Packet); } diff --git a/src/Root.cpp b/src/Root.cpp index 57782fbb4..a1023e8e9 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -648,6 +648,18 @@ void cRoot::BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cCl +void cRoot::BroadcastPlayerListsHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) +{ + for (auto & Entry : m_WorldsByName) + { + Entry.second.BroadcastPlayerListHeaderFooter(a_Header, a_Footer); + } +} + + + + + void cRoot::BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix) { for (auto & Entry : m_WorldsByName) diff --git a/src/Root.h b/src/Root.h index 696b31ce3..74a0acbb4 100644 --- a/src/Root.h +++ b/src/Root.h @@ -166,6 +166,9 @@ public: /** Broadcast playerlist removal through all worlds */ void BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr); + /** Broadcast playerlist header and footer through all worlds */ + void BroadcastPlayerListsHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer); // tolua_export + // tolua_begin /** Sends a chat message to all connected clients (in all worlds) */ diff --git a/src/World.h b/src/World.h index 2fc5040b8..9d68ff47d 100644 --- a/src/World.h +++ b/src/World.h @@ -209,6 +209,7 @@ public: virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp 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 BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override;