From 3e802932a6797fc0f4768ebc61cf9ac4f498c7fb Mon Sep 17 00:00:00 2001 From: changyong guo Date: Mon, 23 Jul 2018 06:23:33 +0800 Subject: recover hotbar selected slot after reconnect (#4249) 1. implement protocol message SendHeldItemChange 2. add save / load inventory equipped item slot in JSON 3. send held item slot message after player connect to server Fixes #4189 --- src/ClientHandle.cpp | 12 ++++++++++++ src/ClientHandle.h | 1 + src/Entities/Player.cpp | 17 +++++++++++++++++ src/Entities/Player.h | 3 +++ src/Protocol/PacketID.cpp | 3 +++ src/Protocol/Protocol.h | 2 ++ src/Protocol/ProtocolRecognizer.cpp | 11 +++++++++++ src/Protocol/ProtocolRecognizer.h | 1 + src/Protocol/Protocol_1_8.cpp | 13 +++++++++++++ src/Protocol/Protocol_1_8.h | 1 + src/Protocol/Protocol_1_9.cpp | 14 ++++++++++++++ src/Protocol/Protocol_1_9.h | 1 + 12 files changed, 79 insertions(+) (limited to 'src') diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index bbcb64d33..9ae0b4adc 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -417,6 +417,9 @@ void cClientHandle::FinishAuthenticate(const AString & a_Name, const cUUID & a_U // Send experience m_Player->SendExperience(); + // Send hotbar active slot + m_Player->SendHotbarActiveSlot(); + // Send player list items SendPlayerListAddPlayer(*m_Player); cRoot::Get()->BroadcastPlayerListsAddPlayer(*m_Player); @@ -2635,6 +2638,15 @@ void cClientHandle::SendHealth(void) +void cClientHandle::SendHeldItemChange(int a_ItemIndex) +{ + m_Protocol->SendHeldItemChange(a_ItemIndex); +} + + + + + void cClientHandle::SendHideTitle(void) { m_Protocol->SendHideTitle(); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 78da199a7..079c57a19 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -176,6 +176,7 @@ public: // tolua_export void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion); void SendGameMode (eGameMode a_GameMode); void SendHealth (void); + void SendHeldItemChange (int a_ItemIndex); void SendHideTitle (void); // tolua_export void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item); void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 6ddfeb75c..bf5daf172 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -743,6 +743,18 @@ void cPlayer::SendHealth(void) +void cPlayer::SendHotbarActiveSlot(void) +{ + if (m_ClientHandle != nullptr) + { + m_ClientHandle->SendHeldItemChange(m_Inventory.GetEquippedSlotNum()); + } +} + + + + + void cPlayer::SendExperience(void) { if (m_ClientHandle != nullptr) @@ -2212,6 +2224,10 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World) } m_Inventory.LoadFromJson(root["inventory"]); + + int equippedSlotNum = root.get("equippedItemSlot", 0).asInt(); + m_Inventory.SetEquippedSlotNum(equippedSlotNum); + cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents); m_LoadedWorldName = root.get("world", "world").asString(); @@ -2302,6 +2318,7 @@ bool cPlayer::SaveToDisk() root["position"] = JSON_PlayerPosition; root["rotation"] = JSON_PlayerRotation; root["inventory"] = JSON_Inventory; + root["equippedItemSlot"] = m_Inventory.GetEquippedSlotNum(); root["enderchestinventory"] = JSON_EnderChestInventory; root["health"] = m_Health; root["xpTotal"] = m_LifetimeTotalXp; diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 8fa463c5a..a2ee13b45 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -431,6 +431,9 @@ public: void SendHealth(void); + // Send current active hotbar slot + void SendHotbarActiveSlot(void); + void SendExperience(void); /** In UI windows, get the item that the player is dragging */ diff --git a/src/Protocol/PacketID.cpp b/src/Protocol/PacketID.cpp index 47d274f25..135d60a6c 100644 --- a/src/Protocol/PacketID.cpp +++ b/src/Protocol/PacketID.cpp @@ -41,6 +41,7 @@ UInt32 cProtocol_1_9_0::GetPacketId(eOutgoingPackets a_Packet) case sendExplosion: return 0x1c; case sendGameMode: return 0x1e; case sendHealth: return 0x3e; + case sendHeldItemChange: return 0x37; case sendInventorySlot: return 0x16; case sendJoinGame: return 0x23; case sendKeepAlive: return 0x1f; @@ -124,6 +125,7 @@ UInt32 cProtocol_1_12::GetPacketId(eOutgoingPackets a_Packet) case sendEntityVelocity: return 0x3d; case sendExperience: return 0x3f; case sendHealth: return 0x40; + case sendHeldItemChange: return 0x39; case sendLeashEntity: return 0x3c; case sendPlayerMaxSpeed: return 0x4d; case sendRemoveEntityEffect: return 0x32; @@ -161,6 +163,7 @@ UInt32 cProtocol_1_12_1::GetPacketId(eOutgoingPackets a_Packet) case sendEntityVelocity: return 0x3e; case sendExperience: return 0x40; case sendHealth: return 0x41; + case sendHeldItemChange: return 0x3a; case sendLeashEntity: return 0x3d; case sendPlayerList: return 0x2e; case sendPlayerAbilities: return 0x2c; diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 235b60020..1a912f8f9 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -89,6 +89,7 @@ public: sendExplosion, sendGameMode, sendHealth, + sendHeldItemChange, sendInventorySlot, sendJoinGame, sendKeepAlive, @@ -160,6 +161,7 @@ public: virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0; virtual void SendGameMode (eGameMode a_GameMode) = 0; virtual void SendHealth (void) = 0; + virtual void SendHeldItemChange (int a_ItemIndex) = 0; virtual void SendHideTitle (void) = 0; virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) = 0; virtual void SendKeepAlive (UInt32 a_PingID) = 0; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 912091acc..27ed2e6ad 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -428,6 +428,17 @@ void cProtocolRecognizer::SendHealth(void) +void cProtocolRecognizer::SendHeldItemChange(int a_ItemIndex) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendHeldItemChange(a_ItemIndex); +} + + + + + + void cProtocolRecognizer::SendHideTitle(void) { ASSERT(m_Protocol != nullptr); diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index a29daad94..805197db8 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -85,6 +85,7 @@ public: virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; + virtual void SendHeldItemChange (int a_ItemIndex) override; virtual void SendHideTitle (void) override; virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; virtual void SendKeepAlive (UInt32 a_PingID) override; diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index 58f067278..643f99841 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -592,6 +592,19 @@ void cProtocol_1_8_0::SendHealth(void) +void cProtocol_1_8_0::SendHeldItemChange(int a_ItemIndex) +{ + ASSERT((a_ItemIndex >= 0) && (a_ItemIndex <= 8)); // Valid check + + cPacketizer Pkt(*this, 0x09); // Held item change + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteBEInt8(static_cast(Player->GetInventory().GetEquippedSlotNum())); +} + + + + + void cProtocol_1_8_0::SendHideTitle(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 108cc9798..fd71a2da3 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -77,6 +77,7 @@ public: virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; + virtual void SendHeldItemChange (int a_ItemIndex) override; virtual void SendHideTitle (void) override; virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; virtual void SendKeepAlive (UInt32 a_PingID) override; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 64721ed04..2621f140c 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -636,6 +636,20 @@ void cProtocol_1_9_0::SendHealth(void) +void cProtocol_1_9_0::SendHeldItemChange(int a_ItemIndex) +{ + ASSERT((a_ItemIndex >= 0) && (a_ItemIndex <= 8)); // Valid check + + cPacketizer Pkt(*this, GetPacketId(sendHeldItemChange)); // Held item change + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteBEInt8(static_cast(Player->GetInventory().GetEquippedSlotNum())); +} + + + + + + void cProtocol_1_9_0::SendHideTitle(void) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h index a7fd137a9..a7111436b 100644 --- a/src/Protocol/Protocol_1_9.h +++ b/src/Protocol/Protocol_1_9.h @@ -83,6 +83,7 @@ public: virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; + virtual void SendHeldItemChange (int a_ItemIndex) override; virtual void SendHideTitle (void) override; virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; virtual void SendKeepAlive (UInt32 a_PingID) override; -- cgit v1.2.3