Add server statistics which are sent by the server to every client each time they change.
This commit is contained in:
@@ -518,6 +518,12 @@ AbstractClientStateReceiving::Process(ClientThread &client)
|
||||
tmpPacket->ToNetPacketUnknownAvatar()->GetData(unknownAvatarData);
|
||||
client.SetUnknownAvatar(unknownAvatarData.requestId);
|
||||
}
|
||||
else if (tmpPacket->ToNetPacketStatisticsChanged())
|
||||
{
|
||||
NetPacketStatisticsChanged::Data statData;
|
||||
tmpPacket->ToNetPacketStatisticsChanged()->GetData(statData);
|
||||
client.UpdateStatData(statData.stats);
|
||||
}
|
||||
else if (tmpPacket->ToNetPacketError())
|
||||
{
|
||||
// Server reported an error.
|
||||
|
||||
@@ -860,6 +860,29 @@ ClientThread::ClearGameInfoMap()
|
||||
m_gameInfoMap.clear();
|
||||
}
|
||||
|
||||
void
|
||||
ClientThread::UpdateStatData(const ServerStats &stats)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_curStatsMutex);
|
||||
if (stats.numberOfPlayersOnServer)
|
||||
m_curStats.numberOfPlayersOnServer = stats.numberOfPlayersOnServer;
|
||||
|
||||
if (stats.totalPlayersEverLoggedIn)
|
||||
m_curStats.totalPlayersEverLoggedIn = stats.totalPlayersEverLoggedIn;
|
||||
|
||||
if (stats.totalGamesEverStarted)
|
||||
m_curStats.totalGamesEverStarted = stats.totalGamesEverStarted;
|
||||
|
||||
GetCallback().SignalNetClientStatsUpdate(m_curStats);
|
||||
}
|
||||
|
||||
ServerStats
|
||||
ClientThread::GetStatData() const
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_curStatsMutex);
|
||||
return m_curStats;
|
||||
}
|
||||
|
||||
bool
|
||||
ClientThread::IsSessionEstablished() const
|
||||
{
|
||||
|
||||
@@ -66,6 +66,7 @@ using namespace std;
|
||||
#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x0064
|
||||
#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x0065
|
||||
#define NET_TYPE_END_OF_GAME 0x0070
|
||||
#define NET_TYPE_STATISTICS_CHANGED 0x0080
|
||||
|
||||
#define NET_TYPE_REMOVED_FROM_GAME 0x0100
|
||||
|
||||
@@ -112,6 +113,11 @@ using namespace std;
|
||||
#define NET_ERR_GENERAL_PLAYER_KICKED 0xFF03
|
||||
#define NET_ERR_OTHER 0xFFFF
|
||||
|
||||
// Statistics types
|
||||
#define NET_STAT_CUR_PLAYERS_ON_SERVER 0x0001
|
||||
#define NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER 0x0002
|
||||
#define NET_STAT_TOTAL_GAMES_EVER_ON_SERVER 0x0003
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#define GCC_PACKED
|
||||
@@ -469,6 +475,19 @@ struct GCC_PACKED NetPacketEndOfGameData
|
||||
u_int32_t winnerPlayerId;
|
||||
};
|
||||
|
||||
struct GCC_PACKED StatisticsData
|
||||
{
|
||||
u_int32_t statisticsType;
|
||||
u_int32_t statisticsValue;
|
||||
};
|
||||
|
||||
struct GCC_PACKED NetPacketStatisticsChangedData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
u_int16_t numberOfStatistics;
|
||||
u_int16_t reserved;
|
||||
};
|
||||
|
||||
struct GCC_PACKED NetPacketRemovedFromGameData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
@@ -735,6 +754,9 @@ NetPacket::Create(char *data, unsigned &dataSize)
|
||||
case NET_TYPE_END_OF_GAME:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketEndOfGame);
|
||||
break;
|
||||
case NET_TYPE_STATISTICS_CHANGED:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketStatisticsChanged);
|
||||
break;
|
||||
case NET_TYPE_REMOVED_FROM_GAME:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketRemovedFromGame);
|
||||
break;
|
||||
@@ -1065,6 +1087,12 @@ NetPacket::ToNetPacketEndOfGame() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NetPacketStatisticsChanged *
|
||||
NetPacket::ToNetPacketStatisticsChanged() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NetPacketRemovedFromGame *
|
||||
NetPacket::ToNetPacketRemovedFromGame() const
|
||||
{
|
||||
@@ -4033,6 +4061,127 @@ NetPacketEndOfGame::InternalCheck(const NetPacketHeader*) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketStatisticsChanged::NetPacketStatisticsChanged()
|
||||
: NetPacket(NET_TYPE_STATISTICS_CHANGED, sizeof(NetPacketStatisticsChangedData), MAX_PACKET_SIZE)
|
||||
{
|
||||
}
|
||||
|
||||
NetPacketStatisticsChanged::~NetPacketStatisticsChanged()
|
||||
{
|
||||
}
|
||||
|
||||
boost::shared_ptr<NetPacket>
|
||||
NetPacketStatisticsChanged::Clone() const
|
||||
{
|
||||
boost::shared_ptr<NetPacket> newPacket(new NetPacketStatisticsChanged);
|
||||
try
|
||||
{
|
||||
newPacket->SetRawData(GetRawData());
|
||||
} catch (const NetException &)
|
||||
{
|
||||
// Need to return the new packet anyway.
|
||||
}
|
||||
return newPacket;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketStatisticsChanged::SetData(const NetPacketStatisticsChanged::Data &inData)
|
||||
{
|
||||
u_int16_t numValues = 0;
|
||||
if (inData.stats.numberOfPlayersOnServer)
|
||||
++numValues;
|
||||
if (inData.stats.totalPlayersEverLoggedIn)
|
||||
++numValues;
|
||||
if (inData.stats.totalGamesEverStarted)
|
||||
++numValues;
|
||||
|
||||
// Resize the packet so that the data fits in.
|
||||
Resize((u_int16_t)
|
||||
(sizeof(NetPacketStatisticsChangedData) + numValues * sizeof(StatisticsData)));
|
||||
|
||||
NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)GetRawData();
|
||||
|
||||
tmpData->numberOfStatistics = htons(numValues);
|
||||
|
||||
StatisticsData *curStatisticsData =
|
||||
(StatisticsData *)((char *)tmpData + sizeof(NetPacketStatisticsChangedData));
|
||||
|
||||
if (inData.stats.numberOfPlayersOnServer)
|
||||
{
|
||||
curStatisticsData->statisticsType = htonl(NET_STAT_CUR_PLAYERS_ON_SERVER);
|
||||
curStatisticsData->statisticsValue = htonl(inData.stats.numberOfPlayersOnServer);
|
||||
++curStatisticsData;
|
||||
}
|
||||
if (inData.stats.totalPlayersEverLoggedIn)
|
||||
{
|
||||
curStatisticsData->statisticsType = htonl(NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER);
|
||||
curStatisticsData->statisticsValue = htonl(inData.stats.totalPlayersEverLoggedIn);
|
||||
++curStatisticsData;
|
||||
}
|
||||
if (inData.stats.totalGamesEverStarted)
|
||||
{
|
||||
curStatisticsData->statisticsType = htonl(NET_STAT_TOTAL_GAMES_EVER_ON_SERVER);
|
||||
curStatisticsData->statisticsValue = htonl(inData.stats.totalGamesEverStarted);
|
||||
}
|
||||
|
||||
// Check the packet - just in case.
|
||||
Check(GetRawData());
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketStatisticsChanged::GetData(NetPacketStatisticsChanged::Data &outData) const
|
||||
{
|
||||
NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)GetRawData();
|
||||
|
||||
u_int16_t numStatistics = ntohs(tmpData->numberOfStatistics);
|
||||
StatisticsData *curStatisticsData =
|
||||
(StatisticsData *)((char *)tmpData + sizeof(NetPacketStatisticsChangedData));
|
||||
|
||||
for (int i = 0; i < numStatistics; i++)
|
||||
{
|
||||
switch(ntohl(curStatisticsData->statisticsType))
|
||||
{
|
||||
case NET_STAT_CUR_PLAYERS_ON_SERVER:
|
||||
outData.stats.numberOfPlayersOnServer = ntohl(curStatisticsData->statisticsValue);
|
||||
break;
|
||||
case NET_STAT_TOTAL_PLAYERS_EVER_ON_SERVER:
|
||||
outData.stats.totalPlayersEverLoggedIn = ntohl(curStatisticsData->statisticsValue);
|
||||
break;
|
||||
case NET_STAT_TOTAL_GAMES_EVER_ON_SERVER:
|
||||
outData.stats.totalGamesEverStarted = ntohl(curStatisticsData->statisticsValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const NetPacketStatisticsChanged *
|
||||
NetPacketStatisticsChanged::ToNetPacketStatisticsChanged() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketStatisticsChanged::InternalCheck(const NetPacketHeader *data) const
|
||||
{
|
||||
u_int16_t dataLen = ntohs(data->length);
|
||||
NetPacketStatisticsChangedData *tmpData = (NetPacketStatisticsChangedData *)data;
|
||||
int numStatistics = ntohs(tmpData->numberOfStatistics);
|
||||
|
||||
if (dataLen !=
|
||||
sizeof(NetPacketStatisticsChangedData)
|
||||
+ numStatistics * sizeof(StatisticsData))
|
||||
{
|
||||
throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
if (!numStatistics)
|
||||
{
|
||||
throw NetException(__FILE__, __LINE__, ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
// Semantic checks not needed, this packet is sent by the server.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketRemovedFromGame::NetPacketRemovedFromGame()
|
||||
: NetPacket(NET_TYPE_REMOVED_FROM_GAME, sizeof(NetPacketRemovedFromGameData), sizeof(NetPacketRemovedFromGameData))
|
||||
{
|
||||
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
|
||||
ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager)
|
||||
: m_gui(gui), m_avatarManager(avatarManager), m_playerConfig(playerConfig),
|
||||
m_curGameId(0), m_curUniquePlayerId(0)
|
||||
m_curGameId(0), m_curUniquePlayerId(0), m_totalPlayersLoggedIn(0), m_totalGamesStarted(0)
|
||||
{
|
||||
m_senderCallback.reset(new ServerSenderCallback(*this));
|
||||
m_sender.reset(new SenderThread(GetSenderCallback()));
|
||||
@@ -634,6 +634,10 @@ ServerLobbyThread::EstablishSession(SessionWrapper session)
|
||||
|
||||
// Session is now established.
|
||||
session.sessionData->SetState(SessionData::Established);
|
||||
|
||||
++m_totalPlayersLoggedIn;
|
||||
|
||||
BroadcastStatisticsUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -698,6 +702,9 @@ ServerLobbyThread::InternalAddGame(boost::shared_ptr<ServerGameThread> game)
|
||||
// Notify all players.
|
||||
m_sessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established);
|
||||
m_gameSessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game);
|
||||
|
||||
++m_totalGamesStarted;
|
||||
BroadcastStatisticsUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -828,6 +835,26 @@ ServerLobbyThread::SendGameList(SOCKET s)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServerLobbyThread::BroadcastStatisticsUpdate()
|
||||
{
|
||||
boost::shared_ptr<NetPacket> packet(new NetPacketStatisticsChanged);
|
||||
NetPacketStatisticsChanged::Data statData;
|
||||
|
||||
unsigned curNumberOfPlayersOnServer = m_sessionManager.GetRawSessionCount() + m_gameSessionManager.GetRawSessionCount();
|
||||
if (curNumberOfPlayersOnServer != m_lastStatData.numberOfPlayersOnServer)
|
||||
m_lastStatData.numberOfPlayersOnServer = statData.stats.numberOfPlayersOnServer = curNumberOfPlayersOnServer;
|
||||
if (m_totalPlayersLoggedIn != m_lastStatData.totalPlayersEverLoggedIn)
|
||||
m_lastStatData.totalPlayersEverLoggedIn = statData.stats.totalPlayersEverLoggedIn = m_totalPlayersLoggedIn;
|
||||
if (m_totalGamesStarted != m_lastStatData.totalGamesEverStarted)
|
||||
m_lastStatData.totalGamesEverStarted = statData.stats.totalGamesEverStarted = m_totalGamesStarted;
|
||||
|
||||
static_cast<NetPacketStatisticsChanged *>(packet.get())->SetData(statData);
|
||||
|
||||
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
|
||||
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
|
||||
}
|
||||
|
||||
ServerCallback &
|
||||
ServerLobbyThread::GetCallback()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user