diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index 9f9bde14..58609ffe 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -758,6 +758,30 @@ Server Notification: End Of Game +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +Server Notification: Statistics Changed + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Message Type = 128 | Message Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Statistics | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Statistics Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Statistics Value | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + \ Additional Statistics (Type and Value) / + | + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Statistics Type: + 0x0001: Number of Players currently playing on the server. + 0x0002: Total number of players ever logged in to the server. + 0x0003: Total number of games ever started on the server. + + Server Notification: Removed From Game 0 1 2 3 diff --git a/src/game_defs.h b/src/game_defs.h index a3406065..aa1241a0 100644 --- a/src/game_defs.h +++ b/src/game_defs.h @@ -67,4 +67,12 @@ enum Button { BUTTON_SMALL_BLIND, BUTTON_BIG_BLIND }; +struct ServerStats +{ + ServerStats() : numberOfPlayersOnServer(0), totalPlayersEverLoggedIn(0), totalGamesEverStarted(0) {} + unsigned numberOfPlayersOnServer; + unsigned totalPlayersEverLoggedIn; + unsigned totalGamesEverStarted; +}; + #endif diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index 72c0d85e..ba8c7601 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -115,6 +115,7 @@ void ServerGuiWrapper::SignalNetClientConnect(int actionID) { if (myClientcb) my void ServerGuiWrapper::SignalNetClientGameInfo(int actionID) { if (myClientcb) myClientcb->SignalNetClientGameInfo(actionID); } void ServerGuiWrapper::SignalNetClientError(int errorID, int osErrorID) { if (myClientcb) myClientcb->SignalNetClientError(errorID, osErrorID); } void ServerGuiWrapper::SignalNetClientNotification(int notificationId) { if (myClientcb) myClientcb->SignalNetClientNotification(notificationId); } +void ServerGuiWrapper::SignalNetClientStatsUpdate(const ServerStats &stats) { if (myClientcb) myClientcb->SignalNetClientStatsUpdate(stats); } void ServerGuiWrapper::SignalNetClientRemovedFromGame(int notificationId) { if (myClientcb) myClientcb->SignalNetClientRemovedFromGame(notificationId); } void ServerGuiWrapper::SignalNetClientSelfJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientSelfJoined(playerId, playerName, rights); } void ServerGuiWrapper::SignalNetClientPlayerJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerId, playerName, rights); } diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index c9c32aac..ae4a0ee9 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -98,6 +98,7 @@ public: void SignalNetClientGameInfo(int actionID); void SignalNetClientError(int errorID, int osErrorID); void SignalNetClientNotification(int notificationId); + void SignalNetClientStatsUpdate(const ServerStats &stats); void SignalNetClientRemovedFromGame(int notificationId); void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp index 92a062d6..d45df067 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp @@ -302,8 +302,9 @@ void gameLobbyDialogImpl::refreshGameStats() { void gameLobbyDialogImpl::refreshPlayerStats() { + ServerStats stats = mySession->getClientStats(); label_nickListCounter->setText("| "+tr("players in chat: %1").arg(treeWidget_NickList->topLevelItemCount())); - label_connectedPlayersCounter->setText(tr("connected players: %1").arg(0)); + label_connectedPlayersCounter->setText(tr("connected players: %1").arg(stats.numberOfPlayersOnServer)); } void gameLobbyDialogImpl::gameAddPlayer(unsigned gameId, unsigned playerId) @@ -357,6 +358,11 @@ void gameLobbyDialogImpl::gameRemovePlayer(unsigned gameId, unsigned playerId) } } +void gameLobbyDialogImpl::updateStats(ServerStats /*stats*/) +{ + refreshPlayerStats(); +} + void gameLobbyDialogImpl::clearDialog() { groupBox_GameInfo->setTitle(tr("Game Info")); diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h index 6ad68a5e..b1abfbe2 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h @@ -61,7 +61,9 @@ public slots: void removeGame(unsigned gameId); void gameAddPlayer(unsigned gameId, unsigned playerId); void gameRemovePlayer(unsigned gameId, unsigned playerId); - + + void updateStats(ServerStats stats); + void refreshGameStats(); void refreshPlayerStats(); diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 363d6182..ca33f48b 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -116,6 +116,7 @@ void GuiWrapper::SignalNetClientConnect(int actionID) { myW->signalNetClientConn void GuiWrapper::SignalNetClientGameInfo(int actionID) { myW->signalNetClientGameInfo(actionID); } void GuiWrapper::SignalNetClientError(int errorID, int osErrorID) { myW->signalNetClientError(errorID, osErrorID); } void GuiWrapper::SignalNetClientNotification(int notificationId) { myW->signalNetClientNotification(notificationId); } +void GuiWrapper::SignalNetClientStatsUpdate(const ServerStats &stats) { myW->signalNetClientStatsUpdate(stats); } void GuiWrapper::SignalNetClientRemovedFromGame(int notificationId) { myW->signalNetClientRemovedFromGame(notificationId); } void GuiWrapper::SignalNetClientSelfJoined(unsigned playerId, const string &playerName, PlayerRights rights) { myW->signalNetClientSelfJoined(playerId, QString::fromUtf8(playerName.c_str()), rights); } void GuiWrapper::SignalNetClientPlayerJoined(unsigned playerId, const string &playerName, PlayerRights rights) { myW->signalNetClientPlayerJoined(playerId, QString::fromUtf8(playerName.c_str()), rights); } diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index 3be29668..1bac3397 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -105,6 +105,7 @@ public: void SignalNetClientGameInfo(int actionID); void SignalNetClientError(int errorID, int osErrorID); void SignalNetClientNotification(int notificationId); + void SignalNetClientStatsUpdate(const ServerStats &stats); void SignalNetClientRemovedFromGame(int notificationId); void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index 0a9cec4c..916a2a35 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -695,6 +695,7 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) connect(this, SIGNAL(signalNetClientGameListPlayerJoined(unsigned, unsigned)), myGameLobbyDialog, SLOT(gameAddPlayer(unsigned, unsigned))); connect(this, SIGNAL(signalNetClientGameListPlayerLeft(unsigned, unsigned)), myGameLobbyDialog, SLOT(gameRemovePlayer(unsigned, unsigned))); connect(this, SIGNAL(signalNetClientRemovedFromGame(int)), myGameLobbyDialog, SLOT(removedFromGame(int))); + connect(this, SIGNAL(signalNetClientStatsUpdate(ServerStats)), myGameLobbyDialog, SLOT(updateStats(ServerStats))); // Errors are handled globally, not within one dialog. connect(this, SIGNAL(signalNetClientError(int, int)), this, SLOT(networkError(int, int))); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index 726c7c2c..4301e25c 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -126,6 +126,7 @@ signals: void signalNetClientGameInfo(int actionID); void signalNetClientError(int errorID, int osErrorID); void signalNetClientNotification(int notificationId); + void signalNetClientStatsUpdate(ServerStats stats); void signalNetClientRemovedFromGame(int notificationId); void signalNetServerError(int errorID, int osErrorID); void signalNetClientSelfJoined(unsigned playerId, QString playerName, int rights); diff --git a/src/net/clientcallback.h b/src/net/clientcallback.h index c2fd999e..37102b04 100644 --- a/src/net/clientcallback.h +++ b/src/net/clientcallback.h @@ -24,6 +24,7 @@ #include #include #include +#include #include class Game; @@ -37,6 +38,7 @@ public: virtual void SignalNetClientGameInfo(int actionID) = 0; virtual void SignalNetClientError(int errorID, int osErrorID) = 0; virtual void SignalNetClientNotification(int notificationId) = 0; + virtual void SignalNetClientStatsUpdate(const ServerStats &stats) = 0; virtual void SignalNetClientRemovedFromGame(int notificationId) = 0; virtual void SignalNetClientGameListNew(unsigned gameId) = 0; diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 24eff246..ad45d10b 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -67,6 +67,7 @@ public: GameInfo GetGameInfo(unsigned playerId) const; PlayerInfo GetPlayerInfo(unsigned playerId) const; + ServerStats GetStatData() const; ClientCallback &GetCallback(); GuiInterface &GetGui(); @@ -134,6 +135,8 @@ protected: void ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId); void ClearGameInfoMap(); + void UpdateStatData(const ServerStats &stats); + bool IsSessionEstablished() const; void SetSessionEstablished(bool flag); @@ -172,6 +175,9 @@ private: unsigned m_guiPlayerId; bool m_sessionEstablished; + mutable boost::mutex m_curStatsMutex; + ServerStats m_curStats; + friend class AbstractClientStateReceiving; friend class ClientStateInit; friend class ClientStateStartResolve; diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index fdca428f..79b32f12 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -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. diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index dd5a9669..394ea296 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -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 { diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index e4097b7b..f39a6715 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -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(new NetPacketEndOfGame); break; + case NET_TYPE_STATISTICS_CHANGED: + tmpPacket = boost::shared_ptr(new NetPacketStatisticsChanged); + break; case NET_TYPE_REMOVED_FROM_GAME: tmpPacket = boost::shared_ptr(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 +NetPacketStatisticsChanged::Clone() const +{ + boost::shared_ptr 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)) { diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index a59b9493..c3196afc 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -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 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 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(packet.get())->SetData(statData); + + m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game); +} + ServerCallback & ServerLobbyThread::GetCallback() { diff --git a/src/net/netpacket.h b/src/net/netpacket.h index 44a9c582..1e06803f 100644 --- a/src/net/netpacket.h +++ b/src/net/netpacket.h @@ -85,6 +85,7 @@ class NetPacketAllInShowCards; class NetPacketEndOfHandShowCards; class NetPacketEndOfHandHideCards; class NetPacketEndOfGame; +class NetPacketStatisticsChanged; class NetPacketRemovedFromGame; class NetPacketSendChatText; class NetPacketChatText; @@ -146,6 +147,7 @@ public: virtual const NetPacketEndOfHandShowCards *ToNetPacketEndOfHandShowCards() const; virtual const NetPacketEndOfHandHideCards *ToNetPacketEndOfHandHideCards() const; virtual const NetPacketEndOfGame *ToNetPacketEndOfGame() const; + virtual const NetPacketStatisticsChanged *ToNetPacketStatisticsChanged() const; virtual const NetPacketRemovedFromGame *ToNetPacketRemovedFromGame() const; virtual const NetPacketSendChatText *ToNetPacketSendChatText() const; virtual const NetPacketChatText *ToNetPacketChatText() const; @@ -1121,6 +1123,29 @@ protected: virtual void InternalCheck(const NetPacketHeader* data) const; }; +class NetPacketStatisticsChanged : public NetPacket +{ +public: + struct Data + { + ServerStats stats; + }; + + NetPacketStatisticsChanged(); + virtual ~NetPacketStatisticsChanged(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketStatisticsChanged *ToNetPacketStatisticsChanged() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + class NetPacketRemovedFromGame : public NetPacket { public: diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index b372b6d4..53944ffc 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -120,6 +120,7 @@ protected: void SendError(SOCKET s, int errorCode); void SendJoinGameFailed(SOCKET s, int reason); void SendGameList(SOCKET s); + void BroadcastStatisticsUpdate(); SenderThread &GetSender(); ReceiverHelper &GetReceiver(); @@ -168,6 +169,10 @@ private: u_int32_t m_curUniquePlayerId; mutable boost::mutex m_curUniquePlayerIdMutex; + + unsigned m_totalPlayersLoggedIn; + unsigned m_totalGamesStarted; + ServerStats m_lastStatData; }; #endif diff --git a/src/pokerth.cpp b/src/pokerth.cpp index e4769e50..effcfc28 100755 --- a/src/pokerth.cpp +++ b/src/pokerth.cpp @@ -110,6 +110,7 @@ int main( int argc, char **argv ) qRegisterMetaType("unsigned"); qRegisterMetaType >("boost::shared_ptr"); + qRegisterMetaType("ServerStats"); /////////////////////////////////////////////////// diff --git a/src/session.cpp b/src/session.cpp index fbbf7182..70804697 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -363,3 +363,11 @@ PlayerInfo Session::getClientPlayerInfo(unsigned playerId) return info; } +ServerStats Session::getClientStats() +{ + ServerStats stats; + if (myNetClient) + stats = myNetClient->GetStatData(); + return stats; +} + diff --git a/src/session.h b/src/session.h index 2d732994..ba7b49c2 100755 --- a/src/session.h +++ b/src/session.h @@ -83,6 +83,7 @@ public: GameInfo getClientGameInfo(unsigned gameId); PlayerInfo getClientPlayerInfo(unsigned playerId); + ServerStats getClientStats(); private: