diff options
author | Tiger Wang <ziwei.tiger@outlook.com> | 2021-04-10 16:57:16 +0200 |
---|---|---|
committer | Tiger Wang <ziwei.tiger@outlook.com> | 2021-04-12 23:35:07 +0200 |
commit | a999c5d845bd759c6d83b356c7b39e67473dc452 (patch) | |
tree | c8da72f5192293648f30b3228e7563fa7c79d13e | |
parent | Add animations for shield/item block & break (diff) | |
download | cuberite-a999c5d845bd759c6d83b356c7b39e67473dc452.tar cuberite-a999c5d845bd759c6d83b356c7b39e67473dc452.tar.gz cuberite-a999c5d845bd759c6d83b356c7b39e67473dc452.tar.bz2 cuberite-a999c5d845bd759c6d83b356c7b39e67473dc452.tar.lz cuberite-a999c5d845bd759c6d83b356c7b39e67473dc452.tar.xz cuberite-a999c5d845bd759c6d83b356c7b39e67473dc452.tar.zst cuberite-a999c5d845bd759c6d83b356c7b39e67473dc452.zip |
Diffstat (limited to '')
-rw-r--r-- | Server/Plugins/APIDump/APIDesc.lua | 116 | ||||
-rw-r--r-- | src/ClientHandle.cpp | 146 | ||||
-rw-r--r-- | src/ClientHandle.h | 20 | ||||
-rw-r--r-- | src/Defines.h | 20 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 33 | ||||
-rw-r--r-- | src/Entities/Player.h | 15 | ||||
-rw-r--r-- | src/Protocol/Protocol.h | 13 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_10.cpp | 22 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_10.h | 10 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_11.cpp | 38 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_11.h | 17 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_12.cpp | 34 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_12.h | 21 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_13.cpp | 566 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_13.h | 51 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_14.cpp | 28 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_14.h | 16 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_8.cpp | 724 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_8.h | 74 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_9.cpp | 433 | ||||
-rw-r--r-- | src/Protocol/Protocol_1_9.h | 109 |
21 files changed, 1214 insertions, 1292 deletions
diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index bebcda6d6..888ce9aef 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -3831,6 +3831,16 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") }, Notes = "(<b>DEPRECATED</b>) Please use cEntity:IsTicking().", }, + IsElytraFlying = + { + Returns = + { + { + Type = "boolean", + }, + }, + Notes = "Returns true if the entity is flying with an elytra. Entities that cannot fly with an elytra return always false.", + }, IsEnderCrystal = { Returns = @@ -3881,7 +3891,7 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") }, Notes = "Returns true if the entity represents a fishing rod floater", }, - IsInvisible = + IsHeadInWater = { Returns = { @@ -3889,9 +3899,9 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") Type = "boolean", }, }, - Notes = "Returns true if the entity is invisible", + Notes = "Returns true if the entity's head is in a water block", }, - IsInFire = + IsInvisible = { Returns = { @@ -3899,9 +3909,9 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") Type = "boolean", }, }, - Notes = "Returns true if any part of the entity is in a fire block", + Notes = "Returns true if the entity is invisible.", }, - IsInLava = + IsInFire = { Returns = { @@ -3909,9 +3919,9 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") Type = "boolean", }, }, - Notes = "Returns true if any part of the entity is in a lava block", + Notes = "Returns true if any part of the entity is in a fire block", }, - IsInWater = + IsInLava = { Returns = { @@ -3919,9 +3929,9 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") Type = "boolean", }, }, - Notes = "Returns true if any part of the entity is in a water block", + Notes = "Returns true if any part of the entity is in a lava block", }, - IsHeadInWater = + IsInWater = { Returns = { @@ -3929,7 +3939,7 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") Type = "boolean", }, }, - Notes = "Returns true if the entity's head is in a water block", + Notes = "Returns true if any part of the entity is in a water block", }, IsItemFrame = { @@ -4071,16 +4081,6 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") }, Notes = "Returns true if the entity is sprinting. Entities that cannot sprint return always false", }, - IsElytraFlying = - { - Returns = - { - { - Type = "boolean", - }, - }, - Notes = "Returns true if the entity is flying with an elytra. Entities that cannot fly with an elytra return always false", - }, IsSubmerged = { Returns = @@ -10449,16 +10449,6 @@ a_Player:OpenWindow(Window); }, Notes = "Returns the player's current maximum speed, relative to the game default speed. Takes into account the sprinting / flying status.", }, - GetMainHand = - { - Returns = - { - { - Type = "eMainHand", - }, - }, - Notes = "Returns the player's main hand.", - }, GetName = { Returns = @@ -10771,6 +10761,16 @@ a_Player:OpenWindow(Window); }, Notes = "Returns true if the player is currently lying in a bed.", }, + IsLeftHanded = + { + Returns = + { + { + Type = "boolean", + }, + }, + Notes = "Returns true if the player's left hand is dominant.", + }, IsSatiated = { Returns = @@ -11101,6 +11101,17 @@ a_Player:OpenWindow(Window); }, Notes = "Sets the item that the player is dragging in a UI window. If no UI window is open, this function does nothing." }, + SetElytraFlight = + { + Params = + { + { + Name = "IsElytraFlying", + Type = "boolean", + }, + }, + Notes = "Sets whether the player is elytra flying or not.", + }, SetFlying = { Params = @@ -11194,16 +11205,16 @@ a_Player:OpenWindow(Window); }, Notes = "Sets the 'IsFishing' flag for the player. The floater entity ID is expected for the true variant, it can be omitted when IsFishing is false. FIXME: Undefined behavior when multiple fishing rods are used simultanously", }, - SetMainHand = + SetLeftHanded = { Params = { { - Name = "Hand", - Type = "eMainHand", + Name = "IsLeftHanded", + Type = "boolean", }, }, - Notes = "Sets the main hand of the player.", + Notes = "Sets the dominant hand of the player.", }, SetName = { @@ -11249,17 +11260,6 @@ a_Player:OpenWindow(Window); }, Notes = "Sets the skin part flags of the player. The value should be a bitwise OR of several {{Globals#eSkinPart|eSkinPart}} constants.", }, - SetElytraFlight = - { - Params = - { - { - Name = "IsElytraFlying", - Type = "boolean", - }, - }, - Notes = "Sets whether the player is elytra flying or not.", - }, SetSprintingMaxSpeed = { Params = @@ -17925,32 +17925,6 @@ end gmXXX constants, the eGameMode_ constants are deprecated and will be removed from the API. ]], }, - eHand = - { - Include = - { - "hMain", - "hOff", - }, - TextBefore = [[ - These constants represent the main and off hand. Currently, these constants are not used, but - are provided for future use when dual-wielding is functional. An action or item can be in the - main hand or the off hand. The main hand can be either the left or the right hand - use - {{cPlayer}}:GetMainHand() to determine which (see {{Globals#eMainHand|eMainHand}}). - ]], - }, - eMainHand = - { - Include = - { - "^mh.*", - }, - TextBefore = [[ - These constants identify which hand is the main hand. The main hand can either be the left hand - or the right hand. Note that this is only visual, as the client behaves the same regardless of the - main hand setting. See {{cPlayer}}:GetMainHand(). - ]], - }, EMCSBiome = { Include = "^bi.*", diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 1a99fa300..2a1ae2357 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -566,6 +566,21 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::Priori +void cClientHandle::HandleAnimation(const bool a_SwingMainHand) +{ + if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_SwingMainHand ? 0 : 1)) + { + // Plugin disagrees, bail out: + return; + } + + m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, a_SwingMainHand ? EntityAnimation::PlayerMainHandSwings : EntityAnimation::PlayerOffHandSwings, this); +} + + + + + void cClientHandle::HandleNPCTrade(int a_SlotNum) { // TODO @@ -757,62 +772,6 @@ void cClientHandle::HandlePlayerAbilities(bool a_IsFlying, float FlyingSpeed, fl -void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, bool a_IsOnGround) -{ - if (m_Player->IsFrozen()) - { - // Ignore client-side updates if the player is frozen - return; - } - - Vector3d NewPosition(a_PosX, a_PosY, a_PosZ); - Vector3d OldPosition = GetPlayer()->GetPosition(); - auto PreviousIsOnGround = GetPlayer()->IsOnGround(); - - #ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wfloat-equal" - #endif - - if ( - (OldPosition == NewPosition) && - (PreviousIsOnGround == a_IsOnGround) - ) - { - // Nothing changed, no need to do anything - return; - } - - #ifdef __clang__ - #pragma clang diagnostic pop - #endif - - // If the player has moved too far, "repair" them: - if ((OldPosition - NewPosition).SqrLength() > 100 * 100) - { - LOGD("Too far away (%0.2f), \"repairing\" the client", (OldPosition - NewPosition).Length()); - SendPlayerMoveLook(); - return; - } - - if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*m_Player, OldPosition, NewPosition, PreviousIsOnGround)) - { - SendPlayerMoveLook(); - return; - } - - // TODO: should do some checks to see if player is not moving through terrain - // TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too - - m_Player->SetPosition(NewPosition); - m_Player->SetTouchGround(a_IsOnGround); - m_Player->UpdateMovementStats(NewPosition - OldPosition, PreviousIsOnGround); -} - - - - - void cClientHandle::HandlePluginMessage(const AString & a_Channel, const ContiguousByteBufferView a_Message) { if (a_Channel == "REGISTER") @@ -1342,7 +1301,7 @@ void cClientHandle::FinishDigAnimation() -void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, eHand a_Hand) +void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, bool a_UsedMainHand) { // This function handles three actions: // (1) Place a block; @@ -1359,8 +1318,8 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e // E.g., when opening a chest with a dirt in hand, if the plugin rejects opening the chest, the dirt will not be placed. // TODO: We are still consuming the items in main hand. Remove this override when the off-hand consumption is handled correctly. - a_Hand = eHand::hMain; - const cItem & HeldItem = (a_Hand == eHand::hOff) ? m_Player->GetInventory().GetShieldSlot() : m_Player->GetEquippedItem(); + a_UsedMainHand = true; + const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot(); cItemHandler * ItemHandler = cItemHandler::GetItemHandler(HeldItem.m_ItemType); // TODO: This distance should be calculated from the point that the cursor pointing at, instead of the center of the block @@ -1369,7 +1328,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e auto CursorPos = Vector3i(a_CursorX, a_CursorY, a_CursorZ); double Dist = (Vector3d(ClickedBlockPos) + Vector3d(0.5, 0.5, 0.5) - m_Player->GetEyePosition()).Length(); FLOGD("HandleRightClick: {0}, face {1}, Cursor {2}, Hand: {3}, HeldItem: {4}; Dist: {5:.02f}", - ClickedBlockPos, a_BlockFace, CursorPos, a_Hand, ItemToFullString(HeldItem), Dist + ClickedBlockPos, a_BlockFace, CursorPos, a_UsedMainHand, ItemToFullString(HeldItem), Dist ); // Check the reach distance: @@ -1518,25 +1477,66 @@ void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsO -void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, float a_Rotation, float a_Pitch, bool a_IsOnGround) +void cClientHandle::HandlePlayerMove(double a_PosX, double a_PosY, double a_PosZ, bool a_IsOnGround) { - HandlePlayerPos(a_PosX, a_PosY, a_PosZ, a_IsOnGround); - HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround); -} + if (m_Player->IsFrozen()) + { + // Ignore client-side updates if the player is frozen: + return; + } + const Vector3d NewPosition(a_PosX, a_PosY, a_PosZ); + const Vector3d OldPosition = GetPlayer()->GetPosition(); + const auto PreviousIsOnGround = GetPlayer()->IsOnGround(); +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfloat-equal" +#endif + if ( + (OldPosition == NewPosition) && + (PreviousIsOnGround == a_IsOnGround) + ) + { + // Nothing changed, no need to do anything: + return; + } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif -void cClientHandle::HandleAnimation(int a_Animation) -{ - if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_Animation)) + // If the player has moved too far, "repair" them: + if ((OldPosition - NewPosition).SqrLength() > 100 * 100) { - // Plugin disagrees, bail out + LOGD("Too far away (%0.2f), \"repairing\" the client", (OldPosition - NewPosition).Length()); + SendPlayerMoveLook(); + return; + } + + if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*m_Player, OldPosition, NewPosition, PreviousIsOnGround)) + { + SendPlayerMoveLook(); return; } - m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, static_cast<char>(a_Animation), this); + // TODO: should do some checks to see if player is not moving through terrain + // TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too + + m_Player->SetPosition(NewPosition); + m_Player->SetTouchGround(a_IsOnGround); + m_Player->UpdateMovementStats(NewPosition - OldPosition, PreviousIsOnGround); +} + + + + + +void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, float a_Rotation, float a_Pitch, bool a_IsOnGround) +{ + HandlePlayerMove(a_PosX, a_PosY, a_PosZ, a_IsOnGround); + HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround); } @@ -1717,20 +1717,20 @@ void cClientHandle::HandleUseEntity(UInt32 a_TargetEntityID, bool a_IsLeftClick) -void cClientHandle::HandleUseItem(eHand a_Hand) +void cClientHandle::HandleUseItem(bool a_UsedMainHand) { // Use the held item without targeting a block: eating, drinking, charging a bow, using buckets // In version 1.8.x, this function shares the same packet id with HandleRightClick. // In version >= 1.9, there is a new packet id for "Use Item". // TODO: We are still consuming the items in main hand. Remove this override when the off-hand consumption is handled correctly. - a_Hand = eHand::hMain; - const cItem & HeldItem = (a_Hand == eHand::hOff) ? m_Player->GetInventory().GetShieldSlot() : m_Player->GetEquippedItem(); + a_UsedMainHand = true; + const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot(); cItemHandler * ItemHandler = cItemHandler::GetItemHandler(HeldItem.m_ItemType); cWorld * World = m_Player->GetWorld(); cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); - LOGD("HandleUseItem: Hand: %d; HeldItem: %s", a_Hand, ItemToFullString(HeldItem).c_str()); + LOGD("HandleUseItem: Hand: %d; HeldItem: %s", a_UsedMainHand, ItemToFullString(HeldItem).c_str()); if (PlgMgr->CallHookPlayerRightClick(*m_Player, -1, 255, -1, BLOCK_FACE_NONE, 0, 0, 0)) { diff --git a/src/ClientHandle.h b/src/ClientHandle.h index cb0ea508a..00d5051d2 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -294,8 +294,8 @@ public: // tolua_export void PacketUnknown(UInt32 a_PacketType); void PacketError(UInt32 a_PacketType); - // Calls that cProtocol descendants use for handling packets: - void HandleAnimation(int a_Animation); + /** Called when the protocol receives a (hand swing) animation packet. */ + void HandleAnimation(bool a_SwingMainHand); /** Called when the protocol receives a MC|ItemName plugin message, indicating that the player named an item in the anvil UI. */ @@ -352,18 +352,18 @@ public: // tolua_export void HandlePing (void); void HandlePlayerAbilities (bool a_IsFlying, float FlyingSpeed, float WalkingSpeed); void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround); - void HandlePlayerMoveLook (double a_PosX, double a_PosY, double a_PosZ, float a_Rotation, float a_Pitch, bool a_IsOnGround); // While m_bPositionConfirmed (normal gameplay) - /** Verifies and sets player position, performing relevant checks - Calls relevant methods to process movement related statistics - Requires state of previous position and on-ground status, so must be called when these are still intact - */ - void HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, bool a_IsOnGround); + /** Verifies and sets player position, performing relevant checks. + Calls relevant methods to process movement related statistics. + Requires state of previous position and on-ground status, so must be called when these are still intact. */ + void HandlePlayerMove(double a_PosX, double a_PosY, double a_PosZ, bool a_IsOnGround); + + void HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, float a_Rotation, float a_Pitch, bool a_IsOnGround); void HandlePluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message); void HandleRespawn (void); - void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, eHand a_Hand); + void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, bool a_UsedMainHand); void HandleSlotSelected (Int16 a_SlotNum); void HandleSpectate (const cUUID & a_PlayerUUID); @@ -382,7 +382,7 @@ public: // tolua_export ); void HandleUnmount (void); void HandleUseEntity (UInt32 a_TargetEntityID, bool a_IsLeftClick); - void HandleUseItem (eHand a_Hand); + void HandleUseItem (bool a_UsedMainHand); void HandleWindowClick (UInt8 a_WindowID, Int16 a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem); void HandleWindowClose (UInt8 a_WindowID); diff --git a/src/Defines.h b/src/Defines.h index a1c1d1cf8..1dbcdda34 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -211,26 +211,6 @@ enum eMobHeadRotation -enum eHand -{ - hMain = 0, - hOff = 1, -} ; - - - - - -enum eMainHand -{ - mhLeft = 0, - mhRight = 1, -} ; - - - - - enum eSkinPart { spCape = 0x01, diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 3b005d8eb..1bfeea6e2 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -123,6 +123,7 @@ cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) : m_IsFlightCapable(false), m_IsFlying(false), m_IsFrozen(false), + m_IsLeftHanded(false), m_IsTeleporting(false), m_IsVisible(true), m_EatingFinishTick(-1), @@ -132,8 +133,7 @@ cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) : m_FloaterID(cEntity::INVALID_ID), m_Team(nullptr), m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL), - m_SkinParts(0), - m_MainHand(mhRight) + m_SkinParts(0) { ASSERT(GetName().length() <= 16); // Otherwise this player could crash many clients... @@ -449,6 +449,15 @@ bool cPlayer::IsInBed(void) const +bool cPlayer::IsLeftHanded() const +{ + return m_IsLeftHanded; +} + + + + + bool cPlayer::IsStanding() const { return std::holds_alternative<BodyStanceStanding>(m_BodyStance); @@ -692,6 +701,16 @@ void cPlayer::SetFlying(const bool a_ShouldFly) +void cPlayer::SetLeftHanded(const bool a_IsLeftHanded) +{ + m_IsLeftHanded = a_IsLeftHanded; + m_World->BroadcastEntityMetadata(*this); +} + + + + + void cPlayer::SetSprint(const bool a_ShouldSprint) { if (a_ShouldSprint && IsStanding()) @@ -2544,16 +2563,6 @@ void cPlayer::SetSkinParts(int a_Parts) -void cPlayer::SetMainHand(eMainHand a_Hand) -{ - m_MainHand = a_Hand; - m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); -} - - - - - void cPlayer::AttachTo(cEntity * a_AttachTo) { // Different attach, if this is a spectator diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 8969099a1..7c8922dbf 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -376,6 +376,9 @@ public: /** Returns true if a player is sleeping in a bed. */ bool IsInBed(void) const; + /** Returns true if the player's left hand is dominant. */ + bool IsLeftHanded() const; + /** Returns true if the player has thrown out a floater */ bool IsFishing(void) const { return m_IsFishing; } @@ -491,6 +494,9 @@ public: /** Starts or stops flying, broadcasting the state change. */ void SetFlying(bool a_ShouldFly); + /** Sets the dominant hand of the player. */ + void SetLeftHanded(bool a_IsLeftHanded); + /** Starts or stops sprinting, if our current body stance permits, broadcasting the state change. */ void SetSprint(bool a_ShouldSprint); @@ -557,9 +563,6 @@ public: int GetSkinParts(void) const { return m_SkinParts; } void SetSkinParts(int a_Parts); - eMainHand GetMainHand(void) const { return m_MainHand; } - void SetMainHand(eMainHand a_Hand); - // tolua_end /** Calls the block placement hooks and places the blocks in the world. @@ -715,6 +718,9 @@ private: /** If true, we are locking m_Position to m_FrozenPosition. */ bool m_IsFrozen; + /** Whether the player is left-handed, or right-handed. */ + bool m_IsLeftHanded; + /** Was the player frozen manually by a plugin or automatically by the server? */ bool m_IsManuallyFrozen; @@ -749,9 +755,6 @@ private: /** Displayed skin part bit mask */ int m_SkinParts; - /** The main hand of the player */ - eMainHand m_MainHand; - /** List on known recipes as Ids */ std::set<UInt32> m_KnownRecipes; diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 75ebb92d4..c87ab4a7d 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -25,12 +25,9 @@ class cExpOrb; class cPlayer; class cEntity; class cWindow; -class cPickup; class cPainting; class cWorld; class cMonster; -class cChunkDataSerializer; -class cFallingBlock; class cCompositeChat; class cStatManager; class cPacketizer; @@ -39,12 +36,6 @@ class cPacketizer; -typedef unsigned char Byte; - - - - - class cProtocol { public: @@ -469,10 +460,10 @@ protected: cByteBuffer m_OutPacketLenBuffer; /** Returns the protocol-specific packet ID given the protocol-agnostic packet enum. */ - virtual UInt32 GetPacketID(ePacketType a_Packet) = 0; + virtual UInt32 GetPacketID(ePacketType a_Packet) const = 0; /** Returns the current protocol's version, for handling status requests. */ - virtual Version GetProtocolVersion() = 0; + virtual Version GetProtocolVersion() const = 0; /** A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it. */ virtual void SendData(ContiguousByteBufferView a_Data) = 0; diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp index 6db08c916..9f4413576 100644 --- a/src/Protocol/Protocol_1_10.cpp +++ b/src/Protocol/Protocol_1_10.cpp @@ -329,22 +329,22 @@ void cProtocol_1_10_0::SendSoundEffect(const AString & a_SoundName, double a_X, -cProtocol::Version cProtocol_1_10_0::GetProtocolVersion() +UInt32 cProtocol_1_10_0::GetProtocolMobType(const eMonsterType a_MobType) const { - return Version::v1_10_0; + switch (a_MobType) + { + case mtPolarBear: return 102; + default: return Super::GetProtocolMobType(a_MobType); + } } -UInt32 cProtocol_1_10_0::GetProtocolMobType(const eMonsterType a_MobType) +cProtocol::Version cProtocol_1_10_0::GetProtocolVersion() const { - switch (a_MobType) - { - case mtPolarBear: return 102; - default: return Super::GetProtocolMobType(a_MobType); - } + return Version::v1_10_0; } @@ -360,7 +360,7 @@ void cProtocol_1_10_0::HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer -void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) +void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { using namespace Metadata; @@ -413,7 +413,7 @@ void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Pkt.WriteBEUInt8(PLAYER_MAIN_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); - a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetMainHand())); + a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: @@ -581,7 +581,7 @@ void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & -void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) +void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { using namespace Metadata; diff --git a/src/Protocol/Protocol_1_10.h b/src/Protocol/Protocol_1_10.h index 639658eb8..f4ede2949 100644 --- a/src/Protocol/Protocol_1_10.h +++ b/src/Protocol/Protocol_1_10.h @@ -32,9 +32,11 @@ protected: virtual void SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; - virtual Version GetProtocolVersion() override; - virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override; + virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; + virtual Version GetProtocolVersion() const override; + virtual void HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) override; - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override; + + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; + virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp index e2436e04c..1bce409f4 100644 --- a/src/Protocol/Protocol_1_11.cpp +++ b/src/Protocol/Protocol_1_11.cpp @@ -492,16 +492,24 @@ void cProtocol_1_11_0::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) -cProtocol::Version cProtocol_1_11_0::GetProtocolVersion() +signed char cProtocol_1_11_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const { - return Version::v1_11_0; + 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); + } } -UInt32 cProtocol_1_11_0::GetProtocolMobType(const eMonsterType a_MobType) +UInt32 cProtocol_1_11_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { @@ -561,17 +569,9 @@ UInt32 cProtocol_1_11_0::GetProtocolMobType(const eMonsterType a_MobType) -signed char cProtocol_1_11_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const +cProtocol::Version cProtocol_1_11_0::GetProtocolVersion() 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); - } + return Version::v1_11_0; } @@ -592,14 +592,14 @@ void cProtocol_1_11_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) 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)); + m_Client->HandleRightClick(BlockX, BlockY, BlockZ, FaceIntToBlockFace(Face), FloorC(CursorX * 16), FloorC(CursorY * 16), FloorC(CursorZ * 16), Hand == 0); } -void cProtocol_1_11_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) +void cProtocol_1_11_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const { a_Writer.AddInt("x", a_BlockEntity.GetPosX()); a_Writer.AddInt("y", a_BlockEntity.GetPosY()); @@ -632,7 +632,7 @@ void cProtocol_1_11_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockE -void cProtocol_1_11_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) +void cProtocol_1_11_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { using namespace Metadata_1_11; @@ -685,7 +685,7 @@ void cProtocol_1_11_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Pkt.WriteBEUInt8(PLAYER_MAIN_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); - a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetMainHand())); + a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: @@ -855,7 +855,7 @@ void cProtocol_1_11_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & -void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) +void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { using namespace Metadata_1_11; @@ -1273,7 +1273,7 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_ //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_11_1: -cProtocol::Version cProtocol_1_11_1::GetProtocolVersion() +cProtocol::Version cProtocol_1_11_1::GetProtocolVersion() const { return Version::v1_11_1; } diff --git a/src/Protocol/Protocol_1_11.h b/src/Protocol/Protocol_1_11.h index f5ed73187..5bf03a9dd 100644 --- a/src/Protocol/Protocol_1_11.h +++ b/src/Protocol/Protocol_1_11.h @@ -40,18 +40,15 @@ protected: virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override; virtual void SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) override; - /** Returns 1.11. */ - virtual Version GetProtocolVersion() override; - - /** Converts eMonsterType to protocol-specific mob IDs */ - virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; + virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; + virtual Version GetProtocolVersion() const override; - virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override; - virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) override; - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override; + virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const override; + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; + virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; @@ -69,5 +66,5 @@ public: protected: - virtual Version GetProtocolVersion() override; + virtual Version GetProtocolVersion() const override; }; diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp index 31daa96f7..d0e77ae80 100644 --- a/src/Protocol/Protocol_1_12.cpp +++ b/src/Protocol/Protocol_1_12.cpp @@ -323,7 +323,7 @@ namespace Metadata_1_12 //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_12: -void cProtocol_1_12::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) +void cProtocol_1_12::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { using namespace Metadata_1_12; @@ -380,7 +380,7 @@ void cProtocol_1_12::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ a_Pkt.WriteBEUInt8(PLAYER_MAIN_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); - a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetMainHand())); + a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: @@ -550,7 +550,7 @@ void cProtocol_1_12::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ -void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) +void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { using namespace Metadata_1_12; @@ -982,7 +982,7 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo -UInt32 cProtocol_1_12::GetPacketID(cProtocol::ePacketType a_Packet) +UInt32 cProtocol_1_12::GetPacketID(cProtocol::ePacketType a_Packet) const { switch (a_Packet) { @@ -1061,15 +1061,6 @@ void cProtocol_1_12::HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer) -cProtocol::Version cProtocol_1_12::GetProtocolVersion() -{ - return Version::v1_12; -} - - - - - signed char cProtocol_1_12::GetProtocolEntityStatus(EntityAnimation a_Animation) const { switch (a_Animation) @@ -1084,7 +1075,7 @@ signed char cProtocol_1_12::GetProtocolEntityStatus(EntityAnimation a_Animation) -UInt32 cProtocol_1_12::GetProtocolMobType(const eMonsterType a_MobType) +UInt32 cProtocol_1_12::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { @@ -1098,6 +1089,15 @@ UInt32 cProtocol_1_12::GetProtocolMobType(const eMonsterType a_MobType) +cProtocol::Version cProtocol_1_12::GetProtocolVersion() const +{ + return Version::v1_12; +} + + + + + bool cProtocol_1_12::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { switch (m_State) @@ -1176,7 +1176,7 @@ bool cProtocol_1_12::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketTyp //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_12_1: -UInt32 cProtocol_1_12_1::GetPacketID(ePacketType a_Packet) +UInt32 cProtocol_1_12_1::GetPacketID(ePacketType a_Packet) const { switch (a_Packet) { @@ -1219,7 +1219,7 @@ UInt32 cProtocol_1_12_1::GetPacketID(ePacketType a_Packet) -cProtocol::Version cProtocol_1_12_1::GetProtocolVersion() +cProtocol::Version cProtocol_1_12_1::GetProtocolVersion() const { return Version::v1_12_1; } @@ -1305,7 +1305,7 @@ bool cProtocol_1_12_1::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketT //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_12_2:: -cProtocol::Version cProtocol_1_12_2::GetProtocolVersion() +cProtocol::Version cProtocol_1_12_2::GetProtocolVersion() const { return Version::v1_12_2; } diff --git a/src/Protocol/Protocol_1_12.h b/src/Protocol/Protocol_1_12.h index 65bc23bcd..0d18c2ae5 100644 --- a/src/Protocol/Protocol_1_12.h +++ b/src/Protocol/Protocol_1_12.h @@ -34,16 +34,18 @@ public: protected: - virtual UInt32 GetPacketID(ePacketType a_Packet) override; - virtual Version GetProtocolVersion() override; + virtual UInt32 GetPacketID(ePacketType a_Packet) const override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; - virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override; + virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; + virtual Version GetProtocolVersion() const override; + virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer); virtual void HandleCraftRecipe(cByteBuffer & a_ByteBuffer); virtual void HandlePacketCraftingBookData(cByteBuffer & a_ByteBuffer); - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override; + + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; + virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; @@ -61,8 +63,9 @@ public: protected: - virtual UInt32 GetPacketID(ePacketType a_Packet) override; - virtual Version GetProtocolVersion() override; + virtual UInt32 GetPacketID(ePacketType a_Packet) const override; + virtual Version GetProtocolVersion() const override; + virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; }; @@ -81,8 +84,10 @@ public: protected: - virtual Version GetProtocolVersion() override; + virtual Version GetProtocolVersion() const override; + virtual void HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) override; + virtual void SendKeepAlive(UInt32 a_PingID) override; virtual void SendUnlockRecipe(UInt32 a_RecipeID) override; virtual void SendInitRecipes(UInt32 a_RecipeID) override; diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp index a802f0074..400dd62b1 100644 --- a/src/Protocol/Protocol_1_13.cpp +++ b/src/Protocol/Protocol_1_13.cpp @@ -238,107 +238,180 @@ void cProtocol_1_13::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) -bool cProtocol_1_13::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) +UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) const { - if (m_State != 3) - { - return Super::HandlePacket(a_ByteBuffer, a_PacketType); - } + const UInt8 Entity = 6; + const UInt8 Living = Entity + 5; + const UInt8 Insentient = Living + 1; + const UInt8 Ageable = Insentient + 1; + const UInt8 AbstractHorse = Ageable + 2; + const UInt8 ChestedHorse = AbstractHorse + 1; + const UInt8 TameableAnimal = Ageable + 2; + const UInt8 Minecart = Entity + 6; - // Game - switch (a_PacketType) + switch (a_Metadata) { - case 0x00: HandleConfirmTeleport(a_ByteBuffer); return true; - case 0x05: HandlePacketTabComplete(a_ByteBuffer); return true; - case 0x02: HandlePacketChatMessage(a_ByteBuffer); return true; - case 0x03: HandlePacketClientStatus(a_ByteBuffer); return true; - case 0x04: HandlePacketClientSettings(a_ByteBuffer); return true; - case 0x06: break; // Confirm transaction - not used in Cuberite - case 0x07: HandlePacketEnchantItem(a_ByteBuffer); return true; - case 0x08: HandlePacketWindowClick(a_ByteBuffer); return true; - case 0x09: HandlePacketWindowClose(a_ByteBuffer); return true; - case 0x0a: HandlePacketPluginMessage(a_ByteBuffer); return true; - case 0x0d: HandlePacketUseEntity(a_ByteBuffer); return true; - case 0x0e: HandlePacketKeepAlive(a_ByteBuffer); return true; - case 0x0f: HandlePacketPlayer(a_ByteBuffer); return true; - case 0x10: HandlePacketPlayerPos(a_ByteBuffer); return true; - case 0x11: HandlePacketPlayerPosLook(a_ByteBuffer); return true; - case 0x12: HandlePacketPlayerLook(a_ByteBuffer); return true; - case 0x13: HandlePacketVehicleMove(a_ByteBuffer); return true; - case 0x14: HandlePacketBoatSteer(a_ByteBuffer); return true; - case 0x15: break; // Pick item - not yet implemented - case 0x16: break; // Craft Recipe Request - not yet implemented - case 0x17: HandlePacketPlayerAbilities(a_ByteBuffer); return true; - case 0x18: HandlePacketBlockDig(a_ByteBuffer); return true; - case 0x19: HandlePacketEntityAction(a_ByteBuffer); return true; - case 0x1a: HandlePacketSteerVehicle(a_ByteBuffer); return true; - case 0x1b: HandlePacketCraftingBookData(a_ByteBuffer); return true; - case 0x1d: break; // Resource pack status - not yet implemented - case 0x1e: HandlePacketAdvancementTab(a_ByteBuffer); return true; - case 0x20: HandlePacketSetBeaconEffect(a_ByteBuffer); return true; - case 0x21: HandlePacketSlotSelect(a_ByteBuffer); return true; - case 0x24: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; - case 0x26: HandlePacketUpdateSign(a_ByteBuffer); return true; - case 0x27: HandlePacketAnimation(a_ByteBuffer); return true; - case 0x28: HandlePacketSpectate(a_ByteBuffer); return true; - case 0x29: HandlePacketBlockPlace(a_ByteBuffer); return true; - case 0x2a: HandlePacketUseItem(a_ByteBuffer); return true; - } + case EntityMetadata::EntityFlags: return 0; + case EntityMetadata::EntityAir: return 1; + case EntityMetadata::EntityCustomName: return 2; + case EntityMetadata::EntityCustomNameVisible: return 3; + case EntityMetadata::EntitySilent: return 4; + case EntityMetadata::EntityNoGravity: return 5; + case EntityMetadata::PotionThrown: return Entity; + case EntityMetadata::FallingBlockPosition: return Entity; + case EntityMetadata::AreaEffectCloudRadius: return Entity; + case EntityMetadata::AreaEffectCloudColor: return Entity + 1; + case EntityMetadata::AreaEffectCloudSinglePointEffect: return Entity + 2; + case EntityMetadata::AreaEffectCloudParticleId: return Entity + 3; + case EntityMetadata::ArrowFlags: return Entity; + case EntityMetadata::TippedArrowColor: return Entity + 1; + case EntityMetadata::BoatLastHitTime: return Entity; + case EntityMetadata::BoatForwardDirection: return Entity + 1; + case EntityMetadata::BoatDamageTaken: return Entity + 2; + case EntityMetadata::BoatType: return Entity + 3; + case EntityMetadata::BoatLeftPaddleTurning: return Entity + 4; + case EntityMetadata::BoatRightPaddleTurning: return Entity + 5; + case EntityMetadata::BoatSplashTimer: return Entity + 6; + case EntityMetadata::EnderCrystalBeamTarget: return Entity; + case EntityMetadata::EnderCrystalShowBottom: return Entity + 1; + case EntityMetadata::WitherSkullInvulnerable: return Entity; + case EntityMetadata::FireworkInfo: return Entity; + case EntityMetadata::FireworkBoostedEntityId: return Entity + 1; + case EntityMetadata::ItemFrameItem: return Entity; + case EntityMetadata::ItemFrameRotation: return Entity + 1; + case EntityMetadata::ItemItem: return Entity; + case EntityMetadata::LivingActiveHand: return Entity; + case EntityMetadata::LivingHealth: return Entity + 1; + case EntityMetadata::LivingPotionEffectColor: return Entity + 2; + case EntityMetadata::LivingPotionEffectAmbient: return Entity + 3; + case EntityMetadata::LivingNumberOfArrows: return Entity + 4; + case EntityMetadata::PlayerAdditionalHearts: return Living; + case EntityMetadata::PlayerScore: return Living + 1; + case EntityMetadata::PlayerDisplayedSkinParts: return Living + 2; + case EntityMetadata::PlayerMainHand: return Living + 3; + case EntityMetadata::ArmorStandStatus: return Living; + case EntityMetadata::ArmorStandHeadRotation: return Living + 1; + case EntityMetadata::ArmorStandBodyRotation: return Living + 2; + case EntityMetadata::ArmorStandLeftArmRotation: return Living + 3; + case EntityMetadata::ArmorStandRightArmRotation: return Living + 4; + case EntityMetadata::ArmorStandLeftLegRotation: return Living + 5; + case EntityMetadata::ArmorStandRightLegRotation: return Living + 6; + case EntityMetadata::InsentientFlags: return Living; + case EntityMetadata::BatHanging: return Insentient; + case EntityMetadata::AgeableIsBaby: return Insentient; + case EntityMetadata::AbstractHorseFlags: return Ageable; + case EntityMetadata::AbstractHorseOwner: return Ageable + 1; + case EntityMetadata::HorseVariant: return AbstractHorse; + case EntityMetadata::HorseArmour: return AbstractHorse + 1; + case EntityMetadata::ChestedHorseChested: return AbstractHorse; + case EntityMetadata::LlamaStrength: return ChestedHorse; + case EntityMetadata::LlamaCarpetColor: return ChestedHorse + 1; + case EntityMetadata::LlamaVariant: return ChestedHorse + 2; + case EntityMetadata::PigHasSaddle: return Ageable; + case EntityMetadata::PigTotalCarrotOnAStickBoost: return Ageable + 1; + case EntityMetadata::RabbitType: return Ageable; + case EntityMetadata::PolarBearStanding: return Ageable; + case EntityMetadata::SheepFlags: return Ageable; + case EntityMetadata::TameableAnimalFlags: return Ageable; + case EntityMetadata::TameableAnimalOwner: return Ageable + 1; + case EntityMetadata::OcelotType: return TameableAnimal; + case EntityMetadata::WolfDamageTaken: return TameableAnimal; + case EntityMetadata::WolfBegging: return TameableAnimal + 1; + case EntityMetadata::WolfCollarColour: return TameableAnimal + 2; + case EntityMetadata::VillagerProfession: return Ageable; + case EntityMetadata::IronGolemPlayerCreated: return Insentient; + case EntityMetadata::ShulkerFacingDirection: return Insentient; + case EntityMetadata::ShulkerAttachmentFallingBlockPosition: return Insentient + 1; + case EntityMetadata::ShulkerShieldHeight: return Insentient + 2; + case EntityMetadata::BlazeOnFire: return Insentient; + case EntityMetadata::CreeperState: return Insentient; + case EntityMetadata::CreeperPowered: return Insentient + 1; + case EntityMetadata::CreeperIgnited: return Insentient + 2; + case EntityMetadata::GuardianStatus: return Insentient; + case EntityMetadata::GuardianTarget: return Insentient + 1; + case EntityMetadata::IllagerFlags: return Insentient; + case EntityMetadata::SpeIlagerSpell: return Insentient + 1; + case EntityMetadata::VexFlags: return Insentient; + case EntityMetadata::SpiderClimbing: return Insentient; + case EntityMetadata::WitchAggresive: return Insentient; + case EntityMetadata::WitherFirstHeadTarget: return Insentient; + case EntityMetadata::WitherSecondHeadTarget: return Insentient + 1; + case EntityMetadata::WitherThirdHeadTarget: return Insentient + 2; + case EntityMetadata::WitherInvulnerableTimer: return Insentient + 3; + case EntityMetadata::ZombieIsBaby: return Insentient; + case EntityMetadata::ZombieHandsRisedUp: return Insentient + 2; + case EntityMetadata::ZombieVillagerConverting: return Insentient + 4; + case EntityMetadata::ZombieVillagerProfession: return Insentient + 5; + case EntityMetadata::EndermanCarriedBlock: return Insentient; + case EntityMetadata::EndermanScreaming: return Insentient + 1; + case EntityMetadata::EnderDragonDragonPhase: return Insentient; + case EntityMetadata::GhastAttacking: return Insentient; + case EntityMetadata::SlimeSize: return Insentient; + case EntityMetadata::MinecartShakingPower: return Entity; + case EntityMetadata::MinecartShakingDirection: return Entity + 1; + case EntityMetadata::MinecartShakingMultiplier: return Entity + 2; + case EntityMetadata::MinecartBlockIDMeta: return Entity + 3; + case EntityMetadata::MinecartBlockY: return Entity + 4; + case EntityMetadata::MinecartShowBlock: return Entity + 5; + case EntityMetadata::MinecartCommandBlockCommand: return Minecart; + case EntityMetadata::MinecartCommandBlockLastOutput: return Minecart + 1; + case EntityMetadata::MinecartFurnacePowered: return Minecart; + case EntityMetadata::TNTPrimedFuseTime: return Entity; - return Super::HandlePacket(a_ByteBuffer, a_PacketType); + case EntityMetadata::EntityPose: + case EntityMetadata::AreaEffectCloudParticleParameter1: + case EntityMetadata::AreaEffectCloudParticleParameter2: + case EntityMetadata::AbstractSkeletonArmsSwinging: + case EntityMetadata::ZombieUnusedWasType: break; + } + UNREACHABLE("Retrieved invalid metadata for protocol"); } -void cProtocol_1_13::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) +UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadataType a_FieldType) const { - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); - - // If the plugin channel is recognized vanilla, handle it directly: - if (Channel.substr(0, 15) == "minecraft:brand") + switch (a_FieldType) { - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Brand); - m_Client->SetClientBrand(Brand); - - // Send back our brand, including the length: - m_Client->SendPluginMessage("minecraft:brand", "\x08""Cuberite"); - return; + case EntityMetadataType::Byte: return 0; + case EntityMetadataType::VarInt: return 1; + case EntityMetadataType::Float: return 2; + case EntityMetadataType::String: return 3; + case EntityMetadataType::Chat: return 4; + case EntityMetadataType::OptChat: return 5; + case EntityMetadataType::Item: return 6; + case EntityMetadataType::Boolean: return 7; + case EntityMetadataType::Rotation: return 8; + case EntityMetadataType::Position: return 9; + case EntityMetadataType::OptPosition: return 10; + case EntityMetadataType::Direction: return 11; + case EntityMetadataType::OptUUID: return 12; + case EntityMetadataType::OptBlockID: return 13; + case EntityMetadataType::NBT: return 14; + case EntityMetadataType::Particle: return 15; + case EntityMetadataType::VillagerData: return 16; + case EntityMetadataType::OptVarInt: return 17; + case EntityMetadataType::Pose: return 18; } - - ContiguousByteBuffer Data; - - // Read the plugin message and relay to clienthandle: - VERIFY(a_ByteBuffer.ReadSome(Data, a_ByteBuffer.GetReadableSpace())); // Always succeeds - m_Client->HandlePluginMessage(Channel, Data); -} - - - - - -void cProtocol_1_13::HandlePacketSetBeaconEffect(cByteBuffer & a_ByteBuffer) -{ - HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Effect1); - HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Effect2); - m_Client->HandleBeaconSelection(Effect1, Effect2); + UNREACHABLE("Translated invalid metadata type for protocol"); } -cProtocol::Version cProtocol_1_13::GetProtocolVersion() +std::pair<short, short> cProtocol_1_13::GetItemFromProtocolID(UInt32 a_ProtocolID) const { - return Version::v1_13; + return PaletteUpgrade::ToItem(Palette_1_13::ToItem(a_ProtocolID)); } -UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) +UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) const { switch (a_PacketType) { @@ -403,6 +476,15 @@ UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) +UInt32 cProtocol_1_13::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const +{ + return Palette_1_13::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); +} + + + + + signed char cProtocol_1_13::GetProtocolEntityStatus(const EntityAnimation a_Animation) const { switch (a_Animation) @@ -416,7 +498,16 @@ signed char cProtocol_1_13::GetProtocolEntityStatus(const EntityAnimation a_Anim -UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) +UInt32 cProtocol_1_13::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const +{ + return Palette_1_13::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); +} + + + + + +UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) const { switch (a_MobType) { @@ -488,207 +579,116 @@ UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) -UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) +UInt32 cProtocol_1_13::GetProtocolStatisticType(Statistic a_Statistic) const { - const UInt8 Entity = 6; - const UInt8 Living = Entity + 5; - const UInt8 Insentient = Living + 1; - const UInt8 Ageable = Insentient + 1; - const UInt8 AbstractHorse = Ageable + 2; - const UInt8 ChestedHorse = AbstractHorse + 1; - const UInt8 TameableAnimal = Ageable + 2; - const UInt8 Minecart = Entity + 6; - - switch (a_Metadata) - { - case EntityMetadata::EntityFlags: return 0; - case EntityMetadata::EntityAir: return 1; - case EntityMetadata::EntityCustomName: return 2; - case EntityMetadata::EntityCustomNameVisible: return 3; - case EntityMetadata::EntitySilent: return 4; - case EntityMetadata::EntityNoGravity: return 5; - case EntityMetadata::PotionThrown: return Entity; - case EntityMetadata::FallingBlockPosition: return Entity; - case EntityMetadata::AreaEffectCloudRadius: return Entity; - case EntityMetadata::AreaEffectCloudColor: return Entity + 1; - case EntityMetadata::AreaEffectCloudSinglePointEffect: return Entity + 2; - case EntityMetadata::AreaEffectCloudParticleId: return Entity + 3; - case EntityMetadata::ArrowFlags: return Entity; - case EntityMetadata::TippedArrowColor: return Entity + 1; - case EntityMetadata::BoatLastHitTime: return Entity; - case EntityMetadata::BoatForwardDirection: return Entity + 1; - case EntityMetadata::BoatDamageTaken: return Entity + 2; - case EntityMetadata::BoatType: return Entity + 3; - case EntityMetadata::BoatLeftPaddleTurning: return Entity + 4; - case EntityMetadata::BoatRightPaddleTurning: return Entity + 5; - case EntityMetadata::BoatSplashTimer: return Entity + 6; - case EntityMetadata::EnderCrystalBeamTarget: return Entity; - case EntityMetadata::EnderCrystalShowBottom: return Entity + 1; - case EntityMetadata::WitherSkullInvulnerable: return Entity; - case EntityMetadata::FireworkInfo: return Entity; - case EntityMetadata::FireworkBoostedEntityId: return Entity + 1; - case EntityMetadata::ItemFrameItem: return Entity; - case EntityMetadata::ItemFrameRotation: return Entity + 1; - case EntityMetadata::ItemItem: return Entity; - case EntityMetadata::LivingActiveHand: return Entity; - case EntityMetadata::LivingHealth: return Entity + 1; - case EntityMetadata::LivingPotionEffectColor: return Entity + 2; - case EntityMetadata::LivingPotionEffectAmbient: return Entity + 3; - case EntityMetadata::LivingNumberOfArrows: return Entity + 4; - case EntityMetadata::PlayerAdditionalHearts: return Living; - case EntityMetadata::PlayerScore: return Living + 1; - case EntityMetadata::PlayerDisplayedSkinParts: return Living + 2; - case EntityMetadata::PlayerMainHand: return Living + 3; - case EntityMetadata::ArmorStandStatus: return Living; - case EntityMetadata::ArmorStandHeadRotation: return Living + 1; - case EntityMetadata::ArmorStandBodyRotation: return Living + 2; - case EntityMetadata::ArmorStandLeftArmRotation: return Living + 3; - case EntityMetadata::ArmorStandRightArmRotation: return Living + 4; - case EntityMetadata::ArmorStandLeftLegRotation: return Living + 5; - case EntityMetadata::ArmorStandRightLegRotation: return Living + 6; - case EntityMetadata::InsentientFlags: return Living; - case EntityMetadata::BatHanging: return Insentient; - case EntityMetadata::AgeableIsBaby: return Insentient; - case EntityMetadata::AbstractHorseFlags: return Ageable; - case EntityMetadata::AbstractHorseOwner: return Ageable + 1; - case EntityMetadata::HorseVariant: return AbstractHorse; - case EntityMetadata::HorseArmour: return AbstractHorse + 1; - case EntityMetadata::ChestedHorseChested: return AbstractHorse; - case EntityMetadata::LlamaStrength: return ChestedHorse; - case EntityMetadata::LlamaCarpetColor: return ChestedHorse + 1; - case EntityMetadata::LlamaVariant: return ChestedHorse + 2; - case EntityMetadata::PigHasSaddle: return Ageable; - case EntityMetadata::PigTotalCarrotOnAStickBoost: return Ageable + 1; - case EntityMetadata::RabbitType: return Ageable; - case EntityMetadata::PolarBearStanding: return Ageable; - case EntityMetadata::SheepFlags: return Ageable; - case EntityMetadata::TameableAnimalFlags: return Ageable; - case EntityMetadata::TameableAnimalOwner: return Ageable + 1; - case EntityMetadata::OcelotType: return TameableAnimal; - case EntityMetadata::WolfDamageTaken: return TameableAnimal; - case EntityMetadata::WolfBegging: return TameableAnimal + 1; - case EntityMetadata::WolfCollarColour: return TameableAnimal + 2; - case EntityMetadata::VillagerProfession: return Ageable; - case EntityMetadata::IronGolemPlayerCreated: return Insentient; - case EntityMetadata::ShulkerFacingDirection: return Insentient; - case EntityMetadata::ShulkerAttachmentFallingBlockPosition: return Insentient + 1; - case EntityMetadata::ShulkerShieldHeight: return Insentient + 2; - case EntityMetadata::BlazeOnFire: return Insentient; - case EntityMetadata::CreeperState: return Insentient; - case EntityMetadata::CreeperPowered: return Insentient + 1; - case EntityMetadata::CreeperIgnited: return Insentient + 2; - case EntityMetadata::GuardianStatus: return Insentient; - case EntityMetadata::GuardianTarget: return Insentient + 1; - case EntityMetadata::IllagerFlags: return Insentient; - case EntityMetadata::SpeIlagerSpell: return Insentient + 1; - case EntityMetadata::VexFlags: return Insentient; - case EntityMetadata::SpiderClimbing: return Insentient; - case EntityMetadata::WitchAggresive: return Insentient; - case EntityMetadata::WitherFirstHeadTarget: return Insentient; - case EntityMetadata::WitherSecondHeadTarget: return Insentient + 1; - case EntityMetadata::WitherThirdHeadTarget: return Insentient + 2; - case EntityMetadata::WitherInvulnerableTimer: return Insentient + 3; - case EntityMetadata::ZombieIsBaby: return Insentient; - case EntityMetadata::ZombieHandsRisedUp: return Insentient + 2; - case EntityMetadata::ZombieVillagerConverting: return Insentient + 4; - case EntityMetadata::ZombieVillagerProfession: return Insentient + 5; - case EntityMetadata::EndermanCarriedBlock: return Insentient; - case EntityMetadata::EndermanScreaming: return Insentient + 1; - case EntityMetadata::EnderDragonDragonPhase: return Insentient; - case EntityMetadata::GhastAttacking: return Insentient; - case EntityMetadata::SlimeSize: return Insentient; - case EntityMetadata::MinecartShakingPower: return Entity; - case EntityMetadata::MinecartShakingDirection: return Entity + 1; - case EntityMetadata::MinecartShakingMultiplier: return Entity + 2; - case EntityMetadata::MinecartBlockIDMeta: return Entity + 3; - case EntityMetadata::MinecartBlockY: return Entity + 4; - case EntityMetadata::MinecartShowBlock: return Entity + 5; - case EntityMetadata::MinecartCommandBlockCommand: return Minecart; - case EntityMetadata::MinecartCommandBlockLastOutput: return Minecart + 1; - case EntityMetadata::MinecartFurnacePowered: return Minecart; - case EntityMetadata::TNTPrimedFuseTime: return Entity; - - case EntityMetadata::EntityPose: - case EntityMetadata::AreaEffectCloudParticleParameter1: - case EntityMetadata::AreaEffectCloudParticleParameter2: - case EntityMetadata::AbstractSkeletonArmsSwinging: - case EntityMetadata::ZombieUnusedWasType: break; - } - UNREACHABLE("Retrieved invalid metadata for protocol"); + return Palette_1_13::From(a_Statistic); } -UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadataType a_FieldType) +cProtocol::Version cProtocol_1_13::GetProtocolVersion() const { - switch (a_FieldType) - { - case EntityMetadataType::Byte: return 0; - case EntityMetadataType::VarInt: return 1; - case EntityMetadataType::Float: return 2; - case EntityMetadataType::String: return 3; - case EntityMetadataType::Chat: return 4; - case EntityMetadataType::OptChat: return 5; - case EntityMetadataType::Item: return 6; - case EntityMetadataType::Boolean: return 7; - case EntityMetadataType::Rotation: return 8; - case EntityMetadataType::Position: return 9; - case EntityMetadataType::OptPosition: return 10; - case EntityMetadataType::Direction: return 11; - case EntityMetadataType::OptUUID: return 12; - case EntityMetadataType::OptBlockID: return 13; - case EntityMetadataType::NBT: return 14; - case EntityMetadataType::Particle: return 15; - case EntityMetadataType::VillagerData: return 16; - case EntityMetadataType::OptVarInt: return 17; - case EntityMetadataType::Pose: return 18; - } - UNREACHABLE("Translated invalid metadata type for protocol"); + return Version::v1_13; } -std::pair<short, short> cProtocol_1_13::GetItemFromProtocolID(UInt32 a_ProtocolID) +bool cProtocol_1_13::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { - return PaletteUpgrade::ToItem(Palette_1_13::ToItem(a_ProtocolID)); + if (m_State != 3) + { + return Super::HandlePacket(a_ByteBuffer, a_PacketType); + } + + // Game + switch (a_PacketType) + { + case 0x00: HandleConfirmTeleport(a_ByteBuffer); return true; + case 0x05: HandlePacketTabComplete(a_ByteBuffer); return true; + case 0x02: HandlePacketChatMessage(a_ByteBuffer); return true; + case 0x03: HandlePacketClientStatus(a_ByteBuffer); return true; + case 0x04: HandlePacketClientSettings(a_ByteBuffer); return true; + case 0x06: break; // Confirm transaction - not used in Cuberite + case 0x07: HandlePacketEnchantItem(a_ByteBuffer); return true; + case 0x08: HandlePacketWindowClick(a_ByteBuffer); return true; + case 0x09: HandlePacketWindowClose(a_ByteBuffer); return true; + case 0x0a: HandlePacketPluginMessage(a_ByteBuffer); return true; + case 0x0d: HandlePacketUseEntity(a_ByteBuffer); return true; + case 0x0e: HandlePacketKeepAlive(a_ByteBuffer); return true; + case 0x0f: HandlePacketPlayer(a_ByteBuffer); return true; + case 0x10: HandlePacketPlayerPos(a_ByteBuffer); return true; + case 0x11: HandlePacketPlayerPosLook(a_ByteBuffer); return true; + case 0x12: HandlePacketPlayerLook(a_ByteBuffer); return true; + case 0x13: HandlePacketVehicleMove(a_ByteBuffer); return true; + case 0x14: HandlePacketBoatSteer(a_ByteBuffer); return true; + case 0x15: break; // Pick item - not yet implemented + case 0x16: break; // Craft Recipe Request - not yet implemented + case 0x17: HandlePacketPlayerAbilities(a_ByteBuffer); return true; + case 0x18: HandlePacketBlockDig(a_ByteBuffer); return true; + case 0x19: HandlePacketEntityAction(a_ByteBuffer); return true; + case 0x1a: HandlePacketSteerVehicle(a_ByteBuffer); return true; + case 0x1b: HandlePacketCraftingBookData(a_ByteBuffer); return true; + case 0x1d: break; // Resource pack status - not yet implemented + case 0x1e: HandlePacketAdvancementTab(a_ByteBuffer); return true; + case 0x20: HandlePacketSetBeaconEffect(a_ByteBuffer); return true; + case 0x21: HandlePacketSlotSelect(a_ByteBuffer); return true; + case 0x24: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; + case 0x26: HandlePacketUpdateSign(a_ByteBuffer); return true; + case 0x27: HandlePacketAnimation(a_ByteBuffer); return true; + case 0x28: HandlePacketSpectate(a_ByteBuffer); return true; + case 0x29: HandlePacketBlockPlace(a_ByteBuffer); return true; + case 0x2a: HandlePacketUseItem(a_ByteBuffer); return true; + } + + return Super::HandlePacket(a_ByteBuffer, a_PacketType); } -UInt32 cProtocol_1_13::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +void cProtocol_1_13::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { - return Palette_1_13::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); -} - + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); + // If the plugin channel is recognized vanilla, handle it directly: + if (Channel.substr(0, 15) == "minecraft:brand") + { + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Brand); + m_Client->SetClientBrand(Brand); + // Send back our brand, including the length: + m_Client->SendPluginMessage("minecraft:brand", "\x08""Cuberite"); + return; + } + ContiguousByteBuffer Data; -UInt32 cProtocol_1_13::GetProtocolItemType(short a_ItemID, short a_ItemDamage) -{ - return Palette_1_13::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); + // Read the plugin message and relay to clienthandle: + VERIFY(a_ByteBuffer.ReadSome(Data, a_ByteBuffer.GetReadableSpace())); // Always succeeds + m_Client->HandlePluginMessage(Channel, Data); } -UInt32 cProtocol_1_13::GetProtocolStatisticType(Statistic a_Statistic) +void cProtocol_1_13::HandlePacketSetBeaconEffect(cByteBuffer & a_ByteBuffer) { - return Palette_1_13::From(a_Statistic); + HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Effect1); + HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Effect2); + m_Client->HandleBeaconSelection(Effect1, Effect2); } -bool cProtocol_1_13::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) +bool cProtocol_1_13::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const { HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemID); if (ItemID == -1) @@ -724,35 +724,7 @@ bool cProtocol_1_13::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t -void cProtocol_1_13::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) -{ - short ItemType = a_Item.m_ItemType; - ASSERT(ItemType >= -1); // Check validity of packets in debug runtime - if (ItemType <= 0) - { - // Fix, to make sure no invalid values are sent. - ItemType = -1; - } - - if (a_Item.IsEmpty()) - { - a_Pkt.WriteBEInt16(-1); - return; - } - - // Normal item - a_Pkt.WriteBEInt16(static_cast<Int16>(GetProtocolItemType(a_Item.m_ItemType, a_Item.m_ItemDamage))); - a_Pkt.WriteBEInt8(a_Item.m_ItemCount); - - // TODO: NBT - a_Pkt.WriteBEInt8(0); -} - - - - - -void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const EntityMetadata a_Metadata, const EntityMetadataType a_FieldType) +void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const EntityMetadata a_Metadata, const EntityMetadataType a_FieldType) const { a_Pkt.WriteBEUInt8(GetEntityMetadataID(a_Metadata)); // Index a_Pkt.WriteBEUInt8(GetEntityMetadataID(a_FieldType)); // Type @@ -762,7 +734,7 @@ void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const EntityMetada -void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) +void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { // Common metadata: Int8 Flags = 0; @@ -809,7 +781,7 @@ void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetSkinParts())); WriteEntityMetadata(a_Pkt, EntityMetadata::PlayerMainHand, EntityMetadataType::Byte); - a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetMainHand())); + a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: @@ -953,7 +925,35 @@ void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ -void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) +void cProtocol_1_13::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const +{ + short ItemType = a_Item.m_ItemType; + ASSERT(ItemType >= -1); // Check validity of packets in debug runtime + if (ItemType <= 0) + { + // Fix, to make sure no invalid values are sent. + ItemType = -1; + } + + if (a_Item.IsEmpty()) + { + a_Pkt.WriteBEInt16(-1); + return; + } + + // Normal item + a_Pkt.WriteBEInt16(static_cast<Int16>(GetProtocolItemType(a_Item.m_ItemType, a_Item.m_ItemDamage))); + a_Pkt.WriteBEInt8(a_Item.m_ItemCount); + + // TODO: NBT + a_Pkt.WriteBEInt8(0); +} + + + + + +void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { // Living Enitiy Metadata if (a_Mob.HasCustomName()) @@ -1444,45 +1444,45 @@ void cProtocol_1_13_1::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSk -cProtocol::Version cProtocol_1_13_1::GetProtocolVersion() +std::pair<short, short> cProtocol_1_13_1::GetItemFromProtocolID(UInt32 a_ProtocolID) const { - return Version::v1_13_1; + return PaletteUpgrade::ToItem(Palette_1_13_1::ToItem(a_ProtocolID)); } -std::pair<short, short> cProtocol_1_13_1::GetItemFromProtocolID(UInt32 a_ProtocolID) +UInt32 cProtocol_1_13_1::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const { - return PaletteUpgrade::ToItem(Palette_1_13_1::ToItem(a_ProtocolID)); + return Palette_1_13_1::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } -UInt32 cProtocol_1_13_1::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +UInt32 cProtocol_1_13_1::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const { - return Palette_1_13_1::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); + return Palette_1_13_1::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); } -UInt32 cProtocol_1_13_1::GetProtocolItemType(short a_ItemID, short a_ItemDamage) +UInt32 cProtocol_1_13_1::GetProtocolStatisticType(Statistic a_Statistic) const { - return Palette_1_13_1::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); + return Palette_1_13_1::From(a_Statistic); } -UInt32 cProtocol_1_13_1::GetProtocolStatisticType(Statistic a_Statistic) +cProtocol::Version cProtocol_1_13_1::GetProtocolVersion() const { - return Palette_1_13_1::From(a_Statistic); + return Version::v1_13_1; } @@ -1492,7 +1492,7 @@ UInt32 cProtocol_1_13_1::GetProtocolStatisticType(Statistic a_Statistic) //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_13_2: -cProtocol::Version cProtocol_1_13_2::GetProtocolVersion() +cProtocol::Version cProtocol_1_13_2::GetProtocolVersion() const { return Version::v1_13_2; } @@ -1501,7 +1501,7 @@ cProtocol::Version cProtocol_1_13_2::GetProtocolVersion() -bool cProtocol_1_13_2::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) +bool cProtocol_1_13_2::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const { HANDLE_PACKET_READ(a_ByteBuffer, ReadBool, bool, Present); if (!Present) @@ -1538,7 +1538,7 @@ bool cProtocol_1_13_2::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size -void cProtocol_1_13_2::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) +void cProtocol_1_13_2::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const { short ItemType = a_Item.m_ItemType; ASSERT(ItemType >= -1); // Check validity of packets in debug runtime diff --git a/src/Protocol/Protocol_1_13.h b/src/Protocol/Protocol_1_13.h index 53de8bbc1..970625877 100644 --- a/src/Protocol/Protocol_1_13.h +++ b/src/Protocol/Protocol_1_13.h @@ -46,33 +46,26 @@ protected: virtual void SendTabCompletionResults (const AStringVector & a_Results) override; virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; - /** Translates outgoing packet types. */ - virtual UInt32 GetPacketID(ePacketType a_PacketType) override; - + virtual UInt8 GetEntityMetadataID(EntityMetadata a_Metadata) const; + virtual UInt8 GetEntityMetadataID(EntityMetadataType a_FieldType) const; + virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) const; + virtual UInt32 GetPacketID(ePacketType a_PacketType) const override; + virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; - - /** Returns 1.13. */ - virtual Version GetProtocolVersion() override; - - /** Converts eMonsterType to protocol-specific mob types */ - virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override; - - virtual UInt8 GetEntityMetadataID(EntityMetadata a_Metadata); - virtual UInt8 GetEntityMetadataID(EntityMetadataType a_FieldType); - virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID); - virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta); - virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage); - virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic); + virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const; + virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; + virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) const; + virtual Version GetProtocolVersion() const override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketSetBeaconEffect(cByteBuffer & a_ByteBuffer); - virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) override; - virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) override; - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, EntityMetadata a_Metadata, EntityMetadataType a_FieldType); - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override; + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const override; + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, EntityMetadata a_Metadata, EntityMetadataType a_FieldType) const; + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; + virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const override; + virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; @@ -93,11 +86,11 @@ 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<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) override; - virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) override; - virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) override; - virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) override; + virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) const override; + virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override; + virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override; + virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) const override; + virtual Version GetProtocolVersion() const override; }; @@ -115,7 +108,7 @@ public: protected: - virtual Version GetProtocolVersion() override; - virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) override; - virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) override; + virtual Version GetProtocolVersion() const override; + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const override; + virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const override; }; diff --git a/src/Protocol/Protocol_1_14.cpp b/src/Protocol/Protocol_1_14.cpp index 77918c7eb..f2bbdd955 100644 --- a/src/Protocol/Protocol_1_14.cpp +++ b/src/Protocol/Protocol_1_14.cpp @@ -131,7 +131,7 @@ void cProtocol_1_14::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, co -UInt32 cProtocol_1_14::GetPacketID(ePacketType a_PacketType) +UInt32 cProtocol_1_14::GetPacketID(ePacketType a_PacketType) const { switch (a_PacketType) { @@ -184,16 +184,7 @@ UInt32 cProtocol_1_14::GetPacketID(ePacketType a_PacketType) -cProtocol::Version cProtocol_1_14::GetProtocolVersion() -{ - return Version::v1_14; -} - - - - - -std::pair<short, short> cProtocol_1_14::GetItemFromProtocolID(UInt32 a_ProtocolID) +std::pair<short, short> cProtocol_1_14::GetItemFromProtocolID(UInt32 a_ProtocolID) const { return PaletteUpgrade::ToItem(Palette_1_14::ToItem(a_ProtocolID)); } @@ -202,7 +193,7 @@ std::pair<short, short> cProtocol_1_14::GetItemFromProtocolID(UInt32 a_ProtocolI -UInt32 cProtocol_1_14::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +UInt32 cProtocol_1_14::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const { return Palette_1_14::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } @@ -238,7 +229,7 @@ signed char cProtocol_1_14::GetProtocolEntityStatus(EntityAnimation a_Animation) -UInt32 cProtocol_1_14::GetProtocolItemType(short a_ItemID, short a_ItemDamage) +UInt32 cProtocol_1_14::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const { return Palette_1_14::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); } @@ -247,7 +238,7 @@ UInt32 cProtocol_1_14::GetProtocolItemType(short a_ItemID, short a_ItemDamage) -UInt32 cProtocol_1_14::GetProtocolStatisticType(Statistic a_Statistic) +UInt32 cProtocol_1_14::GetProtocolStatisticType(Statistic a_Statistic) const { return Palette_1_14::From(a_Statistic); } @@ -256,6 +247,15 @@ UInt32 cProtocol_1_14::GetProtocolStatisticType(Statistic a_Statistic) +cProtocol::Version cProtocol_1_14::GetProtocolVersion() const +{ + return Version::v1_14; +} + + + + + bool cProtocol_1_14::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { if (m_State != State::Game) diff --git a/src/Protocol/Protocol_1_14.h b/src/Protocol/Protocol_1_14.h index d1e5b5a4f..32ae6640e 100644 --- a/src/Protocol/Protocol_1_14.h +++ b/src/Protocol/Protocol_1_14.h @@ -40,19 +40,19 @@ protected: 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 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 UInt32 GetPacketID(ePacketType a_PacketType) const override; + virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) const override; + virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const 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; + virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override; + virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) const override; + virtual Version GetProtocolVersion() const override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) override; - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override {} - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override {} + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override {} + virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override {} }; diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index f815bbd29..4d15d8978 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -1004,10 +1004,6 @@ void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, Vector3 Pkt.WriteVarInt32(static_cast<UInt32>(a_Data[0])); break; } - default: - { - break; - } } } @@ -1832,7 +1828,27 @@ void cProtocol_1_8_0::CompressPacket(CircularBufferCompressor & a_Packet, Contig -UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType) +eBlockFace cProtocol_1_8_0::FaceIntToBlockFace(const Int32 a_BlockFace) +{ + // Normalize the blockface values returned from the protocol + // Anything known gets mapped 1:1, everything else returns BLOCK_FACE_NONE + switch (a_BlockFace) + { + case BLOCK_FACE_XM: return BLOCK_FACE_XM; + case BLOCK_FACE_XP: return BLOCK_FACE_XP; + case BLOCK_FACE_YM: return BLOCK_FACE_YM; + case BLOCK_FACE_YP: return BLOCK_FACE_YP; + case BLOCK_FACE_ZM: return BLOCK_FACE_ZM; + case BLOCK_FACE_ZP: return BLOCK_FACE_ZP; + default: return BLOCK_FACE_NONE; + } +} + + + + + +UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType) const { switch (a_PacketType) { @@ -1923,15 +1939,6 @@ UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType) -cProtocol::Version cProtocol_1_8_0::GetProtocolVersion() -{ - return Version::v1_8_0; -} - - - - - unsigned char cProtocol_1_8_0::GetProtocolEntityAnimation(const EntityAnimation a_Animation) const { switch (a_Animation) @@ -1990,7 +1997,7 @@ signed char cProtocol_1_8_0::GetProtocolEntityStatus(const EntityAnimation a_Ani -UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType) +UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { @@ -2048,6 +2055,15 @@ UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType) +cProtocol::Version cProtocol_1_8_0::GetProtocolVersion() const +{ + return Version::v1_8_0; +} + + + + + bool cProtocol_1_8_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { switch (m_State) @@ -2275,7 +2291,7 @@ void cProtocol_1_8_0::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) void cProtocol_1_8_0::HandlePacketAnimation(cByteBuffer & a_ByteBuffer) { - m_Client->HandleAnimation(0); // Packet exists solely for arm-swing notification + m_Client->HandleAnimation(true); // Packet exists solely for arm-swing notification (main hand). } @@ -2293,6 +2309,7 @@ void cProtocol_1_8_0::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) } HANDLE_READ(a_ByteBuffer, ReadBEInt8, Int8, Face); + m_Client->HandleLeftClick(BlockX, BlockY, BlockZ, FaceIntToBlockFace(Face), Status); } @@ -2316,14 +2333,15 @@ void cProtocol_1_8_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorX); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorZ); + eBlockFace blockFace = FaceIntToBlockFace(Face); if (blockFace == eBlockFace::BLOCK_FACE_NONE) { - m_Client->HandleUseItem(eHand::hMain); + m_Client->HandleUseItem(true); } else { - m_Client->HandleRightClick(BlockX, BlockY, BlockZ, blockFace, CursorX, CursorY, CursorZ, eHand::hMain); + m_Client->HandleRightClick(BlockX, BlockY, BlockZ, blockFace, CursorX, CursorY, CursorZ, true); } } @@ -2334,6 +2352,7 @@ void cProtocol_1_8_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) void cProtocol_1_8_0::HandlePacketChatMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Message); + m_Client->HandleChat(Message); } @@ -2362,6 +2381,7 @@ void cProtocol_1_8_0::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) void cProtocol_1_8_0::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ActionID); + switch (ActionID) { case 0: @@ -2394,6 +2414,7 @@ void cProtocol_1_8_0::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) void cProtocol_1_8_0::HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEInt16, Int16, SlotNum); + cItem Item; if (!ReadItem(a_ByteBuffer, Item)) { @@ -2436,6 +2457,7 @@ void cProtocol_1_8_0::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) void cProtocol_1_8_0::HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, KeepAliveID); + m_Client->HandleKeepAlive(KeepAliveID); } @@ -2478,6 +2500,7 @@ void cProtocol_1_8_0::HandlePacketPlayerLook(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + m_Client->HandlePlayerLook(Yaw, Pitch, IsOnGround); } @@ -2491,7 +2514,8 @@ void cProtocol_1_8_0::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); - m_Client->HandlePlayerPos(PosX, PosY, PosZ, IsOnGround); + + m_Client->HandlePlayerMove(PosX, PosY, PosZ, IsOnGround); } @@ -2506,6 +2530,7 @@ void cProtocol_1_8_0::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, Yaw, Pitch, IsOnGround); } @@ -2557,6 +2582,7 @@ void cProtocol_1_8_0::HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) void cProtocol_1_8_0::HandlePacketSlotSelect(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEInt16, Int16, SlotNum); + m_Client->HandleSlotSelected(SlotNum); } @@ -2633,6 +2659,7 @@ void cProtocol_1_8_0::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) for (int i = 0; i < 4; i++) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line); + if (JsonUtils::ParseString(Line, root) && root.isString()) { Lines[i] = root.asString(); @@ -2703,6 +2730,7 @@ void cProtocol_1_8_0::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Button); HANDLE_READ(a_ByteBuffer, ReadBEUInt16, UInt16, TransactionID); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Mode); + cItem Item; ReadItem(a_ByteBuffer, Item); @@ -2757,6 +2785,7 @@ void cProtocol_1_8_0::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) void cProtocol_1_8_0::HandlePacketWindowClose(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); + m_Client->HandleWindowClose(WindowID); } @@ -2769,6 +2798,7 @@ void cProtocol_1_8_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, con if (a_Channel == "MC|AdvCdm") { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Mode); + switch (Mode) { case 0x00: @@ -2777,6 +2807,7 @@ void cProtocol_1_8_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, con HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockY); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockZ); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Command); + m_Client->HandleCommandBlockBlockChange(BlockX, BlockY, BlockZ, Command); break; } @@ -2793,6 +2824,7 @@ void cProtocol_1_8_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, con else if (a_Channel == "MC|Brand") { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Brand); + m_Client->SetClientBrand(Brand); // Send back our brand, including the length: m_Client->SendPluginMessage("MC|Brand", "\x08""Cuberite"); @@ -2802,18 +2834,21 @@ void cProtocol_1_8_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, con { HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, Effect1); HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, Effect2); + m_Client->HandleBeaconSelection(Effect1, Effect2); return; } else if (a_Channel == "MC|ItemName") { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, ItemName); + m_Client->HandleAnvilItemName(ItemName); return; } else if (a_Channel == "MC|TrSel") { HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, SlotNum); + m_Client->HandleNPCTrade(SlotNum); return; } @@ -2829,67 +2864,7 @@ void cProtocol_1_8_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, con -void cProtocol_1_8_0::SendData(ContiguousByteBufferView a_Data) -{ - if (m_IsEncrypted) - { - std::byte Encrypted[8 KiB]; // Larger buffer, we may be sending lots of data (chunks) - - while (a_Data.size() > 0) - { - const auto NumBytes = (a_Data.size() > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Data.size(); - m_Encryptor.ProcessData(Encrypted, a_Data.data(), NumBytes); - m_Client->SendData({ Encrypted, NumBytes }); - - a_Data = a_Data.substr(NumBytes); - } - } - else - { - m_Client->SendData(a_Data); - } -} - - - - - -bool cProtocol_1_8_0::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) -{ - HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemType); - if (ItemType == -1) - { - // The item is empty, no more data follows - a_Item.Empty(); - return true; - } - a_Item.m_ItemType = ItemType; - - HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt8, Int8, ItemCount); - HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemDamage); - a_Item.m_ItemCount = ItemCount; - a_Item.m_ItemDamage = ItemDamage; - if (ItemCount <= 0) - { - a_Item.Empty(); - } - - ContiguousByteBuffer Metadata; - if (!a_ByteBuffer.ReadSome(Metadata, a_ByteBuffer.GetReadableSpace() - a_KeepRemainingBytes) || Metadata.empty() || (Metadata[0] == std::byte(0))) - { - // No metadata - return true; - } - - ParseItemMetadata(a_Item, Metadata); - return true; -} - - - - - -void cProtocol_1_8_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBufferView a_Metadata) +void cProtocol_1_8_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBufferView a_Metadata) const { // Parse into NBT: cParsedNBT NBT(a_Metadata); @@ -2962,50 +2937,98 @@ void cProtocol_1_8_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBuff -void cProtocol_1_8_0::StartEncryption(const Byte * a_Key) +bool cProtocol_1_8_0::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const { - m_Encryptor.Init(a_Key, a_Key); - m_Decryptor.Init(a_Key, a_Key); - m_IsEncrypted = true; + HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemType); - // Prepare the m_AuthServerID: - cSha1Checksum Checksum; - cServer * Server = cRoot::Get()->GetServer(); - const AString & ServerID = Server->GetServerID(); - Checksum.Update(reinterpret_cast<const Byte *>(ServerID.c_str()), ServerID.length()); - Checksum.Update(a_Key, 16); - Checksum.Update(reinterpret_cast<const Byte *>(Server->GetPublicKeyDER().data()), Server->GetPublicKeyDER().size()); - Byte Digest[20]; - Checksum.Finalize(Digest); - cSha1Checksum::DigestToJava(Digest, m_AuthServerID); + if (ItemType == -1) + { + // The item is empty, no more data follows + a_Item.Empty(); + return true; + } + a_Item.m_ItemType = ItemType; + + HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt8, Int8, ItemCount); + HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemDamage); + + a_Item.m_ItemCount = ItemCount; + a_Item.m_ItemDamage = ItemDamage; + if (ItemCount <= 0) + { + a_Item.Empty(); + } + + ContiguousByteBuffer Metadata; + if (!a_ByteBuffer.ReadSome(Metadata, a_ByteBuffer.GetReadableSpace() - a_KeepRemainingBytes) || Metadata.empty() || (Metadata[0] == std::byte(0))) + { + // No metadata + return true; + } + + ParseItemMetadata(a_Item, Metadata); + return true; } -eBlockFace cProtocol_1_8_0::FaceIntToBlockFace(const Int32 a_BlockFace) +void cProtocol_1_8_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) { - // Normalize the blockface values returned from the protocol - // Anything known gets mapped 1:1, everything else returns BLOCK_FACE_NONE - switch (a_BlockFace) + ASSERT(m_State == 3); // In game mode? + { - case BLOCK_FACE_XM: return BLOCK_FACE_XM; - case BLOCK_FACE_XP: return BLOCK_FACE_XP; - case BLOCK_FACE_YM: return BLOCK_FACE_YM; - case BLOCK_FACE_YP: return BLOCK_FACE_YP; - case BLOCK_FACE_ZM: return BLOCK_FACE_ZM; - case BLOCK_FACE_ZP: return BLOCK_FACE_ZP; - default: return BLOCK_FACE_NONE; + cPacketizer Pkt(*this, pktSpawnObject); + Pkt.WriteVarInt32(a_Entity.GetUniqueID()); + Pkt.WriteBEUInt8(a_ObjectType); + Pkt.WriteFPInt(a_Entity.GetPosX()); // Position appears to be ignored... + Pkt.WriteFPInt(a_Entity.GetPosY()); + Pkt.WriteFPInt(a_Entity.GetPosY()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteBEInt32(a_ObjectData); + + if (a_ObjectData != 0) + { + Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedX() * 400)); + Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedY() * 400)); + Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedZ() * 400)); + } } + + // Otherwise 1.8 clients don't show the entity + SendEntityTeleport(a_Entity); } -//////////////////////////////////////////////////////////////////////////////// -// cProtocol_1_8_0::cPacketizer: +void cProtocol_1_8_0::SendData(ContiguousByteBufferView a_Data) +{ + if (m_IsEncrypted) + { + std::byte Encrypted[8 KiB]; // Larger buffer, we may be sending lots of data (chunks) + + while (a_Data.size() > 0) + { + const auto NumBytes = (a_Data.size() > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Data.size(); + m_Encryptor.ProcessData(Encrypted, a_Data.data(), NumBytes); + m_Client->SendData({ Encrypted, NumBytes }); + + a_Data = a_Data.substr(NumBytes); + } + } + else + { + m_Client->SendData(a_Data); + } +} + + + + void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt) { @@ -3067,38 +3090,7 @@ void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt) -void cProtocol_1_8_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) -{ - ASSERT(m_State == 3); // In game mode? - - { - cPacketizer Pkt(*this, pktSpawnObject); - Pkt.WriteVarInt32(a_Entity.GetUniqueID()); - Pkt.WriteBEUInt8(a_ObjectType); - Pkt.WriteFPInt(a_Entity.GetPosX()); // Position appears to be ignored... - Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteBEInt32(a_ObjectData); - - if (a_ObjectData != 0) - { - Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedX() * 400)); - Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedY() * 400)); - Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedZ() * 400)); - } - } - - // Otherwise 1.8 clients don't show the entity - SendEntityTeleport(a_Entity); -} - - - - - -void cProtocol_1_8_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) +void cProtocol_1_8_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const { a_Writer.AddInt("x", a_BlockEntity.GetPosX()); a_Writer.AddInt("y", a_BlockEntity.GetPosY()); @@ -3205,89 +3197,7 @@ void cProtocol_1_8_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEn -void cProtocol_1_8_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) -{ - short ItemType = a_Item.m_ItemType; - ASSERT(ItemType >= -1); // Check validity of packets in debug runtime - if (ItemType <= 0) - { - // Fix, to make sure no invalid values are sent. - ItemType = -1; - } - - if (a_Item.IsEmpty()) - { - a_Pkt.WriteBEInt16(-1); - return; - } - - a_Pkt.WriteBEInt16(ItemType); - a_Pkt.WriteBEInt8(a_Item.m_ItemCount); - a_Pkt.WriteBEInt16(a_Item.m_ItemDamage); - - if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid()) - { - a_Pkt.WriteBEInt8(0); - return; - } - - - // Send the enchantments and custom names: - cFastNBTWriter Writer; - if (a_Item.m_RepairCost != 0) - { - Writer.AddInt("RepairCost", a_Item.m_RepairCost); - } - if (!a_Item.m_Enchantments.IsEmpty()) - { - const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); - } - if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid()) - { - Writer.BeginCompound("display"); - if (a_Item.m_ItemColor.IsValid()) - { - Writer.AddInt("color", static_cast<Int32>(a_Item.m_ItemColor.m_Color)); - } - - if (!a_Item.IsCustomNameEmpty()) - { - Writer.AddString("Name", a_Item.m_CustomName); - } - if (!a_Item.IsLoreEmpty()) - { - Writer.BeginList("Lore", TAG_String); - - for (const auto & Line : a_Item.m_LoreTable) - { - Writer.AddString("", Line); - } - - Writer.EndList(); - } - Writer.EndCompound(); - } - if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) - { - cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast<ENUM_ITEM_TYPE>(a_Item.m_ItemType)); - } - Writer.Finish(); - - const auto Result = Writer.GetResult(); - if (Result.empty()) - { - a_Pkt.WriteBEInt8(0); - return; - } - a_Pkt.WriteBuf(Result); -} - - - - - -void cProtocol_1_8_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) +void cProtocol_1_8_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { // Common metadata: Byte Flags = 0; @@ -3438,7 +3348,129 @@ void cProtocol_1_8_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a -void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) +void cProtocol_1_8_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity) const +{ + if (a_Entity.IsPlayer()) + { + const auto & Player = static_cast<const cPlayer &>(a_Entity); + + a_Pkt.WriteBEInt32(1); // Count. + a_Pkt.WriteString("generic.movementSpeed"); + a_Pkt.WriteBEDouble(0.1 * Player.GetNormalMaxSpeed()); // The default game speed is 0.1, multiply that value by the relative speed. + + // It seems the modifiers aren't conditionally activated; their effects are applied immediately! + // We have to keep on re-sending this packet when the client notifies us of sprint start and end, and so on. Strange. + + if (Player.IsSprinting()) + { + a_Pkt.WriteVarInt32(1); // Modifier count. + a_Pkt.WriteBEUInt64(0x662a6b8dda3e4c1c); + a_Pkt.WriteBEUInt64(0x881396ea6097278d); // UUID of the modifier (sprinting speed boost). + a_Pkt.WriteBEDouble(Player.GetSprintingMaxSpeed() - Player.GetNormalMaxSpeed()); + a_Pkt.WriteBEUInt8(2); + } + else + { + a_Pkt.WriteVarInt32(0); + } + } + else + { + // const cMonster & Mob = (const cMonster &)a_Entity; + + // TODO: Send properties and modifiers based on the mob type + + a_Pkt.WriteBEInt32(0); + } +} + + + + + +void cProtocol_1_8_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const +{ + short ItemType = a_Item.m_ItemType; + ASSERT(ItemType >= -1); // Check validity of packets in debug runtime + if (ItemType <= 0) + { + // Fix, to make sure no invalid values are sent. + ItemType = -1; + } + + if (a_Item.IsEmpty()) + { + a_Pkt.WriteBEInt16(-1); + return; + } + + a_Pkt.WriteBEInt16(ItemType); + a_Pkt.WriteBEInt8(a_Item.m_ItemCount); + a_Pkt.WriteBEInt16(a_Item.m_ItemDamage); + + if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid()) + { + a_Pkt.WriteBEInt8(0); + return; + } + + + // Send the enchantments and custom names: + cFastNBTWriter Writer; + if (a_Item.m_RepairCost != 0) + { + Writer.AddInt("RepairCost", a_Item.m_RepairCost); + } + if (!a_Item.m_Enchantments.IsEmpty()) + { + const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; + EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); + } + if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid()) + { + Writer.BeginCompound("display"); + if (a_Item.m_ItemColor.IsValid()) + { + Writer.AddInt("color", static_cast<Int32>(a_Item.m_ItemColor.m_Color)); + } + + if (!a_Item.IsCustomNameEmpty()) + { + Writer.AddString("Name", a_Item.m_CustomName); + } + if (!a_Item.IsLoreEmpty()) + { + Writer.BeginList("Lore", TAG_String); + + for (const auto & Line : a_Item.m_LoreTable) + { + Writer.AddString("", Line); + } + + Writer.EndList(); + } + Writer.EndCompound(); + } + if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) + { + cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast<ENUM_ITEM_TYPE>(a_Item.m_ItemType)); + } + Writer.Finish(); + + const auto Result = Writer.GetResult(); + if (Result.empty()) + { + a_Pkt.WriteBEInt8(0); + return; + } + a_Pkt.WriteBuf(Result); +} + + + + + +void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { // Living Enitiy Metadata if (a_Mob.HasCustomName()) @@ -3764,46 +3796,6 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M -void cProtocol_1_8_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity) -{ - if (a_Entity.IsPlayer()) - { - const auto & Player = static_cast<const cPlayer &>(a_Entity); - - a_Pkt.WriteBEInt32(1); // Count. - a_Pkt.WriteString("generic.movementSpeed"); - a_Pkt.WriteBEDouble(0.1 * Player.GetNormalMaxSpeed()); // The default game speed is 0.1, multiply that value by the relative speed. - - // It seems the modifiers aren't conditionally activated; their effects are applied immediately! - // We have to keep on re-sending this packet when the client notifies us of sprint start and end, and so on. Strange. - - if (Player.IsSprinting()) - { - a_Pkt.WriteVarInt32(1); // Modifier count. - a_Pkt.WriteBEUInt64(0x662a6b8dda3e4c1c); - a_Pkt.WriteBEUInt64(0x881396ea6097278d); // UUID of the modifier (sprinting speed boost). - a_Pkt.WriteBEDouble(Player.GetSprintingMaxSpeed() - Player.GetNormalMaxSpeed()); - a_Pkt.WriteBEUInt8(2); - } - else - { - a_Pkt.WriteVarInt32(0); - } - } - else - { - // const cMonster & Mob = (const cMonster &)a_Entity; - - // TODO: Send properties and modifiers based on the mob type - - a_Pkt.WriteBEInt32(0); - } -} - - - - - void cProtocol_1_8_0::AddReceivedData(cByteBuffer & a_Buffer, const ContiguousByteBufferView a_Data) { // Write the incoming data into the comm log file: @@ -3921,98 +3913,6 @@ void cProtocol_1_8_0::AddReceivedData(cByteBuffer & a_Buffer, const ContiguousBy -void cProtocol_1_8_0::HandlePacket(cByteBuffer & a_Buffer) -{ - UInt32 PacketType; - if (!a_Buffer.ReadVarInt(PacketType)) - { - // Not enough data - return; - } - - // Log the packet info into the comm log file: - if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) - { - ContiguousByteBuffer PacketData; - a_Buffer.ReadAll(PacketData); - a_Buffer.ResetRead(); - a_Buffer.ReadVarInt(PacketType); // We have already read the packet type once, it will be there again - ASSERT(PacketData.size() > 0); // We have written an extra NUL, so there had to be at least one byte read - PacketData.resize(PacketData.size() - 1); - AString PacketDataHex; - CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16); - m_CommLogFile.Printf("Next incoming packet is type %u (0x%x), length %u (0x%x) at state %d. Payload:\n%s\n", - PacketType, PacketType, a_Buffer.GetUsedSpace(), a_Buffer.GetUsedSpace(), m_State, PacketDataHex.c_str() - ); - } - - if (!HandlePacket(a_Buffer, PacketType)) - { - // Unknown packet, already been reported, but without the length. Log the length here: - LOGWARNING("Unhandled packet: type 0x%x, state %d, length %u", PacketType, m_State, a_Buffer.GetUsedSpace()); - -#ifndef NDEBUG - // Dump the packet contents into the log: - a_Buffer.ResetRead(); - ContiguousByteBuffer Packet; - a_Buffer.ReadAll(Packet); - Packet.resize(Packet.size() - 1); // Drop the final NUL pushed there for over-read detection - AString Out; - CreateHexDump(Out, Packet.data(), Packet.size(), 24); - LOGD("Packet contents:\n%s", Out.c_str()); -#endif // !NDEBUG - - // Put a message in the comm log: - if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) - { - m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n"); - } - - return; - } - - // The packet should have nothing left in the buffer: - if (a_Buffer.GetReadableSpace() != 0) - { - // Read more or less than packet length, report as error - LOGWARNING("Protocol 1.8: Wrong number of bytes read for packet 0x%x, state %d. Read %zu bytes, packet contained %u bytes", - PacketType, m_State, a_Buffer.GetUsedSpace() - a_Buffer.GetReadableSpace(), a_Buffer.GetUsedSpace() - ); - - // Put a message in the comm log: - if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) - { - m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got %zu left) ^^^^^^\n\n\n", - 1, a_Buffer.GetReadableSpace() - ); - m_CommLogFile.Flush(); - } - - ASSERT(!"Read wrong number of bytes!"); - m_Client->PacketError(PacketType); - } -} - - - - - -void cProtocol_1_8_0::SendEntityTeleport(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, pktTeleportEntity); - Pkt.WriteVarInt32(a_Entity.GetUniqueID()); - Pkt.WriteFPInt(a_Entity.GetPosX()); - Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteFPInt(a_Entity.GetPosZ()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(a_Entity.IsOnGround()); -} - - - - - UInt8 cProtocol_1_8_0::GetProtocolEntityType(const cEntity & a_Entity) { using Type = cEntity::eEntityType; @@ -4230,3 +4130,117 @@ const char * cProtocol_1_8_0::GetProtocolStatisticName(Statistic a_Statistic) default: return ""; } } + + + + + +void cProtocol_1_8_0::HandlePacket(cByteBuffer & a_Buffer) +{ + UInt32 PacketType; + if (!a_Buffer.ReadVarInt(PacketType)) + { + // Not enough data + return; + } + + // Log the packet info into the comm log file: + if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) + { + ContiguousByteBuffer PacketData; + a_Buffer.ReadAll(PacketData); + a_Buffer.ResetRead(); + a_Buffer.ReadVarInt(PacketType); // We have already read the packet type once, it will be there again + ASSERT(PacketData.size() > 0); // We have written an extra NUL, so there had to be at least one byte read + PacketData.resize(PacketData.size() - 1); + AString PacketDataHex; + CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16); + m_CommLogFile.Printf("Next incoming packet is type %u (0x%x), length %u (0x%x) at state %d. Payload:\n%s\n", + PacketType, PacketType, a_Buffer.GetUsedSpace(), a_Buffer.GetUsedSpace(), m_State, PacketDataHex.c_str() + ); + } + + if (!HandlePacket(a_Buffer, PacketType)) + { + // Unknown packet, already been reported, but without the length. Log the length here: + LOGWARNING("Unhandled packet: type 0x%x, state %d, length %u", PacketType, m_State, a_Buffer.GetUsedSpace()); + +#ifndef NDEBUG + // Dump the packet contents into the log: + a_Buffer.ResetRead(); + ContiguousByteBuffer Packet; + a_Buffer.ReadAll(Packet); + Packet.resize(Packet.size() - 1); // Drop the final NUL pushed there for over-read detection + AString Out; + CreateHexDump(Out, Packet.data(), Packet.size(), 24); + LOGD("Packet contents:\n%s", Out.c_str()); +#endif // !NDEBUG + + // Put a message in the comm log: + if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) + { + m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n"); + } + + return; + } + + // The packet should have nothing left in the buffer: + if (a_Buffer.GetReadableSpace() != 0) + { + // Read more or less than packet length, report as error + LOGWARNING("Protocol 1.8: Wrong number of bytes read for packet 0x%x, state %d. Read %zu bytes, packet contained %u bytes", + PacketType, m_State, a_Buffer.GetUsedSpace() - a_Buffer.GetReadableSpace(), a_Buffer.GetUsedSpace() + ); + + // Put a message in the comm log: + if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) + { + m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got %zu left) ^^^^^^\n\n\n", + 1, a_Buffer.GetReadableSpace() + ); + m_CommLogFile.Flush(); + } + + ASSERT(!"Read wrong number of bytes!"); + m_Client->PacketError(PacketType); + } +} + + + + + +void cProtocol_1_8_0::SendEntityTeleport(const cEntity & a_Entity) +{ + cPacketizer Pkt(*this, pktTeleportEntity); + Pkt.WriteVarInt32(a_Entity.GetUniqueID()); + Pkt.WriteFPInt(a_Entity.GetPosX()); + Pkt.WriteFPInt(a_Entity.GetPosY()); + Pkt.WriteFPInt(a_Entity.GetPosZ()); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(a_Entity.IsOnGround()); +} + + + + + +void cProtocol_1_8_0::StartEncryption(const Byte * a_Key) +{ + m_Encryptor.Init(a_Key, a_Key); + m_Decryptor.Init(a_Key, a_Key); + m_IsEncrypted = true; + + // Prepare the m_AuthServerID: + cSha1Checksum Checksum; + cServer * Server = cRoot::Get()->GetServer(); + const AString & ServerID = Server->GetServerID(); + Checksum.Update(reinterpret_cast<const Byte *>(ServerID.c_str()), ServerID.length()); + Checksum.Update(a_Key, 16); + Checksum.Update(reinterpret_cast<const Byte *>(Server->GetPublicKeyDER().data()), Server->GetPublicKeyDER().size()); + Byte Digest[20]; + Checksum.Finalize(Digest); + cSha1Checksum::DigestToJava(Digest, m_AuthServerID); +} diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index d4aa0c899..652ef69c5 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -141,11 +141,12 @@ protected: /** State of the protocol. */ State m_State; - /** Get the packet ID for a given packet. */ - virtual UInt32 GetPacketID(ePacketType a_Packet) override; + /** Converts the BlockFace received by the protocol into eBlockFace constants. + If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */ + static eBlockFace FaceIntToBlockFace(Int32 a_FaceInt); - /** Returns 1.8. */ - virtual Version GetProtocolVersion() override; + /** Get the packet ID for a given packet. */ + virtual UInt32 GetPacketID(ePacketType a_Packet) const 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. */ @@ -156,7 +157,10 @@ protected: virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const; /** Converts eMonsterType to protocol-specific mob types */ - virtual UInt32 GetProtocolMobType(eMonsterType a_MobType); + virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const; + + /** Returns the protocol version. */ + virtual Version GetProtocolVersion() const override; /** 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. */ @@ -201,43 +205,37 @@ protected: The message payload is still in the bytebuffer, the handler reads it specifically for each handled channel */ virtual void HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const AString & a_Channel); - /** Sends the data to the client, encrypting them if needed. */ - virtual void SendData(ContiguousByteBufferView a_Size) override; - - /** Sends the packet to the client. Called by the cPacketizer's destructor. */ - virtual void SendPacket(cPacketizer & a_Packet) override; + /** Parses item metadata as read by ReadItem(), into the item enchantments. */ + virtual void ParseItemMetadata(cItem & a_Item, ContiguousByteBufferView a_Metadata) const; /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data. a_KeepRemainingBytes tells the function to keep that many bytes at the end of the buffer. */ - virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes = 0); - - /** Parses item metadata as read by ReadItem(), into the item enchantments. */ - virtual void ParseItemMetadata(cItem & a_Item, ContiguousByteBufferView a_Metadata); - - virtual void StartEncryption(const Byte * a_Key); - - /** Converts the BlockFace received by the protocol into eBlockFace constants. - If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */ - static eBlockFace FaceIntToBlockFace(Int32 a_FaceInt); + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes = 0) const; /** Sends the entity type and entity-dependent data required for the entity to initially spawn. */ virtual void SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData); - /** Writes the block entity data for the specified block entity into the packet. */ - virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity); + /** Sends the data to the client, encrypting them if needed. */ + virtual void SendData(ContiguousByteBufferView a_Size) override; - /** Writes the item data into a packet. */ - virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item); + /** Sends the packet to the client. Called by the cPacketizer's destructor. */ + virtual void SendPacket(cPacketizer & a_Packet) override; - /** Writes the metadata for the specified entity, not including the terminating 0x7f. */ - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity); + /** Writes the block entity data for the specified block entity into the packet. */ + virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const; - /** Writes the mob-specific metadata for the specified mob */ - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob); + /** Writes the metadata for the specified entity, not including the terminating 0x7f. */ + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const; /** Writes the entity properties for the specified entity, including the Count field. */ - virtual void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity); + virtual void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity) const; + + /** Writes the item data into a packet. */ + virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const; + + /** Writes the mob-specific metadata for the specified mob */ + virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const; private: @@ -259,14 +257,6 @@ private: /** Adds the received (unencrypted) data to m_ReceivedData, parses complete packets */ void AddReceivedData(cByteBuffer & a_Buffer, ContiguousByteBufferView a_Data); - /** Handle a complete packet stored in the given buffer. */ - void HandlePacket(cByteBuffer & a_Buffer); - - /** Sends an entity teleport packet. - Mitigates a 1.8 bug where the position in the entity spawn packet is ignored, - and so entities don't show up until a teleport is sent. */ - void SendEntityTeleport(const cEntity & a_Entity); - /** Converts an entity to a protocol-specific entity type. Only entities that the Send Spawn Entity packet supports are valid inputs to this method */ static UInt8 GetProtocolEntityType(const cEntity & a_Entity); @@ -278,4 +268,14 @@ private: 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. */ static const char * GetProtocolStatisticName(Statistic a_Statistic); + + /** Handle a complete packet stored in the given buffer. */ + void HandlePacket(cByteBuffer & a_Buffer); + + /** Sends an entity teleport packet. + Mitigates a 1.8 bug where the position in the entity spawn packet is ignored, + and so entities don't show up until a teleport is sent. */ + void SendEntityTeleport(const cEntity & a_Entity); + + void StartEncryption(const Byte * a_Key); } ; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 6b240b235..e6f774bdf 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -51,9 +51,11 @@ Implements the 1.9 protocol classes: -/** Value for main hand in Hand parameter for Protocol 1.9. */ -static const UInt32 MAIN_HAND = 0; -static const UInt32 OFF_HAND = 1; +// Value for main hand in Hand parameter for Protocol 1.9. +#define MAIN_HAND 0 + +// Value for left hand in MainHand parameter for Protocol 1.9. +#define LEFT_HAND 0 @@ -602,7 +604,7 @@ void cProtocol_1_9_0::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) -UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet) +UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet) const { switch (a_Packet) { @@ -726,22 +728,22 @@ signed char cProtocol_1_9_0::GetProtocolEntityStatus(const EntityAnimation a_Ani -cProtocol::Version cProtocol_1_9_0::GetProtocolVersion() +UInt32 cProtocol_1_9_0::GetProtocolMobType(const eMonsterType a_MobType) const { - return Version::v1_9_0; + switch (a_MobType) + { + case mtShulker: return 69; + default: return Super::GetProtocolMobType(a_MobType); + } } -UInt32 cProtocol_1_9_0::GetProtocolMobType(const eMonsterType a_MobType) +cProtocol::Version cProtocol_1_9_0::GetProtocolVersion() const { - switch (a_MobType) - { - case mtShulker: return 69; - default: return Super::GetProtocolMobType(a_MobType); - } + return Version::v1_9_0; } @@ -824,7 +826,7 @@ void cProtocol_1_9_0::HandlePacketAnimation(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand); - m_Client->HandleAnimation(0); // Packet exists solely for arm-swing notification + m_Client->HandleAnimation(Hand == MAIN_HAND); // Packet exists solely for arm-swing notification (main and off-hand). } @@ -862,7 +864,8 @@ void cProtocol_1_9_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorX); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorZ); - m_Client->HandleRightClick(BlockX, BlockY, BlockZ, FaceIntToBlockFace(Face), CursorX, CursorY, CursorZ, HandIntToEnum(Hand)); + + m_Client->HandleRightClick(BlockX, BlockY, BlockZ, FaceIntToBlockFace(Face), CursorX, CursorY, CursorZ, Hand == MAIN_HAND); } @@ -899,12 +902,12 @@ void cProtocol_1_9_0::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ChatFlags); HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinParts); - HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, MainHand); + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, MainHand); m_Client->SetLocale(Locale); m_Client->SetViewDistance(ViewDistance); m_Client->GetPlayer()->SetSkinParts(SkinParts); - m_Client->GetPlayer()->SetMainHand(static_cast<eMainHand>(MainHand)); + m_Client->GetPlayer()->SetLeftHanded(MainHand == LEFT_HAND); // TODO: Handle chat flags and chat colors } @@ -964,7 +967,7 @@ void cProtocol_1_9_0::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) if (m_IsTeleportIdConfirmed) { - m_Client->HandlePlayerPos(PosX, PosY, PosZ, IsOnGround); + m_Client->HandlePlayerMove(PosX, PosY, PosZ, IsOnGround); } } @@ -1065,6 +1068,7 @@ void cProtocol_1_9_0::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) case 0: { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Hand); + if (Hand == MAIN_HAND) // TODO: implement handling of off-hand actions; ignore them for now to avoid processing actions twice { m_Client->HandleUseEntity(EntityID, false); @@ -1102,7 +1106,7 @@ void cProtocol_1_9_0::HandlePacketUseItem(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand); - m_Client->HandleUseItem(HandIntToEnum(Hand)); + m_Client->HandleUseItem(Hand == MAIN_HAND); } @@ -1193,7 +1197,7 @@ void cProtocol_1_9_0::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) -void cProtocol_1_9_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBufferView a_Metadata) +void cProtocol_1_9_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBufferView a_Metadata) const { // Parse into NBT: cParsedNBT NBT(a_Metadata); @@ -1397,25 +1401,6 @@ void cProtocol_1_9_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBuff -eHand cProtocol_1_9_0::HandIntToEnum(Int32 a_Hand) -{ - // Convert hand parameter into eHand enum - switch (a_Hand) - { - case MAIN_HAND: return eHand::hMain; - case OFF_HAND: return eHand::hOff; - default: - { - ASSERT(!"Unknown hand value"); - return eHand::hMain; - } - } -} - - - - - void cProtocol_1_9_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) { ASSERT(m_State == 3); // In game mode? @@ -1443,7 +1428,7 @@ void cProtocol_1_9_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_Ob -void cProtocol_1_9_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) +void cProtocol_1_9_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const { a_Writer.AddInt("x", a_BlockEntity.GetPosX()); a_Writer.AddInt("y", a_BlockEntity.GetPosY()); @@ -1467,177 +1452,7 @@ void cProtocol_1_9_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEn -void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) -{ - short ItemType = a_Item.m_ItemType; - ASSERT(ItemType >= -1); // Check validity of packets in debug runtime - if (ItemType <= 0) - { - // Fix, to make sure no invalid values are sent. - ItemType = -1; - } - - if (a_Item.IsEmpty()) - { - a_Pkt.WriteBEInt16(-1); - return; - } - - if ((ItemType == E_ITEM_POTION) && ((a_Item.m_ItemDamage & 0x4000) != 0)) - { - // Ugly special case for splash potion ids which changed in 1.9; this can be removed when the new 1.9 ids are implemented - a_Pkt.WriteBEInt16(438); // minecraft:splash_potion - } - else - { - // Normal item - a_Pkt.WriteBEInt16(ItemType); - } - a_Pkt.WriteBEInt8(a_Item.m_ItemCount); - if ((ItemType == E_ITEM_POTION) || (ItemType == E_ITEM_SPAWN_EGG)) - { - // These items lost their metadata; if it is sent they don't render correctly. - a_Pkt.WriteBEInt16(0); - } - else - { - a_Pkt.WriteBEInt16(a_Item.m_ItemDamage); - } - - if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (ItemType != E_ITEM_FIREWORK_ROCKET) && (ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid() && (ItemType != E_ITEM_POTION) && (ItemType != E_ITEM_SPAWN_EGG)) - { - a_Pkt.WriteBEInt8(0); - return; - } - - - // Send the enchantments and custom names: - cFastNBTWriter Writer; - if (a_Item.m_RepairCost != 0) - { - Writer.AddInt("RepairCost", a_Item.m_RepairCost); - } - if (!a_Item.m_Enchantments.IsEmpty()) - { - const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); - } - if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid()) - { - Writer.BeginCompound("display"); - if (a_Item.m_ItemColor.IsValid()) - { - Writer.AddInt("color", static_cast<Int32>(a_Item.m_ItemColor.m_Color)); - } - - if (!a_Item.IsCustomNameEmpty()) - { - Writer.AddString("Name", a_Item.m_CustomName); - } - if (!a_Item.IsLoreEmpty()) - { - Writer.BeginList("Lore", TAG_String); - - for (const auto & Line : a_Item.m_LoreTable) - { - Writer.AddString("", Line); - } - - Writer.EndList(); - } - Writer.EndCompound(); - } - if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) - { - cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast<ENUM_ITEM_TYPE>(a_Item.m_ItemType)); - } - if (a_Item.m_ItemType == E_ITEM_POTION) - { - // 1.9 potions use a different format. In the future (when only 1.9+ is supported) this should be its own class - AString PotionID = "empty"; // Fallback of "Uncraftable potion" for unhandled cases - - cEntityEffect::eType Type = cEntityEffect::GetPotionEffectType(a_Item.m_ItemDamage); - if (Type != cEntityEffect::effNoEffect) - { - switch (Type) - { - case cEntityEffect::effRegeneration: PotionID = "regeneration"; break; - case cEntityEffect::effSpeed: PotionID = "swiftness"; break; - case cEntityEffect::effFireResistance: PotionID = "fire_resistance"; break; - case cEntityEffect::effPoison: PotionID = "poison"; break; - case cEntityEffect::effInstantHealth: PotionID = "healing"; break; - case cEntityEffect::effNightVision: PotionID = "night_vision"; break; - case cEntityEffect::effWeakness: PotionID = "weakness"; break; - case cEntityEffect::effStrength: PotionID = "strength"; break; - case cEntityEffect::effSlowness: PotionID = "slowness"; break; - case cEntityEffect::effJumpBoost: PotionID = "leaping"; break; - case cEntityEffect::effInstantDamage: PotionID = "harming"; break; - case cEntityEffect::effWaterBreathing: PotionID = "water_breathing"; break; - case cEntityEffect::effInvisibility: PotionID = "invisibility"; break; - default: ASSERT(!"Unknown potion effect"); break; - } - if (cEntityEffect::GetPotionEffectIntensity(a_Item.m_ItemDamage) == 1) - { - PotionID = "strong_" + PotionID; - } - else if (a_Item.m_ItemDamage & 0x40) - { - // Extended potion bit - PotionID = "long_" + PotionID; - } - } - else - { - // Empty potions: Water bottles and other base ones - if (a_Item.m_ItemDamage == 0) - { - // No other bits set; thus it's a water bottle - PotionID = "water"; - } - else - { - switch (a_Item.m_ItemDamage & 0x3f) - { - case 0x00: PotionID = "mundane"; break; - case 0x10: PotionID = "awkward"; break; - case 0x20: PotionID = "thick"; break; - } - // Default cases will use "empty" from before. - } - } - - PotionID = "minecraft:" + PotionID; - - Writer.AddString("Potion", PotionID); - } - if (a_Item.m_ItemType == E_ITEM_SPAWN_EGG) - { - // Convert entity ID to the name. - eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(a_Item.m_ItemDamage); - if (MonsterType != eMonsterType::mtInvalidType) - { - Writer.BeginCompound("EntityTag"); - Writer.AddString("id", "minecraft:" + cMonster::MobTypeToVanillaNBT(MonsterType)); - Writer.EndCompound(); - } - } - - Writer.Finish(); - - const auto Result = Writer.GetResult(); - if (Result.empty()) - { - a_Pkt.WriteBEInt8(0); - return; - } - a_Pkt.WriteBuf(Result); -} - - - - - -void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) +void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { // Common metadata: Int8 Flags = 0; @@ -1692,7 +1507,7 @@ void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a a_Pkt.WriteBEUInt8(13); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); - a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetMainHand())); + a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: @@ -1859,7 +1674,177 @@ void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a -void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) +void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const +{ + short ItemType = a_Item.m_ItemType; + ASSERT(ItemType >= -1); // Check validity of packets in debug runtime + if (ItemType <= 0) + { + // Fix, to make sure no invalid values are sent. + ItemType = -1; + } + + if (a_Item.IsEmpty()) + { + a_Pkt.WriteBEInt16(-1); + return; + } + + if ((ItemType == E_ITEM_POTION) && ((a_Item.m_ItemDamage & 0x4000) != 0)) + { + // Ugly special case for splash potion ids which changed in 1.9; this can be removed when the new 1.9 ids are implemented + a_Pkt.WriteBEInt16(438); // minecraft:splash_potion + } + else + { + // Normal item + a_Pkt.WriteBEInt16(ItemType); + } + a_Pkt.WriteBEInt8(a_Item.m_ItemCount); + if ((ItemType == E_ITEM_POTION) || (ItemType == E_ITEM_SPAWN_EGG)) + { + // These items lost their metadata; if it is sent they don't render correctly. + a_Pkt.WriteBEInt16(0); + } + else + { + a_Pkt.WriteBEInt16(a_Item.m_ItemDamage); + } + + if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (ItemType != E_ITEM_FIREWORK_ROCKET) && (ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid() && (ItemType != E_ITEM_POTION) && (ItemType != E_ITEM_SPAWN_EGG)) + { + a_Pkt.WriteBEInt8(0); + return; + } + + + // Send the enchantments and custom names: + cFastNBTWriter Writer; + if (a_Item.m_RepairCost != 0) + { + Writer.AddInt("RepairCost", a_Item.m_RepairCost); + } + if (!a_Item.m_Enchantments.IsEmpty()) + { + const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; + EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); + } + if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid()) + { + Writer.BeginCompound("display"); + if (a_Item.m_ItemColor.IsValid()) + { + Writer.AddInt("color", static_cast<Int32>(a_Item.m_ItemColor.m_Color)); + } + + if (!a_Item.IsCustomNameEmpty()) + { + Writer.AddString("Name", a_Item.m_CustomName); + } + if (!a_Item.IsLoreEmpty()) + { + Writer.BeginList("Lore", TAG_String); + + for (const auto & Line : a_Item.m_LoreTable) + { + Writer.AddString("", Line); + } + + Writer.EndList(); + } + Writer.EndCompound(); + } + if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) + { + cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast<ENUM_ITEM_TYPE>(a_Item.m_ItemType)); + } + if (a_Item.m_ItemType == E_ITEM_POTION) + { + // 1.9 potions use a different format. In the future (when only 1.9+ is supported) this should be its own class + AString PotionID = "empty"; // Fallback of "Uncraftable potion" for unhandled cases + + cEntityEffect::eType Type = cEntityEffect::GetPotionEffectType(a_Item.m_ItemDamage); + if (Type != cEntityEffect::effNoEffect) + { + switch (Type) + { + case cEntityEffect::effRegeneration: PotionID = "regeneration"; break; + case cEntityEffect::effSpeed: PotionID = "swiftness"; break; + case cEntityEffect::effFireResistance: PotionID = "fire_resistance"; break; + case cEntityEffect::effPoison: PotionID = "poison"; break; + case cEntityEffect::effInstantHealth: PotionID = "healing"; break; + case cEntityEffect::effNightVision: PotionID = "night_vision"; break; + case cEntityEffect::effWeakness: PotionID = "weakness"; break; + case cEntityEffect::effStrength: PotionID = "strength"; break; + case cEntityEffect::effSlowness: PotionID = "slowness"; break; + case cEntityEffect::effJumpBoost: PotionID = "leaping"; break; + case cEntityEffect::effInstantDamage: PotionID = "harming"; break; + case cEntityEffect::effWaterBreathing: PotionID = "water_breathing"; break; + case cEntityEffect::effInvisibility: PotionID = "invisibility"; break; + default: ASSERT(!"Unknown potion effect"); break; + } + if (cEntityEffect::GetPotionEffectIntensity(a_Item.m_ItemDamage) == 1) + { + PotionID = "strong_" + PotionID; + } + else if (a_Item.m_ItemDamage & 0x40) + { + // Extended potion bit + PotionID = "long_" + PotionID; + } + } + else + { + // Empty potions: Water bottles and other base ones + if (a_Item.m_ItemDamage == 0) + { + // No other bits set; thus it's a water bottle + PotionID = "water"; + } + else + { + switch (a_Item.m_ItemDamage & 0x3f) + { + case 0x00: PotionID = "mundane"; break; + case 0x10: PotionID = "awkward"; break; + case 0x20: PotionID = "thick"; break; + } + // Default cases will use "empty" from before. + } + } + + PotionID = "minecraft:" + PotionID; + + Writer.AddString("Potion", PotionID); + } + if (a_Item.m_ItemType == E_ITEM_SPAWN_EGG) + { + // Convert entity ID to the name. + eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(a_Item.m_ItemDamage); + if (MonsterType != eMonsterType::mtInvalidType) + { + Writer.BeginCompound("EntityTag"); + Writer.AddString("id", "minecraft:" + cMonster::MobTypeToVanillaNBT(MonsterType)); + Writer.EndCompound(); + } + } + + Writer.Finish(); + + const auto Result = Writer.GetResult(); + if (Result.empty()) + { + a_Pkt.WriteBEInt8(0); + return; + } + a_Pkt.WriteBuf(Result); +} + + + + + +void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { // Living entity metadata if (a_Mob.HasCustomName()) @@ -2294,7 +2279,7 @@ void cProtocol_1_9_1::SendLogin(const cPlayer & a_Player, const cWorld & a_World -cProtocol::Version cProtocol_1_9_1::GetProtocolVersion() +cProtocol::Version cProtocol_1_9_1::GetProtocolVersion() const { return Version::v1_9_1; } @@ -2306,7 +2291,7 @@ cProtocol::Version cProtocol_1_9_1::GetProtocolVersion() //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_9_2: -cProtocol::Version cProtocol_1_9_2::GetProtocolVersion() +cProtocol::Version cProtocol_1_9_2::GetProtocolVersion() const { return Version::v1_9_2; } @@ -2354,16 +2339,7 @@ void cProtocol_1_9_4::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, c -cProtocol::Version cProtocol_1_9_4::GetProtocolVersion() -{ - return Version::v1_9_4; -} - - - - - -UInt32 cProtocol_1_9_4::GetPacketID(cProtocol::ePacketType a_Packet) +UInt32 cProtocol_1_9_4::GetPacketID(cProtocol::ePacketType a_Packet) const { switch (a_Packet) { @@ -2376,3 +2352,12 @@ UInt32 cProtocol_1_9_4::GetPacketID(cProtocol::ePacketType a_Packet) default: return Super::GetPacketID(a_Packet); } } + + + + + +cProtocol::Version cProtocol_1_9_4::GetProtocolVersion() const +{ + return Version::v1_9_4; +} diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h index 00d6c477a..c2005c4b9 100644 --- a/src/Protocol/Protocol_1_9.h +++ b/src/Protocol/Protocol_1_9.h @@ -21,10 +21,6 @@ Declares the 1.9 protocol classes: #include "Protocol.h" #include "Protocol_1_8.h" -#include "../ByteBuffer.h" - -#include "../mbedTLS++/AesCfb128Decryptor.h" -#include "../mbedTLS++/AesCfb128Encryptor.h" @@ -39,54 +35,45 @@ public: cProtocol_1_9_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State); - /** 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; - virtual void SendEntityPosition (const cEntity & a_Entity) 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; - virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; - virtual void SendPaintingSpawn (const cPainting & a_Painting) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendUnleashEntity (const cEntity & a_Entity) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; + 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; + virtual void SendEntityPosition (const cEntity & a_Entity) 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; + virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; + virtual void SendSpawnMob (const cMonster & a_Mob) override; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendUnleashEntity (const cEntity & a_Entity) override; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; protected: - /** The current teleport ID, and whether it has been confirmed by the client */ + /** The current teleport ID. */ bool m_IsTeleportIdConfirmed; - UInt32 m_OutstandingTeleportId; - /** Get the packet ID for a given packet. */ - virtual UInt32 GetPacketID(ePacketType a_Packet) override; + /** Whether the current teleport ID has been confirmed by the client. */ + UInt32 m_OutstandingTeleportId; + virtual UInt32 GetPacketID(ePacketType a_Packet) const override; virtual unsigned char GetProtocolEntityAnimation(EntityAnimation a_Animation) const override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; + virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; + virtual Version GetProtocolVersion() const override; - /** Returns 1.9. */ - virtual Version GetProtocolVersion() override; - - /** Converts eMonsterType to protocol-specific mob types */ - virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override; - - /** 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. */ - virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; - - // Packet handlers while in the Game state (m_State == 3): + virtual bool HandlePacket (cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketAnimation (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer) override; @@ -104,27 +91,12 @@ protected: virtual void HandlePacketVehicleMove (cByteBuffer & a_ByteBuffer); virtual void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer) override; - /** Parses item metadata as read by ReadItem(), into the item enchantments. */ - virtual void ParseItemMetadata(cItem & a_Item, ContiguousByteBufferView a_Metadata) override; - - /** Converts the hand parameter received by the protocol into eHand constants. - If the received value doesn't match any of the know value, raise an assertion fail or return hMain. */ - static eHand HandIntToEnum(Int32 a_Hand); - - /** Sends the entity type and entity-dependent data required for the entity to initially spawn. */ + virtual void ParseItemMetadata(cItem & a_Item, ContiguousByteBufferView a_Metadata) const override; virtual void SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) override; - - /** Writes the block entity data for the specified block entity into the packet. */ - virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) override; - - /** Writes the item data into a packet. */ - virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) override; - - /** Writes the metadata for the specified entity, not including the terminating 0xff. */ - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; - - /** Writes the mob-specific metadata for the specified mob */ - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override; + virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const override; + virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; + virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const override; + virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; /** Types used within metadata */ enum eMetadataType @@ -163,8 +135,7 @@ protected: virtual void SendLogin(const cPlayer & a_Player, const cWorld & a_World) override; - /** Returns 1.9.1. */ - virtual Version GetProtocolVersion() override; + virtual Version GetProtocolVersion() const override; } ; @@ -183,8 +154,7 @@ public: protected: - /** Returns 1.9.2. */ - virtual Version GetProtocolVersion() override; + virtual Version GetProtocolVersion() const override; } ; @@ -205,7 +175,6 @@ protected: 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; - /** Returns 1.9.4. */ - virtual Version GetProtocolVersion() override; - virtual UInt32 GetPacketID(ePacketType a_Packet) override; + virtual UInt32 GetPacketID(ePacketType a_Packet) const override; + virtual Version GetProtocolVersion() const override; } ; |