From 0da29b387430c4271feebd5cd58f2f1c390718a4 Mon Sep 17 00:00:00 2001 From: lotodore Date: Thu, 2 Aug 2007 20:52:13 +0000 Subject: [PATCH] The console server can now be fully used for a single game. The first player to join the game is admin, he can start the game and kick players. However, if the admin player leaves, a new game can only be started if all players have left before (this is a bug, admin status should be passed to another player). --- docs/net_protocol.txt | 48 ++-- src/gui/generic/serverguiwrapper.cpp | 4 +- src/gui/generic/serverguiwrapper.h | 4 +- src/gui/qt/guiwrapper.cpp | 10 +- src/gui/qt/guiwrapper.h | 7 +- src/gui/qt/mainwindow/mainwindowimpl.cpp | 47 ++-- src/gui/qt/mainwindow/mainwindowimpl.h | 11 +- .../startnetworkgamedialogimpl.cpp | 25 +- .../startnetworkgamedialogimpl.h | 5 +- src/net/clientcallback.h | 4 +- src/net/clientthread.h | 3 + src/net/common/clientstate.cpp | 4 +- src/net/common/clientthread.cpp | 52 ++++- src/net/common/netpacket.cpp | 153 ++++++++++-- src/net/common/serverrecvstate.cpp | 220 ++++++++++-------- src/net/common/serverrecvthread.cpp | 33 +-- src/net/common/serverthread.cpp | 20 -- src/net/netpacket.h | 43 ++++ src/net/servercallback.h | 2 - src/net/serverrecvthread.h | 5 +- src/net/serverthread.h | 2 - src/playerdata.cpp | 4 +- src/playerdata.h | 5 +- src/session.cpp | 30 ++- src/session.h | 2 +- 25 files changed, 481 insertions(+), 262 deletions(-) diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index 130cdedd..ebdd867c 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -1,4 +1,6 @@ Changelog: +08-02-2007: Added new requests for game start and kick player. + Type ids changed. 07-24-2007: Join Game ACK / Player Joined do not specify player number. Player order is transferred on game start. This is not compatible to the previous protocol. @@ -113,12 +115,32 @@ Server Notification: Player Left +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +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 = 5 | Message Length = 8 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Player ID | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + +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 = 6 | Message Length = 4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + 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 = 5 | Message Length | + | Message Type = 7 | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Start Dealer Player Id | Number of Players | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -147,7 +169,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 = 6 | Message Length = 8 | + | Message Type = 8 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Your 1st Card | Your 2nd Card | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -161,7 +183,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 = 7 | Message Length = 8 | + | Message Type = 9 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game State | Player ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -178,7 +200,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 = 8 | Message Length = 12 | + | Message Type = 10 | Message Length = 12 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game State | Player Action | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -203,7 +225,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 = 9 | Message Length = 20 | + | Message Type = 11 | Message Length = 20 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game State | Player Id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -224,7 +246,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 = 10 | Message Length = 16 | + | Message Type = 12 | Message Length = 16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game State | Player Action | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -252,7 +274,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 = 11 | Message Length = 12 | + | Message Type = 13 | Message Length = 12 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Flop 1st Card | Flop 2nd Card | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -265,7 +287,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 = 12 | Message Length = 8 | + | Message Type = 14 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Turn Card | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -276,7 +298,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 = 13 | Message Length = 8 | + | Message Type = 15 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | River Card | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -287,7 +309,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 = 14 | Message Length | + | Message Type = 16 | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Number Of PlayerCards Records | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -309,7 +331,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 = 15 | Message Length | + | Message Type = 17 | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Number Of PlayerResult Records | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -341,7 +363,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 = 16 | Message Length = 16 | + | Message Type = 18 | Message Length = 16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Player Id | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -356,7 +378,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 = 17 | Message Length = 8 | + | Message Type = 19 | Message Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Winner Player Id | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index 8dbe6ca0..161155e9 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -105,7 +105,8 @@ void ServerGuiWrapper::logPlayerWinGame(std::string playerName, int gameID) {} void ServerGuiWrapper::SignalNetClientConnect(int actionID) { if (myClientcb) myClientcb->SignalNetClientConnect(actionID); } 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::SignalNetClientPlayerJoined(const string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerName); } +void ServerGuiWrapper::SignalNetClientSelfJoined(const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientSelfJoined(playerName, rights); } +void ServerGuiWrapper::SignalNetClientPlayerJoined(const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerName, rights); } void ServerGuiWrapper::SignalNetClientPlayerLeft(const string &playerName) { if (myClientcb) myClientcb->SignalNetClientPlayerLeft(playerName); } void ServerGuiWrapper::SignalNetClientGameStart(boost::shared_ptr game) { if (myClientcb) myClientcb->SignalNetClientGameStart(game); } void ServerGuiWrapper::SignalNetClientChatMsg(const string &playerName, const string &msg) { if (myClientcb) myClientcb->SignalNetClientChatMsg(playerName, msg); } @@ -115,5 +116,4 @@ void ServerGuiWrapper::SignalNetServerSuccess(int actionID) { if (myServercb) my void ServerGuiWrapper::SignalNetServerError(int errorID, int osErrorID) { if (myServercb) myServercb->SignalNetServerError(errorID, osErrorID); } void ServerGuiWrapper::SignalNetServerPlayerJoined(const string &playerName) { if (myServercb) myServercb->SignalNetServerPlayerJoined(playerName); } void ServerGuiWrapper::SignalNetServerPlayerLeft(const string &playerName) { if (myServercb) myServercb->SignalNetServerPlayerLeft(playerName); } -void ServerGuiWrapper::SignalNetServerStartDialog() { if (myServercb) myServercb->SignalNetServerStartDialog(); } diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index ed24cf72..8151fcf3 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -89,7 +89,8 @@ public: void SignalNetClientConnect(int actionID); void SignalNetClientGameInfo(int actionID); void SignalNetClientError(int errorID, int osErrorID); - void SignalNetClientPlayerJoined(const std::string &playerName); + void SignalNetClientSelfJoined(const std::string &playerName, PlayerRights rights); + void SignalNetClientPlayerJoined(const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerLeft(const std::string &playerName); void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg); void SignalNetClientWaitDialog(); @@ -100,7 +101,6 @@ public: void SignalNetServerError(int errorID, int osErrorID); void SignalNetServerPlayerJoined(const std::string &playerName); void SignalNetServerPlayerLeft(const std::string &playerName); - void SignalNetServerStartDialog(); private: diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 56099c78..beb9ec47 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -107,7 +107,8 @@ void GuiWrapper::logPlayerWinGame(std::string playerName, int gameID) { myLog->s void GuiWrapper::SignalNetClientConnect(int actionID) { myW->signalNetClientConnect(actionID); } void GuiWrapper::SignalNetClientGameInfo(int actionID) { myW->signalNetClientGameInfo(actionID); } void GuiWrapper::SignalNetClientError(int errorID, int osErrorID) { myW->signalNetClientError(errorID, osErrorID); } -void GuiWrapper::SignalNetClientPlayerJoined(const string &playerName) { myW->signalNetClientPlayerJoined(QString::fromUtf8(playerName.c_str())); } +void GuiWrapper::SignalNetClientSelfJoined(const string &playerName, PlayerRights rights) { myW->signalNetClientSelfJoined(QString::fromUtf8(playerName.c_str()), rights); } +void GuiWrapper::SignalNetClientPlayerJoined(const string &playerName, PlayerRights rights) { myW->signalNetClientPlayerJoined(QString::fromUtf8(playerName.c_str()), rights); } void GuiWrapper::SignalNetClientPlayerLeft(const string &playerName) { QString tmpName(QString::fromUtf8(playerName.c_str())); @@ -116,11 +117,10 @@ void GuiWrapper::SignalNetClientPlayerLeft(const string &playerName) } void GuiWrapper::SignalNetClientGameStart(boost::shared_ptr game) { myW->signalNetClientGameStart(game); } void GuiWrapper::SignalNetClientChatMsg(const string &playerName, const string &msg) { myChat->signalChatMessage(QString::fromUtf8(playerName.c_str()), QString::fromUtf8(msg.c_str())); } -void GuiWrapper::SignalNetClientWaitDialog() { myW->signalShowClientWaitDialog(); } +void GuiWrapper::SignalNetClientWaitDialog() { myW->signalShowNetworkStartDialog(); } void GuiWrapper::SignalNetServerSuccess(int actionID) { } void GuiWrapper::SignalNetServerError(int errorID, int osErrorID) { myW->signalNetServerError(errorID, osErrorID); } -void GuiWrapper::SignalNetServerPlayerJoined(const string &playerName) { myW->signalNetServerPlayerJoined(QString::fromUtf8(playerName.c_str())); } -void GuiWrapper::SignalNetServerPlayerLeft(const string &playerName) { myW->signalNetServerPlayerLeft(QString::fromUtf8(playerName.c_str())); } -void GuiWrapper::SignalNetServerStartDialog() { myW->signalShowServerStartDialog(); } +void GuiWrapper::SignalNetServerPlayerJoined(const string &playerName) { } +void GuiWrapper::SignalNetServerPlayerLeft(const string &playerName) { } diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index 4e46196a..ab7b6d15 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -42,9 +42,6 @@ public: Session &getSession(); void setSession(boost::shared_ptr session); - void showServerStartDialog(); - void showClientWaitDialog(); - void refreshSet() const; void refreshCash() const; void refreshAction(int =-1, int =-1) const; @@ -99,7 +96,8 @@ public: void SignalNetClientConnect(int actionID); void SignalNetClientGameInfo(int actionID); void SignalNetClientError(int errorID, int osErrorID); - void SignalNetClientPlayerJoined(const std::string &playerName); + void SignalNetClientSelfJoined(const std::string &playerName, PlayerRights rights); + void SignalNetClientPlayerJoined(const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerLeft(const std::string &playerName); void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg); void SignalNetClientWaitDialog(); @@ -110,7 +108,6 @@ public: void SignalNetServerError(int errorID, int osErrorID); void SignalNetServerPlayerJoined(const std::string &playerName); void SignalNetServerPlayerLeft(const std::string &playerName); - void SignalNetServerStartDialog(); private: diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index cce06496..9e37b048 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -587,8 +587,7 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) //Nachrichten Thread-Save connect(this, SIGNAL(signalInitGui(int)), this, SLOT(initGui(int))); - connect(this, SIGNAL(signalShowServerStartDialog()), this, SLOT(showServerStartDialog())); - connect(this, SIGNAL(signalShowClientWaitDialog()), this, SLOT(showClientWaitDialog())); + connect(this, SIGNAL(signalShowNetworkStartDialog()), this, SLOT(showNetworkStartDialog())); connect(this, SIGNAL(signalRefreshSet()), this, SLOT(refreshSet())); connect(this, SIGNAL(signalRefreshCash()), this, SLOT(refreshCash())); @@ -631,18 +630,16 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) connect(this, SIGNAL(signalNextRoundCleanGui()), this, SLOT(nextRoundCleanGui())); connect(this, SIGNAL(signalNetClientConnect(int)), myConnectToServerDialog, SLOT(refresh(int))); - connect(this, SIGNAL(signalNetClientGameInfo(int)), myWaitingForServerGameDialog, SLOT(refresh(int))); - connect(this, SIGNAL(signalNetClientPlayerJoined(QString)), myWaitingForServerGameDialog, SLOT(addConnectedPlayer(QString))); - connect(this, SIGNAL(signalNetClientPlayerLeft(QString)), myWaitingForServerGameDialog, SLOT(removePlayer(QString))); + connect(this, SIGNAL(signalNetClientGameInfo(int)), myStartNetworkGameDialog, SLOT(refresh(int))); + connect(this, SIGNAL(signalNetClientSelfJoined(QString, int)), myStartNetworkGameDialog, SLOT(joinedNetworkGame(QString, int))); + connect(this, SIGNAL(signalNetClientPlayerJoined(QString, int)), myStartNetworkGameDialog, SLOT(addConnectedPlayer(QString, int))); + connect(this, SIGNAL(signalNetClientPlayerLeft(QString)), myStartNetworkGameDialog, SLOT(removePlayer(QString))); // Errors are handled globally, not within one dialog. connect(this, SIGNAL(signalNetClientError(int, int)), this, SLOT(networkError(int, int))); connect(this, SIGNAL(signalNetServerError(int, int)), this, SLOT(networkError(int, int))); connect(this, SIGNAL(signalNetClientGameStart(boost::shared_ptr)), this, SLOT(networkStart(boost::shared_ptr))); - connect(this, SIGNAL(signalNetServerPlayerJoined(QString)), myStartNetworkGameDialog, SLOT(addConnectedPlayer(QString))); - connect(this, SIGNAL(signalNetServerPlayerLeft(QString)), myStartNetworkGameDialog, SLOT(removePlayer(QString))); - //Sound mySDLPlayer = new SDLPlayer(myConfig); @@ -743,7 +740,7 @@ void mainWindowImpl::callCreateNetworkGameDialog() { gameData.guiSpeed = 4; gameData.playerActionTimeoutSec = myCreateNetworkGameDialog->spinBox_netTimeOutPlayerAction->value(); - myStartNetworkGameDialog->setSession(&myServerGuiInterface->getSession()); + myStartNetworkGameDialog->setSession(&getSession()); myStartNetworkGameDialog->treeWidget->clear(); myServerGuiInterface->getSession().startNetworkServer(gameData); @@ -751,7 +748,7 @@ void mainWindowImpl::callCreateNetworkGameDialog() { myStartNetworkGameDialog->setMaxPlayerNumber(gameData.maxNumberOfPlayers); - showServerStartDialog(); + showNetworkStartDialog(); } } @@ -766,7 +763,8 @@ void mainWindowImpl::callJoinNetworkGameDialog() { if (myServerGuiInterface.get()) myServerGuiInterface->getSession().terminateNetworkServer(); - myWaitingForServerGameDialog->treeWidget->clear(); + myStartNetworkGameDialog->setSession(&getSession()); + myStartNetworkGameDialog->treeWidget->clear(); // Maybe use QUrl::toPunycode. mySession->startNetworkClient( myJoinNetworkGameDialog->lineEdit_ipAddress->text().toUtf8().constData(), @@ -783,7 +781,7 @@ void mainWindowImpl::callJoinNetworkGameDialog() { actionJoin_network_Game->trigger(); // re-trigger } else { - showClientWaitDialog(); + showNetworkStartDialog(); } } } @@ -891,7 +889,7 @@ void mainWindowImpl::initGui(int speed) } } -void mainWindowImpl::showServerStartDialog() +void mainWindowImpl::showNetworkStartDialog() { myStartNetworkGameDialog->exec(); @@ -899,28 +897,11 @@ void mainWindowImpl::showServerStartDialog() //some gui modifications networkGameModification(); - myServerGuiInterface->getSession().initiateNetworkServerGame(); - } else { mySession->terminateNetworkClient(); - myServerGuiInterface->getSession().terminateNetworkServer(); - } -} - -void mainWindowImpl::showClientWaitDialog() -{ - if (!myServerGuiInterface.get() || !myServerGuiInterface->getSession().isNetworkServerRunning()) - { - myWaitingForServerGameDialog->exec(); - - if (myWaitingForServerGameDialog->result() == QDialog::Accepted) { - //some gui modifications - networkGameModification(); - } - else { - mySession->terminateNetworkClient(); - } + if (myServerGuiInterface) + myServerGuiInterface->getSession().terminateNetworkServer(); } } @@ -2547,7 +2528,7 @@ void mainWindowImpl::networkError(int errorID, int osErrorID) { } // close dialogs myConnectToServerDialog->reject(); - myWaitingForServerGameDialog->reject(); + myStartNetworkGameDialog->reject(); } void mainWindowImpl::networkStart(boost::shared_ptr game) diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index dc14e865..66bbf4af 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -76,8 +76,7 @@ public: signals: void signalInitGui(int speed); - void signalShowServerStartDialog(); - void signalShowClientWaitDialog(); + void signalShowNetworkStartDialog(); void signalRefreshSet(); void signalRefreshCash(); @@ -123,18 +122,16 @@ signals: void signalNetClientGameInfo(int actionID); void signalNetClientError(int errorID, int osErrorID); void signalNetServerError(int errorID, int osErrorID); - void signalNetClientPlayerJoined(QString playerName); + void signalNetClientSelfJoined(QString playerName, int rights); + void signalNetClientPlayerJoined(QString playerName, int rights); void signalNetClientPlayerLeft(QString playerName); void signalNetClientGameStart(boost::shared_ptr game); - void signalNetServerPlayerJoined(QString playerName); - void signalNetServerPlayerLeft(QString playerName); public slots: void initGui(int speed); - void showServerStartDialog(); - void showClientWaitDialog(); + void showNetworkStartDialog(); //refresh-Funktionen void refreshSet(); diff --git a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp index e43acea8..23172389 100644 --- a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp +++ b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp @@ -20,9 +20,10 @@ #include "startnetworkgamedialogimpl.h" #include "session.h" #include "configfile.h" +#include startNetworkGameDialogImpl::startNetworkGameDialogImpl(QWidget *parent, ConfigFile *config) - : QDialog(parent), myConfig(config) + : QDialog(parent), myConfig(config), isAdmin(false) { setupUi(this); @@ -36,15 +37,29 @@ startNetworkGameDialogImpl::startNetworkGameDialogImpl(QWidget *parent, ConfigFi } void startNetworkGameDialogImpl::startGame() { - + assert(mySession); + mySession->sendStartEvent(); } void startNetworkGameDialogImpl::cancel() { } +void startNetworkGameDialogImpl::refresh(int actionID) { -void startNetworkGameDialogImpl::addConnectedPlayer(QString playerName) { + if (actionID == MSG_NET_GAME_CLIENT_START) + { + QTimer::singleShot(500, this, SLOT(accept())); + } +} + +void startNetworkGameDialogImpl::joinedNetworkGame(QString playerName, int rights) { + + isAdmin = rights == PLAYER_RIGHTS_ADMIN; + addConnectedPlayer(playerName, rights); +} + +void startNetworkGameDialogImpl::addConnectedPlayer(QString playerName, int rights) { QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget,0); item->setData(0, 0, playerName); @@ -64,7 +79,7 @@ void startNetworkGameDialogImpl::removePlayer(QString playerName) { void startNetworkGameDialogImpl::playerSelected(QTreeWidgetItem*, int) { - pushButton_Kick->setEnabled(TRUE); + pushButton_Kick->setEnabled(isAdmin); } void startNetworkGameDialogImpl::kickPlayer() { @@ -89,7 +104,7 @@ void startNetworkGameDialogImpl::kickPlayer() { void startNetworkGameDialogImpl::checkPlayerQuantity() { - if (treeWidget->topLevelItemCount() >= 2) + if (treeWidget->topLevelItemCount() >= 2 && isAdmin) pushButton_startGame->setEnabled(TRUE); else pushButton_startGame->setEnabled(FALSE); diff --git a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h index 956ba630..cc13ce0f 100644 --- a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h +++ b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.h @@ -37,7 +37,9 @@ public slots: void startGame(); void cancel(); - void addConnectedPlayer(QString playerName); + void refresh(int actionID); + void joinedNetworkGame(QString playerName, int rights); + void addConnectedPlayer(QString playerName, int rights); void removePlayer(QString playerName); void playerSelected(QTreeWidgetItem*, int); void kickPlayer(); @@ -54,6 +56,7 @@ public slots: private: int maxPlayerNumber; + bool isAdmin; ConfigFile *myConfig; Session *mySession; }; diff --git a/src/net/clientcallback.h b/src/net/clientcallback.h index c25f5647..773da121 100644 --- a/src/net/clientcallback.h +++ b/src/net/clientcallback.h @@ -23,6 +23,7 @@ #include #include +#include class Game; @@ -36,7 +37,8 @@ public: virtual void SignalNetClientError(int errorID, int osErrorID) = 0; virtual void SignalNetClientGameStart(boost::shared_ptr game) = 0; - virtual void SignalNetClientPlayerJoined(const std::string &playerName) = 0; + virtual void SignalNetClientSelfJoined(const std::string &playerName, PlayerRights rights) = 0; + virtual void SignalNetClientPlayerJoined(const std::string &playerName, PlayerRights rights) = 0; virtual void SignalNetClientPlayerLeft(const std::string &playerName) = 0; virtual void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg) = 0; diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 413a1b56..194b1ec8 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -52,6 +52,8 @@ public: const std::string &pwd, const std::string &playerName); + void SendKickPlayer(const std::string &playerName); + void SendStartEvent(); void SendPlayerAction(); void SendChatMessage(const std::string &msg); @@ -89,6 +91,7 @@ protected: void MapPlayerDataList(); const PlayerDataList &GetPlayerDataList() const; boost::shared_ptr GetPlayerDataByUniqueId(unsigned id); + boost::shared_ptr GetPlayerDataByName(const std::string &name); void RemoveDisconnectedPlayers(); diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 9c4539cb..1b575625 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -447,7 +447,7 @@ ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr< // TODO: Type Human is fixed here. // Player number is 0 on join. Will be set when the game starts. boost::shared_ptr playerData( - new PlayerData(joinGameAckData.yourPlayerUniqueId, 0, PLAYER_TYPE_HUMAN)); + new PlayerData(joinGameAckData.yourPlayerUniqueId, 0, joinGameAckData.ptype, joinGameAckData.prights)); playerData->SetName(context.GetPlayerName()); client.AddPlayerData(playerData); @@ -516,7 +516,7 @@ ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptrToNetPacketPlayerJoined()->GetData(netPlayerData); boost::shared_ptr playerData( - new PlayerData(netPlayerData.playerId, 0, netPlayerData.ptype)); + new PlayerData(netPlayerData.playerId, 0, netPlayerData.ptype, netPlayerData.prights)); playerData->SetName(netPlayerData.playerName); client.AddPlayerData(playerData); } diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index f232bb0f..12bdce9e 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -85,6 +85,30 @@ ClientThread::Init( context.SetPlayerName(playerName); } +void +ClientThread::SendKickPlayer(const string &playerName) +{ + boost::shared_ptr tmpPlayer = GetPlayerDataByName(playerName); + if (tmpPlayer.get()) + { + boost::shared_ptr request(new NetPacketKickPlayer); + NetPacketKickPlayer::Data requestData; + requestData.playerId = tmpPlayer->GetUniqueId(); + static_cast(request.get())->SetData(requestData); + GetSender().Send(GetContext().GetSocket(), request); + } +} + +void +ClientThread::SendStartEvent() +{ + // Warning: This function is called in the context of the GUI thread. + // Create a network packet for the server start event. + boost::shared_ptr startEvent(new NetPacketStartEvent); + // The sender is thread-safe, so just dump the packet. + GetSender().Send(GetContext().GetSocket(), startEvent); +} + void ClientThread::SendPlayerAction() { @@ -274,7 +298,10 @@ ClientThread::AddPlayerData(boost::shared_ptr playerData) if (playerData.get() && !playerData->GetName().empty()) { m_playerDataList.push_back(playerData); - GetCallback().SignalNetClientPlayerJoined(playerData->GetName()); + if (playerData->GetUniqueId() == GetGuiPlayerId()) + GetCallback().SignalNetClientSelfJoined(playerData->GetName(), playerData->GetRights()); + else + GetCallback().SignalNetClientPlayerJoined(playerData->GetName(), playerData->GetRights()); } } @@ -360,6 +387,29 @@ ClientThread::GetPlayerDataByUniqueId(unsigned id) return tmpPlayer; } +boost::shared_ptr +ClientThread::GetPlayerDataByName(const std::string &name) +{ + boost::shared_ptr tmpPlayer; + + if (!name.empty()) + { + PlayerDataList::const_iterator i = m_playerDataList.begin(); + PlayerDataList::const_iterator end = m_playerDataList.end(); + + while (i != end) + { + if ((*i)->GetName() == name) + { + tmpPlayer = *i; + break; + } + ++i; + } + } + return tmpPlayer; +} + void ClientThread::RemoveDisconnectedPlayers() { diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index ea72fc6f..9d5edf64 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -31,19 +31,21 @@ using namespace std; #define NET_TYPE_JOIN_GAME_ACK 0x0002 #define NET_TYPE_PLAYER_JOINED 0x0003 #define NET_TYPE_PLAYER_LEFT 0x0004 -#define NET_TYPE_GAME_START 0x0005 -#define NET_TYPE_HAND_START 0x0006 -#define NET_TYPE_PLAYERS_TURN 0x0007 -#define NET_TYPE_PLAYERS_ACTION 0x0008 -#define NET_TYPE_PLAYERS_ACTION_DONE 0x0009 -#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x000A -#define NET_TYPE_DEAL_FLOP_CARDS 0x000B -#define NET_TYPE_DEAL_TURN_CARD 0x000C -#define NET_TYPE_DEAL_RIVER_CARD 0x000D -#define NET_TYPE_ALL_IN_SHOW_CARDS 0x000E -#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x000F -#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x0010 -#define NET_TYPE_END_OF_GAME 0x0011 +#define NET_TYPE_KICK_PLAYER 0x0005 +#define NET_TYPE_START_EVENT 0x0006 +#define NET_TYPE_GAME_START 0x0007 +#define NET_TYPE_HAND_START 0x0008 +#define NET_TYPE_PLAYERS_TURN 0x0009 +#define NET_TYPE_PLAYERS_ACTION 0x000A +#define NET_TYPE_PLAYERS_ACTION_DONE 0x000B +#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x000C +#define NET_TYPE_DEAL_FLOP_CARDS 0x000D +#define NET_TYPE_DEAL_TURN_CARD 0x000E +#define NET_TYPE_DEAL_RIVER_CARD 0x000F +#define NET_TYPE_ALL_IN_SHOW_CARDS 0x0010 +#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x0011 +#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x0012 +#define NET_TYPE_END_OF_GAME 0x0013 #define NET_TYPE_SEND_CHAT_TEXT 0x0200 #define NET_TYPE_CHAT_TEXT 0x0201 @@ -126,6 +128,18 @@ struct GCC_PACKED NetPacketPlayerLeftData u_int16_t reserved; }; +struct GCC_PACKED NetPacketKickPlayerData +{ + NetPacketHeader head; + u_int16_t playerId; + u_int16_t reserved; +}; + +struct GCC_PACKED NetPacketStartEventData +{ + NetPacketHeader head; +}; + struct GCC_PACKED NetPacketGameStartData { NetPacketHeader head; @@ -324,6 +338,12 @@ NetPacket::Create(char *data, unsigned &dataSize) case NET_TYPE_PLAYER_LEFT: tmpPacket = boost::shared_ptr(new NetPacketPlayerLeft); break; + case NET_TYPE_KICK_PLAYER: + tmpPacket = boost::shared_ptr(new NetPacketKickPlayer); + break; + case NET_TYPE_START_EVENT: + tmpPacket = boost::shared_ptr(new NetPacketStartEvent); + break; case NET_TYPE_GAME_START: tmpPacket = boost::shared_ptr(new NetPacketGameStart); break; @@ -480,6 +500,18 @@ NetPacket::ToNetPacketPlayerLeft() const return NULL; } +const NetPacketKickPlayer * +NetPacket::ToNetPacketKickPlayer() const +{ + return NULL; +} + +const NetPacketStartEvent * +NetPacket::ToNetPacketStartEvent() const +{ + return NULL; +} + const NetPacketGameStart * NetPacket::ToNetPacketGameStart() const { @@ -983,6 +1015,101 @@ NetPacketPlayerLeft::InternalCheck(const NetPacketHeader* data) const //----------------------------------------------------------------------------- +NetPacketKickPlayer::NetPacketKickPlayer() +: NetPacket(NET_TYPE_KICK_PLAYER, sizeof(NetPacketKickPlayerData), sizeof(NetPacketKickPlayerData)) +{ +} + +NetPacketKickPlayer::~NetPacketKickPlayer() +{ +} + +boost::shared_ptr +NetPacketKickPlayer::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketKickPlayer); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketKickPlayer::SetData(const NetPacketKickPlayer::Data &inData) +{ + NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData(); + + // Set the data. + tmpData->playerId = htons(inData.playerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketKickPlayer::GetData(NetPacketKickPlayer::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData(); + + outData.playerId = ntohs(tmpData->playerId); +} + +const NetPacketKickPlayer * +NetPacketKickPlayer::ToNetPacketKickPlayer() const +{ + return this; +} + +void +NetPacketKickPlayer::InternalCheck(const NetPacketHeader* data) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + +NetPacketStartEvent::NetPacketStartEvent() +: NetPacket(NET_TYPE_START_EVENT, sizeof(NetPacketStartEventData), sizeof(NetPacketStartEventData)) +{ +} + +NetPacketStartEvent::~NetPacketStartEvent() +{ +} + +boost::shared_ptr +NetPacketStartEvent::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketStartEvent); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +const NetPacketStartEvent * +NetPacketStartEvent::ToNetPacketStartEvent() const +{ + return this; +} + +void +NetPacketStartEvent::InternalCheck(const NetPacketHeader* data) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + NetPacketGameStart::NetPacketGameStart() : NetPacket(NET_TYPE_GAME_START, sizeof(NetPacketGameStartData), MAX_PACKET_SIZE) { diff --git a/src/net/common/serverrecvstate.cpp b/src/net/common/serverrecvstate.cpp index 26aa289c..00faa6da 100644 --- a/src/net/common/serverrecvstate.cpp +++ b/src/net/common/serverrecvstate.cpp @@ -232,109 +232,129 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se { int retVal = MSG_SOCK_INIT_DONE; - // Session should be in initial state. - if (session.sessionData->GetState() != SessionData::Init) + if (packet->ToNetPacketJoinGame()) { - server.SessionError(session, ERR_SOCK_INVALID_STATE); - return retVal; - } + // Session should be in initial state. + if (session.sessionData->GetState() != SessionData::Init) + { + server.SessionError(session, ERR_SOCK_INVALID_STATE); + return retVal; + } - // Only accept join game packets. - const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame(); - if (!tmpPacket) + const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame(); + + NetPacketJoinGame::Data joinGameData; + tmpPacket->GetData(joinGameData); + + // Check the protocol version. + if (joinGameData.versionMajor != NET_VERSION_MAJOR) + { + server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED); + return retVal; + } + + size_t curNumPlayers = server.GetCurNumberOfPlayers(); + + // Check the number of players. + if (curNumPlayers >= (size_t)server.GetGameData().maxNumberOfPlayers) + { + server.SessionError(session, ERR_NET_SERVER_FULL); + return retVal; + } + + // Check the server password. + if (!server.CheckPassword(joinGameData.password)) + { + server.SessionError(session, ERR_NET_INVALID_PASSWORD); + return retVal; + } + + // Check whether the player name is correct. + // Paranoia check, this is also done in netpacket. + if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE) + { + server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME); + return retVal; + } + + // Check whether this player is already connected. + if (server.IsPlayerConnected(joinGameData.playerName)) + { + server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE); + return retVal; + } + + // Create player data object. + // TODO HACK first player is admin + PlayerRights rights = PLAYER_RIGHTS_NORMAL; + if (server.GetCurNumberOfPlayers() == 0) + rights = PLAYER_RIGHTS_ADMIN; + boost::shared_ptr tmpPlayerData( + new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_HUMAN, rights)); + tmpPlayerData->SetName(joinGameData.playerName); + tmpPlayerData->SetNetSessionData(session.sessionData); + + // Send ACK to client. + boost::shared_ptr answer(new NetPacketJoinGameAck); + NetPacketJoinGameAck::Data joinGameAckData; + joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused. + joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId(); + joinGameAckData.gameData = server.GetGameData(); + joinGameAckData.ptype = tmpPlayerData->GetType(); + joinGameAckData.prights = tmpPlayerData->GetRights(); + static_cast(answer.get())->SetData(joinGameAckData); + server.GetSender().Send(session.sessionData->GetSocket(), answer); + + // Send notifications for connected players to client. + PlayerDataList tmpPlayerList = server.GetPlayerDataList(); + PlayerDataList::iterator player_i = tmpPlayerList.begin(); + PlayerDataList::iterator player_end = tmpPlayerList.end(); + while (player_i != player_end) + { + boost::shared_ptr otherPlayerJoined(new NetPacketPlayerJoined); + NetPacketPlayerJoined::Data otherPlayerJoinedData; + otherPlayerJoinedData.playerId = (*player_i)->GetUniqueId(); + otherPlayerJoinedData.playerName = (*player_i)->GetName(); + otherPlayerJoinedData.ptype = (*player_i)->GetType(); + static_cast(otherPlayerJoined.get())->SetData(otherPlayerJoinedData); + server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined); + + ++player_i; + } + + // Send "Player Joined" to other fully connected clients. + boost::shared_ptr thisPlayerJoined(new NetPacketPlayerJoined); + NetPacketPlayerJoined::Data thisPlayerJoinedData; + thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId(); + thisPlayerJoinedData.playerName = tmpPlayerData->GetName(); + thisPlayerJoinedData.ptype = tmpPlayerData->GetType(); + thisPlayerJoinedData.prights = tmpPlayerData->GetRights(); + static_cast(thisPlayerJoined.get())->SetData(thisPlayerJoinedData); + server.SendToAllPlayers(thisPlayerJoined); + + // Set player data for session. + server.SetSessionPlayerData(session.sessionData, tmpPlayerData); + + // Session is now established. + session.sessionData->SetState(SessionData::Established); + } + else if (packet->ToNetPacketStartEvent()) + { + server.InternalStartGame(); + server.SetState(SERVER_START_GAME_STATE::Instance()); + } + else if (packet->ToNetPacketKickPlayer()) + { + NetPacketKickPlayer::Data kickPlayerData; + packet->ToNetPacketKickPlayer()->GetData(kickPlayerData); + + server.InternalKickPlayer(kickPlayerData.playerId); + } + else { server.SessionError(session, ERR_SOCK_INVALID_PACKET); - return retVal; } - NetPacketJoinGame::Data joinGameData; - tmpPacket->GetData(joinGameData); - - // Check the protocol version. - if (joinGameData.versionMajor != NET_VERSION_MAJOR) - { - server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED); - return retVal; - } - - size_t curNumPlayers = server.GetCurNumberOfPlayers(); - - // Check the number of players. - if (curNumPlayers >= (size_t)server.GetGameData().maxNumberOfPlayers) - { - server.SessionError(session, ERR_NET_SERVER_FULL); - return retVal; - } - - // Check the server password. - if (!server.CheckPassword(joinGameData.password)) - { - server.SessionError(session, ERR_NET_INVALID_PASSWORD); - return retVal; - } - - // Check whether the player name is correct. - // Paranoia check, this is also done in netpacket. - if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE) - { - server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME); - return retVal; - } - - // Check whether this player is already connected. - if (server.IsPlayerConnected(joinGameData.playerName)) - { - server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE); - return retVal; - } - - // Create player data object. - boost::shared_ptr tmpPlayerData( - new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_HUMAN)); - tmpPlayerData->SetName(joinGameData.playerName); - tmpPlayerData->SetNetSessionData(session.sessionData); - - // Send ACK to client. - boost::shared_ptr answer(new NetPacketJoinGameAck); - NetPacketJoinGameAck::Data joinGameAckData; - joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused. - joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId(); - joinGameAckData.gameData = server.GetGameData(); - static_cast(answer.get())->SetData(joinGameAckData); - server.GetSender().Send(session.sessionData->GetSocket(), answer); - - // Send notifications for connected players to client. - PlayerDataList tmpPlayerList = server.GetPlayerDataList(); - PlayerDataList::iterator player_i = tmpPlayerList.begin(); - PlayerDataList::iterator player_end = tmpPlayerList.end(); - while (player_i != player_end) - { - boost::shared_ptr otherPlayerJoined(new NetPacketPlayerJoined); - NetPacketPlayerJoined::Data otherPlayerJoinedData; - otherPlayerJoinedData.playerId = (*player_i)->GetUniqueId(); - otherPlayerJoinedData.playerName = (*player_i)->GetName(); - otherPlayerJoinedData.ptype = (*player_i)->GetType(); - static_cast(otherPlayerJoined.get())->SetData(otherPlayerJoinedData); - server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined); - - ++player_i; - } - - // Send "Player Joined" to other fully connected clients. - boost::shared_ptr thisPlayerJoined(new NetPacketPlayerJoined); - NetPacketPlayerJoined::Data thisPlayerJoinedData; - thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId(); - thisPlayerJoinedData.playerName = tmpPlayerData->GetName(); - thisPlayerJoinedData.ptype = tmpPlayerData->GetType(); - static_cast(thisPlayerJoined.get())->SetData(thisPlayerJoinedData); - server.SendToAllPlayers(thisPlayerJoined); - - // Set player data for session. - server.SetSessionPlayerData(session.sessionData, tmpPlayerData); - - // Session is now established. - session.sessionData->SetState(SessionData::Established); - return retVal; } @@ -1039,11 +1059,7 @@ ServerRecvStateNextGameDelay::Process(ServerRecvThread &server) server.SendToAllPlayers(endGame); - // Switch back to the GUI, wait for the start of a new game. - // Luckily, the names are still in the GUI dialog. - // We just need to show the proper dialog, and people can - // join or leave as usual. - server.GetCallback().SignalNetServerStartDialog(); + // Wait for the start of a new game. server.SetState(ServerRecvStateInit::Instance()); } diff --git a/src/net/common/serverrecvthread.cpp b/src/net/common/serverrecvthread.cpp index d48816b4..d62855e2 100644 --- a/src/net/common/serverrecvthread.cpp +++ b/src/net/common/serverrecvthread.cpp @@ -140,15 +140,10 @@ ServerRecvThread::NotificationLoop() Notification notification = m_notificationQueue.front(); m_notificationQueue.pop_front(); - switch(notification.message) - { - case NOTIFY_GAME_START: - InternalStartGame(); - break; - case NOTIFY_KICK_PLAYER: - InternalKickPlayer(notification.param); - break; - } +// switch(notification.message) +// { +// break; +// } } } @@ -249,8 +244,6 @@ ServerRecvThread::CleanupSessionMap() void ServerRecvThread::InternalStartGame() { - SetState(SERVER_START_GAME_STATE::Instance()); - // Kick all players which are not fully connected. RemoveNotEstablishedSessions(); // Set order of players. @@ -295,14 +288,10 @@ ServerRecvThread::InternalStartGame() } void -ServerRecvThread::InternalKickPlayer(const string playerName) +ServerRecvThread::InternalKickPlayer(unsigned uniqueId) { - if (!playerName.empty()) - { - SessionWrapper tmpSession = GetSessionByPlayerName(playerName); - - SessionError(tmpSession, ERR_NET_PLAYER_KICKED); - } + SessionWrapper tmpSession = GetSessionByUniquePlayerId(uniqueId); + SessionError(tmpSession, ERR_NET_PLAYER_KICKED); } SessionWrapper @@ -394,9 +383,11 @@ ServerRecvThread::AddSession(boost::shared_ptr sessionData) void ServerRecvThread::SessionError(SessionWrapper session, int errorCode) { - assert(session.sessionData.get()); - SendError(session.sessionData->GetSocket(), errorCode); - CloseSessionDelayed(session); + if (session.sessionData.get()) + { + SendError(session.sessionData->GetSocket(), errorCode); + CloseSessionDelayed(session); + } } void diff --git a/src/net/common/serverthread.cpp b/src/net/common/serverthread.cpp index e150a2ac..014563d0 100644 --- a/src/net/common/serverthread.cpp +++ b/src/net/common/serverthread.cpp @@ -57,26 +57,6 @@ ServerThread::Init(unsigned serverPort, bool ipv6, bool sctp, const std::string GetRecvThread().Init(pwd, gameData); } -void -ServerThread::StartGame() -{ - if (!IsRunning()) - return; // TODO: throw exception - - // Thread-safe notification. - GetRecvThread().AddNotification(NOTIFY_GAME_START, ""); -} - -void -ServerThread::KickPlayer(const string &playerName) -{ - if (!IsRunning()) - return; // TODO: throw exception - - // Thread-safe notification. - GetRecvThread().AddNotification(NOTIFY_KICK_PLAYER, playerName); -} - ServerCallback & ServerThread::GetCallback() { diff --git a/src/net/netpacket.h b/src/net/netpacket.h index da390b25..d0d4340e 100644 --- a/src/net/netpacket.h +++ b/src/net/netpacket.h @@ -44,6 +44,8 @@ class NetPacketJoinGame; class NetPacketJoinGameAck; class NetPacketPlayerJoined; class NetPacketPlayerLeft; +class NetPacketKickPlayer; +class NetPacketStartEvent; class NetPacketGameStart; class NetPacketHandStart; class NetPacketPlayersTurn; @@ -82,6 +84,8 @@ public: virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const; virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const; virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const; + virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const; + virtual const NetPacketStartEvent *ToNetPacketStartEvent() const; virtual const NetPacketGameStart *ToNetPacketGameStart() const; virtual const NetPacketHandStart *ToNetPacketHandStart() const; virtual const NetPacketPlayersTurn *ToNetPacketPlayersTurn() const; @@ -215,6 +219,45 @@ protected: virtual void InternalCheck(const NetPacketHeader* data) const; }; +class NetPacketKickPlayer : public NetPacket +{ +public: + struct Data + { + u_int16_t playerId; + }; + + NetPacketKickPlayer(); + virtual ~NetPacketKickPlayer(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + +class NetPacketStartEvent : public NetPacket +{ +public: + + NetPacketStartEvent(); + virtual ~NetPacketStartEvent(); + + virtual boost::shared_ptr Clone() const; + + virtual const NetPacketStartEvent *ToNetPacketStartEvent() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + class NetPacketGameStart : public NetPacket { public: diff --git a/src/net/servercallback.h b/src/net/servercallback.h index afb2064a..4278585f 100644 --- a/src/net/servercallback.h +++ b/src/net/servercallback.h @@ -33,8 +33,6 @@ public: virtual void SignalNetServerPlayerJoined(const std::string &playerName) = 0; virtual void SignalNetServerPlayerLeft(const std::string &playerName) = 0; - - virtual void SignalNetServerStartDialog() = 0; }; #endif diff --git a/src/net/serverrecvthread.h b/src/net/serverrecvthread.h index 8334a9a8..e1ef511b 100644 --- a/src/net/serverrecvthread.h +++ b/src/net/serverrecvthread.h @@ -36,9 +36,6 @@ #define RECEIVER_THREAD_TERMINATE_TIMEOUT 200 -// Notifications -#define NOTIFY_GAME_START 1 -#define NOTIFY_KICK_PLAYER 2 class ServerRecvState; class SenderThread; @@ -103,7 +100,7 @@ protected: void CleanupSessionMap(); void InternalStartGame(); - void InternalKickPlayer(const std::string playerName); + void InternalKickPlayer(unsigned uniqueId); SessionWrapper GetSession(SOCKET sock) const; SessionWrapper GetSessionByPlayerName(const std::string playerName) const; diff --git a/src/net/serverthread.h b/src/net/serverthread.h index 3a9ec85c..c6f50c5e 100644 --- a/src/net/serverthread.h +++ b/src/net/serverthread.h @@ -43,8 +43,6 @@ public: // Set the parameters. void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, const GameData &gameData); - void StartGame(); - void KickPlayer(const std::string &playerName); ServerCallback &GetCallback(); GuiInterface &GetGui(); diff --git a/src/playerdata.cpp b/src/playerdata.cpp index 6d3ad608..53c4b88a 100644 --- a/src/playerdata.cpp +++ b/src/playerdata.cpp @@ -19,8 +19,8 @@ #include -PlayerData::PlayerData(unsigned uniqueId, int number, PlayerType type) -: m_uniqueId(uniqueId), m_number(number), m_type(type) +PlayerData::PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights) +: m_uniqueId(uniqueId), m_number(number), m_type(type), m_rights(rights) { } diff --git a/src/playerdata.h b/src/playerdata.h index 6b8a6f7e..16473986 100644 --- a/src/playerdata.h +++ b/src/playerdata.h @@ -43,7 +43,7 @@ enum PlayerRights class PlayerData { public: - PlayerData(unsigned uniqueId, int number, PlayerType type); + PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights); ~PlayerData(); const std::string &GetName() const @@ -60,6 +60,8 @@ public: {m_netSessionData = session;} PlayerType GetType() const {return m_type;} + PlayerRights GetRights() const + {return m_rights;} unsigned GetUniqueId() const {return m_uniqueId;} int GetNumber() const @@ -76,6 +78,7 @@ private: std::string m_name; std::string m_avatarFile; PlayerType m_type; + PlayerRights m_rights; boost::shared_ptr m_netSessionData; }; diff --git a/src/session.cpp b/src/session.cpp index f2993cce..10422b70 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -69,7 +69,9 @@ void Session::startLocalGame(const GameData &gameData, const StartData &startDat //PlayerData erzeugen // UniqueId = PlayerNumber for local games. - boost::shared_ptr playerData(new PlayerData(i, i, i == 0 ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER)); + boost::shared_ptr playerData(new PlayerData(i, i, + i == 0 ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER, + i == 0 ? PLAYER_RIGHTS_ADMIN : PLAYER_RIGHTS_NORMAL)); playerData->SetName(myConfig->readConfigString(myName.str())); playerData->SetAvatarFile(myConfig->readConfigString(myAvatar.str())); @@ -172,16 +174,6 @@ void Session::startNetworkServer(const GameData &gameData) myNetServer->Run(); } -void Session::initiateNetworkServerGame() -{ - if (!myNetServer) - { - assert(false); - return; - } - myNetServer->StartGame(); -} - void Session::terminateNetworkServer() { if (!myNetServer) @@ -207,6 +199,13 @@ void Session::waitForNetworkServer(unsigned timeoutMsec) } } +void Session::sendStartEvent() +{ + if (!myNetClient) + return; // only act if client is running. + myNetClient->SendStartEvent(); +} + void Session::sendClientPlayerAction() { if (!myNetClient) @@ -223,12 +222,9 @@ void Session::sendChatMessage(const std::string &message) void Session::kickPlayer(const std::string &playerName) { - if (!myNetServer) - { - assert(false); - return; - } - myNetServer->KickPlayer(playerName); + if (!myNetClient) + return; // only act if client is running. + myNetClient->SendKickPlayer(playerName); } bool Session::isNetworkClientRunning() const diff --git a/src/session.h b/src/session.h index 78fb4c56..2636f97c 100755 --- a/src/session.h +++ b/src/session.h @@ -50,7 +50,7 @@ public: void terminateNetworkClient(); void startNetworkServer(const GameData &gameData); - void initiateNetworkServerGame(); + void sendStartEvent(); void terminateNetworkServer(); void waitForNetworkServer(unsigned timeoutMsec);