1
0

Split cMap::UpdateClient

This commit is contained in:
andrew 2014-02-21 15:26:33 +02:00
parent f201f4f176
commit 8bf5d116fe
2 changed files with 119 additions and 78 deletions

View File

@ -278,28 +278,35 @@ void cMap::UpdateDecorators(void)
void cMap::UpdateClient(cPlayer * a_Player)
void cMap::AddPlayer(cPlayer * a_Player, cClientHandle * a_Handle, Int64 a_WorldAge)
{
ASSERT(a_Player != NULL);
cClientHandle * Handle = a_Player->GetClientHandle();
cMapClient MapClient;
if (Handle == NULL)
{
return;
}
MapClient.m_LastUpdate = a_WorldAge;
MapClient.m_SendInfo = true;
MapClient.m_Handle = a_Handle;
Int64 WorldAge = a_Player->GetWorld()->GetWorldAge();
m_Clients.push_back(MapClient);
// Remove invalid clients
cMapDecorator PlayerDecorator(this, a_Player);
m_Decorators.push_back(PlayerDecorator);
}
void cMap::RemoveInactiveClients(Int64 a_WorldAge)
{
for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end();)
{
// Check if client is active
if (it->m_LastUpdate < WorldAge - 5)
if (it->m_LastUpdate < a_WorldAge)
{
// Remove associated decorators
for (cMapDecoratorList::iterator it2 = m_Decorators.begin(); it2 != m_Decorators.end();)
{
if (it2->GetPlayer()->GetClientHandle() == Handle)
if (it2->GetPlayer()->GetClientHandle() == it->m_Handle)
{
// Erase decorator
cMapDecoratorList::iterator temp = it2;
@ -322,6 +329,66 @@ void cMap::UpdateClient(cPlayer * a_Player)
++it;
}
}
}
void cMap::StreamNext(cMapClient & a_Client)
{
cClientHandle * Handle = a_Client.m_Handle;
if (a_Client.m_SendInfo)
{
Handle->SendMapInfo(m_ID, m_Scale);
a_Client.m_SendInfo = false;
return;
}
++a_Client.m_NextDecoratorUpdate;
if (a_Client.m_NextDecoratorUpdate >= 4)
{
// TODO 2014-02-19 xdot
// This is dangerous as the player object may have been destroyed before the decorator is erased from the list
UpdateDecorators();
Handle->SendMapDecorators(m_ID, m_Decorators);
a_Client.m_NextDecoratorUpdate = 0;
}
else
{
++a_Client.m_DataUpdate;
unsigned int Y = (a_Client.m_DataUpdate * 11) % m_Width;
const Byte * Colors = &m_Data[Y * m_Height];
Handle->SendMapColumn(m_ID, Y, 0, Colors, m_Height);
}
}
void cMap::UpdateClient(cPlayer * a_Player)
{
ASSERT(a_Player != NULL);
cClientHandle * Handle = a_Player->GetClientHandle();
if (Handle == NULL)
{
return;
}
Int64 WorldAge = a_Player->GetWorld()->GetWorldAge();
RemoveInactiveClients(WorldAge - 5);
// Linear search for client state
for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end(); ++it)
@ -330,55 +397,14 @@ void cMap::UpdateClient(cPlayer * a_Player)
{
it->m_LastUpdate = WorldAge;
if (it->m_SendInfo)
{
Handle->SendMapInfo(m_ID, m_Scale);
it->m_SendInfo = false;
return;
}
++it->m_NextDecoratorUpdate;
if (it->m_NextDecoratorUpdate >= 4)
{
// TODO 2014-02-19 xdot
// This is dangerous as the player object may have been destroyed before the decorator is erased from the list
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);
}
StreamNext(*it);
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);
AddPlayer(a_Player, Handle, WorldAge);
}

View File

@ -105,29 +105,6 @@ public:
typedef std::vector<ColorID> cColorList;
/** Encapsulates the state of a map client.
*
* In order to enhance performace, maps are streamed column-by-column to each client.
* This structure stores the state of the stream.
*/
struct cMapClient
{
cClientHandle * m_Handle;
/** Whether the map scale was modified and needs to be resent. */
bool m_SendInfo;
/** Ticks since last decorator update. */
unsigned int m_NextDecoratorUpdate;
/** Number of pixel data updates. */
Int64 m_DataUpdate;
Int64 m_LastUpdate;
};
typedef std::list<cMapClient> cMapClientList;
public:
@ -185,6 +162,32 @@ public:
// tolua_end
protected:
/** Encapsulates the state of a map client.
*
* In order to enhance performace, maps are streamed column-by-column to each client.
* This structure stores the state of the stream.
*/
struct cMapClient
{
cClientHandle * m_Handle;
/** Whether the map scale was modified and needs to be resent. */
bool m_SendInfo;
/** Ticks since last decorator update. */
unsigned int m_NextDecoratorUpdate;
/** Number of pixel data updates. */
Int64 m_DataUpdate;
Int64 m_LastUpdate;
};
typedef std::list<cMapClient> cMapClientList;
private:
/** Update the associated decorators. */
@ -193,6 +196,15 @@ private:
/** Update the specified pixel. */
bool UpdatePixel(unsigned int a_X, unsigned int a_Z);
/** Add a new map client. */
void AddPlayer(cPlayer * a_Player, cClientHandle * a_Handle, Int64 a_WorldAge);
/** Remove inactive or invalid clients. */
void RemoveInactiveClients(Int64 a_WorldAge);
/** Send next update packet to the specified client. */
void StreamNext(cMapClient & a_Client);
unsigned int m_ID;
unsigned int m_Width;
@ -218,3 +230,6 @@ private:
friend class cMapSerializer;
};