Players should now be able to leave a network game, the other players can continue the game (if it wasn't the server who left).

This commit is contained in:
lotodore
2007-06-03 14:57:33 +00:00
parent 1fcb0c80fd
commit f932e39983
4 changed files with 125 additions and 56 deletions
+27 -7
View File
@@ -385,6 +385,33 @@ AbstractClientStateReceiving::Process(ClientThread &client)
if (tmpPlayer.get())
client.GetCallback().SignalNetClientChatMsg(tmpPlayer->GetName(), chatData.text);
}
else if (tmpPacket->ToNetPacketPlayerLeft())
{
// A player left the game.
NetPacketPlayerLeft::Data playerLeftData;
tmpPacket->ToNetPacketPlayerLeft()->GetData(playerLeftData);
// Signal to GUI.
client.RemovePlayerData(playerLeftData.playerId);
// If the game is running, deactivate player.
boost::shared_ptr<Game> curGame = client.GetGame();
if (curGame.get())
{
PlayerInterface *tmpPlayer = curGame->getPlayerByUniqueId(playerLeftData.playerId);
if (!tmpPlayer)
throw ClientException(ERR_NET_UNKNOWN_PLAYER_ID, 0);
// Reset his action and his cash.
tmpPlayer->setMyAction(PLAYER_ACTION_FOLD);
tmpPlayer->setMyCash(0);
// Player is now inactive.
tmpPlayer->setMyActiveStatus(false);
client.GetGui().refreshAction();
client.GetGui().refreshCash();
}
}
else
retVal = InternalProcess(client, tmpPacket);
}
@@ -490,13 +517,6 @@ ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptr<Net
playerData->SetName(netPlayerData.playerName);
client.AddPlayerData(playerData);
}
else if (packet->ToNetPacketPlayerLeft())
{
// Another player left the network game.
NetPacketPlayerLeft::Data netPlayerData;
packet->ToNetPacketPlayerLeft()->GetData(netPlayerData);
client.RemovePlayerData(netPlayerData.playerId);
}
// TODO: handle error packet (kicked from server)
return retVal;
+81 -47
View File
@@ -35,6 +35,34 @@ using namespace std;
#define SERVER_WAIT_TIMEOUT_MSEC 50
#define SERVER_NEXT_HAND_DELAY_SEC 10
// Helper functions
static PlayerInterface *GetCurrentPlayer(Game &curGame)
{
int curPlayerNum = 0;
// TODO: no switch needed here if game states are polymorphic
switch(curGame.getCurrentHand()->getActualRound()) {
case GAME_STATE_PREFLOP: {
curPlayerNum = curGame.getCurrentHand()->getPreflop()->getPlayersTurn();
} break;
case GAME_STATE_FLOP: {
curPlayerNum = curGame.getCurrentHand()->getFlop()->getPlayersTurn();
} break;
case GAME_STATE_TURN: {
curPlayerNum = curGame.getCurrentHand()->getTurn()->getPlayersTurn();
} break;
case GAME_STATE_RIVER: {
curPlayerNum = curGame.getCurrentHand()->getRiver()->getPlayersTurn();
} break;
default: {
//
}
}
assert(curPlayerNum < curGame.getStartQuantityPlayers()); // TODO: throw exception
return curGame.getPlayerArray()[curPlayerNum];
}
//-----------------------------------------------------------------------------
ServerRecvState::~ServerRecvState()
{
@@ -567,32 +595,6 @@ ServerRecvStateStartRound::GameRun(Game &curGame)
}
}
PlayerInterface *
ServerRecvStateStartRound::GetCurrentPlayer(Game &curGame)
{
int curPlayerNum = 0;
// TODO: no switch needed here if game states are polymorphic
switch(curGame.getCurrentHand()->getActualRound()) {
case GAME_STATE_PREFLOP: {
curPlayerNum = curGame.getCurrentHand()->getPreflop()->getPlayersTurn();
} break;
case GAME_STATE_FLOP: {
curPlayerNum = curGame.getCurrentHand()->getFlop()->getPlayersTurn();
} break;
case GAME_STATE_TURN: {
curPlayerNum = curGame.getCurrentHand()->getTurn()->getPlayersTurn();
} break;
case GAME_STATE_RIVER: {
curPlayerNum = curGame.getCurrentHand()->getRiver()->getPlayersTurn();
} break;
default: {
//
}
}
assert(curPlayerNum < curGame.getStartQuantityPlayers()); // TODO: throw exception
return curGame.getPlayerArray()[curPlayerNum];
}
void
ServerRecvStateStartRound::SendNewRoundCards(ServerRecvThread &server, Game &curGame, int state)
{
@@ -655,6 +657,28 @@ ServerRecvStateWaitPlayerAction::~ServerRecvStateWaitPlayerAction()
{
}
int
ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server)
{
int retVal;
// If the player we are waiting for left, continue without him.
PlayerInterface *tmpPlayer = GetCurrentPlayer(server.GetGame());
assert(tmpPlayer);
if (!tmpPlayer->getMyActiveStatus())
{
assert(tmpPlayer->getMyAction() == PLAYER_ACTION_FOLD && tmpPlayer->getMyCash() == 0);
PerformPlayerAction(server, tmpPlayer, PLAYER_ACTION_FOLD, 0);
server.SetState(ServerRecvStateStartRound::Instance());
retVal = MSG_NET_GAME_SERVER_ACTION;
}
else
retVal = ServerRecvStateReceiving::Process(server);
return retVal;
}
int
ServerRecvStateWaitPlayerAction::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{
@@ -668,28 +692,10 @@ ServerRecvStateWaitPlayerAction::InternalProcess(ServerRecvThread &server, Sessi
Game &curGame = server.GetGame();
PlayerInterface *tmpPlayer = curGame.getPlayerByUniqueId(session.playerData->GetUniqueId());
assert(tmpPlayer); // TODO throw exception
// TODO: check whether this is the correct player
// TODO: check game state
tmpPlayer->setMyAction(actionData.playerAction);
// Only change the player bet if action is not fold/check
if (actionData.playerAction != PLAYER_ACTION_FOLD && actionData.playerAction != PLAYER_ACTION_CHECK)
{
tmpPlayer->setMySet(actionData.playerBet);
if (tmpPlayer->getMySet() > GetHighestSet(curGame))
SetHighestSet(curGame, tmpPlayer->getMySet());
}
boost::shared_ptr<NetPacket> notifyActionDone(new NetPacketPlayersActionDone);
NetPacketPlayersActionDone::Data actionDoneData;
actionDoneData.gameState = static_cast<GameState>(curGame.getCurrentHand()->getActualRound());
actionDoneData.playerId = session.playerData->GetUniqueId();
actionDoneData.playerAction = actionData.playerAction;
actionDoneData.totalPlayerBet = tmpPlayer->getMySet();
actionDoneData.playerMoney = tmpPlayer->getMyCash();
actionDoneData.potSize = curGame.getCurrentHand()->getBoard()->getPot();
actionDoneData.curHandBets = curGame.getCurrentHand()->getBoard()->getSets();
static_cast<NetPacketPlayersActionDone *>(notifyActionDone.get())->SetData(actionDoneData);
server.SendToAllPlayers(notifyActionDone);
PerformPlayerAction(server, tmpPlayer, actionData.playerAction, actionData.playerBet);
server.SetState(ServerRecvStateStartRound::Instance());
retVal = MSG_NET_GAME_SERVER_ACTION;
@@ -698,6 +704,34 @@ ServerRecvStateWaitPlayerAction::InternalProcess(ServerRecvThread &server, Sessi
return retVal;
}
void
ServerRecvStateWaitPlayerAction::PerformPlayerAction(ServerRecvThread &server, PlayerInterface *player, PlayerAction action, int bet)
{
Game &curGame = server.GetGame();
assert(player);
player->setMyAction(action);
// Only change the player bet if action is not fold/check
if (action != PLAYER_ACTION_FOLD && action != PLAYER_ACTION_CHECK)
{
player->setMySet(bet);
if (player->getMySet() > GetHighestSet(curGame))
SetHighestSet(curGame, player->getMySet());
}
boost::shared_ptr<NetPacket> notifyActionDone(new NetPacketPlayersActionDone);
NetPacketPlayersActionDone::Data actionDoneData;
actionDoneData.gameState = static_cast<GameState>(curGame.getCurrentHand()->getActualRound());
actionDoneData.playerId = player->getMyUniqueID();
actionDoneData.playerAction = static_cast<PlayerAction>(player->getMyAction());
actionDoneData.totalPlayerBet = player->getMySet();
actionDoneData.playerMoney = player->getMyCash();
actionDoneData.potSize = curGame.getCurrentHand()->getBoard()->getPot();
actionDoneData.curHandBets = curGame.getCurrentHand()->getBoard()->getSets();
static_cast<NetPacketPlayersActionDone *>(notifyActionDone.get())->SetData(actionDoneData);
server.SendToAllPlayers(notifyActionDone);
}
int
ServerRecvStateWaitPlayerAction::GetHighestSet(Game &curGame)
{
+13 -1
View File
@@ -346,7 +346,17 @@ ServerRecvThread::CloseSessionDelayed(SessionWrapper session)
boost::shared_ptr<PlayerData> tmpPlayerData = session.playerData;
if (tmpPlayerData.get() && !tmpPlayerData->GetName().empty())
{
GetCallback().SignalNetServerPlayerLeft(tmpPlayerData->GetName());
// Set player inactive.
if (m_game.get())
{
PlayerInterface *player = GetGame().getPlayerByUniqueId(tmpPlayerData->GetUniqueId());
if (player)
{
player->setMyAction(PLAYER_ACTION_FOLD);
player->setMyCash(0);
player->setMyActiveStatus(false);
}
}
// Send "Player Left" to clients.
boost::shared_ptr<NetPacket> thisPlayerLeft(new NetPacketPlayerLeft);
@@ -354,6 +364,8 @@ ServerRecvThread::CloseSessionDelayed(SessionWrapper session)
thisPlayerLeftData.playerId = tmpPlayerData->GetUniqueId();
static_cast<NetPacketPlayerLeft *>(thisPlayerLeft.get())->SetData(thisPlayerLeftData);
SendToAllPlayers(thisPlayerLeft);
GetCallback().SignalNetServerPlayerLeft(tmpPlayerData->GetName());
}
boost::microsec_timer closeTimer;
+4 -1
View File
@@ -157,7 +157,6 @@ protected:
ServerRecvStateStartRound();
static void GameRun(Game &curGame);
static PlayerInterface *GetCurrentPlayer(Game &curGame);
static void SendNewRoundCards(ServerRecvThread &server, Game &curGame, int state);
};
@@ -170,6 +169,9 @@ public:
virtual ~ServerRecvStateWaitPlayerAction();
// Handle leaving players.
virtual int Process(ServerRecvThread &server);
protected:
// Protected constructor - this is a singleton.
@@ -177,6 +179,7 @@ protected:
virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
static void PerformPlayerAction(ServerRecvThread &server, PlayerInterface *player, PlayerAction action, int bet);
static int GetHighestSet(Game &curGame);
static void SetHighestSet(Game &curGame, int highestSet);
};