summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua9
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua17
-rw-r--r--src/ClientHandle.cpp12
-rw-r--r--src/ClientHandle.h2
-rw-r--r--src/Entities/Boat.cpp2
-rw-r--r--src/Entities/Entity.h2
-rw-r--r--src/Entities/ItemFrame.cpp2
-rw-r--r--src/Entities/Minecart.cpp5
-rw-r--r--src/Entities/Pawn.cpp9
-rw-r--r--src/Entities/Player.cpp47
-rw-r--r--src/Entities/Player.h15
-rw-r--r--src/Mobs/Monster.cpp54
-rw-r--r--src/Mobs/Monster.h23
-rw-r--r--src/Mobs/Sheep.cpp2
-rw-r--r--src/Protocol/Protocol.h2
-rw-r--r--src/Protocol/Protocol125.cpp23
-rw-r--r--src/Protocol/Protocol125.h2
-rw-r--r--src/Protocol/Protocol132.cpp9
-rw-r--r--src/Protocol/Protocol17x.cpp36
-rw-r--r--src/Protocol/Protocol17x.h2
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp4
-rw-r--r--src/Protocol/ProtocolRecognizer.h2
-rw-r--r--src/World.cpp14
-rw-r--r--src/World.h2
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp2
-rw-r--r--src/WorldStorage/WSSAnvil.cpp13
26 files changed, 265 insertions, 47 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index e7f9e9b18..f109638e9 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -1629,6 +1629,11 @@ a_Player:OpenWindow(Window);
]],
Functions =
{
+ HasCustomName = { Params = "", Return = "bool", Notes = "Returns true if the monster has a custom name." },
+ GetCustomName = { Params = "", Return = "string", Notes = "Gets the custom name of the monster. If no custom name is set, the function returns an empty string." },
+ SetCustomName = { Params = "string", Return = "", Notes = "Sets the custom name of the monster. You see the name over the monster. If you want to disable the custom name, simply set an empty string." },
+ IsCustomNameAlwaysVisible = { Params = "", Return = "bool", Notes = "Is the custom name of this monster always visible? If not, you only see the name when you sight the mob." },
+ SetCustomNameAlwaysVisible = { Params = "bool", Return = "", Notes = "Sets the custom name visiblity of this monster. If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name." },
FamilyFromType = { Params = "{{cMonster#MobType|MobType}}", Return = "{{cMonster#MobFamily|MobFamily}}", Notes = "(STATIC) Returns the mob family ({{cMonster#MobFamily|mfXXX}} constants) based on the mob type ({{cMonster#MobType|mtXXX}} constants)" },
GetMobFamily = { Params = "", Return = "{{cMonster#MobFamily|MobFamily}}", Notes = "Returns this mob's family ({{cMonster#MobFamily|mfXXX}} constant)" },
GetMobType = { Params = "", Return = "{{cMonster#MobType|MobType}}", Notes = "Returns the type of this mob ({{cMonster#MobType|mtXXX}} constant)" },
@@ -1752,6 +1757,7 @@ a_Player:OpenWindow(Window);
ForceSetSpeed = { Params = "{{Vector3d|Direction}}", Notes = "Forces the player to move to the given direction." },
GetClientHandle = { Params = "", Return = "{{cClientHandle}}", Notes = "Returns the client handle representing the player's connection. May be nil (AI players)." },
GetColor = { Return = "string", Notes = "Returns the full color code to be used for this player's messages (based on their rank). Prefix player messages with this code." },
+ GetTabListName = { Return = "string", Notes = "Returns the name that is used in the tablist." },
GetCurrentXp = { Params = "", Return = "number", Notes = "Returns the current amount of XP" },
GetEffectiveGameMode = { Params = "", Return = "{{Globals#GameMode|GameMode}}", Notes = "(OBSOLETE) Returns the current resolved game mode of the player. If the player is set to inherit the world's gamemode, returns that instead. See also GetGameMode() and IsGameModeXXX() functions. Note that this function is the same as GetGameMode(), use that function instead." },
GetEquippedItem = { Params = "", Return = "{{cItem}}", Notes = "Returns the item that the player is currently holding; empty item if holding nothing." },
@@ -1802,6 +1808,9 @@ a_Player:OpenWindow(Window);
SendMessagePrivateMsg = { Params = "Message, SenderName", Return = "", Notes = "Prepends Light Blue [MSG: *SenderName*] / prepends SenderName and colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For private messaging." },
SendMessageSuccess = { Params = "Message", Return = "", Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Success notification." },
SendMessageWarning = { Params = "Message, Sender", Return = "", Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Denotes that something concerning, such as plugin reload, is about to happen." },
+ HasCustomName = { Params = "", Return = "bool", Notes = "Returns true if the player has a custom name." },
+ GetCustomName = { Params = "", Return = "string", Notes = "Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string." },
+ SetCustomName = { Params = "string", Return = "", Notes = "Sets the custom name of this player. If you want to disable the custom name, simply set an empty string. The custom name will be used in the tab-list, in the player nametag and in the tab-completion." },
SetCanFly = { Params = "CanFly", Notes = "Sets if the player can fly or not." },
SetCrouch = { Params = "IsCrouched", Return = "", Notes = "Sets the crouch state, broadcasts the change to other players." },
SetCurrentExperience = { Params = "XPAmount", Return = "", Notes = "Sets the current amount of experience (and indirectly, the XP level)." },
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 179935c08..65ce0993a 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -38,6 +38,7 @@ function Initialize(Plugin)
-- _X: Disabled so that the normal operation doesn't interfere with anything
-- PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
+ PM:BindCommand("/cm", "debuggers", HandleCustomNameCmd, "- Gives you a custom name");
PM:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities");
PM:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities");
PM:BindCommand("/wool", "debuggers", HandleWoolCmd, "- Sets all your armor to blue wool");
@@ -768,6 +769,22 @@ end
+function HandleCustomNameCmd(Split, Player)
+ if (Split[2] == nil) then
+ Player:SendMessage("Usage: /cm [CustomName]");
+ return true;
+ end
+
+ local NewName = Split[2]
+ Player:SetCustomName(NewName);
+ Player:SendMessageSuccess("Custom name setted to " .. Player:GetCustomName() .. "!")
+ return true
+end
+
+
+
+
+
function HandleListEntitiesCmd(Split, Player)
local NumEntities = 0;
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index f9c6a664c..e97c126a1 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -124,13 +124,11 @@ cClientHandle::~cClientHandle()
if (m_Player != NULL)
{
cWorld * World = m_Player->GetWorld();
- if (!m_Username.empty() && (World != NULL))
- {
- // Send the Offline PlayerList packet:
- World->BroadcastPlayerListItem(*m_Player, false, this);
- }
if (World != NULL)
{
+ // Send the Offline PlayerList packet:
+ World->BroadcastPlayerListItem(m_Player->GetTabListName(), false, 0, this);
+
World->RemovePlayer(m_Player, true); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again
m_Player->Destroy();
}
@@ -2371,9 +2369,9 @@ void cClientHandle::SendPlayerAbilities()
-void cClientHandle::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
+void cClientHandle::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping)
{
- m_Protocol->SendPlayerListItem(a_Player, a_IsOnline);
+ m_Protocol->SendPlayerListItem(a_PlayerName, a_IsOnline, a_Ping);
}
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 7ae70a07f..529ee4555 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -156,7 +156,7 @@ public:
void SendEntityAnimation (const cEntity & a_Entity, char a_Animation); // tolua_export
void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount);
void SendPlayerAbilities (void);
- void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline);
+ void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0);
void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+)
void SendPlayerMoveLook (void);
void SendPlayerPosition (void);
diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp
index 8ff8866a1..328a70846 100644
--- a/src/Entities/Boat.cpp
+++ b/src/Entities/Boat.cpp
@@ -62,6 +62,8 @@ bool cBoat::DoTakeDamage(TakeDamageInfo & TDI)
void cBoat::OnRightClicked(cPlayer & a_Player)
{
+ super::OnRightClicked(a_Player);
+
if (m_Attachee != NULL)
{
if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index b9c280b6b..774cdb062 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -447,7 +447,7 @@ public:
// tolua_end
/// Called when the specified player right-clicks this entity
- virtual void OnRightClicked(cPlayer &) {}
+ virtual void OnRightClicked(cPlayer & a_Player) {}
/// Returns the list of drops for this pawn when it is killed. May check a_Killer for special handling (sword of looting etc.). Called from KilledBy().
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL)
diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp
index 0bc10ec60..3ccb95998 100644
--- a/src/Entities/ItemFrame.cpp
+++ b/src/Entities/ItemFrame.cpp
@@ -22,6 +22,8 @@ cItemFrame::cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_
void cItemFrame::OnRightClicked(cPlayer & a_Player)
{
+ super::OnRightClicked(a_Player);
+
if (!m_Item.IsEmpty())
{
// Item not empty, rotate, clipping values to zero to three inclusive
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index 1501eea84..5fabbb542 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -1072,6 +1072,8 @@ cRideableMinecart::cRideableMinecart(double a_X, double a_Y, double a_Z, const c
void cRideableMinecart::OnRightClicked(cPlayer & a_Player)
{
+ super::OnRightClicked(a_Player);
+
if (m_Attachee != NULL)
{
if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
@@ -1124,8 +1126,7 @@ void cMinecartWithChest::SetSlot(size_t a_Idx, const cItem & a_Item)
void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
{
- // Show the chest UI window to the player
- // TODO
+ // TODO: Show the chest UI window to the player
}
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index fe6c24a7a..fc8ca3d47 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -9,9 +9,9 @@
-cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height):
- super(a_EntityType, 0, 0, 0, a_Width, a_Height),
- m_EntityEffects(tEffectMap())
+cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height) :
+ super(a_EntityType, 0, 0, 0, a_Width, a_Height)
+ , m_EntityEffects(tEffectMap())
{
}
@@ -111,3 +111,6 @@ void cPawn::ClearEntityEffects()
RemoveEntityEffect(EffectType);
}
}
+
+
+
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 756410989..a2934d036 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -81,7 +81,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) :
m_Team(NULL),
m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
m_bIsTeleporting(false),
- m_UUID((a_Client != NULL) ? a_Client->GetUUID() : "")
+ m_UUID((a_Client != NULL) ? a_Client->GetUUID() : ""),
+ m_CustomName("")
{
m_InventoryWindow = new cInventoryWindow(*this);
m_CurrentWindow = m_InventoryWindow;
@@ -813,6 +814,28 @@ void cPlayer::SetCanFly(bool a_CanFly)
+void cPlayer::SetCustomName(const AString & a_CustomName)
+{
+ if (m_CustomName == a_CustomName)
+ {
+ return;
+ }
+ m_World->BroadcastPlayerListItem(GetTabListName(), false, 0); // Remove old tab-list entry
+
+ m_CustomName = a_CustomName;
+ if (m_CustomName.length() > 16)
+ {
+ m_CustomName = m_CustomName.substr(0, 16);
+ }
+
+ m_World->BroadcastSpawnEntity(*this, m_ClientHandle);
+ m_World->BroadcastPlayerListItem(GetTabListName(), true, GetClientHandle()->GetPing());
+}
+
+
+
+
+
void cPlayer::SetFlying(bool a_IsFlying)
{
if (a_IsFlying == m_IsFlying)
@@ -1443,6 +1466,28 @@ AString cPlayer::GetColor(void) const
+AString cPlayer::GetTabListName(void) const
+{
+ const AString & Color = GetColor();
+
+ if (HasCustomName())
+ {
+ return m_CustomName;
+ }
+ else if ((GetName().length() <= 14) && !Color.empty())
+ {
+ return Printf("%s%s", Color.c_str(), GetName().c_str());
+ }
+ else
+ {
+ return GetName();
+ }
+}
+
+
+
+
+
void cPlayer::TossEquippedItem(char a_Amount)
{
cItems Drops;
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index 9821cc6d9..49380c776 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -251,6 +251,9 @@ public:
The returned value either is empty, or includes the cChatColor::Delimiter. */
AString GetColor(void) const;
+ /** Returns the name that is used in the tablist. */
+ AString GetTabListName(void) const;
+
/** tosses the item in the selected hotbar slot */
void TossEquippedItem(char a_Amount = 1);
@@ -398,6 +401,16 @@ public:
/** If true the player can fly even when he's not in creative. */
void SetCanFly(bool a_CanFly);
+ /** Returns true if the player has a custom name. */
+ bool HasCustomName(void) const { return !m_CustomName.empty(); }
+
+ /** Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string. */
+ const AString & GetCustomName(void) const { return m_CustomName; }
+
+ /** Sets the custom name of this player. If you want to disable the custom name, simply set an empty string.
+ The custom name will be used in the tab-list, in the player nametag and in the tab-completion. */
+ void SetCustomName(const AString & a_CustomName);
+
/** Gets the last position that the player slept in
This is initialised to the world spawn point if the player has not slept in a bed as of yet
*/
@@ -562,6 +575,8 @@ protected:
If no ClientHandle is given, the UUID is initialized to empty. */
AString m_UUID;
+ AString m_CustomName;
+
/** 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/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index f7ee0b0c0..b0b836dff 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -75,6 +75,8 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString
, m_IdleInterval(0)
, m_DestroyTimer(0)
, m_MobType(a_MobType)
+ , m_CustomName("")
+ , m_CustomNameAlwaysVisible(false)
, m_SoundHurt(a_SoundHurt)
, m_SoundDeath(a_SoundDeath)
, m_AttackRate(3)
@@ -551,6 +553,25 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI)
+void cMonster::OnRightClicked(cPlayer & a_Player)
+{
+ super::OnRightClicked(a_Player);
+
+ const cItem & EquippedItem = a_Player.GetEquippedItem();
+ if ((EquippedItem.m_ItemType == E_ITEM_NAME_TAG) && !EquippedItem.m_CustomName.empty())
+ {
+ SetCustomName(EquippedItem.m_CustomName);
+ if (!a_Player.IsGameModeCreative())
+ {
+ a_Player.GetInventory().RemoveOneEquippedItem();
+ }
+ }
+}
+
+
+
+
+
// Checks to see if EventSeePlayer should be fired
// monster sez: Do I see the player
void cMonster::CheckEventSeePlayer(void)
@@ -679,6 +700,39 @@ void cMonster::InStateEscaping(float a_Dt)
+void cMonster::SetCustomName(const AString & a_CustomName)
+{
+ m_CustomName = a_CustomName;
+
+ // The maximal length is 64
+ if (a_CustomName.length() > 64)
+ {
+ m_CustomName = a_CustomName.substr(0, 64);
+ }
+
+ if (m_World != NULL)
+ {
+ m_World->BroadcastEntityMetadata(*this);
+ }
+}
+
+
+
+
+
+void cMonster::SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible)
+{
+ m_CustomNameAlwaysVisible = a_CustomNameAlwaysVisible;
+ if (m_World != NULL)
+ {
+ m_World->BroadcastEntityMetadata(*this);
+ }
+}
+
+
+
+
+
void cMonster::GetMonsterConfig(const AString & a_Name)
{
cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name);
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index cdbd26c09..1d66d50e5 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -92,6 +92,8 @@ public:
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
+ virtual void OnRightClicked(cPlayer & a_Player) override;
+
virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export
virtual bool ReachedDestination(void);
@@ -144,7 +146,24 @@ public:
virtual bool IsSitting (void) const { return false; }
// tolua_begin
-
+
+ /** Returns true if the monster has a custom name. */
+ bool HasCustomName(void) const { return !m_CustomName.empty(); }
+
+ /** Gets the custom name of the monster. If no custom name is set, the function returns an empty string. */
+ const AString & GetCustomName(void) const { return m_CustomName; }
+
+ /** Sets the custom name of the monster. You see the name over the monster.
+ If you want to disable the custom name, simply set an empty string. */
+ void SetCustomName(const AString & a_CustomName);
+
+ /** Is the custom name of this monster always visible? If not, you only see the name when you sight the mob. */
+ bool IsCustomNameAlwaysVisible(void) const { return m_CustomNameAlwaysVisible; }
+
+ /** Sets the custom name visiblity of this monster.
+ If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name. */
+ void SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible);
+
/// Translates MobType enum to a string, empty string if unknown
static AString MobTypeToString(eType a_MobType);
@@ -228,6 +247,8 @@ protected:
float m_DestroyTimer;
eType m_MobType;
+ AString m_CustomName;
+ bool m_CustomNameAlwaysVisible;
AString m_SoundHurt;
AString m_SoundDeath;
diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp
index 9fb47201d..ee3236bba 100644
--- a/src/Mobs/Sheep.cpp
+++ b/src/Mobs/Sheep.cpp
@@ -47,6 +47,8 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cSheep::OnRightClicked(cPlayer & a_Player)
{
+ super::OnRightClicked(a_Player);
+
const cItem & EquippedItem = a_Player.GetEquippedItem();
if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && !IsSheared() && !IsBaby())
{
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 8e1842ec1..9b64faf79 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -93,7 +93,7 @@ public:
virtual void SendPlayerAbilities (void) = 0;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0;
virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) = 0;
- virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) = 0;
+ virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) = 0;
virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+)
virtual void SendPlayerMoveLook (void) = 0;
virtual void SendPlayerPosition (void) = 0;
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index a66c64309..0b5e3de91 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -719,21 +719,13 @@ void cProtocol125::SendPaintingSpawn(const cPainting & a_Painting)
-void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
+void cProtocol125::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping)
{
cCSLock Lock(m_CSPacket);
- AString PlayerName(a_Player.GetColor());
- PlayerName.append(a_Player.GetName());
- if (PlayerName.length() > 14)
- {
- PlayerName.erase(14);
- }
- PlayerName += cChatColor::White;
-
WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM);
- WriteString(PlayerName);
+ WriteString(a_PlayerName);
WriteBool (a_IsOnline);
- WriteShort (a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0);
+ WriteShort (a_Ping);
Flush();
}
@@ -792,7 +784,14 @@ void cProtocol125::SendPlayerSpawn(const cPlayer & a_Player)
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_PLAYER_SPAWN);
WriteInt (a_Player.GetUniqueID());
- WriteString(a_Player.GetName());
+ if (a_Player.HasCustomName())
+ {
+ WriteString(a_Player.GetCustomName());
+ }
+ else
+ {
+ WriteString(a_Player.GetName());
+ }
WriteInt ((int)(a_Player.GetPosX() * 32));
WriteInt ((int)(a_Player.GetPosY() * 32));
WriteInt ((int)(a_Player.GetPosZ() * 32));
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index 1063777a2..9ab0adfcd 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -65,7 +65,7 @@ public:
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
- virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override;
+ virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) override;
virtual void SendPlayerMaxSpeed (void) override;
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp
index 5c58ab0ba..af3bc68ee 100644
--- a/src/Protocol/Protocol132.cpp
+++ b/src/Protocol/Protocol132.cpp
@@ -260,7 +260,14 @@ void cProtocol132::SendPlayerSpawn(const cPlayer & a_Player)
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_PLAYER_SPAWN);
WriteInt (a_Player.GetUniqueID());
- WriteString(a_Player.GetName());
+ if (a_Player.HasCustomName())
+ {
+ WriteString(a_Player.GetCustomName());
+ }
+ else
+ {
+ WriteString(a_Player.GetName());
+ }
WriteInt ((int)(a_Player.GetPosX() * 32));
WriteInt ((int)(a_Player.GetPosY() * 32));
WriteInt ((int)(a_Player.GetPosZ() * 32));
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 1091b877f..2ac1d0d0f 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1,3 +1,4 @@
+
// Protocol17x.cpp
/*
@@ -864,14 +865,14 @@ void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_Sr
-void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
+void cProtocol172::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping)
{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x38); // Playerlist Item packet
- Pkt.WriteString(a_Player.GetName());
+ Pkt.WriteString(a_PlayerName);
Pkt.WriteBool(a_IsOnline);
- Pkt.WriteShort(a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0);
+ Pkt.WriteShort(a_Ping);
}
@@ -945,9 +946,16 @@ void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player)
// Called to spawn another player for the client
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
- Pkt.WriteVarInt(a_Player.GetUniqueID());
+ Pkt.WriteVarInt((UInt32) a_Player.GetUniqueID());
Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID()));
- Pkt.WriteString(a_Player.GetName());
+ if (a_Player.HasCustomName())
+ {
+ Pkt.WriteString(a_Player.GetCustomName());
+ }
+ else
+ {
+ Pkt.WriteString(a_Player.GetName());
+ }
Pkt.WriteFPInt(a_Player.GetPosX());
Pkt.WriteFPInt(a_Player.GetPosY());
Pkt.WriteFPInt(a_Player.GetPosZ());
@@ -3021,6 +3029,15 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
break;
}
} // switch (a_Mob.GetType())
+
+ // Custom name:
+ if (a_Mob.HasCustomName())
+ {
+ WriteByte(0x8a);
+ WriteString(a_Mob.GetCustomName());
+ WriteByte(0x0b);
+ WriteByte(a_Mob.IsCustomNameAlwaysVisible() ? 1 : 0);
+ }
}
@@ -3065,7 +3082,14 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player)
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
Pkt.WriteVarInt(a_Player.GetUniqueID());
Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID()));
- Pkt.WriteString(a_Player.GetName());
+ if (a_Player.HasCustomName())
+ {
+ Pkt.WriteString(a_Player.GetCustomName());
+ }
+ else
+ {
+ Pkt.WriteString(a_Player.GetName());
+ }
const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties();
Pkt.WriteVarInt(Properties.size());
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index ccfa19eb6..eb64f6ad5 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -97,7 +97,7 @@ public:
virtual void SendPlayerAbilities (void) override;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override;
- virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override;
+ virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) override;
virtual void SendPlayerMaxSpeed (void) override;
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 8b395230a..2cd2a935b 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -487,10 +487,10 @@ void cProtocolRecognizer::SendEntityAnimation(const cEntity & a_Entity, char a_A
-void cProtocolRecognizer::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
+void cProtocolRecognizer::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendPlayerListItem(a_Player, a_IsOnline);
+ m_Protocol->SendPlayerListItem(a_PlayerName, a_IsOnline, a_Ping);
}
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index a05aeda70..95fcae1d3 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -100,7 +100,7 @@ public:
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
- virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override;
+ virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) override;
virtual void SendPlayerMaxSpeed (void) override;
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
diff --git a/src/World.cpp b/src/World.cpp
index 99e09c658..469606012 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2147,7 +2147,7 @@ void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src
-void cWorld::BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude)
+void cWorld::BroadcastPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSPlayers);
for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
@@ -2157,7 +2157,7 @@ void cWorld::BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline,
{
continue;
}
- ch->SendPlayerListItem(a_Player, a_IsOnline);
+ ch->SendPlayerListItem(a_PlayerName, a_IsOnline, a_Ping);
}
}
@@ -2669,7 +2669,7 @@ void cWorld::SendPlayerList(cPlayer * a_DestPlayer)
cClientHandle * ch = (*itr)->GetClientHandle();
if ((ch != NULL) && !ch->IsDestroyed())
{
- a_DestPlayer->GetClientHandle()->SendPlayerListItem(*(*itr), true);
+ a_DestPlayer->GetClientHandle()->SendPlayerListItem((*itr)->GetTabListName(), true, (*itr)->GetClientHandle()->GetPing());
}
}
}
@@ -3209,13 +3209,17 @@ void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Resul
for (cPlayerList::iterator itr = m_Players.begin(), end = m_Players.end(); itr != end; ++itr)
{
AString PlayerName ((*itr)->GetName());
+ if ((*itr)->HasCustomName())
+ {
+ PlayerName = (*itr)->GetCustomName();
+ }
+
AString::size_type Found = PlayerName.find(LastWord); // Try to find last word in playername
-
if (Found == AString::npos)
{
continue; // No match
}
-
+
UsernamesByWeight.push_back(std::make_pair(Found, PlayerName)); // Match! Store it with the position of the match as a weight
}
Lock.Unlock();
diff --git a/src/World.h b/src/World.h
index 578c9682b..5f4466603 100644
--- a/src/World.h
+++ b/src/World.h
@@ -237,7 +237,7 @@ public:
void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override; // tolua_export
void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export
- void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL);
+ void BroadcastPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0, const cClientHandle * a_Exclude = NULL);
void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode);
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 68e541eba..1962d42ff 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -504,6 +504,8 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster)
m_Writer.AddFloat("", a_Monster->GetDropChanceBoots());
m_Writer.EndList();
m_Writer.AddByte("CanPickUpLoot", (char)a_Monster->CanPickUpLoot());
+ m_Writer.AddString("CustomName", a_Monster->GetCustomName());
+ m_Writer.AddByte("CustomNameVisible", (char)a_Monster->IsCustomNameAlwaysVisible());
switch (a_Monster->GetMobType())
{
case cMonster::mtBat:
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index e79cc291d..5c155aeef 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -2640,6 +2640,19 @@ bool cWSSAnvil::LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT &
a_Monster.SetCanPickUpLoot(CanPickUpLoot);
}
+ int CustomNameTag = a_NBT.FindChildByName(a_TagIdx, "CustomName");
+ if ((CustomNameTag > 0) && (a_NBT.GetType(CustomNameTag) == TAG_String))
+ {
+ a_Monster.SetCustomName(a_NBT.GetString(CustomNameTag));
+ }
+
+ int CustomNameVisibleTag = a_NBT.FindChildByName(a_TagIdx, "CustomNameVisible");
+ if ((CustomNameVisibleTag > 0) && (a_NBT.GetType(CustomNameVisibleTag) == TAG_Byte))
+ {
+ bool CustomNameVisible = (a_NBT.GetByte(CustomNameVisibleTag) == 1);
+ a_Monster.SetCustomNameAlwaysVisible(CustomNameVisible);
+ }
+
return true;
}