From 9a3e45d71018d21d512bb9e841a9bbb08efa1434 Mon Sep 17 00:00:00 2001 From: lotodore Date: Tue, 5 Jun 2007 21:28:47 +0000 Subject: [PATCH] Added delays between dealing cards. Added check for IPv6. --- pokerth.pro | 1 + .../joinnetworkgamedialogimpl.cpp | 1 + src/gui/qt/mainwindow/mainwindowimpl.cpp | 7 +- .../qt/settingsdialog/settingsdialogimpl.cpp | 1 + src/gui/qt/sound/sdlplayer.cpp | 2 +- src/net/common/serverrecvstate.cpp | 296 +++++++++++------- src/net/common/socket_startup_cmn.cpp | 49 +++ src/net/linux/socket_startup.cpp | 15 - src/net/serverrecvstate.h | 26 ++ src/net/serverrecvthread.h | 1 + src/net/socket_msg.h | 1 + src/net/socket_startup.h | 1 + src/net/win32/socket_startup.cpp | 6 - 13 files changed, 266 insertions(+), 141 deletions(-) create mode 100644 src/net/common/socket_startup_cmn.cpp diff --git a/pokerth.pro b/pokerth.pro index c1678295..9962cba2 100755 --- a/pokerth.pro +++ b/pokerth.pro @@ -204,6 +204,7 @@ SOURCES += src/game.cpp \ src/net/common/serverrecvstate.cpp \ src/net/common/servercallback.cpp \ src/net/common/sessiondata.cpp \ + src/net/common/socket_startup_cmn.cpp \ src/net/common/socket_helper_cmn.cpp \ src/net/common/clientexception.cpp \ src/net/common/netcontext.cpp \ diff --git a/src/gui/qt/joinnetworkgamedialog/joinnetworkgamedialogimpl.cpp b/src/gui/qt/joinnetworkgamedialog/joinnetworkgamedialogimpl.cpp index 32e0f65a..5793ccf1 100644 --- a/src/gui/qt/joinnetworkgamedialog/joinnetworkgamedialogimpl.cpp +++ b/src/gui/qt/joinnetworkgamedialog/joinnetworkgamedialogimpl.cpp @@ -91,6 +91,7 @@ void joinNetworkGameDialogImpl::exec() { fillServerProfileList(); } + checkBox_ipv6->setEnabled(socket_has_ipv6()); checkBox_sctp->setEnabled(socket_has_sctp()); QDialog::exec(); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index 65001bbb..6f453d0b 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -2597,12 +2597,11 @@ void mainWindowImpl::networkGameModification() { void mainWindowImpl::closeEvent(QCloseEvent *event) { quitPokerTH(); } void mainWindowImpl::quitPokerTH() { - + mySession->terminateNetworkClient(); if (myServerGuiInterface.get()) myServerGuiInterface->getSession().terminateNetworkServer(); - - mySDLPlayer->closeAudio(); - + + // cout << "PokerTH finished" << endl; qApp->quit(); } diff --git a/src/gui/qt/settingsdialog/settingsdialogimpl.cpp b/src/gui/qt/settingsdialog/settingsdialogimpl.cpp index 9738b662..d785d606 100644 --- a/src/gui/qt/settingsdialog/settingsdialogimpl.cpp +++ b/src/gui/qt/settingsdialog/settingsdialogimpl.cpp @@ -137,6 +137,7 @@ void settingsDialogImpl::exec() { spinBox_logStoreDuration->setValue(myConfig->readConfigInt("LogStoreDuration")); comboBox_logInterval->setCurrentIndex(myConfig->readConfigInt("LogInterval")); + checkBox_useIpv6->setEnabled(socket_has_ipv6()); checkBox_useSctp->setEnabled(socket_has_sctp()); QDialog::exec(); diff --git a/src/gui/qt/sound/sdlplayer.cpp b/src/gui/qt/sound/sdlplayer.cpp index c7fddc64..80750e01 100644 --- a/src/gui/qt/sound/sdlplayer.cpp +++ b/src/gui/qt/sound/sdlplayer.cpp @@ -87,6 +87,6 @@ void SDLPlayer::closeAudio() { if(audioEnabled) { audioDone(); Mix_CloseAudio(); - SDL_Quit(); } + SDL_Quit(); } diff --git a/src/net/common/serverrecvstate.cpp b/src/net/common/serverrecvstate.cpp index a18ab7a9..0c79e3ce 100644 --- a/src/net/common/serverrecvstate.cpp +++ b/src/net/common/serverrecvstate.cpp @@ -32,8 +32,11 @@ using namespace std; -#define SERVER_WAIT_TIMEOUT_MSEC 50 -#define SERVER_NEXT_HAND_DELAY_SEC 10 +#define SERVER_WAIT_TIMEOUT_MSEC 50 +#define SERVER_NEXT_HAND_DELAY_SEC 10 +#define SERVER_DEAL_FLOP_CARDS_SEC 6 +#define SERVER_DEAL_TURN_CARD_SEC 3 +#define SERVER_DEAL_RIVER_CARD_SEC 3 // Helper functions @@ -440,129 +443,132 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server) int retVal = MSG_SOCK_INTERNAL_PENDING; Game &curGame = server.GetGame(); - // Call main loop - if state changes, call again. + // Main game loop. + int curRound = curGame.getCurrentHand()->getActualRound(); + curGame.getCurrentHand()->switchRounds(); + if (!curGame.getCurrentHand()->getAllInCondition()) + GameRun(curGame); int newRound = curGame.getCurrentHand()->getActualRound(); - int curRound; - do + + // If round changes, deal cards if needed. + if (newRound != curRound) { - curRound = newRound; - curGame.getCurrentHand()->switchRounds(); - if (!curGame.getCurrentHand()->getAllInCondition()) - GameRun(curGame); - newRound = curGame.getCurrentHand()->getActualRound(); + assert(newRound > curRound); + SendNewRoundCards(server, curGame, newRound); - // If round changes, deal cards if needed. - if (newRound != curRound) - { - assert(newRound > curRound); - SendNewRoundCards(server, curGame, newRound); - } - } while (newRound != curRound); - - if (newRound != GAME_STATE_POST_RIVER) // continue hand - { - if (!curGame.getCurrentHand()->getAllInCondition()) - { - // Retrieve current player. - PlayerInterface *curPlayer = GetCurrentPlayer(curGame); - assert(curPlayer); // TODO throw exception - assert(curPlayer->getMyActiveStatus()); // TODO throw exception - - boost::shared_ptr notification(new NetPacketPlayersTurn); - NetPacketPlayersTurn::Data playersTurnData; - playersTurnData.gameState = (GameState)curGame.getCurrentHand()->getActualRound(); - playersTurnData.playerId = curPlayer->getMyUniqueID(); - static_cast(notification.get())->SetData(playersTurnData); - - server.SendToAllPlayers(notification); - - server.SetState(ServerRecvStateWaitPlayerAction::Instance()); - - retVal = MSG_NET_GAME_SERVER_ROUND; - } + boost::microsec_timer delayTimer; + delayTimer.start(); + ServerRecvStateDealCardsDelay::Instance().SetTimer(delayTimer); + server.SetState(ServerRecvStateDealCardsDelay::Instance()); + retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; } - else // hand is over + else { - // Let the engine find out the winner(s). - curGame.getCurrentHand()->getRiver()->postRiverRun(); - - // Count active players. If only one player is left, no cards are shown. - int activePlayersCounter = 0; - std::list activePlayers; - for (int i = 0; i < curGame.getStartQuantityPlayers() ; i++) - { - if (curGame.getPlayerArray()[i]->getMyActiveStatus() - && curGame.getPlayerArray()[i]->getMyAction() != PLAYER_ACTION_FOLD) + if (newRound != GAME_STATE_POST_RIVER) // continue hand + { + if (!curGame.getCurrentHand()->getAllInCondition()) { - activePlayersCounter++; - activePlayers.push_back(curGame.getPlayerArray()[i]); + // Retrieve current player. + PlayerInterface *curPlayer = GetCurrentPlayer(curGame); + assert(curPlayer); // TODO throw exception + assert(curPlayer->getMyActiveStatus()); // TODO throw exception + + boost::shared_ptr notification(new NetPacketPlayersTurn); + NetPacketPlayersTurn::Data playersTurnData; + playersTurnData.gameState = (GameState)curGame.getCurrentHand()->getActualRound(); + playersTurnData.playerId = curPlayer->getMyUniqueID(); + static_cast(notification.get())->SetData(playersTurnData); + + server.SendToAllPlayers(notification); + + server.SetState(ServerRecvStateWaitPlayerAction::Instance()); + + retVal = MSG_NET_GAME_SERVER_ROUND; } } - assert(activePlayersCounter); - assert(!activePlayers.empty()); - - if (activePlayersCounter == 1) + else // hand is over { - // End of Hand, but keep cards hidden. - PlayerInterface *player = activePlayers.front(); - boost::shared_ptr endHand(new NetPacketEndOfHandHideCards); - NetPacketEndOfHandHideCards::Data endHandData; - endHandData.playerId = player->getMyUniqueID(); - endHandData.moneyWon = 0; // TODO - endHandData.playerMoney = player->getMyCash(); - static_cast(endHand.get())->SetData(endHandData); + // Let the engine find out the winner(s). + curGame.getCurrentHand()->getRiver()->postRiverRun(); - server.SendToAllPlayers(endHand); - } - else - { - // End of Hand - show cards of active players. - boost::shared_ptr endHand(new NetPacketEndOfHandShowCards); - NetPacketEndOfHandShowCards::Data endHandData; - - std::list::iterator i = activePlayers.begin(); - std::list::iterator end = activePlayers.end(); - - while (i != end) - { - NetPacketEndOfHandShowCards::PlayerResult tmpPlayerResult; - tmpPlayerResult.playerId = (*i)->getMyUniqueID(); - - int tmpCards[2]; - (*i)->getMyCards(tmpCards); - tmpPlayerResult.cards[0] = static_cast(tmpCards[0]); - tmpPlayerResult.cards[1] = static_cast(tmpCards[1]); - - for (int num = 0; num < 5; num++) - tmpPlayerResult.bestHandPos[num] = (*i)->getMyBestHandPosition()[num]; - - tmpPlayerResult.valueOfCards = (*i)->getMyCardsValueInt(); - tmpPlayerResult.moneyWon = 0; // TODO - tmpPlayerResult.playerMoney = (*i)->getMyCash(); - - endHandData.playerResults.push_back(tmpPlayerResult); - ++i; + // Count active players. If only one player is left, no cards are shown. + int activePlayersCounter = 0; + std::list activePlayers; + for (int i = 0; i < curGame.getStartQuantityPlayers() ; i++) + { + if (curGame.getPlayerArray()[i]->getMyActiveStatus() + && curGame.getPlayerArray()[i]->getMyAction() != PLAYER_ACTION_FOLD) + { + activePlayersCounter++; + activePlayers.push_back(curGame.getPlayerArray()[i]); + } } - static_cast(endHand.get())->SetData(endHandData); + assert(activePlayersCounter); + assert(!activePlayers.empty()); - server.SendToAllPlayers(endHand); - } - // Start next hand - if enough players are left. - int playersPositiveCashCounter = 0; - for (int i = 0; i < curGame.getStartQuantityPlayers(); i++) - { - if (curGame.getCurrentHand()->getPlayerArray()[i]->getMyCash() > 0) - playersPositiveCashCounter++; - } - if (playersPositiveCashCounter == 1) - server.SetState(ServerRecvStateFinal::Instance()); // TODO - else - { - boost::microsec_timer delayTimer; - delayTimer.start(); - ServerRecvStateNextHand::Instance().SetTimer(delayTimer); - server.SetState(ServerRecvStateNextHand::Instance()); - retVal = MSG_NET_GAME_SERVER_HAND_END; + if (activePlayersCounter == 1) + { + // End of Hand, but keep cards hidden. + PlayerInterface *player = activePlayers.front(); + boost::shared_ptr endHand(new NetPacketEndOfHandHideCards); + NetPacketEndOfHandHideCards::Data endHandData; + endHandData.playerId = player->getMyUniqueID(); + endHandData.moneyWon = 0; // TODO + endHandData.playerMoney = player->getMyCash(); + static_cast(endHand.get())->SetData(endHandData); + + server.SendToAllPlayers(endHand); + } + else + { + // End of Hand - show cards of active players. + boost::shared_ptr endHand(new NetPacketEndOfHandShowCards); + NetPacketEndOfHandShowCards::Data endHandData; + + std::list::iterator i = activePlayers.begin(); + std::list::iterator end = activePlayers.end(); + + while (i != end) + { + NetPacketEndOfHandShowCards::PlayerResult tmpPlayerResult; + tmpPlayerResult.playerId = (*i)->getMyUniqueID(); + + int tmpCards[2]; + (*i)->getMyCards(tmpCards); + tmpPlayerResult.cards[0] = static_cast(tmpCards[0]); + tmpPlayerResult.cards[1] = static_cast(tmpCards[1]); + + for (int num = 0; num < 5; num++) + tmpPlayerResult.bestHandPos[num] = (*i)->getMyBestHandPosition()[num]; + + tmpPlayerResult.valueOfCards = (*i)->getMyCardsValueInt(); + tmpPlayerResult.moneyWon = 0; // TODO + tmpPlayerResult.playerMoney = (*i)->getMyCash(); + + endHandData.playerResults.push_back(tmpPlayerResult); + ++i; + } + static_cast(endHand.get())->SetData(endHandData); + + server.SendToAllPlayers(endHand); + } + // Start next hand - if enough players are left. + int playersPositiveCashCounter = 0; + for (int i = 0; i < curGame.getStartQuantityPlayers(); i++) + { + if (curGame.getCurrentHand()->getPlayerArray()[i]->getMyCash() > 0) + playersPositiveCashCounter++; + } + if (playersPositiveCashCounter == 1) + server.SetState(ServerRecvStateFinal::Instance()); // TODO + else + { + boost::microsec_timer delayTimer; + delayTimer.start(); + ServerRecvStateNextHand::Instance().SetTimer(delayTimer); + server.SetState(ServerRecvStateNextHand::Instance()); + retVal = MSG_NET_GAME_SERVER_HAND_END; + } } } return retVal; @@ -737,7 +743,8 @@ ServerRecvStateWaitPlayerAction::GetHighestSet(Game &curGame) { int highestSet = 0; // TODO: no switch needed here if game states are polymorphic - switch(curGame.getCurrentHand()->getActualRound()) { + switch(curGame.getCurrentHand()->getActualRound()) + { case GAME_STATE_PREFLOP: { highestSet = curGame.getCurrentHand()->getPreflop()->getHighestSet(); } break; @@ -761,7 +768,8 @@ void ServerRecvStateWaitPlayerAction::SetHighestSet(Game &curGame, int highestSet) { // TODO: no switch needed here if game states are polymorphic - switch(curGame.getCurrentHand()->getActualRound()) { + switch(curGame.getCurrentHand()->getActualRound()) + { case GAME_STATE_PREFLOP: { curGame.getCurrentHand()->getPreflop()->setHighestSet(highestSet); } break; @@ -782,6 +790,64 @@ ServerRecvStateWaitPlayerAction::SetHighestSet(Game &curGame, int highestSet) //----------------------------------------------------------------------------- +ServerRecvStateDealCardsDelay & +ServerRecvStateDealCardsDelay::Instance() +{ + static ServerRecvStateDealCardsDelay state; + return state; +} + +ServerRecvStateDealCardsDelay::ServerRecvStateDealCardsDelay() +{ +} + +ServerRecvStateDealCardsDelay::~ServerRecvStateDealCardsDelay() +{ +} + +void +ServerRecvStateDealCardsDelay::SetTimer(const boost::microsec_timer &timer) +{ + m_delayTimer = timer; +} + +int +ServerRecvStateDealCardsDelay::Process(ServerRecvThread &server) +{ + int retVal = ServerRecvStateReceiving::Process(server); + + Game &curGame = server.GetGame(); + + int allInDelay = curGame.getCurrentHand()->getAllInCondition() ? 2 : 0; + + switch(curGame.getCurrentHand()->getActualRound()) + { + case GAME_STATE_FLOP: + if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_FLOP_CARDS_SEC + allInDelay) + server.SetState(ServerRecvStateStartRound::Instance()); + break; + case GAME_STATE_TURN: + if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_TURN_CARD_SEC + allInDelay) + server.SetState(ServerRecvStateStartRound::Instance()); + break; + case GAME_STATE_RIVER: + if (m_delayTimer.elapsed().seconds() >= SERVER_DEAL_RIVER_CARD_SEC + allInDelay) + server.SetState(ServerRecvStateStartRound::Instance()); + break; + default: + server.SetState(ServerRecvStateStartRound::Instance()); + } + return retVal; +} + +int +ServerRecvStateDealCardsDelay::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +{ + return MSG_SOCK_INTERNAL_PENDING; +} + +//----------------------------------------------------------------------------- + ServerRecvStateNextHand & ServerRecvStateNextHand::Instance() { diff --git a/src/net/common/socket_startup_cmn.cpp b/src/net/common/socket_startup_cmn.cpp new file mode 100644 index 00000000..8027d8a7 --- /dev/null +++ b/src/net/common/socket_startup_cmn.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + + +bool +socket_has_sctp() +{ +#ifdef IPPROTO_SCTP + SOCKET test = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (test == INVALID_SOCKET) + return false; + CLOSESOCKET(test); + return true; +#else + return false; +#endif +} + +bool +socket_has_ipv6() +{ + SOCKET test = socket(AF_INET6, SOCK_STREAM, 0); + + if (test == INVALID_SOCKET) + return false; + CLOSESOCKET(test); + return true; +} + diff --git a/src/net/linux/socket_startup.cpp b/src/net/linux/socket_startup.cpp index bf7159d5..be4840ed 100644 --- a/src/net/linux/socket_startup.cpp +++ b/src/net/linux/socket_startup.cpp @@ -38,18 +38,3 @@ socket_cleanup() { } -bool -socket_has_sctp() -{ -#ifdef IPPROTO_SCTP - int test = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); - - if (test == -1) - return false; - close(test); - return true; -#else - return false; -#endif -} - diff --git a/src/net/serverrecvstate.h b/src/net/serverrecvstate.h index 9d0f61da..4db81519 100644 --- a/src/net/serverrecvstate.h +++ b/src/net/serverrecvstate.h @@ -184,6 +184,32 @@ protected: static void SetHighestSet(Game &curGame, int highestSet); }; +// State: Delay after dealing cards +class ServerRecvStateDealCardsDelay : public ServerRecvStateReceiving, public ServerRecvStateRunning +{ +public: + // Access the state singleton. + static ServerRecvStateDealCardsDelay &Instance(); + + virtual ~ServerRecvStateDealCardsDelay(); + + // Overwrite default processing + virtual int Process(ServerRecvThread &server); + + void SetTimer(const boost::microsec_timer &timer); + +protected: + + // Protected constructor - this is a singleton. + ServerRecvStateDealCardsDelay(); + + 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 abfdbbfc..4ed0de3e 100644 --- a/src/net/serverrecvthread.h +++ b/src/net/serverrecvthread.h @@ -169,6 +169,7 @@ friend class ServerRecvStateStartGame; friend class ServerRecvStateStartHand; friend class ServerRecvStateStartRound; friend class ServerRecvStateWaitPlayerAction; +friend class ServerRecvStateDealCardsDelay; friend class ServerRecvStateNextHand; }; diff --git a/src/net/socket_msg.h b/src/net/socket_msg.h index 1def77b9..b0cb7b37 100644 --- a/src/net/socket_msg.h +++ b/src/net/socket_msg.h @@ -73,6 +73,7 @@ #define MSG_NET_GAME_SERVER_HAND_END 10 #define MSG_NET_GAME_SERVER_ROUND 11 #define MSG_NET_GAME_SERVER_ACTION 12 +#define MSG_NET_GAME_SERVER_CARDS_DELAY 13 #endif diff --git a/src/net/socket_startup.h b/src/net/socket_startup.h index 8e18e5d0..5a0bd30c 100644 --- a/src/net/socket_startup.h +++ b/src/net/socket_startup.h @@ -24,6 +24,7 @@ bool socket_startup(); void socket_cleanup(); bool socket_has_sctp(); +bool socket_has_ipv6(); #endif diff --git a/src/net/win32/socket_startup.cpp b/src/net/win32/socket_startup.cpp index 52f2fe49..2aec0c21 100644 --- a/src/net/win32/socket_startup.cpp +++ b/src/net/win32/socket_startup.cpp @@ -66,9 +66,3 @@ socket_cleanup() WSACleanup(); } -bool -socket_has_sctp() -{ - return false; /* no SCTP on Windows */ -} -