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;
} ;