From 05a86be4fe2a11d738d979a2860979a0ee521d6c Mon Sep 17 00:00:00 2001 From: lotodore Date: Thu, 7 Jun 2007 14:06:22 +0000 Subject: [PATCH] Delay after showing cards when all in condition is true. Added option TCP_NODELAY. Round is now shown before dealing cards. --- src/engine/local_engine/localhand.cpp | 2 +- src/engine/network_engine/clienthand.h | 6 +- src/gui/generic/serverguiwrapper.cpp | 2 +- src/gui/generic/serverguiwrapper.h | 2 +- src/gui/guiinterface.h | 2 +- src/gui/qt/guiwrapper.cpp | 2 +- src/gui/qt/guiwrapper.h | 2 +- src/gui/qt/mainwindow/mainwindowimpl.cpp | 6 +- src/gui/qt/mainwindow/mainwindowimpl.h | 4 +- src/net/clientstate.h | 1 + src/net/common/clientstate.cpp | 45 +++-- src/net/common/serverrecvstate.cpp | 234 ++++++++++++++--------- src/net/common/serverthread.cpp | 4 +- src/net/serverrecvstate.h | 27 ++- src/net/serverrecvthread.h | 9 +- src/net/socket_msg.h | 1 + 16 files changed, 223 insertions(+), 126 deletions(-) diff --git a/src/engine/local_engine/localhand.cpp b/src/engine/local_engine/localhand.cpp index 1a9f95ea..180bcd12 100755 --- a/src/engine/local_engine/localhand.cpp +++ b/src/engine/local_engine/localhand.cpp @@ -355,7 +355,7 @@ void LocalHand::switchRounds() { //unhighlight actual players groupbox if(playerArray[lastPlayersTurn]->getMyActiveStatus() == 1) myGui->refreshGroupbox(lastPlayersTurn,1); - myGui->refreshGameLabels(); + myGui->refreshGameLabels((GameState)getActualRound()); // /*/*/*/*cout <<*/*/*/*/ "NextPlayerSpeed1 stop" << endl; // // cout << "NextPlayerSpeed2 start" << endl; diff --git a/src/engine/network_engine/clienthand.h b/src/engine/network_engine/clienthand.h index 2d15174d..2edbbcbe 100644 --- a/src/engine/network_engine/clienthand.h +++ b/src/engine/network_engine/clienthand.h @@ -79,8 +79,8 @@ public: void setLastPlayersTurn(int theValue) { lastPlayersTurn = theValue; } int getLastPlayersTurn() const { return lastPlayersTurn; } - void setCardsShown(bool theValue) { cardsShown = theValue; } - bool getCardsShown() const { return cardsShown; } + void setCardsShown(bool theValue) { cardsShown = theValue; } + bool getCardsShown() const { return cardsShown; } void switchRounds(); @@ -108,7 +108,7 @@ private: int lastPlayersTurn; bool allInCondition; - bool cardsShown; + bool cardsShown; // hier steht bis zu welcher bettingRound der human player gespielt hat: 0 - nur Preflop, 1 - bis Flop, ... int bettingRoundsPlayed; diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index c8eb5df4..2323f191 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -60,7 +60,7 @@ void ServerGuiWrapper::refreshPot() const {} void ServerGuiWrapper::refreshGroupbox(int playerID, int status) const {} void ServerGuiWrapper::refreshPlayerName() const {} void ServerGuiWrapper::refreshButton() const {} -void ServerGuiWrapper::refreshGameLabels() const {} +void ServerGuiWrapper::refreshGameLabels(GameState state) const {} void ServerGuiWrapper::dealHoleCards() {} void ServerGuiWrapper::dealFlopCards() {} diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index 924382a4..2219f6d9 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -44,7 +44,7 @@ public: void refreshAll() const; void refreshPlayerName() const; void refreshButton() const; - void refreshGameLabels() const; + void refreshGameLabels(GameState state) const; void dealHoleCards(); void dealFlopCards(); diff --git a/src/gui/guiinterface.h b/src/gui/guiinterface.h index 89a753a4..83d13c55 100644 --- a/src/gui/guiinterface.h +++ b/src/gui/guiinterface.h @@ -49,7 +49,7 @@ public: virtual void refreshAll() const=0; virtual void refreshPlayerName() const=0; virtual void refreshButton() const =0; - virtual void refreshGameLabels() const=0; + virtual void refreshGameLabels(GameState state) const=0; // // Karten-Funktionen virtual void dealHoleCards()=0; diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index cc692d8c..72c98294 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -58,7 +58,7 @@ void GuiWrapper::refreshPot() const { myW->signalRefreshPot(); } void GuiWrapper::refreshGroupbox(int playerID, int status) const { myW->signalRefreshGroupbox(playerID, status); } void GuiWrapper::refreshPlayerName() const { myW->signalRefreshPlayerName(); } void GuiWrapper::refreshButton() const { myW->signalRefreshButton(); } -void GuiWrapper::refreshGameLabels() const { myW->signalRefreshGameLabels(); } +void GuiWrapper::refreshGameLabels(GameState state) const { myW->signalRefreshGameLabels(state); } void GuiWrapper::dealHoleCards() { myW->signalDealHoleCards(); } void GuiWrapper::dealFlopCards() { myW->signalDealFlopCards0(); } diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index d4f889a9..bc86979b 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -52,7 +52,7 @@ public: void refreshAll() const; void refreshPlayerName() const; void refreshButton() const; - void refreshGameLabels() const; + void refreshGameLabels(GameState state) const; void dealHoleCards(); void dealFlopCards(); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index 344e9cbd..91a1457a 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -582,7 +582,7 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) connect(this, SIGNAL(signalRefreshAll()), this, SLOT(refreshAll())); connect(this, SIGNAL(signalRefreshPlayerName()), this, SLOT(refreshPlayerName())); connect(this, SIGNAL(signalRefreshButton()), this, SLOT(refreshButton())); - connect(this, SIGNAL(signalRefreshGameLabels()), this, SLOT(refreshGameLabels())); + connect(this, SIGNAL(signalRefreshGameLabels(int)), this, SLOT(refreshGameLabels(int))); connect(this, SIGNAL(signalMeInAction()), this, SLOT(meInAction())); @@ -1186,9 +1186,9 @@ void mainWindowImpl::refreshGroupbox(int playerID, int status) { } } -void mainWindowImpl::refreshGameLabels() { +void mainWindowImpl::refreshGameLabels(int gameState) { - switch(mySession->getCurrentGame()->getCurrentHand()->getActualRound()) { + switch(gameState) { case 0: { textLabel_handLabel->setText("Preflop"); } break; diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index 7b2e1132..34fcd649 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -84,6 +84,7 @@ signals: void signalRefreshAll(); void signalRefreshPlayerName(); void signalRefreshButton(); + void signalRefreshGameLabels(int); void signalMeInAction(); @@ -92,7 +93,6 @@ signals: void signalDealTurnCards0(); void signalDealRiverCards0(); - void signalRefreshGameLabels(); void signalNextPlayerAnimation(); void signalPreflopAnimation1(); @@ -134,7 +134,7 @@ public slots: void refreshGroupbox(int =-1, int =-1); void refreshAll(); void refreshPlayerName(); - void refreshGameLabels(); + void refreshGameLabels(int); void refreshButton(); void refreshPlayerAvatar(); diff --git a/src/net/clientstate.h b/src/net/clientstate.h index ae25935c..42f2274d 100644 --- a/src/net/clientstate.h +++ b/src/net/clientstate.h @@ -255,6 +255,7 @@ protected: static void SetHighestSet(Game &curGame, int highestSet); static int GetPlayersTurn(Game &curGame); static void SetPlayersTurn(Game &curGame, int playersTurn); + static void ResetPlayerActions(Game &curGame); }; // State: Final (just for testing, should not be used). diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index f5b8b828..b0620bfe 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -66,8 +66,8 @@ ClientStateInit::Process(ClientThread &client) if (context.GetServerAddr().empty()) throw ClientException(ERR_SOCK_SERVERADDR_NOT_SET, 0); -// if (context.GetServerPort() < 1024) -// throw ClientException(ERR_SOCK_INVALID_PORT, 0); + if (context.GetServerPort() < 1024) + throw ClientException(ERR_SOCK_INVALID_PORT, 0); context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, context.GetProtocol())); if (!IS_VALID_SOCKET(context.GetSocket())) @@ -77,6 +77,10 @@ ClientStateInit::Process(ClientThread &client) if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) throw ClientException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); + // The following call is optional - the return value is not checked. + int nodelay = 1; + setsockopt(context.GetSocket(), SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); + client.SetState(ClientStateStartResolve::Instance()); return MSG_SOCK_INIT_DONE; @@ -558,7 +562,7 @@ ClientStateWaitHand::InternalProcess(ClientThread &client, boost::shared_ptrinitHand(); client.GetGame()->startHand(); client.GetGui().dealHoleCards(); - client.GetGui().refreshGameLabels(); + client.GetGui().refreshGameLabels(GAME_STATE_PREFLOP); client.SetState(ClientStateRunHand::Instance()); retVal = MSG_NET_GAME_CLIENT_HAND_START; @@ -637,22 +641,10 @@ ClientStateRunHand::InternalProcess(ClientThread &client, boost::shared_ptrgetCurrentHand()->getActualRound() != turnData.gameState) { - // Reset player actions - for (int i = 0; i < MAX_NUMBER_OF_PLAYERS; i++) - { - int action = curGame->getPlayerArray()[i]->getMyAction(); - if (action != 1 && action != 6) - curGame->getPlayerArray()[i]->setMyAction(0); - curGame->getPlayerArray()[i]->setMySetNull(); - } - + ResetPlayerActions(*curGame); curGame->getCurrentHand()->setActualRound(turnData.gameState); - - client.GetGui().refreshPot(); - client.GetGui().refreshSet(); + // Refresh actions. client.GetGui().refreshAction(); - client.GetGui().refreshCash(); - client.GetGui().refreshGameLabels(); } // Next player's turn. @@ -678,6 +670,8 @@ ClientStateRunHand::InternalProcess(ClientThread &client, boost::shared_ptr(cardsData.flopCards[num]); tmpCards[3] = tmpCards[4] = 0; curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); + + client.GetGui().refreshGameLabels(GAME_STATE_FLOP); client.GetGui().dealFlopCards(); } else if (packet->ToNetPacketDealTurnCard()) @@ -688,6 +682,8 @@ ClientStateRunHand::InternalProcess(ClientThread &client, boost::shared_ptrgetCurrentHand()->getBoard()->getMyCards(tmpCards); tmpCards[3] = static_cast(cardsData.turnCard); curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); + + client.GetGui().refreshGameLabels(GAME_STATE_TURN); client.GetGui().dealTurnCard(); } else if (packet->ToNetPacketDealRiverCard()) @@ -698,6 +694,8 @@ ClientStateRunHand::InternalProcess(ClientThread &client, boost::shared_ptrgetCurrentHand()->getBoard()->getMyCards(tmpCards); tmpCards[4] = static_cast(cardsData.riverCard); curGame->getCurrentHand()->getBoard()->setMyCards(tmpCards); + + client.GetGui().refreshGameLabels(GAME_STATE_RIVER); client.GetGui().dealRiverCard(); } else if (packet->ToNetPacketAllInShowCards()) @@ -888,6 +886,19 @@ ClientStateRunHand::SetPlayersTurn(Game &curGame, int playersTurn) } } +void +ClientStateRunHand::ResetPlayerActions(Game &curGame) +{ + // Reset player actions + for (int i = 0; i < MAX_NUMBER_OF_PLAYERS; i++) + { + int action = curGame.getPlayerArray()[i]->getMyAction(); + if (action != 1 && action != 6) + curGame.getPlayerArray()[i]->setMyAction(0); + curGame.getPlayerArray()[i]->setMySetNull(); + } +} + //----------------------------------------------------------------------------- ClientStateFinal & diff --git a/src/net/common/serverrecvstate.cpp b/src/net/common/serverrecvstate.cpp index 05e49cef..e7a34a68 100644 --- a/src/net/common/serverrecvstate.cpp +++ b/src/net/common/serverrecvstate.cpp @@ -32,13 +32,16 @@ using namespace std; -#define SERVER_WAIT_TIMEOUT_MSEC 50 -#define SERVER_NEXT_HAND_DELAY_SEC 10 -#define SERVER_DEAL_FLOP_CARDS_SEC 5 -#define SERVER_DEAL_TURN_CARD_SEC 3 -#define SERVER_DEAL_RIVER_CARD_SEC 3 +#define SERVER_WAIT_TIMEOUT_MSEC 50 +#define SERVER_DELAY_NEXT_HAND_SEC 10 +#define SERVER_DEAL_FLOP_CARDS_DELAY_SEC 5 +#define SERVER_DEAL_TURN_CARD_DELAY_SEC 2 +#define SERVER_DEAL_RIVER_CARD_DELAY_SEC 2 +#define SERVER_DEAL_ADD_ALL_IN_DELAY_SEC 1 +#define SERVER_SHOW_CARDS_DELAY_SEC 2 // Helper functions +// TODO: these are hacks. static PlayerInterface *GetCurrentPlayer(Game &curGame) { @@ -65,6 +68,50 @@ static PlayerInterface *GetCurrentPlayer(Game &curGame) return curGame.getPlayerArray()[curPlayerNum]; } +static void SendNewRoundCards(ServerRecvThread &server, Game &curGame, int state) +{ + // TODO: no switch needed here if game states are polymorphic + switch(state) { + case GAME_STATE_PREFLOP: { + // nothing to do + } break; + case GAME_STATE_FLOP: { + // deal flop cards + int cards[5]; + curGame.getCurrentHand()->getBoard()->getMyCards(cards); + boost::shared_ptr notifyCards(new NetPacketDealFlopCards); + NetPacketDealFlopCards::Data notifyCardsData; + for (int num = 0; num < 3; num++) + notifyCardsData.flopCards[num] = static_cast(cards[num]); + static_cast(notifyCards.get())->SetData(notifyCardsData); + server.SendToAllPlayers(notifyCards); + } break; + case GAME_STATE_TURN: { + // deal turn card + int cards[5]; + curGame.getCurrentHand()->getBoard()->getMyCards(cards); + boost::shared_ptr notifyCards(new NetPacketDealTurnCard); + NetPacketDealTurnCard::Data notifyCardsData; + notifyCardsData.turnCard = static_cast(cards[3]); + static_cast(notifyCards.get())->SetData(notifyCardsData); + server.SendToAllPlayers(notifyCards); + } break; + case GAME_STATE_RIVER: { + // deal river card + int cards[5]; + curGame.getCurrentHand()->getBoard()->getMyCards(cards); + boost::shared_ptr notifyCards(new NetPacketDealRiverCard); + NetPacketDealRiverCard::Data notifyCardsData; + notifyCardsData.riverCard = static_cast(cards[4]); + static_cast(notifyCards.get())->SetData(notifyCardsData); + server.SendToAllPlayers(notifyCards); + } break; + default: { + // + } + } +} + //----------------------------------------------------------------------------- ServerRecvState::~ServerRecvState() @@ -454,49 +501,53 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server) if (newRound != curRound) { assert(newRound > curRound); + // Retrieve active players. If only one player is left, no cards are shown. + std::list activePlayers = GetActivePlayers(curGame); if (curGame.getCurrentHand()->getAllInCondition() - && !curGame.getCurrentHand()->getCardsShown()) + && !curGame.getCurrentHand()->getCardsShown() + && activePlayers.size() > 1) { - // Retrieve active players. If only one player is left, no cards are shown. - std::list activePlayers = GetActivePlayers(curGame); - assert(!activePlayers.empty()); - if (activePlayers.size() > 1) + // Send cards of all active players to all players (all in). + boost::shared_ptr allIn(new NetPacketAllInShowCards); + NetPacketAllInShowCards::Data allInData; + + std::list::iterator i = activePlayers.begin(); + std::list::iterator end = activePlayers.end(); + + while (i != end) { - // Send cards of all active players to all players (all in). - boost::shared_ptr allIn(new NetPacketAllInShowCards); - NetPacketAllInShowCards::Data allInData; + NetPacketAllInShowCards::PlayerCards tmpPlayerCards; + tmpPlayerCards.playerId = (*i)->getMyUniqueID(); - std::list::iterator i = activePlayers.begin(); - std::list::iterator end = activePlayers.end(); + int tmpCards[2]; + (*i)->getMyCards(tmpCards); + tmpPlayerCards.cards[0] = static_cast(tmpCards[0]); + tmpPlayerCards.cards[1] = static_cast(tmpCards[1]); - while (i != end) - { - NetPacketAllInShowCards::PlayerCards tmpPlayerCards; - tmpPlayerCards.playerId = (*i)->getMyUniqueID(); - - int tmpCards[2]; - (*i)->getMyCards(tmpCards); - tmpPlayerCards.cards[0] = static_cast(tmpCards[0]); - tmpPlayerCards.cards[1] = static_cast(tmpCards[1]); - - allInData.playerCards.push_back(tmpPlayerCards); - ++i; - } - static_cast(allIn.get())->SetData(allInData); - server.SendToAllPlayers(allIn); - - curGame.getCurrentHand()->setCardsShown(true); + allInData.playerCards.push_back(tmpPlayerCards); + ++i; } + static_cast(allIn.get())->SetData(allInData); + server.SendToAllPlayers(allIn); + curGame.getCurrentHand()->setCardsShown(true); + + boost::microsec_timer delayTimer; + delayTimer.start(); + ServerRecvStateShowCardsDelay::Instance().SetTimer(delayTimer); + server.SetState(ServerRecvStateShowCardsDelay::Instance()); + retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; } + else + { + SendNewRoundCards(server, curGame, newRound); - SendNewRoundCards(server, curGame, newRound); - - boost::microsec_timer delayTimer; - delayTimer.start(); - ServerRecvStateDealCardsDelay::Instance().SetTimer(delayTimer); - server.SetState(ServerRecvStateDealCardsDelay::Instance()); - retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; + boost::microsec_timer delayTimer; + delayTimer.start(); + ServerRecvStateDealCardsDelay::Instance().SetTimer(delayTimer); + server.SetState(ServerRecvStateDealCardsDelay::Instance()); + retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; + } } else { @@ -625,51 +676,6 @@ ServerRecvStateStartRound::GameRun(Game &curGame) } } -void -ServerRecvStateStartRound::SendNewRoundCards(ServerRecvThread &server, Game &curGame, int state) -{ - // TODO: no switch needed here if game states are polymorphic - switch(state) { - case GAME_STATE_PREFLOP: { - // nothing to do - } break; - case GAME_STATE_FLOP: { - // deal flop cards - int cards[5]; - curGame.getCurrentHand()->getBoard()->getMyCards(cards); - boost::shared_ptr notifyCards(new NetPacketDealFlopCards); - NetPacketDealFlopCards::Data notifyCardsData; - for (int num = 0; num < 3; num++) - notifyCardsData.flopCards[num] = static_cast(cards[num]); - static_cast(notifyCards.get())->SetData(notifyCardsData); - server.SendToAllPlayers(notifyCards); - } break; - case GAME_STATE_TURN: { - // deal turn card - int cards[5]; - curGame.getCurrentHand()->getBoard()->getMyCards(cards); - boost::shared_ptr notifyCards(new NetPacketDealTurnCard); - NetPacketDealTurnCard::Data notifyCardsData; - notifyCardsData.turnCard = static_cast(cards[3]); - static_cast(notifyCards.get())->SetData(notifyCardsData); - server.SendToAllPlayers(notifyCards); - } break; - case GAME_STATE_RIVER: { - // deal river card - int cards[5]; - curGame.getCurrentHand()->getBoard()->getMyCards(cards); - boost::shared_ptr notifyCards(new NetPacketDealRiverCard); - NetPacketDealRiverCard::Data notifyCardsData; - notifyCardsData.riverCard = static_cast(cards[4]); - static_cast(notifyCards.get())->SetData(notifyCardsData); - server.SendToAllPlayers(notifyCards); - } break; - default: { - // - } - } -} - std::list ServerRecvStateStartRound::GetActivePlayers(Game &curGame) { @@ -857,20 +863,20 @@ ServerRecvStateDealCardsDelay::Process(ServerRecvThread &server) Game &curGame = server.GetGame(); - int allInDelay = curGame.getCurrentHand()->getAllInCondition() ? 1 : 0; + int allInDelay = curGame.getCurrentHand()->getAllInCondition() ? SERVER_DEAL_ADD_ALL_IN_DELAY_SEC : 0; switch(curGame.getCurrentHand()->getActualRound()) { case GAME_STATE_FLOP: - if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_FLOP_CARDS_SEC - allInDelay) + if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_FLOP_CARDS_DELAY_SEC + allInDelay) server.SetState(ServerRecvStateStartRound::Instance()); break; case GAME_STATE_TURN: - if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_TURN_CARD_SEC /*+ allInDelay*/) + if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_TURN_CARD_DELAY_SEC) server.SetState(ServerRecvStateStartRound::Instance()); break; case GAME_STATE_RIVER: - if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_RIVER_CARD_SEC /*+ allInDelay*/) + if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_RIVER_CARD_DELAY_SEC) server.SetState(ServerRecvStateStartRound::Instance()); break; default: @@ -887,6 +893,56 @@ ServerRecvStateDealCardsDelay::InternalProcess(ServerRecvThread &server, Session //----------------------------------------------------------------------------- +ServerRecvStateShowCardsDelay & +ServerRecvStateShowCardsDelay::Instance() +{ + static ServerRecvStateShowCardsDelay state; + return state; +} + +ServerRecvStateShowCardsDelay::ServerRecvStateShowCardsDelay() +{ +} + +ServerRecvStateShowCardsDelay::~ServerRecvStateShowCardsDelay() +{ +} + +void +ServerRecvStateShowCardsDelay::SetTimer(const boost::microsec_timer &timer) +{ + m_delayTimer = timer; +} + +int +ServerRecvStateShowCardsDelay::Process(ServerRecvThread &server) +{ + int retVal = ServerRecvStateReceiving::Process(server); + + Game &curGame = server.GetGame(); + + if (m_delayTimer.elapsed().seconds() >= SERVER_SHOW_CARDS_DELAY_SEC) + { + SendNewRoundCards(server, curGame, curGame.getCurrentHand()->getActualRound()); + + boost::microsec_timer delayTimer; + delayTimer.start(); + ServerRecvStateDealCardsDelay::Instance().SetTimer(delayTimer); + server.SetState(ServerRecvStateDealCardsDelay::Instance()); + retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; + } + + return retVal; +} + +int +ServerRecvStateShowCardsDelay::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +{ + return MSG_SOCK_INTERNAL_PENDING; +} + +//----------------------------------------------------------------------------- + ServerRecvStateNextHand & ServerRecvStateNextHand::Instance() { @@ -913,7 +969,7 @@ ServerRecvStateNextHand::Process(ServerRecvThread &server) { int retVal = ServerRecvStateReceiving::Process(server); - if (m_delayTimer.elapsed().seconds() >= SERVER_NEXT_HAND_DELAY_SEC) + if (m_delayTimer.elapsed().seconds() >= SERVER_DELAY_NEXT_HAND_SEC) server.SetState(ServerRecvStateStartHand::Instance()); return retVal; diff --git a/src/net/common/serverthread.cpp b/src/net/common/serverthread.cpp index b6db9a8a..d20a50b7 100644 --- a/src/net/common/serverthread.cpp +++ b/src/net/common/serverthread.cpp @@ -115,9 +115,11 @@ ServerThread::Listen() if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) throw ServerException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); - // The following call is optional. If it fails, we don't care. + // The following two calls are optional. If they fail, we don't care. int reuse = 1; setsockopt(context.GetSocket(), SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)); + int nodelay = 1; + setsockopt(context.GetSocket(), SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); context.GetServerSockaddr()->ss_family = context.GetAddrFamily(); diff --git a/src/net/serverrecvstate.h b/src/net/serverrecvstate.h index 58044051..98b1e19c 100644 --- a/src/net/serverrecvstate.h +++ b/src/net/serverrecvstate.h @@ -157,7 +157,6 @@ protected: ServerRecvStateStartRound(); static void GameRun(Game &curGame); - static void SendNewRoundCards(ServerRecvThread &server, Game &curGame, int state); static std::list GetActivePlayers(Game &curGame); }; @@ -211,6 +210,32 @@ private: boost::microsec_timer m_delayTimer; }; +// State: Delay after showing cards (all in) +class ServerRecvStateShowCardsDelay : public ServerRecvStateReceiving, public ServerRecvStateRunning +{ +public: + // Access the state singleton. + static ServerRecvStateShowCardsDelay &Instance(); + + virtual ~ServerRecvStateShowCardsDelay(); + + // Overwrite default processing + virtual int Process(ServerRecvThread &server); + + void SetTimer(const boost::microsec_timer &timer); + +protected: + + // Protected constructor - this is a singleton. + ServerRecvStateShowCardsDelay(); + + virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + boost::microsec_timer m_delayTimer; +}; + // State: Delay before next hand. class ServerRecvStateNextHand : public ServerRecvStateReceiving, public ServerRecvStateRunning { diff --git a/src/net/serverrecvthread.h b/src/net/serverrecvthread.h index 4ed0de3e..6d34cc6e 100644 --- a/src/net/serverrecvthread.h +++ b/src/net/serverrecvthread.h @@ -70,6 +70,10 @@ public: ServerCallback &GetCallback(); + void SendError(SOCKET s, int errorCode); + void SendToAllPlayers(boost::shared_ptr packet); + void SendToAllButOnePlayers(boost::shared_ptr packet, SOCKET except); + protected: struct Notification @@ -114,10 +118,6 @@ protected: int GetNextPlayerNumber() const; - void SendError(SOCKET s, int errorCode); - void SendToAllPlayers(boost::shared_ptr packet); - void SendToAllButOnePlayers(boost::shared_ptr packet, SOCKET except); - ServerRecvState &GetState(); void SetState(ServerRecvState &newState); @@ -169,6 +169,7 @@ friend class ServerRecvStateStartGame; friend class ServerRecvStateStartHand; friend class ServerRecvStateStartRound; friend class ServerRecvStateWaitPlayerAction; +friend class ServerRecvStateShowCardsDelay; friend class ServerRecvStateDealCardsDelay; friend class ServerRecvStateNextHand; }; diff --git a/src/net/socket_msg.h b/src/net/socket_msg.h index 54d172ab..07ad017d 100644 --- a/src/net/socket_msg.h +++ b/src/net/socket_msg.h @@ -52,6 +52,7 @@ #define ERR_NET_INVALID_PLAYER_RESULTS 109 #define ERR_NET_INVALID_CHAT_TEXT 110 #define ERR_NET_UNKNOWN_PLAYER_ID 111 +#define ERR_NET_INVALID_ROUND 112 // This is an internal message which is not reported. #define MSG_SOCK_INTERNAL_PENDING 0