Add server statistics which are sent by the server to every client each time they change.

This commit is contained in:
lotodore
2007-10-20 22:22:11 +00:00
parent c5246aaef3
commit 4bc57f07d0
21 changed files with 302 additions and 3 deletions
+24
View File
@@ -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
+8
View File
@@ -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
+1
View File
@@ -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); }
+1
View File
@@ -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);
@@ -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"));
@@ -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();
+1
View File
@@ -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); }
+1
View File
@@ -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);
+1
View File
@@ -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)));
+1
View File
@@ -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);
+2
View File
@@ -24,6 +24,7 @@
#include <string>
#include <boost/shared_ptr.hpp>
#include <playerdata.h>
#include <game_defs.h>
#include <gamedata.h>
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;
+6
View File
@@ -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;
+6
View File
@@ -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.
+23
View File
@@ -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
{
+149
View File
@@ -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))
{
+28 -1
View File
@@ -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()
{
+25
View File
@@ -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<NetPacket> 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:
+5
View File
@@ -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
+1
View File
@@ -110,6 +110,7 @@ int main( int argc, char **argv )
qRegisterMetaType<unsigned>("unsigned");
qRegisterMetaType<boost::shared_ptr<Game> >("boost::shared_ptr<Game>");
qRegisterMetaType<ServerStats>("ServerStats");
///////////////////////////////////////////////////
+8
View File
@@ -363,3 +363,11 @@ PlayerInfo Session::getClientPlayerInfo(unsigned playerId)
return info;
}
ServerStats Session::getClientStats()
{
ServerStats stats;
if (myNetClient)
stats = myNetClient->GetStatData();
return stats;
}
+1
View File
@@ -83,6 +83,7 @@ public:
GameInfo getClientGameInfo(unsigned gameId);
PlayerInfo getClientPlayerInfo(unsigned playerId);
ServerStats getClientStats();
private: