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 = "(DEPRECATED) 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,6 +3891,16 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") }, Notes = "Returns true if the entity represents a fishing rod floater", }, + IsHeadInWater = + { + Returns = + { + { + Type = "boolean", + }, + }, + Notes = "Returns true if the entity's head is in a water block", + }, IsInvisible = { Returns = @@ -3889,7 +3909,7 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") Type = "boolean", }, }, - Notes = "Returns true if the entity is invisible", + Notes = "Returns true if the entity is invisible.", }, IsInFire = { @@ -3921,16 +3941,6 @@ local Hash = cCryptoHash.sha1HexString("DataToHash") }, Notes = "Returns true if any part of the entity is in a water block", }, - IsHeadInWater = - { - Returns = - { - { - Type = "boolean", - }, - }, - Notes = "Returns true if the entity's head is in a water block", - }, IsItemFrame = { Returns = @@ -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 + + // 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::HandleAnimation(int a_Animation) +void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, float a_Rotation, float a_Pitch, bool a_IsOnGround) { - if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_Animation)) - { - // Plugin disagrees, bail out - return; - } - - m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, static_cast(a_Animation), this); + 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 & 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 & 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(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 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,16 +329,7 @@ void cProtocol_1_10_0::SendSoundEffect(const AString & a_SoundName, double a_X, -cProtocol::Version cProtocol_1_10_0::GetProtocolVersion() -{ - return Version::v1_10_0; -} - - - - - -UInt32 cProtocol_1_10_0::GetProtocolMobType(const eMonsterType a_MobType) +UInt32 cProtocol_1_10_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { @@ -351,6 +342,15 @@ UInt32 cProtocol_1_10_0::GetProtocolMobType(const eMonsterType a_MobType) +cProtocol::Version cProtocol_1_10_0::GetProtocolVersion() const +{ + return Version::v1_10_0; +} + + + + + void cProtocol_1_10_0::HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); @@ -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(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(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(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,257 +238,7 @@ void cProtocol_1_13::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) -bool cProtocol_1_13::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) -{ - 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); -} - - - - - -void cProtocol_1_13::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) -{ - 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; - - // 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); -} - - - - - -cProtocol::Version cProtocol_1_13::GetProtocolVersion() -{ - return Version::v1_13; -} - - - - - -UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) -{ - switch (a_PacketType) - { - case pktAttachEntity: return 0x46; - case pktBlockChanges: return 0x0f; - case pktCameraSetTo: return 0x3c; - case pktChatRaw: return 0x0e; - case pktCollectEntity: return 0x4f; - case pktDestroyEntity: return 0x35; - case pktDisconnectDuringGame: return 0x1b; - case pktEditSign: return 0x2c; - case pktEntityEffect: return 0x53; - case pktEntityEquipment: return 0x42; - case pktEntityHeadLook: return 0x39; - case pktEntityLook: return 0x2a; - case pktEntityMeta: return 0x3f; - case pktEntityProperties: return 0x52; - case pktEntityRelMove: return 0x28; - case pktEntityRelMoveLook: return 0x29; - case pktEntityStatus: return 0x1c; - case pktEntityVelocity: return 0x41; - case pktExperience: return 0x43; - case pktExplosion: return 0x1e; - case pktGameMode: return 0x20; - case pktHeldItemChange: return 0x3d; - case pktInventorySlot: return 0x17; - case pktJoinGame: return 0x25; - case pktKeepAlive: return 0x21; - case pktLeashEntity: return 0x40; - case pktMapData: return 0x26; - case pktParticleEffect: return 0x24; - case pktPlayerAbilities: return 0x2e; - case pktPlayerList: return 0x30; - case pktPlayerListHeaderFooter: return 0x4e; - case pktPlayerMoveLook: return 0x32; - case pktPluginMessage: return 0x19; - case pktRemoveEntityEffect: return 0x36; - case pktRespawn: return 0x38; - case pktScoreboardObjective: return 0x45; - case pktSoundEffect: return 0x1a; - case pktSoundParticleEffect: return 0x23; - case pktSpawnPosition: return 0x49; - case pktTabCompletionResults: return 0x10; - case pktTeleportEntity: return 0x50; - case pktTimeUpdate: return 0x4a; - case pktTitle: return 0x4b; - case pktUnloadChunk: return 0x1f; - case pktUnlockRecipe: return 0x32; - case pktUpdateHealth: return 0x44; - case pktUpdateScore: return 0x48; - case pktUpdateSign: return GetPacketID(pktUpdateBlockEntity); - case pktUseBed: return 0x33; - case pktWindowClose: return 0x13; - case pktWindowItems: return 0x15; - case pktWindowOpen: return 0x14; - case pktWindowProperty: return 0x16; - default: return Super::GetPacketID(a_PacketType); - } -} - - - - - -signed char cProtocol_1_13::GetProtocolEntityStatus(const EntityAnimation a_Animation) const -{ - switch (a_Animation) - { - case EntityAnimation::DolphinShowsHappiness: return 38; - default: return Super::GetProtocolEntityStatus(a_Animation); - } -} - - - - - -UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) -{ - switch (a_MobType) - { - // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong) - case mtInvalidType: return 27; - case mtBat: return 3; - case mtCat: return 48; - case mtBlaze: return 4; - case mtCaveSpider: return 6; - case mtChicken: return 7; - case mtCod: return 8; - case mtCow: return 9; - case mtCreeper: return 10; - case mtDonkey: return 11; - case mtDolphin: return 12; - case mtDrowned: return 14; - case mtElderGuardian: return 15; - case mtEnderDragon: return 17; - case mtEnderman: return 18; - case mtEndermite: return 19; - case mtEvoker: return 21; - case mtGhast: return 26; - case mtGiant: return 27; - case mtGuardian: return 28; - case mtHorse: return 29; - case mtHusk: return 30; - case mtIllusioner: return 31; - case mtIronGolem: return 80; - case mtLlama: return 36; - case mtMagmaCube: return 38; - case mtMule: return 46; - case mtMooshroom: return 47; - case mtOcelot: return 48; - case mtParrot: return 50; - case mtPhantom: return 90; - case mtPig: return 51; - case mtPufferfish: return 52; - case mtPolarBear: return 54; - case mtRabbit: return 56; - case mtSalmon: return 57; - case mtSheep: return 58; - case mtShulker: return 59; - case mtSilverfish: return 61; - case mtSkeleton: return 62; - case mtSkeletonHorse: return 63; - case mtSlime: return 64; - case mtSnowGolem: return 66; - case mtSpider: return 69; - case mtSquid: return 70; - case mtStray: return 71; - case mtTropicalFish: return 72; - case mtTurtle: return 73; - case mtVex: return 78; - case mtVillager: return 79; - case mtVindicator: return 81; - case mtWitch: return 82; - case mtWither: return 83; - case mtWitherSkeleton: return 84; - case mtWolf: return 86; - case mtZombie: return 87; - case mtZombiePigman: return 53; - case mtZombieHorse: return 88; - case mtZombieVillager: return 89; - default: return 0; - } -} - - - - - -UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) +UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) const { const UInt8 Entity = 6; const UInt8 Living = Entity + 5; @@ -621,7 +371,7 @@ UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) -UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadataType a_FieldType) +UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadataType a_FieldType) const { switch (a_FieldType) { @@ -652,7 +402,7 @@ UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadataType a_FieldType) -std::pair cProtocol_1_13::GetItemFromProtocolID(UInt32 a_ProtocolID) +std::pair cProtocol_1_13::GetItemFromProtocolID(UInt32 a_ProtocolID) const { return PaletteUpgrade::ToItem(Palette_1_13::ToItem(a_ProtocolID)); } @@ -661,7 +411,72 @@ std::pair cProtocol_1_13::GetItemFromProtocolID(UInt32 a_ProtocolI -UInt32 cProtocol_1_13::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) const +{ + switch (a_PacketType) + { + case pktAttachEntity: return 0x46; + case pktBlockChanges: return 0x0f; + case pktCameraSetTo: return 0x3c; + case pktChatRaw: return 0x0e; + case pktCollectEntity: return 0x4f; + case pktDestroyEntity: return 0x35; + case pktDisconnectDuringGame: return 0x1b; + case pktEditSign: return 0x2c; + case pktEntityEffect: return 0x53; + case pktEntityEquipment: return 0x42; + case pktEntityHeadLook: return 0x39; + case pktEntityLook: return 0x2a; + case pktEntityMeta: return 0x3f; + case pktEntityProperties: return 0x52; + case pktEntityRelMove: return 0x28; + case pktEntityRelMoveLook: return 0x29; + case pktEntityStatus: return 0x1c; + case pktEntityVelocity: return 0x41; + case pktExperience: return 0x43; + case pktExplosion: return 0x1e; + case pktGameMode: return 0x20; + case pktHeldItemChange: return 0x3d; + case pktInventorySlot: return 0x17; + case pktJoinGame: return 0x25; + case pktKeepAlive: return 0x21; + case pktLeashEntity: return 0x40; + case pktMapData: return 0x26; + case pktParticleEffect: return 0x24; + case pktPlayerAbilities: return 0x2e; + case pktPlayerList: return 0x30; + case pktPlayerListHeaderFooter: return 0x4e; + case pktPlayerMoveLook: return 0x32; + case pktPluginMessage: return 0x19; + case pktRemoveEntityEffect: return 0x36; + case pktRespawn: return 0x38; + case pktScoreboardObjective: return 0x45; + case pktSoundEffect: return 0x1a; + case pktSoundParticleEffect: return 0x23; + case pktSpawnPosition: return 0x49; + case pktTabCompletionResults: return 0x10; + case pktTeleportEntity: return 0x50; + case pktTimeUpdate: return 0x4a; + case pktTitle: return 0x4b; + case pktUnloadChunk: return 0x1f; + case pktUnlockRecipe: return 0x32; + case pktUpdateHealth: return 0x44; + case pktUpdateScore: return 0x48; + case pktUpdateSign: return GetPacketID(pktUpdateBlockEntity); + case pktUseBed: return 0x33; + case pktWindowClose: return 0x13; + case pktWindowItems: return 0x15; + case pktWindowOpen: return 0x14; + case pktWindowProperty: return 0x16; + default: return Super::GetPacketID(a_PacketType); + } +} + + + + + +UInt32 cProtocol_1_13::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const { return Palette_1_13::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } @@ -670,7 +485,20 @@ UInt32 cProtocol_1_13::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_ -UInt32 cProtocol_1_13::GetProtocolItemType(short a_ItemID, short a_ItemDamage) +signed char cProtocol_1_13::GetProtocolEntityStatus(const EntityAnimation a_Animation) const +{ + switch (a_Animation) + { + case EntityAnimation::DolphinShowsHappiness: return 38; + default: return Super::GetProtocolEntityStatus(a_Animation); + } +} + + + + + +UInt32 cProtocol_1_13::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const { return Palette_1_13::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); } @@ -679,7 +507,79 @@ UInt32 cProtocol_1_13::GetProtocolItemType(short a_ItemID, short a_ItemDamage) -UInt32 cProtocol_1_13::GetProtocolStatisticType(Statistic a_Statistic) +UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) const +{ + switch (a_MobType) + { + // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong) + case mtInvalidType: return 27; + case mtBat: return 3; + case mtCat: return 48; + case mtBlaze: return 4; + case mtCaveSpider: return 6; + case mtChicken: return 7; + case mtCod: return 8; + case mtCow: return 9; + case mtCreeper: return 10; + case mtDonkey: return 11; + case mtDolphin: return 12; + case mtDrowned: return 14; + case mtElderGuardian: return 15; + case mtEnderDragon: return 17; + case mtEnderman: return 18; + case mtEndermite: return 19; + case mtEvoker: return 21; + case mtGhast: return 26; + case mtGiant: return 27; + case mtGuardian: return 28; + case mtHorse: return 29; + case mtHusk: return 30; + case mtIllusioner: return 31; + case mtIronGolem: return 80; + case mtLlama: return 36; + case mtMagmaCube: return 38; + case mtMule: return 46; + case mtMooshroom: return 47; + case mtOcelot: return 48; + case mtParrot: return 50; + case mtPhantom: return 90; + case mtPig: return 51; + case mtPufferfish: return 52; + case mtPolarBear: return 54; + case mtRabbit: return 56; + case mtSalmon: return 57; + case mtSheep: return 58; + case mtShulker: return 59; + case mtSilverfish: return 61; + case mtSkeleton: return 62; + case mtSkeletonHorse: return 63; + case mtSlime: return 64; + case mtSnowGolem: return 66; + case mtSpider: return 69; + case mtSquid: return 70; + case mtStray: return 71; + case mtTropicalFish: return 72; + case mtTurtle: return 73; + case mtVex: return 78; + case mtVillager: return 79; + case mtVindicator: return 81; + case mtWitch: return 82; + case mtWither: return 83; + case mtWitherSkeleton: return 84; + case mtWolf: return 86; + case mtZombie: return 87; + case mtZombiePigman: return 53; + case mtZombieHorse: return 88; + case mtZombieVillager: return 89; + default: return 0; + } +} + + + + + +UInt32 cProtocol_1_13::GetProtocolStatisticType(Statistic a_Statistic) const { return Palette_1_13::From(a_Statistic); } @@ -688,7 +588,107 @@ UInt32 cProtocol_1_13::GetProtocolStatisticType(Statistic a_Statistic) -bool cProtocol_1_13::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) +cProtocol::Version cProtocol_1_13::GetProtocolVersion() const +{ + return Version::v1_13; +} + + + + + +bool cProtocol_1_13::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) +{ + 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); +} + + + + + +void cProtocol_1_13::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) +{ + 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; + + // 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); +} + + + + + +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(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(Player.GetSkinParts())); WriteEntityMetadata(a_Pkt, EntityMetadata::PlayerMainHand, EntityMetadataType::Byte); - a_Pkt.WriteBEUInt8(static_cast(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(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,16 +1444,7 @@ void cProtocol_1_13_1::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSk -cProtocol::Version cProtocol_1_13_1::GetProtocolVersion() -{ - return Version::v1_13_1; -} - - - - - -std::pair cProtocol_1_13_1::GetItemFromProtocolID(UInt32 a_ProtocolID) +std::pair cProtocol_1_13_1::GetItemFromProtocolID(UInt32 a_ProtocolID) const { return PaletteUpgrade::ToItem(Palette_1_13_1::ToItem(a_ProtocolID)); } @@ -1462,7 +1453,7 @@ std::pair cProtocol_1_13_1::GetItemFromProtocolID(UInt32 a_Protoco -UInt32 cProtocol_1_13_1::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +UInt32 cProtocol_1_13_1::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const { return Palette_1_13_1::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } @@ -1471,7 +1462,7 @@ UInt32 cProtocol_1_13_1::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE -UInt32 cProtocol_1_13_1::GetProtocolItemType(short a_ItemID, short a_ItemDamage) +UInt32 cProtocol_1_13_1::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const { return Palette_1_13_1::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); } @@ -1480,7 +1471,7 @@ UInt32 cProtocol_1_13_1::GetProtocolItemType(short a_ItemID, short a_ItemDamage) -UInt32 cProtocol_1_13_1::GetProtocolStatisticType(Statistic a_Statistic) +UInt32 cProtocol_1_13_1::GetProtocolStatisticType(Statistic a_Statistic) const { return Palette_1_13_1::From(a_Statistic); } @@ -1489,10 +1480,19 @@ UInt32 cProtocol_1_13_1::GetProtocolStatisticType(Statistic a_Statistic) +cProtocol::Version cProtocol_1_13_1::GetProtocolVersion() const +{ + return Version::v1_13_1; +} + + + + + //////////////////////////////////////////////////////////////////////////////// // 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 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 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 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 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 cProtocol_1_14::GetItemFromProtocolID(UInt32 a_ProtocolID) +std::pair cProtocol_1_14::GetItemFromProtocolID(UInt32 a_ProtocolID) const { return PaletteUpgrade::ToItem(Palette_1_14::ToItem(a_ProtocolID)); } @@ -202,7 +193,7 @@ std::pair 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 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 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(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,41 +2937,92 @@ 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(ServerID.c_str()), ServerID.length()); - Checksum.Update(a_Key, 16); - Checksum.Update(reinterpret_cast(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(a_Entity.GetSpeedX() * 400)); + Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedY() * 400)); + Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedZ() * 400)); + } + } + + // Otherwise 1.8 clients don't show the entity + SendEntityTeleport(a_Entity); +} + + + + + +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); } } @@ -3004,9 +3030,6 @@ eBlockFace cProtocol_1_8_0::FaceIntToBlockFace(const Int32 a_BlockFace) -//////////////////////////////////////////////////////////////////////////////// -// cProtocol_1_8_0::cPacketizer: - void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt) { ASSERT(m_OutPacketBuffer.GetReadableSpace() == m_OutPacketBuffer.GetUsedSpace()); @@ -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(a_Entity.GetSpeedX() * 400)); - Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedY() * 400)); - Pkt.WriteBEInt16(static_cast(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(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(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(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(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(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(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(ServerID.c_str()), ServerID.length()); + Checksum.Update(a_Key, 16); + Checksum.Update(reinterpret_cast(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); + /** 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) 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); + /** 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; - /** 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); - - /** 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); - - /** Writes the item data into a packet. */ - virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item); + virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const; /** Writes the metadata for the specified entity, not including the terminating 0x7f. */ - virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity); - - /** Writes the mob-specific metadata for the specified mob */ - virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob); + 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,16 +728,7 @@ signed char cProtocol_1_9_0::GetProtocolEntityStatus(const EntityAnimation a_Ani -cProtocol::Version cProtocol_1_9_0::GetProtocolVersion() -{ - return Version::v1_9_0; -} - - - - - -UInt32 cProtocol_1_9_0::GetProtocolMobType(const eMonsterType a_MobType) +UInt32 cProtocol_1_9_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { @@ -748,6 +741,15 @@ UInt32 cProtocol_1_9_0::GetProtocolMobType(const eMonsterType a_MobType) +cProtocol::Version cProtocol_1_9_0::GetProtocolVersion() const +{ + return Version::v1_9_0; +} + + + + + bool cProtocol_1_9_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { switch (m_State) @@ -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(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,7 +1452,229 @@ void cProtocol_1_9_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEn -void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) +void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const +{ + // Common metadata: + Int8 Flags = 0; + if (a_Entity.IsOnFire()) + { + Flags |= 0x01; + } + if (a_Entity.IsCrouched()) + { + Flags |= 0x02; + } + if (a_Entity.IsSprinting()) + { + Flags |= 0x08; + } + if (a_Entity.IsRclking()) + { + Flags |= 0x10; + } + if (a_Entity.IsInvisible()) + { + Flags |= 0x20; + } + if (a_Entity.IsElytraFlying()) + { + Flags |= 0x80; + } + a_Pkt.WriteBEUInt8(0); // Index 0 + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type + a_Pkt.WriteBEInt8(Flags); + + switch (a_Entity.GetEntityType()) + { + case cEntity::etPlayer: + { + auto & Player = static_cast(a_Entity); + + // TODO Set player custom name to their name. + // Then it's possible to move the custom name of mobs to the entities + // and to remove the "special" player custom name. + a_Pkt.WriteBEUInt8(2); // Index 2: Custom name + a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); + a_Pkt.WriteString(Player.GetName()); + + a_Pkt.WriteBEUInt8(6); // Index 6: Health + a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); + a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); + + a_Pkt.WriteBEUInt8(12); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); + + a_Pkt.WriteBEUInt8(13); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); + break; + } + case cEntity::etPickup: + { + a_Pkt.WriteBEUInt8(5); // Index 5: Item + a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); + WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); + break; + } + case cEntity::etMinecart: + { + a_Pkt.WriteBEUInt8(5); // Index 5: Shaking power + a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); + + // The following expression makes Minecarts shake more with less health or higher damage taken + auto & Minecart = static_cast(a_Entity); + auto maxHealth = a_Entity.GetMaxHealth(); + auto curHealth = a_Entity.GetHealth(); + a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); + + a_Pkt.WriteBEUInt8(6); // Index 6: Shaking direction (doesn't seem to effect anything) + a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteVarInt32(1); + + a_Pkt.WriteBEUInt8(7); // Index 7: Shake multiplier / damage taken + a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); + a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); + + if (Minecart.GetPayload() == cMinecart::mpNone) + { + auto & RideableMinecart = static_cast(Minecart); + const cItem & MinecartContent = RideableMinecart.GetContent(); + if (!MinecartContent.IsEmpty()) + { + a_Pkt.WriteBEUInt8(8); // Index 8: Block ID and damage + a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); + int Content = MinecartContent.m_ItemType; + Content |= MinecartContent.m_ItemDamage << 8; + a_Pkt.WriteVarInt32(static_cast(Content)); + + a_Pkt.WriteBEUInt8(9); // Index 9: Block ID and damage + a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); + + a_Pkt.WriteBEUInt8(10); // Index 10: Show block + a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(true); + } + } + else if (Minecart.GetPayload() == cMinecart::mpFurnace) + { + a_Pkt.WriteBEUInt8(11); // Index 11: Is powered + a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); + } + break; + } // case etMinecart + + case cEntity::etProjectile: + { + auto & Projectile = static_cast(a_Entity); + switch (Projectile.GetProjectileKind()) + { + case cProjectileEntity::pkArrow: + { + a_Pkt.WriteBEUInt8(5); // Index 5: Is critical + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); + break; + } + case cProjectileEntity::pkFirework: + { + a_Pkt.WriteBEUInt8(5); // Index 5: Firework item used for this firework + a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); + WriteItem(a_Pkt, static_cast(Projectile).GetItem()); + break; + } + case cProjectileEntity::pkSplashPotion: + { + a_Pkt.WriteBEUInt8(5); // Index 5: Potion item which was thrown + a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); + WriteItem(a_Pkt, static_cast(Projectile).GetItem()); + } + default: + { + break; + } + } + break; + } // case etProjectile + + case cEntity::etMonster: + { + WriteMobMetadata(a_Pkt, static_cast(a_Entity)); + break; + } + + case cEntity::etBoat: + { + auto & Boat = static_cast(a_Entity); + + a_Pkt.WriteBEInt8(5); // Index 6: Time since last hit + a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); + + a_Pkt.WriteBEInt8(6); // Index 7: Forward direction + a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); + + a_Pkt.WriteBEInt8(7); // Index 8: Damage taken + a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); + a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); + + a_Pkt.WriteBEInt8(8); // Index 9: Type + a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); + + a_Pkt.WriteBEInt8(9); // Index 10: Right paddle turning + a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); + + a_Pkt.WriteBEInt8(10); // Index 11: Left paddle turning + a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(Boat.IsLeftPaddleUsed()); + + break; + } // case etBoat + + case cEntity::etItemFrame: + { + auto & Frame = static_cast(a_Entity); + a_Pkt.WriteBEUInt8(5); // Index 5: Item + a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); + WriteItem(a_Pkt, Frame.GetItem()); + a_Pkt.WriteBEUInt8(6); // Index 6: Rotation + a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteVarInt32(Frame.GetItemRotation()); + break; + } // case etItemFrame + + case cEntity::etEnderCrystal: + { + const auto & EnderCrystal = static_cast(a_Entity); + a_Pkt.WriteBEUInt8(5); + a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); + a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); + if (EnderCrystal.DisplaysBeam()) + { + a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); + } + a_Pkt.WriteBEUInt8(6); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); + break; + } // case etEnderCrystal + default: + { + break; + } + } +} + + + + + +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 @@ -1637,229 +1844,7 @@ void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) -void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) -{ - // Common metadata: - Int8 Flags = 0; - if (a_Entity.IsOnFire()) - { - Flags |= 0x01; - } - if (a_Entity.IsCrouched()) - { - Flags |= 0x02; - } - if (a_Entity.IsSprinting()) - { - Flags |= 0x08; - } - if (a_Entity.IsRclking()) - { - Flags |= 0x10; - } - if (a_Entity.IsInvisible()) - { - Flags |= 0x20; - } - if (a_Entity.IsElytraFlying()) - { - Flags |= 0x80; - } - a_Pkt.WriteBEUInt8(0); // Index 0 - a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type - a_Pkt.WriteBEInt8(Flags); - - switch (a_Entity.GetEntityType()) - { - case cEntity::etPlayer: - { - auto & Player = static_cast(a_Entity); - - // TODO Set player custom name to their name. - // Then it's possible to move the custom name of mobs to the entities - // and to remove the "special" player custom name. - a_Pkt.WriteBEUInt8(2); // Index 2: Custom name - a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); - a_Pkt.WriteString(Player.GetName()); - - a_Pkt.WriteBEUInt8(6); // Index 6: Health - a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); - a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); - - a_Pkt.WriteBEUInt8(12); - a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); - a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); - - a_Pkt.WriteBEUInt8(13); - a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); - a_Pkt.WriteBEUInt8(static_cast(Player.GetMainHand())); - break; - } - case cEntity::etPickup: - { - a_Pkt.WriteBEUInt8(5); // Index 5: Item - a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); - WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); - break; - } - case cEntity::etMinecart: - { - a_Pkt.WriteBEUInt8(5); // Index 5: Shaking power - a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); - - // The following expression makes Minecarts shake more with less health or higher damage taken - auto & Minecart = static_cast(a_Entity); - auto maxHealth = a_Entity.GetMaxHealth(); - auto curHealth = a_Entity.GetHealth(); - a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); - - a_Pkt.WriteBEUInt8(6); // Index 6: Shaking direction (doesn't seem to effect anything) - a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(1); - - a_Pkt.WriteBEUInt8(7); // Index 7: Shake multiplier / damage taken - a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); - a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); - - if (Minecart.GetPayload() == cMinecart::mpNone) - { - auto & RideableMinecart = static_cast(Minecart); - const cItem & MinecartContent = RideableMinecart.GetContent(); - if (!MinecartContent.IsEmpty()) - { - a_Pkt.WriteBEUInt8(8); // Index 8: Block ID and damage - a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); - int Content = MinecartContent.m_ItemType; - Content |= MinecartContent.m_ItemDamage << 8; - a_Pkt.WriteVarInt32(static_cast(Content)); - - a_Pkt.WriteBEUInt8(9); // Index 9: Block ID and damage - a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); - - a_Pkt.WriteBEUInt8(10); // Index 10: Show block - a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); - a_Pkt.WriteBool(true); - } - } - else if (Minecart.GetPayload() == cMinecart::mpFurnace) - { - a_Pkt.WriteBEUInt8(11); // Index 11: Is powered - a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); - a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); - } - break; - } // case etMinecart - - case cEntity::etProjectile: - { - auto & Projectile = static_cast(a_Entity); - switch (Projectile.GetProjectileKind()) - { - case cProjectileEntity::pkArrow: - { - a_Pkt.WriteBEUInt8(5); // Index 5: Is critical - a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); - a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); - break; - } - case cProjectileEntity::pkFirework: - { - a_Pkt.WriteBEUInt8(5); // Index 5: Firework item used for this firework - a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); - WriteItem(a_Pkt, static_cast(Projectile).GetItem()); - break; - } - case cProjectileEntity::pkSplashPotion: - { - a_Pkt.WriteBEUInt8(5); // Index 5: Potion item which was thrown - a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); - WriteItem(a_Pkt, static_cast(Projectile).GetItem()); - } - default: - { - break; - } - } - break; - } // case etProjectile - - case cEntity::etMonster: - { - WriteMobMetadata(a_Pkt, static_cast(a_Entity)); - break; - } - - case cEntity::etBoat: - { - auto & Boat = static_cast(a_Entity); - - a_Pkt.WriteBEInt8(5); // Index 6: Time since last hit - a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); - - a_Pkt.WriteBEInt8(6); // Index 7: Forward direction - a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); - - a_Pkt.WriteBEInt8(7); // Index 8: Damage taken - a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); - a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); - - a_Pkt.WriteBEInt8(8); // Index 9: Type - a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); - - a_Pkt.WriteBEInt8(9); // Index 10: Right paddle turning - a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); - a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); - - a_Pkt.WriteBEInt8(10); // Index 11: Left paddle turning - a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); - a_Pkt.WriteBool(Boat.IsLeftPaddleUsed()); - - break; - } // case etBoat - - case cEntity::etItemFrame: - { - auto & Frame = static_cast(a_Entity); - a_Pkt.WriteBEUInt8(5); // Index 5: Item - a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); - WriteItem(a_Pkt, Frame.GetItem()); - a_Pkt.WriteBEUInt8(6); // Index 6: Rotation - a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(Frame.GetItemRotation()); - break; - } // case etItemFrame - - case cEntity::etEnderCrystal: - { - const auto & EnderCrystal = static_cast(a_Entity); - a_Pkt.WriteBEUInt8(5); - a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); - a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); - if (EnderCrystal.DisplaysBeam()) - { - a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); - } - a_Pkt.WriteBEUInt8(6); - a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); - a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); - break; - } // case etEnderCrystal - default: - { - break; - } - } -} - - - - - -void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) +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; + + /** Whether the current teleport ID has been confirmed by the client. */ UInt32 m_OutstandingTeleportId; - /** Get the packet ID for a given packet. */ - virtual UInt32 GetPacketID(ePacketType a_Packet) override; - + 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; } ;