summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ClientHandle.cpp22
-rw-r--r--src/ClientHandle.h2
-rw-r--r--src/Items/ItemMap.h4
-rw-r--r--src/Map.cpp232
-rw-r--r--src/Map.h75
-rw-r--r--src/Protocol/Protocol.h3
-rw-r--r--src/Protocol/Protocol125.cpp25
-rw-r--r--src/Protocol/Protocol125.h1
-rw-r--r--src/Protocol/Protocol17x.cpp20
-rw-r--r--src/Protocol/Protocol17x.h1
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp10
-rw-r--r--src/Protocol/ProtocolRecognizer.h1
12 files changed, 351 insertions, 45 deletions
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index a2cbaefff..efc5a9f64 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -1190,19 +1190,6 @@ void cClientHandle::HandleSlotSelected(short a_SlotNum)
{
m_Player->GetInventory().SetEquippedSlotNum(a_SlotNum);
m_Player->GetWorld()->BroadcastEntityEquipment(*m_Player, 0, m_Player->GetInventory().GetEquippedItem(), this);
-
- const cItem & Item = m_Player->GetInventory().GetEquippedItem();
- if (Item.m_ItemType == E_ITEM_MAP)
- {
- // TODO 2014-02-14 xdot: Do not hardcode this.
- cMap * Map = m_Player->GetWorld()->GetMapData(Item.m_ItemDamage);
-
- if (Map != NULL)
- {
- // TODO 2014-02-14 xdot: Optimization - Do not send the whole map.
- Map->SendTo(*this);
- }
- }
}
@@ -2079,6 +2066,15 @@ void cClientHandle::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Col
+void cClientHandle::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators)
+{
+ m_Protocol->SendMapDecorators(a_ID, a_Decorators);
+}
+
+
+
+
+
void cClientHandle::SendMapInfo(int a_ID, unsigned int a_Scale)
{
m_Protocol->SendMapInfo(a_ID, a_Scale);
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index a714cf8b9..a613a76e8 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -17,6 +17,7 @@
#include "ChunkDef.h"
#include "ByteBuffer.h"
#include "Scoreboard.h"
+#include "Map.h"
@@ -110,6 +111,7 @@ public:
void SendHealth (void);
void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item);
void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length);
+ void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators);
void SendMapInfo (int a_ID, unsigned int a_Scale);
void SendPickupSpawn (const cPickup & a_Pickup);
void SendEntityAnimation (const cEntity & a_Entity, char a_Animation);
diff --git a/src/Items/ItemMap.h b/src/Items/ItemMap.h
index c3e605547..9bb16b189 100644
--- a/src/Items/ItemMap.h
+++ b/src/Items/ItemMap.h
@@ -36,8 +36,8 @@ public:
return;
}
- // Map->AddTrackedPlayer(a_Player);
-
Map->UpdateRadius(*a_Player, DEFAULT_RADIUS);
+
+ Map->UpdateClient(a_Player);
}
} ;
diff --git a/src/Map.cpp b/src/Map.cpp
index e85c23d3a..f32d232fa 100644
--- a/src/Map.cpp
+++ b/src/Map.cpp
@@ -14,6 +14,111 @@
+cMapDecorator::cMapDecorator(cMap * a_Map, eType a_Type, int a_X, int a_Z, unsigned int a_Rot)
+ : m_Map(a_Map)
+ , m_Type(a_Type)
+ , m_PixelX(a_X)
+ , m_PixelZ(a_Z)
+ , m_Rot(a_Rot)
+ , m_Player(NULL)
+{
+}
+
+
+
+
+
+cMapDecorator::cMapDecorator(cMap * a_Map, cPlayer * a_Player)
+ : m_Map(a_Map)
+ , m_Type(E_TYPE_PLAYER)
+ , m_Player(a_Player)
+{
+ Update();
+}
+
+
+
+
+
+template <typename T>
+T Clamp(T a_X, T a_Min, T a_Max)
+{
+ return std::min(std::max(a_X, a_Min), a_Max);
+}
+
+
+
+
+
+void cMapDecorator::Update(void)
+{
+ ASSERT(m_Map != NULL);
+ unsigned int PixelWidth = m_Map->GetPixelWidth();
+
+ int InsideWidth = (m_Map->GetWidth() / 2) - 1;
+ int InsideHeight = (m_Map->GetHeight() / 2) - 1;
+
+ if (m_Player)
+ {
+ int PixelX = (m_Player->GetPosX() - m_Map->GetCenterX()) / PixelWidth;
+ int PixelZ = (m_Player->GetPosZ() - m_Map->GetCenterZ()) / PixelWidth;
+
+ // Center of pixel
+ m_PixelX = (2 * PixelX) + 1;
+ m_PixelZ = (2 * PixelZ) + 1;
+
+ // 1px border
+ if ((PixelX > -InsideWidth) && (PixelX <= InsideWidth) && (PixelZ > -InsideHeight) && (PixelZ <= InsideHeight))
+ {
+ double Yaw = m_Player->GetYaw();
+
+ m_Rot = (Yaw * 16) / 360;
+
+ if (m_Map->GetDimension() == dimNether)
+ {
+ Int64 WorldAge = m_Player->GetWorld()->GetWorldAge();
+
+ // TODO 2014-02-18 xdot: Random rotations
+ }
+
+ m_Type = E_TYPE_PLAYER;
+ }
+ else
+ {
+ if ((abs(PixelX) > 320.0) || (abs(PixelZ) > 320.0))
+ {
+ // TODO 2014-02-18 xdot: Remove decorator
+ }
+
+ m_Rot = 0;
+
+ m_Type = E_TYPE_PLAYER_OUTSIDE;
+
+ // Move to border
+ if (PixelX <= -InsideWidth)
+ {
+ m_PixelX = (2 * -InsideWidth) + 1;
+ }
+ if (PixelZ <= -InsideHeight)
+ {
+ m_PixelZ = (2 * -InsideHeight) + 1;
+ }
+ if (PixelX > InsideWidth)
+ {
+ m_PixelX = (2 * InsideWidth) + 1;
+ }
+ if (PixelZ > InsideHeight)
+ {
+ m_PixelZ = (2 * InsideHeight) + 1;
+ }
+ }
+ }
+}
+
+
+
+
+
cMap::cMap(unsigned int a_ID, cWorld * a_World)
: m_ID(a_ID)
, m_Width(cChunkDef::Width * 8)
@@ -50,16 +155,6 @@ cMap::cMap(unsigned int a_ID, int a_CenterX, int a_CenterZ, cWorld * a_World, un
-template <typename T>
-T Clamp(T a_X, T a_Min, T a_Max)
-{
- return std::min(std::max(a_X, a_Min), a_Max);
-}
-
-
-
-
-
void cMap::UpdateRadius(int a_PixelX, int a_PixelZ, unsigned int a_Radius)
{
int PixelRadius = a_Radius / GetPixelWidth();
@@ -174,33 +269,117 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
-void cMap::UpdateTrackedPlayers(void)
+void cMap::UpdateDecorators(void)
+{
+ for (cMapDecoratorList::iterator it = m_Decorators.begin(); it != m_Decorators.end(); ++it)
+ {
+ it->Update();
+ }
+}
+
+
+
+
+
+void cMap::UpdateClient(cPlayer * a_Player)
{
- cTrackedPlayerList NewList;
+ ASSERT(a_Player != NULL);
+ cClientHandle * Handle = a_Player->GetClientHandle();
- for (cTrackedPlayerList::iterator it = m_TrackedPlayers.begin(); it != m_TrackedPlayers.end(); ++it)
+ if (Handle == NULL)
{
- cPlayer * Player = *it;
+ return;
+ }
+
+ Int64 WorldAge = a_Player->GetWorld()->GetWorldAge();
- UpdateRadius(*Player, DEFAULT_RADIUS);
+ // Remove invalid clients
+ for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end();)
+ {
+ // Check if client is active
+ if (it->m_LastUpdate < WorldAge - 5)
+ {
+ // Remove associated decorators
+ for (cMapDecoratorList::iterator it2 = m_Decorators.begin(); it2 != m_Decorators.end();)
+ {
+ if (it2->GetPlayer()->GetClientHandle() == Handle)
+ {
+ // Erase decorator
+ cMapDecoratorList::iterator temp = it2;
+ ++it2;
+ m_Decorators.erase(temp);
+ }
+ else
+ {
+ ++it2;
+ }
+ }
- if (true)
+ // Erase client
+ cMapClientList::iterator temp = it;
+ ++it;
+ m_Clients.erase(temp);
+ }
+ else
{
- NewList.insert(Player);
+ ++it;
}
}
- std::swap(m_TrackedPlayers, NewList);
-}
+ // Linear search for client state
+ for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end(); ++it)
+ {
+ if (it->m_Handle == Handle)
+ {
+ it->m_LastUpdate = WorldAge;
+ if (it->m_SendInfo)
+ {
+ Handle->SendMapInfo(m_ID, m_Scale);
+ it->m_SendInfo = false;
+ return;
+ }
+ ++it->m_NextDecoratorUpdate;
-void cMap::AddTrackedPlayer(cPlayer * a_Player)
-{
- ASSERT(a_Player != NULL);
- m_TrackedPlayers.insert(a_Player);
+ if (it->m_NextDecoratorUpdate >= 4)
+ {
+ UpdateDecorators();
+
+ Handle->SendMapDecorators(m_ID, m_Decorators);
+
+ it->m_NextDecoratorUpdate = 0;
+ }
+ else
+ {
+ ++it->m_DataUpdate;
+
+ unsigned int Y = (it->m_DataUpdate * 11) % m_Width;
+
+ const Byte * Colors = &m_Data[Y * m_Height];
+
+ Handle->SendMapColumn(m_ID, Y, 0, Colors, m_Height);
+ }
+
+ return;
+ }
+ }
+
+ // New player, construct a new client state
+ cMapClient MapClient;
+
+ MapClient.m_LastUpdate = WorldAge;
+ MapClient.m_SendInfo = true;
+ MapClient.m_Handle = a_Player->GetClientHandle();
+
+ m_Clients.push_back(MapClient);
+
+ // Insert new decorator
+ cMapDecorator PlayerDecorator(this, a_Player);
+
+ m_Decorators.push_back(PlayerDecorator);
}
@@ -267,6 +446,11 @@ void cMap::SetScale(unsigned int a_Scale)
}
m_Scale = a_Scale;
+
+ for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end(); ++it)
+ {
+ it->m_SendInfo = true;
+ }
}
@@ -283,6 +467,8 @@ void cMap::SendTo(cClientHandle & a_Client)
a_Client.SendMapColumn(m_ID, i, 0, Colors, m_Height);
}
+
+ a_Client.SendMapDecorators(m_ID, m_Decorators);
}
diff --git a/src/Map.h b/src/Map.h
index 805dfb845..76e459621 100644
--- a/src/Map.h
+++ b/src/Map.h
@@ -22,6 +22,55 @@
class cClientHandle;
class cWorld;
class cPlayer;
+class cMap;
+
+
+
+
+
+class cMapDecorator
+{
+public:
+ enum eType
+ {
+ E_TYPE_PLAYER = 0x00,
+ E_TYPE_ITEM_FRAME = 0x01,
+ E_TYPE_PLAYER_OUTSIDE = 0x06
+ };
+
+
+public:
+
+ cMapDecorator(cMap * a_Map, eType a_Type, int a_X, int a_Z, unsigned int a_Rot);
+
+ cMapDecorator(cMap * a_Map, cPlayer * a_Player);
+
+ void Update(void);
+
+ unsigned int GetPixelX(void) const { return m_PixelX; }
+ unsigned int GetPixelZ(void) const { return m_PixelZ; }
+ unsigned int GetRot(void) const { return m_Rot; }
+
+ eType GetType(void) const { return m_Type; }
+
+ cPlayer * GetPlayer(void) { return m_Player; }
+
+
+protected:
+
+ cMap * m_Map;
+
+ eType m_Type;
+
+ unsigned int m_PixelX;
+ unsigned int m_PixelZ;
+
+ unsigned int m_Rot;
+
+ cPlayer * m_Player;
+};
+
+typedef std::list<cMapDecorator> cMapDecoratorList;
@@ -38,7 +87,19 @@ public:
typedef std::vector<ColorID> cColorList;
- static const unsigned int DEFAULT_RADIUS = 128;
+ struct cMapClient
+ {
+ cClientHandle * m_Handle;
+
+ bool m_SendInfo;
+
+ unsigned int m_NextDecoratorUpdate;
+
+ Int64 m_DataUpdate;
+ Int64 m_LastUpdate;
+ };
+
+ typedef std::list<cMapClient> cMapClientList;
public:
@@ -56,9 +117,8 @@ public:
void UpdateRadius(cPlayer & a_Player, unsigned int a_Radius);
- void UpdateTrackedPlayers(void);
-
- void AddTrackedPlayer(cPlayer * a_Player);
+ /** Send next update packet and remove invalid decorators */
+ void UpdateClient(cPlayer * a_Player);
// tolua_begin
@@ -98,6 +158,9 @@ public:
private:
+ /** Update the associated decorators. */
+ void UpdateDecorators(void);
+
/** Update the specified pixel. */
bool UpdatePixel(unsigned int a_X, unsigned int a_Z);
@@ -117,9 +180,9 @@ private:
cWorld * m_World;
- typedef std::set<cPlayer*> cTrackedPlayerList;
+ cMapDecoratorList m_Decorators;
- cTrackedPlayerList m_TrackedPlayers;
+ cMapClientList m_Clients;
AString m_Name;
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 5f89799e1..4a1601487 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -13,6 +13,7 @@
#include "../Defines.h"
#include "../Endianness.h"
#include "../Scoreboard.h"
+#include "../Map.h"
@@ -28,7 +29,6 @@ class cWorld;
class cMonster;
class cChunkDataSerializer;
class cFallingBlock;
-class cMap;
@@ -81,6 +81,7 @@ public:
virtual void SendKeepAlive (int a_PingID) = 0;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) = 0;
virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) = 0;
+ virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) = 0;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) = 0;
virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0;
virtual void SendPlayerAbilities (void) = 0;
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index edb22fae6..220fa18cf 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -602,6 +602,31 @@ void cProtocol125::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colo
+void cProtocol125::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators)
+{
+ cCSLock Lock(m_CSPacket);
+
+ WriteByte (PACKET_ITEM_DATA);
+ WriteShort(E_ITEM_MAP);
+ WriteShort(a_ID);
+ WriteShort(1 + (3 * a_Decorators.size()));
+
+ WriteByte(1);
+
+ for (cMapDecoratorList::const_iterator it = a_Decorators.begin(); it != a_Decorators.end(); ++it)
+ {
+ WriteByte((it->GetType() << 4) | (it->GetRot() & 0xf));
+ WriteByte(it->GetPixelX());
+ WriteByte(it->GetPixelZ());
+ }
+
+ Flush();
+}
+
+
+
+
+
void cProtocol125::SendPickupSpawn(const cPickup & a_Pickup)
{
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index 467aee002..1eeb15120 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -55,6 +55,7 @@ public:
virtual void SendKeepAlive (int a_PingID) override;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override;
+ virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override {} // This protocol doesn't support such message
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 SendPickupSpawn (const cPickup & a_Pickup) override;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 4acc61586..38b4ed786 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -516,6 +516,26 @@ void cProtocol172::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colo
+void cProtocol172::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators)
+{
+ cPacketizer Pkt(*this, 0x34);
+ Pkt.WriteVarInt(a_ID);
+ Pkt.WriteShort (1 + (3 * a_Decorators.size()));
+
+ Pkt.WriteByte(1);
+
+ for (cMapDecoratorList::const_iterator it = a_Decorators.begin(); it != a_Decorators.end(); ++it)
+ {
+ Pkt.WriteByte((it->GetType() << 4) | (it->GetRot() & 0xf));
+ Pkt.WriteByte(it->GetPixelX());
+ Pkt.WriteByte(it->GetPixelZ());
+ }
+}
+
+
+
+
+
void cProtocol172::SendMapInfo(int a_ID, unsigned int a_Scale)
{
cPacketizer Pkt(*this, 0x34);
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 0e50db45d..4edf51d2f 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -77,6 +77,7 @@ public:
virtual void SendKeepAlive (int a_PingID) override;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override;
+ virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override;
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 447fa516b..0a9369c0d 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -396,6 +396,16 @@ void cProtocolRecognizer::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte *
+void cProtocolRecognizer::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendMapDecorators(a_ID, a_Decorators);
+}
+
+
+
+
+
void cProtocolRecognizer::SendMapInfo(int a_ID, unsigned int a_Scale)
{
ASSERT(m_Protocol != NULL);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 3c37d5138..ff4549ff5 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -90,6 +90,7 @@ public:
virtual void SendKeepAlive (int a_PingID) override;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override;
+ virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) 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 SendPickupSpawn (const cPickup & a_Pickup) override;