Added delays between dealing cards. Added check for IPv6.

This commit is contained in:
lotodore
2007-06-05 21:28:47 +00:00
parent 750138ab55
commit 9a3e45d710
13 changed files with 266 additions and 141 deletions
+1
View File
@@ -204,6 +204,7 @@ SOURCES += src/game.cpp \
src/net/common/serverrecvstate.cpp \ src/net/common/serverrecvstate.cpp \
src/net/common/servercallback.cpp \ src/net/common/servercallback.cpp \
src/net/common/sessiondata.cpp \ src/net/common/sessiondata.cpp \
src/net/common/socket_startup_cmn.cpp \
src/net/common/socket_helper_cmn.cpp \ src/net/common/socket_helper_cmn.cpp \
src/net/common/clientexception.cpp \ src/net/common/clientexception.cpp \
src/net/common/netcontext.cpp \ src/net/common/netcontext.cpp \
@@ -91,6 +91,7 @@ void joinNetworkGameDialogImpl::exec() {
fillServerProfileList(); fillServerProfileList();
} }
checkBox_ipv6->setEnabled(socket_has_ipv6());
checkBox_sctp->setEnabled(socket_has_sctp()); checkBox_sctp->setEnabled(socket_has_sctp());
QDialog::exec(); QDialog::exec();
-1
View File
@@ -2601,7 +2601,6 @@ void mainWindowImpl::quitPokerTH() {
mySession->terminateNetworkClient(); mySession->terminateNetworkClient();
if (myServerGuiInterface.get()) myServerGuiInterface->getSession().terminateNetworkServer(); if (myServerGuiInterface.get()) myServerGuiInterface->getSession().terminateNetworkServer();
mySDLPlayer->closeAudio();
// cout << "PokerTH finished" << endl; // cout << "PokerTH finished" << endl;
qApp->quit(); qApp->quit();
@@ -137,6 +137,7 @@ void settingsDialogImpl::exec() {
spinBox_logStoreDuration->setValue(myConfig->readConfigInt("LogStoreDuration")); spinBox_logStoreDuration->setValue(myConfig->readConfigInt("LogStoreDuration"));
comboBox_logInterval->setCurrentIndex(myConfig->readConfigInt("LogInterval")); comboBox_logInterval->setCurrentIndex(myConfig->readConfigInt("LogInterval"));
checkBox_useIpv6->setEnabled(socket_has_ipv6());
checkBox_useSctp->setEnabled(socket_has_sctp()); checkBox_useSctp->setEnabled(socket_has_sctp());
QDialog::exec(); QDialog::exec();
+1 -1
View File
@@ -87,6 +87,6 @@ void SDLPlayer::closeAudio() {
if(audioEnabled) { if(audioEnabled) {
audioDone(); audioDone();
Mix_CloseAudio(); Mix_CloseAudio();
SDL_Quit();
} }
SDL_Quit();
} }
+179 -113
View File
@@ -32,8 +32,11 @@
using namespace std; using namespace std;
#define SERVER_WAIT_TIMEOUT_MSEC 50 #define SERVER_WAIT_TIMEOUT_MSEC 50
#define SERVER_NEXT_HAND_DELAY_SEC 10 #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 // Helper functions
@@ -440,129 +443,132 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server)
int retVal = MSG_SOCK_INTERNAL_PENDING; int retVal = MSG_SOCK_INTERNAL_PENDING;
Game &curGame = server.GetGame(); 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 newRound = curGame.getCurrentHand()->getActualRound();
int curRound;
do // If round changes, deal cards if needed.
if (newRound != curRound)
{ {
curRound = newRound; assert(newRound > curRound);
curGame.getCurrentHand()->switchRounds(); SendNewRoundCards(server, curGame, newRound);
if (!curGame.getCurrentHand()->getAllInCondition())
GameRun(curGame);
newRound = curGame.getCurrentHand()->getActualRound();
// If round changes, deal cards if needed. boost::microsec_timer delayTimer;
if (newRound != curRound) delayTimer.start();
{ ServerRecvStateDealCardsDelay::Instance().SetTimer(delayTimer);
assert(newRound > curRound); server.SetState(ServerRecvStateDealCardsDelay::Instance());
SendNewRoundCards(server, curGame, newRound); retVal = MSG_NET_GAME_SERVER_CARDS_DELAY;
}
} 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<NetPacket> notification(new NetPacketPlayersTurn);
NetPacketPlayersTurn::Data playersTurnData;
playersTurnData.gameState = (GameState)curGame.getCurrentHand()->getActualRound();
playersTurnData.playerId = curPlayer->getMyUniqueID();
static_cast<NetPacketPlayersTurn *>(notification.get())->SetData(playersTurnData);
server.SendToAllPlayers(notification);
server.SetState(ServerRecvStateWaitPlayerAction::Instance());
retVal = MSG_NET_GAME_SERVER_ROUND;
}
} }
else // hand is over else
{ {
// Let the engine find out the winner(s). if (newRound != GAME_STATE_POST_RIVER) // continue hand
curGame.getCurrentHand()->getRiver()->postRiverRun();
// Count active players. If only one player is left, no cards are shown.
int activePlayersCounter = 0;
std::list<PlayerInterface *> activePlayers;
for (int i = 0; i < curGame.getStartQuantityPlayers() ; i++)
{ {
if (curGame.getPlayerArray()[i]->getMyActiveStatus() if (!curGame.getCurrentHand()->getAllInCondition())
&& curGame.getPlayerArray()[i]->getMyAction() != PLAYER_ACTION_FOLD)
{ {
activePlayersCounter++; // Retrieve current player.
activePlayers.push_back(curGame.getPlayerArray()[i]); PlayerInterface *curPlayer = GetCurrentPlayer(curGame);
assert(curPlayer); // TODO throw exception
assert(curPlayer->getMyActiveStatus()); // TODO throw exception
boost::shared_ptr<NetPacket> notification(new NetPacketPlayersTurn);
NetPacketPlayersTurn::Data playersTurnData;
playersTurnData.gameState = (GameState)curGame.getCurrentHand()->getActualRound();
playersTurnData.playerId = curPlayer->getMyUniqueID();
static_cast<NetPacketPlayersTurn *>(notification.get())->SetData(playersTurnData);
server.SendToAllPlayers(notification);
server.SetState(ServerRecvStateWaitPlayerAction::Instance());
retVal = MSG_NET_GAME_SERVER_ROUND;
} }
} }
assert(activePlayersCounter); else // hand is over
assert(!activePlayers.empty());
if (activePlayersCounter == 1)
{ {
// End of Hand, but keep cards hidden. // Let the engine find out the winner(s).
PlayerInterface *player = activePlayers.front(); curGame.getCurrentHand()->getRiver()->postRiverRun();
boost::shared_ptr<NetPacket> endHand(new NetPacketEndOfHandHideCards);
NetPacketEndOfHandHideCards::Data endHandData;
endHandData.playerId = player->getMyUniqueID();
endHandData.moneyWon = 0; // TODO
endHandData.playerMoney = player->getMyCash();
static_cast<NetPacketEndOfHandHideCards *>(endHand.get())->SetData(endHandData);
server.SendToAllPlayers(endHand); // Count active players. If only one player is left, no cards are shown.
} int activePlayersCounter = 0;
else std::list<PlayerInterface *> activePlayers;
{ for (int i = 0; i < curGame.getStartQuantityPlayers() ; i++)
// End of Hand - show cards of active players.
boost::shared_ptr<NetPacket> endHand(new NetPacketEndOfHandShowCards);
NetPacketEndOfHandShowCards::Data endHandData;
std::list<PlayerInterface *>::iterator i = activePlayers.begin();
std::list<PlayerInterface *>::iterator end = activePlayers.end();
while (i != end)
{ {
NetPacketEndOfHandShowCards::PlayerResult tmpPlayerResult; if (curGame.getPlayerArray()[i]->getMyActiveStatus()
tmpPlayerResult.playerId = (*i)->getMyUniqueID(); && curGame.getPlayerArray()[i]->getMyAction() != PLAYER_ACTION_FOLD)
{
int tmpCards[2]; activePlayersCounter++;
(*i)->getMyCards(tmpCards); activePlayers.push_back(curGame.getPlayerArray()[i]);
tmpPlayerResult.cards[0] = static_cast<u_int16_t>(tmpCards[0]); }
tmpPlayerResult.cards[1] = static_cast<u_int16_t>(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<NetPacketEndOfHandShowCards *>(endHand.get())->SetData(endHandData); assert(activePlayersCounter);
assert(!activePlayers.empty());
server.SendToAllPlayers(endHand); if (activePlayersCounter == 1)
} {
// Start next hand - if enough players are left. // End of Hand, but keep cards hidden.
int playersPositiveCashCounter = 0; PlayerInterface *player = activePlayers.front();
for (int i = 0; i < curGame.getStartQuantityPlayers(); i++) boost::shared_ptr<NetPacket> endHand(new NetPacketEndOfHandHideCards);
{ NetPacketEndOfHandHideCards::Data endHandData;
if (curGame.getCurrentHand()->getPlayerArray()[i]->getMyCash() > 0) endHandData.playerId = player->getMyUniqueID();
playersPositiveCashCounter++; endHandData.moneyWon = 0; // TODO
} endHandData.playerMoney = player->getMyCash();
if (playersPositiveCashCounter == 1) static_cast<NetPacketEndOfHandHideCards *>(endHand.get())->SetData(endHandData);
server.SetState(ServerRecvStateFinal::Instance()); // TODO
else server.SendToAllPlayers(endHand);
{ }
boost::microsec_timer delayTimer; else
delayTimer.start(); {
ServerRecvStateNextHand::Instance().SetTimer(delayTimer); // End of Hand - show cards of active players.
server.SetState(ServerRecvStateNextHand::Instance()); boost::shared_ptr<NetPacket> endHand(new NetPacketEndOfHandShowCards);
retVal = MSG_NET_GAME_SERVER_HAND_END; NetPacketEndOfHandShowCards::Data endHandData;
std::list<PlayerInterface *>::iterator i = activePlayers.begin();
std::list<PlayerInterface *>::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<u_int16_t>(tmpCards[0]);
tmpPlayerResult.cards[1] = static_cast<u_int16_t>(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<NetPacketEndOfHandShowCards *>(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; return retVal;
@@ -737,7 +743,8 @@ ServerRecvStateWaitPlayerAction::GetHighestSet(Game &curGame)
{ {
int highestSet = 0; int highestSet = 0;
// TODO: no switch needed here if game states are polymorphic // TODO: no switch needed here if game states are polymorphic
switch(curGame.getCurrentHand()->getActualRound()) { switch(curGame.getCurrentHand()->getActualRound())
{
case GAME_STATE_PREFLOP: { case GAME_STATE_PREFLOP: {
highestSet = curGame.getCurrentHand()->getPreflop()->getHighestSet(); highestSet = curGame.getCurrentHand()->getPreflop()->getHighestSet();
} break; } break;
@@ -761,7 +768,8 @@ void
ServerRecvStateWaitPlayerAction::SetHighestSet(Game &curGame, int highestSet) ServerRecvStateWaitPlayerAction::SetHighestSet(Game &curGame, int highestSet)
{ {
// TODO: no switch needed here if game states are polymorphic // TODO: no switch needed here if game states are polymorphic
switch(curGame.getCurrentHand()->getActualRound()) { switch(curGame.getCurrentHand()->getActualRound())
{
case GAME_STATE_PREFLOP: { case GAME_STATE_PREFLOP: {
curGame.getCurrentHand()->getPreflop()->setHighestSet(highestSet); curGame.getCurrentHand()->getPreflop()->setHighestSet(highestSet);
} break; } 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<NetPacket> packet)
{
return MSG_SOCK_INTERNAL_PENDING;
}
//-----------------------------------------------------------------------------
ServerRecvStateNextHand & ServerRecvStateNextHand &
ServerRecvStateNextHand::Instance() ServerRecvStateNextHand::Instance()
{ {
+49
View File
@@ -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 <net/socket_startup.h>
#include <net/socket_helper.h>
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;
}
-15
View File
@@ -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
}
+26
View File
@@ -184,6 +184,32 @@ protected:
static void SetHighestSet(Game &curGame, int highestSet); 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<NetPacket> packet);
private:
boost::microsec_timer m_delayTimer;
};
// State: Delay before next hand. // State: Delay before next hand.
class ServerRecvStateNextHand : public ServerRecvStateReceiving, public ServerRecvStateRunning class ServerRecvStateNextHand : public ServerRecvStateReceiving, public ServerRecvStateRunning
{ {
+1
View File
@@ -169,6 +169,7 @@ friend class ServerRecvStateStartGame;
friend class ServerRecvStateStartHand; friend class ServerRecvStateStartHand;
friend class ServerRecvStateStartRound; friend class ServerRecvStateStartRound;
friend class ServerRecvStateWaitPlayerAction; friend class ServerRecvStateWaitPlayerAction;
friend class ServerRecvStateDealCardsDelay;
friend class ServerRecvStateNextHand; friend class ServerRecvStateNextHand;
}; };
+1
View File
@@ -73,6 +73,7 @@
#define MSG_NET_GAME_SERVER_HAND_END 10 #define MSG_NET_GAME_SERVER_HAND_END 10
#define MSG_NET_GAME_SERVER_ROUND 11 #define MSG_NET_GAME_SERVER_ROUND 11
#define MSG_NET_GAME_SERVER_ACTION 12 #define MSG_NET_GAME_SERVER_ACTION 12
#define MSG_NET_GAME_SERVER_CARDS_DELAY 13
#endif #endif
+1
View File
@@ -24,6 +24,7 @@ bool socket_startup();
void socket_cleanup(); void socket_cleanup();
bool socket_has_sctp(); bool socket_has_sctp();
bool socket_has_ipv6();
#endif #endif
-6
View File
@@ -66,9 +66,3 @@ socket_cleanup()
WSACleanup(); WSACleanup();
} }
bool
socket_has_sctp()
{
return false; /* no SCTP on Windows */
}