summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Server/Plugins/APIDump/APIDesc.lua143
-rw-r--r--src/Defines.h36
-rw-r--r--src/Entities/Player.cpp24
-rw-r--r--src/Entities/Player.h13
-rw-r--r--src/Protocol/Protocol_1_10.cpp8
-rw-r--r--src/Protocol/Protocol_1_8.cpp20
-rw-r--r--src/Protocol/Protocol_1_9.cpp16
7 files changed, 253 insertions, 7 deletions
diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua
index d4a814cb9..f9fed612f 100644
--- a/Server/Plugins/APIDump/APIDesc.lua
+++ b/Server/Plugins/APIDump/APIDesc.lua
@@ -11351,6 +11351,16 @@ 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 =
@@ -11411,6 +11421,16 @@ a_Player:OpenWindow(Window);
},
Notes = "Returns the player's maximum sprinting speed, relative to the game default speed. Defaults to 1.3, but plugins may modify it for faster or slower sprinting.",
},
+ GetSkinParts =
+ {
+ Returns =
+ {
+ {
+ Type = "number",
+ },
+ },
+ Notes = "Returns the player's current set of skin part flags. This is a bitwise OR of various {{eSkinPart}} constants. Note that HasSkinPart may be easier to use in most situations.",
+ },
GetStance =
{
Returns =
@@ -11535,6 +11555,23 @@ a_Player:OpenWindow(Window);
},
Notes = "Returns true if the player has the specified permission",
},
+ HasSkinPart =
+ {
+ Params =
+ {
+ {
+ Name = "Part",
+ Type = "eSkinPart",
+ },
+ },
+ Returns =
+ {
+ {
+ Type = "boolean",
+ },
+ },
+ Notes = "Returns true if the player has the specified skin part enabled",
+ },
Heal =
{
Params =
@@ -12063,6 +12100,17 @@ 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 =
+ {
+ Params =
+ {
+ {
+ Name = "Hand",
+ Type = "eMainHand",
+ },
+ },
+ Notes = "Sets the main hand of the player.",
+ },
SetName =
{
Params =
@@ -12096,6 +12144,17 @@ a_Player:OpenWindow(Window);
},
Notes = "Sets whether the player is sprinting or not.",
},
+ SetSkinParts =
+ {
+ Params =
+ {
+ {
+ Name = "Parts",
+ Type = "number",
+ },
+ },
+ Notes = "Sets the skin part flags of the player. The value should be a bitwise OR of several {{eSkinPart}} constants.",
+ },
SetSprintingMaxSpeed =
{
Params =
@@ -16632,6 +16691,54 @@ end
{
Notes = "Something concerning (i.e. reload) is about to happen",
},
+ hMain =
+ {
+ Notes = "The main hand",
+ },
+ hOff =
+ {
+ Notes = "The off hand",
+ },
+ mhLeft =
+ {
+ Notes = "The left hand is the main hand",
+ },
+ mhRight =
+ {
+ Notes = "The right hand is the main hand",
+ },
+ spCape =
+ {
+ Notes = "The cape skin part",
+ },
+ spJacket =
+ {
+ Notes = "The jacket skin part",
+ },
+ spLeftSleeve =
+ {
+ Notes = "The left sleeve skin part",
+ },
+ spRightSleeve =
+ {
+ Notes = "The right sleeve skin part",
+ },
+ spLeftPants =
+ {
+ Notes = "The left pants leg skin part",
+ },
+ spRightPants =
+ {
+ Notes = "The right pants leg skin part",
+ },
+ spHat =
+ {
+ Notes = "The hat/head skin part",
+ },
+ spMask =
+ {
+ Notes = "A mask of all valid skin parts combined",
+ },
},
ConstantGroups =
{
@@ -16717,6 +16824,32 @@ 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 {{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.*",
@@ -16809,6 +16942,16 @@ end
The following constants define the block types that are propelled outwards after an explosion.
]],
},
+ eSkinPart =
+ {
+ Include =
+ {
+ "^sp.*",
+ },
+ TextBefore = [[
+ These constants represent various skin part flags.
+ ]],
+ },
eSpreadSource =
{
Include = "^ss.*",
diff --git a/src/Defines.h b/src/Defines.h
index f8af22ef2..a1de94897 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -203,6 +203,42 @@ enum eMobHeadRotation
+enum eHand
+{
+ hMain = 0,
+ hOff = 1,
+} ;
+
+
+
+
+
+enum eMainHand
+{
+ mhLeft = 0,
+ mhRight = 1,
+} ;
+
+
+
+
+
+enum eSkinPart
+{
+ spCape = 0x01,
+ spJacket = 0x02,
+ spLeftSleeve = 0x04,
+ spRightSleeve = 0x08,
+ spLeftPants = 0x10,
+ spRightPants = 0x20,
+ spHat = 0x40,
+ spMask = 0x7F,
+};
+
+
+
+
+
inline const char * ClickActionToString(int a_ClickAction)
{
switch (a_ClickAction)
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index f3ea45cf4..9fba0d015 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -90,7 +90,9 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
m_bIsTeleporting(false),
m_UUID((a_Client != nullptr) ? a_Client->GetUUID() : ""),
- m_CustomName("")
+ m_CustomName(""),
+ m_SkinParts(0),
+ m_MainHand(mhRight)
{
ASSERT(a_PlayerName.length() <= 16); // Otherwise this player could crash many clients...
@@ -2632,6 +2634,26 @@ bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
+void cPlayer::SetSkinParts(int a_Parts)
+{
+ m_SkinParts = a_Parts & spMask;
+ m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get());
+}
+
+
+
+
+
+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 dab814692..b592913bd 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -499,6 +499,13 @@ public:
The blocks in range (a_BlockX - a_Range, a_BlockX + a_Range) are sent (NY-metric). */
void SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Range = 1);
+ bool HasSkinPart(eSkinPart a_Part) const { return (m_SkinParts & a_Part) != 0; }
+ 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.
@@ -682,6 +689,12 @@ protected:
AString m_CustomName;
+ /** Displayed skin part bit mask */
+ int m_SkinParts;
+
+ /** The main hand of the player */
+ eMainHand m_MainHand;
+
/** Sets the speed and sends it to the client, so that they are forced to move so. */
virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) override;
diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp
index c0d9d921f..1cd7153a7 100644
--- a/src/Protocol/Protocol_1_10.cpp
+++ b/src/Protocol/Protocol_1_10.cpp
@@ -400,6 +400,14 @@ void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity &
a_Pkt.WriteBEUInt8(LIVING_HEALTH);
a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT);
a_Pkt.WriteBEFloat(static_cast<float>(Player.GetHealth()));
+
+ a_Pkt.WriteBEUInt8(PLAYER_DISPLAYED_SKIN_PARTS);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE);
+ a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetSkinParts()));
+
+ a_Pkt.WriteBEUInt8(PLAYER_MAIN_HAND);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE);
+ a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetMainHand()));
break;
}
case cEntity::etPickup:
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index bbeb3ae8b..2e7902303 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -2311,11 +2311,12 @@ void cProtocol_1_8_0::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ViewDistance);
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ChatFlags);
HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors);
- HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinFlags);
+ HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinParts);
m_Client->SetLocale(Locale);
m_Client->SetViewDistance(ViewDistance);
- // TODO: Handle other values
+ m_Client->GetPlayer()->SetSkinParts(SkinParts);
+ // TODO: Handle chat flags and chat colors
}
@@ -3234,7 +3235,20 @@ void cProtocol_1_8_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a
switch (a_Entity.GetEntityType())
{
- case cEntity::etPlayer: break; // TODO?
+ case cEntity::etPlayer:
+ {
+ auto & Player = reinterpret_cast<const cPlayer &>(a_Entity);
+
+ // Player health (not handled since players aren't monsters)
+ a_Pkt.WriteBEUInt8(0x66);
+ a_Pkt.WriteBEFloat(static_cast<float>(Player.GetHealth()));
+
+ // Skin flags
+ a_Pkt.WriteBEUInt8(0x0A);
+ a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetSkinParts()));
+
+ break;
+ }
case cEntity::etPickup:
{
a_Pkt.WriteBEUInt8((5 << 5) | 10); // Slot(5) + index 10
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index 680675ca3..69b8deb55 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -2355,12 +2355,14 @@ void cProtocol_1_9_0::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ViewDistance);
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ChatFlags);
HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors);
- HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinFlags);
+ HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinParts);
HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, MainHand);
m_Client->SetLocale(Locale);
m_Client->SetViewDistance(ViewDistance);
- // TODO: Handle other values
+ m_Client->GetPlayer()->SetSkinParts(SkinParts);
+ m_Client->GetPlayer()->SetMainHand(static_cast<eMainHand>(MainHand));
+ // TODO: Handle chat flags and chat colors
}
@@ -3552,9 +3554,17 @@ void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a
a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING);
a_Pkt.WriteString(Player.GetName());
- a_Pkt.WriteBEUInt8(6); // Start metadata - Index 6: Health
+ a_Pkt.WriteBEUInt8(6); // Index 6: Health
a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT);
a_Pkt.WriteBEFloat(static_cast<float>(Player.GetHealth()));
+
+ a_Pkt.WriteBEUInt8(12);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE);
+ a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetSkinParts()));
+
+ a_Pkt.WriteBEUInt8(13);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE);
+ a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetMainHand()));
break;
}
case cEntity::etPickup: