diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index 87fa85ea..7703c716 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -168,6 +168,7 @@ Client Reply/Request: Player's Action [ Game State is confirmed to ensure consistency. ] Player Action: + 0 - None (e.g. Small Blind or Big Blind in Preflop) 1 - Fold 2 - Check 3 - Call @@ -178,14 +179,16 @@ Cash Value: 0 - states fold, check, call, all in > 0 - states bet, raise -Server Reply/Notification: Player's Action Done +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 = 12 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Game State | Player Action | + | Game State | Player Id | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Player Action | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cash Value | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ diff --git a/src/game.cpp b/src/game.cpp index 358718c9..bce4d2d6 100755 --- a/src/game.cpp +++ b/src/game.cpp @@ -173,3 +173,17 @@ void Game::startHand() actualHand->start(); } + +PlayerInterface *Game::getPlayerByUniqueId(unsigned id) +{ + PlayerInterface *tmpPlayer = NULL; + for (int i = 0; i < startQuantityPlayers; i++) + { + if (playerArray[i]->getMyUniqueID() == id) + { + tmpPlayer = playerArray[i]; + break; + } + } + return tmpPlayer; +} diff --git a/src/game.h b/src/game.h index 2df32732..eee023ff 100755 --- a/src/game.h +++ b/src/game.h @@ -75,6 +75,7 @@ public: void setActualHandID(const int& theValue) { actualHandID = theValue; } int getActualHandID() const { return actualHandID; } + PlayerInterface * getPlayerByUniqueId(unsigned id); private: boost::shared_ptr myFactory; diff --git a/src/game_defs.h b/src/game_defs.h index 66ac2a3a..125e16b6 100644 --- a/src/game_defs.h +++ b/src/game_defs.h @@ -39,4 +39,8 @@ enum PlayerAction { PLAYER_ACTION_RAISE, PLAYER_ACTION_ALLIN }; +enum Button { + BUTTON_SMALL_BLIND = 2, + BUTTON_BIG_BLIND = 3 }; + #endif diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index be61c7d8..42bbc4f8 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -505,11 +505,11 @@ ClientStateWaitHand::Process(ClientThread &client) if (tmpPacket.get()) { + // TODO: Hack if (tmpPacket->ToNetPacketHandStart()) { NetPacketHandStart::Data tmpData; tmpPacket->ToNetPacketHandStart()->GetData(tmpData); - // TODO: Hack int myCards[2]; myCards[0] = (int)tmpData.yourCards[0]; myCards[1] = (int)tmpData.yourCards[1]; @@ -518,6 +518,31 @@ ClientStateWaitHand::Process(ClientThread &client) client.GetGame()->startHand(); client.GetGui().dealHoleCards(); } + else if (tmpPacket->ToNetPacketPlayersActionDone()) + { + NetPacketPlayersActionDone::Data tmpData; + tmpPacket->ToNetPacketPlayersActionDone()->GetData(tmpData); + PlayerInterface *tmpPlayer = client.GetGame()->getPlayerByUniqueId(tmpData.playerId); + if (tmpPlayer) + { + if (tmpData.gameState == GAME_STATE_PREFLOP_SMALL_BLIND) + { + tmpPlayer->setMyButton(BUTTON_SMALL_BLIND); + tmpPlayer->setMyAction(tmpData.playerAction); + tmpPlayer->setMySet(tmpData.cashValue); + client.GetGui().refreshSet(); + client.GetGui().refreshPot(); + } + else if (tmpData.gameState == GAME_STATE_PREFLOP_BIG_BLIND) + { + tmpPlayer->setMyButton(BUTTON_BIG_BLIND); + tmpPlayer->setMyAction(tmpData.playerAction); + tmpPlayer->setMySet(tmpData.cashValue); + client.GetGui().refreshSet(); + client.GetGui().refreshPot(); + } + } + } } return MSG_SOCK_INTERNAL_PENDING; diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index f76d1ad1..7d804a5c 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -35,7 +35,8 @@ using namespace std; #define NET_TYPE_HAND_START 0x0006 #define NET_TYPE_PLAYERS_TURN 0x0007 #define NET_TYPE_PLAYERS_ACTION 0x0008 -#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x0009 +#define NET_TYPE_PLAYERS_ACTION_DONE 0x0009 +#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x000A #define NET_TYPE_ERROR 0x0400 @@ -142,6 +143,16 @@ struct GCC_PACKED NetPacketPlayersActionData u_int32_t cashValue; }; +struct GCC_PACKED NetPacketPlayersActionDoneData +{ + NetPacketHeader head; + u_int16_t gameState; + u_int16_t playerId; + u_int16_t playerAction; + u_int16_t reserved; + u_int32_t cashValue; +}; + struct GCC_PACKED NetPacketPlayersActionRejectedData { NetPacketHeader head; @@ -209,6 +220,9 @@ NetPacket::Create(char *data, unsigned &dataSize) case NET_TYPE_PLAYERS_ACTION: tmpPacket = boost::shared_ptr(new NetPacketPlayersAction); break; + case NET_TYPE_PLAYERS_ACTION_DONE: + tmpPacket = boost::shared_ptr(new NetPacketPlayersActionDone); + break; case NET_TYPE_PLAYERS_ACTION_REJECTED: tmpPacket = boost::shared_ptr(new NetPacketPlayersActionRejected); break; @@ -344,6 +358,12 @@ NetPacket::ToNetPacketPlayersAction() const return NULL; } +const NetPacketPlayersActionDone * +NetPacket::ToNetPacketPlayersActionDone() const +{ + return NULL; +} + const NetPacketPlayersActionRejected * NetPacket::ToNetPacketPlayersActionRejected() const { @@ -1009,6 +1029,81 @@ NetPacketPlayersAction::Check(const NetPacketHeader* data) const //----------------------------------------------------------------------------- +NetPacketPlayersActionDone::NetPacketPlayersActionDone() +: NetPacket(NET_TYPE_PLAYERS_ACTION_DONE, sizeof(NetPacketPlayersActionDoneData)) +{ +} + +NetPacketPlayersActionDone::~NetPacketPlayersActionDone() +{ +} + +boost::shared_ptr +NetPacketPlayersActionDone::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketPlayersActionDone); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketPlayersActionDone::SetData(const NetPacketPlayersActionDone::Data &inData) +{ + NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)GetRawData(); + assert(tmpData); + + tmpData->gameState = htons(inData.gameState); + tmpData->playerId = htons(inData.playerId); + tmpData->playerAction = htons(inData.playerAction); + tmpData->cashValue = htonl(inData.cashValue); +} + +void +NetPacketPlayersActionDone::GetData(NetPacketPlayersActionDone::Data &outData) const +{ + NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)GetRawData(); + assert(tmpData); + + outData.gameState = static_cast(ntohs(tmpData->gameState)); + outData.playerId = ntohs(tmpData->playerId); + outData.playerAction = static_cast(ntohs(tmpData->playerAction)); + outData.cashValue = ntohl(tmpData->cashValue); +} + +const NetPacketPlayersActionDone * +NetPacketPlayersActionDone::ToNetPacketPlayersActionDone() const +{ + return this; +} + +void +NetPacketPlayersActionDone::Check(const NetPacketHeader* data) const +{ + assert(data); + + u_int16_t dataLen = ntohs(data->length); + if (dataLen < sizeof(NetPacketPlayersActionDoneData)) + { + throw NetException(ERR_SOCK_INVALID_PACKET, 0); + } + + NetPacketPlayersActionDoneData *tmpData = (NetPacketPlayersActionDoneData *)data; + // TODO: Check whether the state is valid. + // Check whether the player action is valid. + if (ntohs(tmpData->playerAction) > PLAYER_ACTION_ALLIN) + { + throw NetException(ERR_SOCK_INVALID_PACKET, 0); + } +} + +//----------------------------------------------------------------------------- + NetPacketPlayersActionRejected::NetPacketPlayersActionRejected() : NetPacket(NET_TYPE_PLAYERS_ACTION_REJECTED, sizeof(NetPacketPlayersActionRejectedData)) { diff --git a/src/net/common/serverrecvstate.cpp b/src/net/common/serverrecvstate.cpp index 16f5b792..d1221c2d 100644 --- a/src/net/common/serverrecvstate.cpp +++ b/src/net/common/serverrecvstate.cpp @@ -271,23 +271,55 @@ ServerRecvStateStartHand::Process(ServerRecvThread &server) // Send cards to all players. for (int i = 0; i < curGame.getActualQuantityPlayers(); i++) { - if (playerArray[i]->getNetSessionData().get()) + if (playerArray[i]->getNetSessionData().get()) // TODO: this is an assert. { int cards[2]; playerArray[i]->getMyCards(cards); - boost::shared_ptr notification(new NetPacketHandStart); + boost::shared_ptr notifyCards(new NetPacketHandStart); NetPacketHandStart::Data handStartData; handStartData.yourCards[0] = static_cast(cards[0]); handStartData.yourCards[1] = static_cast(cards[1]); - static_cast(notification.get())->SetData(handStartData); + static_cast(notifyCards.get())->SetData(handStartData); - server.GetSender().Send(playerArray[i]->getNetSessionData()->GetSocket(), notification); + server.GetSender().Send(playerArray[i]->getNetSessionData()->GetSocket(), notifyCards); } } // Start hand. curGame.startHand(); + // Auto small blind / big blind at the beginning of preflop. + for (int i = 0; i < curGame.getActualQuantityPlayers(); i++) + { + if(playerArray[i]->getMyButton() == BUTTON_SMALL_BLIND) + { + boost::shared_ptr notifySmallBlind(new NetPacketPlayersActionDone); + NetPacketPlayersActionDone::Data actionDoneData; + actionDoneData.gameState = GAME_STATE_PREFLOP_SMALL_BLIND; + actionDoneData.playerId = playerArray[i]->getMyUniqueID(); + actionDoneData.playerAction = (PlayerAction)playerArray[i]->getMyAction(); + actionDoneData.cashValue = playerArray[i]->getMySet(); + static_cast(notifySmallBlind.get())->SetData(actionDoneData); + server.SendToAllPlayers(notifySmallBlind); + break; + } + } + for (int i = 0; i < curGame.getActualQuantityPlayers(); i++) + { + if(playerArray[i]->getMyButton() == BUTTON_BIG_BLIND) + { + boost::shared_ptr notifyBigBlind(new NetPacketPlayersActionDone); + NetPacketPlayersActionDone::Data actionDoneData; + actionDoneData.gameState = GAME_STATE_PREFLOP_BIG_BLIND; + actionDoneData.playerId = playerArray[i]->getMyUniqueID(); + actionDoneData.playerAction = (PlayerAction)playerArray[i]->getMyAction(); + actionDoneData.cashValue = playerArray[i]->getMySet(); + static_cast(notifyBigBlind.get())->SetData(actionDoneData); + server.SendToAllPlayers(notifyBigBlind); + break; + } + } + server.SetState(ServerRecvStateStartRound::Instance()); return MSG_NET_GAME_SERVER_HAND; diff --git a/src/net/netpacket.h b/src/net/netpacket.h index 23978603..d2d0c8c2 100644 --- a/src/net/netpacket.h +++ b/src/net/netpacket.h @@ -45,6 +45,7 @@ class NetPacketGameStart; class NetPacketHandStart; class NetPacketPlayersTurn; class NetPacketPlayersAction; +class NetPacketPlayersActionDone; class NetPacketPlayersActionRejected; class NetPacketError; @@ -73,6 +74,7 @@ public: virtual const NetPacketHandStart *ToNetPacketHandStart() const; virtual const NetPacketPlayersTurn *ToNetPacketPlayersTurn() const; virtual const NetPacketPlayersAction *ToNetPacketPlayersAction() const; + virtual const NetPacketPlayersActionDone *ToNetPacketPlayersActionDone() const; virtual const NetPacketPlayersActionRejected *ToNetPacketPlayersActionRejected() const; virtual const NetPacketError *ToNetPacketError() const; @@ -285,6 +287,32 @@ protected: virtual void Check(const NetPacketHeader* data) const; }; +class NetPacketPlayersActionDone : public NetPacket +{ +public: + struct Data + { + GameState gameState; + u_int16_t playerId; + PlayerAction playerAction; + u_int32_t cashValue; + }; + + NetPacketPlayersActionDone(); + virtual ~NetPacketPlayersActionDone(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketPlayersActionDone *ToNetPacketPlayersActionDone() const; + +protected: + + virtual void Check(const NetPacketHeader* data) const; +}; + class NetPacketPlayersActionRejected : public NetPacket { public: