From 076d44b0aeb3236e702a082c6543dc38fed88870 Mon Sep 17 00:00:00 2001 From: lotodore Date: Wed, 3 Oct 2007 13:36:47 +0000 Subject: [PATCH] Pass on admin state if the admin leaves the network game, so that someone else can start the game. --- docs/net_protocol.txt | 43 ++++--- src/gui/generic/serverguiwrapper.cpp | 9 +- src/gui/generic/serverguiwrapper.h | 1 + .../gamelobbydialog/gamelobbydialogimpl.cpp | 13 ++- .../qt/gamelobbydialog/gamelobbydialogimpl.h | 2 + src/gui/qt/guiwrapper.cpp | 1 + src/gui/qt/guiwrapper.h | 1 + src/gui/qt/mainwindow/mainwindowimpl.cpp | 2 + src/gui/qt/mainwindow/mainwindowimpl.h | 1 + .../startnetworkgamedialogimpl.cpp | 14 ++- .../startnetworkgamedialogimpl.h | 3 + src/net/clientcallback.h | 1 + src/net/clientthread.h | 1 + src/net/common/clientstate.cpp | 25 ++-- src/net/common/clientthread.cpp | 12 ++ src/net/common/netpacket.cpp | 107 +++++++++++++++--- src/net/common/servergamestate.cpp | 10 +- src/net/common/servergamethread.cpp | 17 +++ src/net/netpacket.h | 25 ++++ 19 files changed, 239 insertions(+), 49 deletions(-) diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index 375f393a..e8c1280c 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -330,13 +330,24 @@ Server Notification: Player Left +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -Client Request: Kick Player +Server Notification: Game Admin 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 = 15 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | New Admin Player ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + +Client Request: Kick Player + + 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 = 16 | Message Length = 8 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Player ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -346,7 +357,7 @@ Client Request: Leave Current Game 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 = 16 | Message Length = 8 | + | Message Type = 17 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -358,7 +369,7 @@ Client Request: Start Event 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 = 17 | Message Length = 8 | + | Message Type = 18 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Start Flags | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -371,7 +382,7 @@ Server Notification: Game Start 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 = 18 | Message Length | + | Message Type = 19 | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Start Dealer Player Id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -402,7 +413,7 @@ Server Notification: Hand Start 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 = 19 | Message Length = 8 | + | Message Type = 20 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Your 1st Card | Your 2nd Card | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -416,7 +427,7 @@ Server Request/Notification: Player's Turn 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 = 20 | Message Length = 8 | + | Message Type = 21 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Player ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -435,7 +446,7 @@ Client Reply/Request: Player's Action 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 = 21 | Message Length = 12 | + | Message Type = 22 | Message Length = 12 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game State | Player Action | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -460,7 +471,7 @@ Server Notification: Player's Action Done 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 = 22 | Message Length = 20 | + | Message Type = 23 | Message Length = 20 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Player ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -481,7 +492,7 @@ Server Reply: Player's Action Rejected 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 = 23 | Message Length = 16 | + | Message Type = 24 | Message Length = 16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game State | Player Action | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -509,7 +520,7 @@ Server Notification: Deal Flop Cards 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 = 24 | Message Length = 12 | + | Message Type = 25 | Message Length = 12 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Flop 1st Card | Flop 2nd Card | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -522,7 +533,7 @@ Server Notification: Deal Turn Card 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 = 25 | Message Length = 8 | + | Message Type = 26 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Turn Card | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -533,7 +544,7 @@ Server Notification: Deal River Card 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 = 26 | Message Length = 8 | + | Message Type = 27 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | River Card | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -544,7 +555,7 @@ Server Notification: All In Show Cards 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 = 27 | Message Length | + | Message Type = 28 | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Number Of PlayerCards Records | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -566,7 +577,7 @@ Server Notification: End Of Hand Show Cards 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 = 28 | Message Length | + | Message Type = 29 | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Number Of PlayerResult Records | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -600,7 +611,7 @@ Server Notification: End Of Hand Hide Cards 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 = 29 | Message Length = 16 | + | Message Type = 30 | Message Length = 16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Player ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -615,7 +626,7 @@ Server Notification: End Of Game 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 = 30 | Message Length = 8 | + | Message Type = 31 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Winner Player Id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index 003917c2..57861ae0 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -110,10 +110,11 @@ void ServerGuiWrapper::SignalNetClientGameInfo(int actionID) { if (myClientcb) m 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::SignalNetClientRemovedFromGame(int notificationId) { if (myClientcb) myClientcb->SignalNetClientRemovedFromGame(notificationId); } -void ServerGuiWrapper::SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientSelfJoined(playerId, playerName, rights); } -void ServerGuiWrapper::SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerId, playerName, rights); } -void ServerGuiWrapper::SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName) { if (myClientcb) myClientcb->SignalNetClientPlayerChanged(playerId, newPlayerName); } -void ServerGuiWrapper::SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerLeft(playerId, playerName); } +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); } +void ServerGuiWrapper::SignalNetClientPlayerChanged(unsigned playerId, const string &newPlayerName) { if (myClientcb) myClientcb->SignalNetClientPlayerChanged(playerId, newPlayerName); } +void ServerGuiWrapper::SignalNetClientPlayerLeft(unsigned playerId, const string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerLeft(playerId, playerName); } +void ServerGuiWrapper::SignalNetClientNewGameAdmin(unsigned playerId, const string &playerName) { if (myClientcb) myClientcb->SignalNetClientNewGameAdmin(playerId, playerName); } void ServerGuiWrapper::SignalNetClientGameListNew(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListNew(gameId); } void ServerGuiWrapper::SignalNetClientGameListRemove(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListRemove(gameId); } void ServerGuiWrapper::SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) { if (myClientcb) myClientcb->SignalNetClientGameListUpdateMode(gameId, mode); } diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index e4f16f2b..cfab385b 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -98,6 +98,7 @@ public: void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName); void SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName); + void SignalNetClientNewGameAdmin(unsigned playerId, const std::string &playerName); void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg); void SignalNetClientWaitDialog(); diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp index 5157244f..8f16cefa 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp @@ -18,7 +18,7 @@ #include gameLobbyDialogImpl::gameLobbyDialogImpl(QWidget *parent, ConfigFile *c) - : QDialog(parent), myW(NULL), myConfig(c), mySession(NULL), currentGameName(""), isAdmin(false), inGame(false), myChat(NULL) + : QDialog(parent), myW(NULL), myConfig(c), mySession(NULL), currentGameName(""), myPlayerId(0), isAdmin(false), inGame(false), myChat(NULL) { setupUi(this); @@ -343,6 +343,7 @@ void gameLobbyDialogImpl::clearDialog() myChat->clearChat(); inGame = false; isAdmin = false; + myPlayerId = 0; } void gameLobbyDialogImpl::checkPlayerQuantity() { @@ -367,6 +368,7 @@ void gameLobbyDialogImpl::joinedNetworkGame(unsigned playerId, QString playerNam inGame = true; joinedGameDialogUpdate(); + myPlayerId = playerId; isAdmin = rights == PLAYER_RIGHTS_ADMIN; addConnectedPlayer(playerId, playerName, rights); } @@ -418,6 +420,15 @@ void gameLobbyDialogImpl::removePlayer(unsigned playerId, QString) { checkPlayerQuantity(); } +void gameLobbyDialogImpl::newGameAdmin(unsigned playerId, QString) +{ + if (myPlayerId == playerId) + { + isAdmin = true; + checkPlayerQuantity(); + } +} + void gameLobbyDialogImpl::joinedGameDialogUpdate() { groupBox_GameInfo->setEnabled(true); groupBox_GameInfo->setTitle(currentGameName); diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h index 8d8f9233..383fee59 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h @@ -71,6 +71,7 @@ public slots: void addConnectedPlayer(unsigned, QString, int); void updatePlayer(unsigned, QString); void removePlayer(unsigned, QString); + void newGameAdmin(unsigned, QString); void playerSelected(QTreeWidgetItem*, QTreeWidgetItem*); void refresh(int actionID); @@ -99,6 +100,7 @@ private: Session *mySession; createInternetGameDialogImpl *myCreateInternetGameDialog; QString currentGameName; + unsigned myPlayerId; bool isAdmin; bool inGame; LobbyChat *myChat; diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 1bcb7ae1..e519cfae 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -126,6 +126,7 @@ void GuiWrapper::SignalNetClientPlayerLeft(unsigned playerId, const string &play if (!playerName.empty() && playerName[0] != '#') myLog->signalLogPlayerLeftMsg(tmpName); } +void GuiWrapper::SignalNetClientNewGameAdmin(unsigned playerId, const string &playerName) { myW->signalNetClientNewGameAdmin(playerId, QString::fromUtf8(playerName.c_str())); } void GuiWrapper::SignalNetClientGameListNew(unsigned gameId) { myW->signalNetClientGameListNew(gameId); } void GuiWrapper::SignalNetClientGameListRemove(unsigned gameId) { myW->signalNetClientGameListRemove(gameId); } diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index 76957cbd..ce83b0d7 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -105,6 +105,7 @@ public: void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName); void SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName); + void SignalNetClientNewGameAdmin(unsigned playerId, const std::string &playerName); void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg); void SignalNetClientWaitDialog(); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index 9c008f28..1b921e51 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -659,11 +659,13 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) connect(this, SIGNAL(signalNetClientPlayerJoined(unsigned, QString, int)), myStartNetworkGameDialog, SLOT(addConnectedPlayer(unsigned, QString, int))); connect(this, SIGNAL(signalNetClientPlayerChanged(unsigned, QString)), myStartNetworkGameDialog, SLOT(updatePlayer(unsigned, QString))); connect(this, SIGNAL(signalNetClientPlayerLeft(unsigned, QString)), myStartNetworkGameDialog, SLOT(removePlayer(unsigned, QString))); + connect(this, SIGNAL(signalNetClientNewGameAdmin(unsigned, QString)), myStartNetworkGameDialog, SLOT(newGameAdmin(unsigned, QString))); connect(this, SIGNAL(signalNetClientSelfJoined(unsigned, QString, int)), myGameLobbyDialog, SLOT(joinedNetworkGame(unsigned, QString, int))); connect(this, SIGNAL(signalNetClientPlayerJoined(unsigned, QString, int)), myGameLobbyDialog, SLOT(addConnectedPlayer(unsigned, QString, int))); connect(this, SIGNAL(signalNetClientPlayerChanged(unsigned, QString)), myGameLobbyDialog, SLOT(updatePlayer(unsigned, QString))); connect(this, SIGNAL(signalNetClientPlayerLeft(unsigned, QString)), myGameLobbyDialog, SLOT(removePlayer(unsigned, QString))); + connect(this, SIGNAL(signalNetClientNewGameAdmin(unsigned, QString)), myGameLobbyDialog, SLOT(newGameAdmin(unsigned, QString))); connect(this, SIGNAL(signalNetClientGameListNew(unsigned)), myGameLobbyDialog, SLOT(addGame(unsigned))); connect(this, SIGNAL(signalNetClientGameListRemove(unsigned)), myGameLobbyDialog, SLOT(removeGame(unsigned))); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index 5e20ee7e..d00a54db 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -132,6 +132,7 @@ signals: void signalNetClientPlayerJoined(unsigned playerId, QString playerName, int rights); void signalNetClientPlayerChanged(unsigned playerId, QString newPlayerName); void signalNetClientPlayerLeft(unsigned playerId, QString playerName); + void signalNetClientNewGameAdmin(unsigned playerId, QString playerName); void signalNetClientGameListNew(unsigned gameId); void signalNetClientGameListRemove(unsigned gameId); void signalNetClientGameListUpdateMode(unsigned gameId, int mode); diff --git a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp index 7553b628..1bbda9d1 100644 --- a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp +++ b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp @@ -23,7 +23,7 @@ #include startNetworkGameDialogImpl::startNetworkGameDialogImpl(QWidget *parent, ConfigFile *config) - : QDialog(parent), myW(NULL), isAdmin(false), myConfig(config), mySession(NULL) + : QDialog(parent), myW(NULL), myPlayerId(0), isAdmin(false), myConfig(config), mySession(NULL) { setupUi(this); @@ -64,6 +64,7 @@ void startNetworkGameDialogImpl::refresh(int actionID) { void startNetworkGameDialogImpl::joinedNetworkGame(unsigned playerId, QString playerName, int rights) { + myPlayerId = playerId; isAdmin = rights == PLAYER_RIGHTS_ADMIN; addConnectedPlayer(playerId, playerName, rights); } @@ -116,6 +117,15 @@ void startNetworkGameDialogImpl::removePlayer(unsigned playerId, QString) { checkPlayerQuantity(); } +void startNetworkGameDialogImpl::newGameAdmin(unsigned playerId, QString) +{ + if (myPlayerId == playerId) + { + isAdmin = true; + checkPlayerQuantity(); + } +} + void startNetworkGameDialogImpl::playerSelected(QTreeWidgetItem* item, QTreeWidgetItem*) { if (item) @@ -166,6 +176,8 @@ void startNetworkGameDialogImpl::clearDialog() pushButton_startGame->setEnabled(false); treeWidget->clear(); checkBox_fillUpWithComputerOpponents->hide(); + + myPlayerId = 0; } void startNetworkGameDialogImpl::setSession(Session *session) diff --git a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h index 350916ee..372bb8a5 100644 --- a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h +++ b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h @@ -49,6 +49,8 @@ public slots: void addConnectedPlayer(unsigned playerId, QString playerName, int rights); void updatePlayer(unsigned playerId, QString newPlayerName); void removePlayer(unsigned playerId, QString playerName); + void newGameAdmin(unsigned playerId, QString playerName); + void playerSelected(QTreeWidgetItem*, QTreeWidgetItem*); void kickPlayer(); void checkPlayerQuantity(); @@ -67,6 +69,7 @@ private: mainWindowImpl* myW; int maxPlayerNumber; + unsigned myPlayerId; bool isAdmin; ConfigFile *myConfig; Session *mySession; diff --git a/src/net/clientcallback.h b/src/net/clientcallback.h index 024d3a73..c7576baa 100644 --- a/src/net/clientcallback.h +++ b/src/net/clientcallback.h @@ -50,6 +50,7 @@ public: virtual void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights) = 0; virtual void SignalNetClientPlayerChanged(unsigned playerId, const std::string &newPlayerName) = 0; virtual void SignalNetClientPlayerLeft(unsigned playerId, const std::string &playerName) = 0; + virtual void SignalNetClientNewGameAdmin(unsigned playerId, const std::string &playerName) = 0; virtual void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg) = 0; virtual void SignalNetClientWaitDialog() = 0; diff --git a/src/net/clientthread.h b/src/net/clientthread.h index ba5a24ae..e25734a9 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -86,6 +86,7 @@ protected: bool GetCachedPlayerInfo(unsigned id, PlayerInfo &info) const; void RequestPlayerInfo(unsigned id); void SetPlayerInfo(unsigned id, const PlayerInfo &info); + void SetNewGameAdmin(unsigned id); const ClientContext &GetContext() const; ClientContext &GetContext(); diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index ff443318..fa3184d7 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -401,14 +401,6 @@ AbstractClientStateReceiving::Process(ClientThread &client) client.GetCallback().SignalNetClientRemovedFromGame(removedData.removeReason); client.SetState(ClientStateWaitJoin::Instance()); } - else if (tmpPacket->ToNetPacketError()) - { - // Server reported an error. - NetPacketError::Data errorData; - tmpPacket->ToNetPacketError()->GetData(errorData); - // Show the error. - throw ClientException(errorData.errorCode, 0); - } else if (tmpPacket->ToNetPacketChatText()) { // Chat message - display it in the GUI. @@ -428,6 +420,15 @@ AbstractClientStateReceiving::Process(ClientThread &client) // Signal to GUI and remove from data list. client.RemovePlayerData(playerLeftData.playerId); } + else if (tmpPacket->ToNetPacketGameAdminChanged()) + { + // New admin for the game. + NetPacketGameAdminChanged::Data adminChangedData; + tmpPacket->ToNetPacketGameAdminChanged()->GetData(adminChangedData); + + // Set new game admin and signal to GUI. + client.SetNewGameAdmin(adminChangedData.playerId); + } else if (tmpPacket->ToNetPacketGameListNew()) { // A new game was created on the server. @@ -478,6 +479,14 @@ AbstractClientStateReceiving::Process(ClientThread &client) tmpPacket->ToNetPacketGameListPlayerLeft()->GetData(playerLeftData); client.ModifyGameInfoRemovePlayer(playerLeftData.gameId, playerLeftData.playerId); } + else if (tmpPacket->ToNetPacketError()) + { + // Server reported an error. + NetPacketError::Data errorData; + tmpPacket->ToNetPacketError()->GetData(errorData); + // Show the error. + throw ClientException(errorData.errorCode, 0); + } else retVal = InternalProcess(client, tmpPacket); } diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index 3e524760..ee887e75 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -404,6 +404,18 @@ ClientThread::SetPlayerInfo(unsigned id, const PlayerInfo &info) GetCallback().SignalNetClientPlayerChanged(id, info.playerName); } +void +ClientThread::SetNewGameAdmin(unsigned id) +{ + // Update player data for current game. + boost::shared_ptr playerData = GetPlayerDataByUniqueId(id); + if (playerData.get()) + { + playerData->SetRights(PLAYER_RIGHTS_ADMIN); + GetCallback().SignalNetClientNewGameAdmin(id, playerData->GetName()); + } +} + const ClientContext & ClientThread::GetContext() const { diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index 88d20b3e..3091c97d 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -41,22 +41,23 @@ using namespace std; #define NET_TYPE_JOIN_GAME_FAILED 0x000C #define NET_TYPE_PLAYER_JOINED 0x000D #define NET_TYPE_PLAYER_LEFT 0x000E -#define NET_TYPE_KICK_PLAYER 0x000F -#define NET_TYPE_LEAVE_CURRENT_GAME 0x0010 -#define NET_TYPE_START_EVENT 0x0011 -#define NET_TYPE_GAME_START 0x0012 -#define NET_TYPE_HAND_START 0x0013 -#define NET_TYPE_PLAYERS_TURN 0x0014 -#define NET_TYPE_PLAYERS_ACTION 0x0015 -#define NET_TYPE_PLAYERS_ACTION_DONE 0x0016 -#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x0017 -#define NET_TYPE_DEAL_FLOP_CARDS 0x0018 -#define NET_TYPE_DEAL_TURN_CARD 0x0019 -#define NET_TYPE_DEAL_RIVER_CARD 0x001A -#define NET_TYPE_ALL_IN_SHOW_CARDS 0x001B -#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x001C -#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x001D -#define NET_TYPE_END_OF_GAME 0x001E +#define NET_TYPE_GAME_ADMIN_CHANGED 0x000F +#define NET_TYPE_KICK_PLAYER 0x0010 +#define NET_TYPE_LEAVE_CURRENT_GAME 0x0011 +#define NET_TYPE_START_EVENT 0x0012 +#define NET_TYPE_GAME_START 0x0013 +#define NET_TYPE_HAND_START 0x0014 +#define NET_TYPE_PLAYERS_TURN 0x0015 +#define NET_TYPE_PLAYERS_ACTION 0x0016 +#define NET_TYPE_PLAYERS_ACTION_DONE 0x0017 +#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x0018 +#define NET_TYPE_DEAL_FLOP_CARDS 0x0019 +#define NET_TYPE_DEAL_TURN_CARD 0x001A +#define NET_TYPE_DEAL_RIVER_CARD 0x001B +#define NET_TYPE_ALL_IN_SHOW_CARDS 0x001C +#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x001D +#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x001E +#define NET_TYPE_END_OF_GAME 0x001F #define NET_TYPE_REMOVED_FROM_GAME 0x0100 @@ -239,6 +240,12 @@ struct GCC_PACKED NetPacketPlayerLeftData u_int32_t playerId; }; +struct GCC_PACKED NetPacketGameAdminChangedData +{ + NetPacketHeader head; + u_int32_t playerId; +}; + struct GCC_PACKED NetPacketKickPlayerData { NetPacketHeader head; @@ -582,6 +589,9 @@ NetPacket::Create(char *data, unsigned &dataSize) case NET_TYPE_PLAYER_LEFT: tmpPacket = boost::shared_ptr(new NetPacketPlayerLeft); break; + case NET_TYPE_GAME_ADMIN_CHANGED: + tmpPacket = boost::shared_ptr(new NetPacketGameAdminChanged); + break; case NET_TYPE_KICK_PLAYER: tmpPacket = boost::shared_ptr(new NetPacketKickPlayer); break; @@ -810,6 +820,12 @@ NetPacket::ToNetPacketPlayerLeft() const return NULL; } +const NetPacketGameAdminChanged * +NetPacket::ToNetPacketGameAdminChanged() const +{ + return NULL; +} + const NetPacketKickPlayer * NetPacket::ToNetPacketKickPlayer() const { @@ -2189,6 +2205,65 @@ NetPacketPlayerLeft::InternalCheck(const NetPacketHeader*) const // Nothing to do. } + +//----------------------------------------------------------------------------- + +NetPacketGameAdminChanged::NetPacketGameAdminChanged() +: NetPacket(NET_TYPE_GAME_ADMIN_CHANGED, sizeof(NetPacketGameAdminChangedData), sizeof(NetPacketGameAdminChangedData)) +{ +} + +NetPacketGameAdminChanged::~NetPacketGameAdminChanged() +{ +} + +boost::shared_ptr +NetPacketGameAdminChanged::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameAdminChanged); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameAdminChanged::SetData(const NetPacketGameAdminChanged::Data &inData) +{ + NetPacketGameAdminChangedData *tmpData = (NetPacketGameAdminChangedData *)GetRawData(); + + // Set the data. + tmpData->playerId = htonl(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameAdminChanged::GetData(NetPacketGameAdminChanged::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameAdminChangedData *tmpData = (NetPacketGameAdminChangedData *)GetRawData(); + + outData.playerId = ntohl(tmpData->playerId); +} + +const NetPacketGameAdminChanged * +NetPacketGameAdminChanged::ToNetPacketGameAdminChanged() const +{ + return this; +} + +void +NetPacketGameAdminChanged::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + //----------------------------------------------------------------------------- NetPacketKickPlayer::NetPacketKickPlayer() diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index a4ab4344..95a846b6 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -312,10 +312,14 @@ ServerGameStateInit::InternalProcess(ServerGameThread &server, SessionWrapper se } else if (packet->ToNetPacketKickPlayer()) { - NetPacketKickPlayer::Data kickPlayerData; - packet->ToNetPacketKickPlayer()->GetData(kickPlayerData); + // Only admins are allowed to kick. + if (session.playerData->GetRights() == PLAYER_RIGHTS_ADMIN) + { + NetPacketKickPlayer::Data kickPlayerData; + packet->ToNetPacketKickPlayer()->GetData(kickPlayerData); - server.InternalKickPlayer(kickPlayerData.playerId); + server.InternalKickPlayer(kickPlayerData.playerId); + } } else { diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp index de427521..5dffd923 100644 --- a/src/net/common/servergamethread.cpp +++ b/src/net/common/servergamethread.cpp @@ -300,6 +300,23 @@ ServerGameThread::GracefulRemoveSession(SessionWrapper session) static_cast(thisPlayerLeft.get())->SetData(thisPlayerLeftData); GetSessionManager().SendToAllSessions(GetSender(), thisPlayerLeft, SessionData::Game); + if (tmpPlayerData->GetRights() == PLAYER_RIGHTS_ADMIN) + { + // Find new admin for the game + PlayerIdList idList(GetSessionManager().GetPlayerIdList()); + if (!idList.empty()) + { + // Send "Game Admin Changed" to clients. + boost::shared_ptr adminChanged(new NetPacketGameAdminChanged); + NetPacketGameAdminChanged::Data adminChangedData; + adminChangedData.playerId = idList.front(); // Choose next player as admin. + static_cast(adminChanged.get())->SetData(adminChangedData); + GetSessionManager().SendToAllSessions(GetSender(), adminChanged, SessionData::Game); + } + } + // Reset player rights. + tmpPlayerData->SetRights(PLAYER_RIGHTS_NORMAL); + GetLobbyThread().NotifyPlayerLeftGame(GetId(), session.playerData->GetUniqueId()); } } diff --git a/src/net/netpacket.h b/src/net/netpacket.h index 1d2ec0f9..a5c2d8fd 100644 --- a/src/net/netpacket.h +++ b/src/net/netpacket.h @@ -56,6 +56,7 @@ class NetPacketJoinGameAck; class NetPacketJoinGameFailed; class NetPacketPlayerJoined; class NetPacketPlayerLeft; +class NetPacketGameAdminChanged; class NetPacketKickPlayer; class NetPacketLeaveCurrentGame; class NetPacketStartEvent; @@ -108,6 +109,7 @@ public: virtual const NetPacketJoinGameFailed *ToNetPacketJoinGameFailed() const; virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const; virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const; + virtual const NetPacketGameAdminChanged *ToNetPacketGameAdminChanged() const; virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const; virtual const NetPacketLeaveCurrentGame *ToNetPacketLeaveCurrentGame() const; virtual const NetPacketStartEvent *ToNetPacketStartEvent() const; @@ -484,6 +486,29 @@ protected: virtual void InternalCheck(const NetPacketHeader* data) const; }; +class NetPacketGameAdminChanged : public NetPacket +{ +public: + struct Data + { + u_int32_t playerId; + }; + + NetPacketGameAdminChanged(); + virtual ~NetPacketGameAdminChanged(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameAdminChanged *ToNetPacketGameAdminChanged() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + class NetPacketKickPlayer : public NetPacket { public: