From a304903883f78ddfa2746dd9aeb3304e91ead801 Mon Sep 17 00:00:00 2001 From: lotodore Date: Tue, 24 Sep 2013 23:40:10 +0200 Subject: [PATCH 1/3] Send dealer player id with each hand start message. --- pokerth.proto | 1 + src/net/common/servergamestate.cpp | 1 + src/third_party/protobuf/pokerth.pb.cc | 35 +++++++++ src/third_party/protobuf/pokerth.pb.h | 34 ++++++++- tests/src/de/pokerth/protocol/ProtoBuf.java | 81 +++++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) diff --git a/pokerth.proto b/pokerth.proto index 3f7632b3..9724b6d0 100644 --- a/pokerth.proto +++ b/pokerth.proto @@ -451,6 +451,7 @@ message HandStartMessage { optional bytes encryptedCards = 3; required uint32 smallBlind = 4; repeated NetPlayerState seatStates = 5; + optional uint32 dealerPlayerId = 6; } message PlayersTurnMessage { diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index b066b4d6..7b9fa67b 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -438,6 +438,7 @@ AbstractServerGameStateReceiving::CreateNetPacketHandStart(const ServerGame &ser } netHandStart->set_smallblind(curGame.getCurrentHand()->getSmallBlind()); + netHandStart->set_dealerplayerid(curGame.getCurrentHand()->getDealerPosition()); return notifyCards; } diff --git a/src/third_party/protobuf/pokerth.pb.cc b/src/third_party/protobuf/pokerth.pb.cc index 872ff030..83b7ccc3 100644 --- a/src/third_party/protobuf/pokerth.pb.cc +++ b/src/third_party/protobuf/pokerth.pb.cc @@ -12596,6 +12596,7 @@ const int HandStartMessage::kPlainCardsFieldNumber; const int HandStartMessage::kEncryptedCardsFieldNumber; const int HandStartMessage::kSmallBlindFieldNumber; const int HandStartMessage::kSeatStatesFieldNumber; +const int HandStartMessage::kDealerPlayerIdFieldNumber; #endif // !_MSC_VER HandStartMessage::HandStartMessage() @@ -12624,6 +12625,7 @@ void HandStartMessage::SharedCtor() { plaincards_ = NULL; encryptedcards_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); smallblind_ = 0u; + dealerplayerid_ = 0u; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -12676,6 +12678,7 @@ void HandStartMessage::Clear() { } } smallblind_ = 0u; + dealerplayerid_ = 0u; } seatstates_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -12769,6 +12772,22 @@ bool HandStartMessage::MergePartialFromCodedStream( goto handle_uninterpreted; } if (input->ExpectTag(40)) goto parse_seatStates; + if (input->ExpectTag(48)) goto parse_dealerPlayerId; + break; + } + + // optional uint32 dealerPlayerId = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_dealerPlayerId: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &dealerplayerid_))); + set_has_dealerplayerid(); + } else { + goto handle_uninterpreted; + } if (input->ExpectAtEnd()) return true; break; } @@ -12818,6 +12837,11 @@ void HandStartMessage::SerializeWithCachedSizes( 5, this->seatstates(i), output); } + // optional uint32 dealerPlayerId = 6; + if (has_dealerplayerid()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(6, this->dealerplayerid(), output); + } + } int HandStartMessage::ByteSize() const { @@ -12852,6 +12876,13 @@ int HandStartMessage::ByteSize() const { this->smallblind()); } + // optional uint32 dealerPlayerId = 6; + if (has_dealerplayerid()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->dealerplayerid()); + } + } // repeated .NetPlayerState seatStates = 5; { @@ -12890,6 +12921,9 @@ void HandStartMessage::MergeFrom(const HandStartMessage& from) { if (from.has_smallblind()) { set_smallblind(from.smallblind()); } + if (from.has_dealerplayerid()) { + set_dealerplayerid(from.dealerplayerid()); + } } } @@ -12915,6 +12949,7 @@ void HandStartMessage::Swap(HandStartMessage* other) { std::swap(encryptedcards_, other->encryptedcards_); std::swap(smallblind_, other->smallblind_); seatstates_.Swap(&other->seatstates_); + std::swap(dealerplayerid_, other->dealerplayerid_); std::swap(_has_bits_[0], other->_has_bits_[0]); std::swap(_cached_size_, other->_cached_size_); } diff --git a/src/third_party/protobuf/pokerth.pb.h b/src/third_party/protobuf/pokerth.pb.h index 2e791ee4..53ca9f8e 100644 --- a/src/third_party/protobuf/pokerth.pb.h +++ b/src/third_party/protobuf/pokerth.pb.h @@ -6028,6 +6028,13 @@ class HandStartMessage : public ::google::protobuf::MessageLite { inline const ::google::protobuf::RepeatedField& seatstates() const; inline ::google::protobuf::RepeatedField* mutable_seatstates(); + // optional uint32 dealerPlayerId = 6; + inline bool has_dealerplayerid() const; + inline void clear_dealerplayerid(); + static const int kDealerPlayerIdFieldNumber = 6; + inline ::google::protobuf::uint32 dealerplayerid() const; + inline void set_dealerplayerid(::google::protobuf::uint32 value); + // @@protoc_insertion_point(class_scope:HandStartMessage) private: inline void set_has_gameid(); @@ -6038,15 +6045,18 @@ class HandStartMessage : public ::google::protobuf::MessageLite { inline void clear_has_encryptedcards(); inline void set_has_smallblind(); inline void clear_has_smallblind(); + inline void set_has_dealerplayerid(); + inline void clear_has_dealerplayerid(); ::HandStartMessage_PlainCards* plaincards_; ::google::protobuf::uint32 gameid_; ::google::protobuf::uint32 smallblind_; ::std::string* encryptedcards_; ::google::protobuf::RepeatedField seatstates_; + ::google::protobuf::uint32 dealerplayerid_; mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32]; + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER friend void protobuf_AddDesc_pokerth_2eproto_impl(); @@ -15865,6 +15875,28 @@ HandStartMessage::mutable_seatstates() { return &seatstates_; } +// optional uint32 dealerPlayerId = 6; +inline bool HandStartMessage::has_dealerplayerid() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void HandStartMessage::set_has_dealerplayerid() { + _has_bits_[0] |= 0x00000020u; +} +inline void HandStartMessage::clear_has_dealerplayerid() { + _has_bits_[0] &= ~0x00000020u; +} +inline void HandStartMessage::clear_dealerplayerid() { + dealerplayerid_ = 0u; + clear_has_dealerplayerid(); +} +inline ::google::protobuf::uint32 HandStartMessage::dealerplayerid() const { + return dealerplayerid_; +} +inline void HandStartMessage::set_dealerplayerid(::google::protobuf::uint32 value) { + set_has_dealerplayerid(); + dealerplayerid_ = value; +} + // ------------------------------------------------------------------- // PlayersTurnMessage diff --git a/tests/src/de/pokerth/protocol/ProtoBuf.java b/tests/src/de/pokerth/protocol/ProtoBuf.java index df31b13d..f741871a 100644 --- a/tests/src/de/pokerth/protocol/ProtoBuf.java +++ b/tests/src/de/pokerth/protocol/ProtoBuf.java @@ -27845,6 +27845,16 @@ public final class ProtoBuf { * repeated .NetPlayerState seatStates = 5; */ de.pokerth.protocol.ProtoBuf.NetPlayerState getSeatStates(int index); + + // optional uint32 dealerPlayerId = 6; + /** + * optional uint32 dealerPlayerId = 6; + */ + boolean hasDealerPlayerId(); + /** + * optional uint32 dealerPlayerId = 6; + */ + int getDealerPlayerId(); } /** * Protobuf type {@code HandStartMessage} @@ -27946,6 +27956,11 @@ public final class ProtoBuf { input.popLimit(oldLimit); break; } + case 48: { + bitField0_ |= 0x00000010; + dealerPlayerId_ = input.readUInt32(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -28492,12 +28507,29 @@ public final class ProtoBuf { return seatStates_.get(index); } + // optional uint32 dealerPlayerId = 6; + public static final int DEALERPLAYERID_FIELD_NUMBER = 6; + private int dealerPlayerId_; + /** + * optional uint32 dealerPlayerId = 6; + */ + public boolean hasDealerPlayerId() { + return ((bitField0_ & 0x00000010) == 0x00000010); + } + /** + * optional uint32 dealerPlayerId = 6; + */ + public int getDealerPlayerId() { + return dealerPlayerId_; + } + private void initFields() { gameId_ = 0; plainCards_ = de.pokerth.protocol.ProtoBuf.HandStartMessage.PlainCards.getDefaultInstance(); encryptedCards_ = com.google.protobuf.ByteString.EMPTY; smallBlind_ = 0; seatStates_ = java.util.Collections.emptyList(); + dealerPlayerId_ = 0; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -28540,6 +28572,9 @@ public final class ProtoBuf { for (int i = 0; i < seatStates_.size(); i++) { output.writeEnum(5, seatStates_.get(i).getNumber()); } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + output.writeUInt32(6, dealerPlayerId_); + } } private int memoizedSerializedSize = -1; @@ -28573,6 +28608,10 @@ public final class ProtoBuf { size += dataSize; size += 1 * seatStates_.size(); } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(6, dealerPlayerId_); + } memoizedSerializedSize = size; return size; } @@ -28674,6 +28713,8 @@ public final class ProtoBuf { bitField0_ = (bitField0_ & ~0x00000008); seatStates_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000010); + dealerPlayerId_ = 0; + bitField0_ = (bitField0_ & ~0x00000020); return this; } @@ -28718,6 +28759,10 @@ public final class ProtoBuf { bitField0_ = (bitField0_ & ~0x00000010); } result.seatStates_ = seatStates_; + if (((from_bitField0_ & 0x00000020) == 0x00000020)) { + to_bitField0_ |= 0x00000010; + } + result.dealerPlayerId_ = dealerPlayerId_; result.bitField0_ = to_bitField0_; return result; } @@ -28746,6 +28791,9 @@ public final class ProtoBuf { } } + if (other.hasDealerPlayerId()) { + setDealerPlayerId(other.getDealerPlayerId()); + } return this; } @@ -29021,6 +29069,39 @@ public final class ProtoBuf { return this; } + // optional uint32 dealerPlayerId = 6; + private int dealerPlayerId_ ; + /** + * optional uint32 dealerPlayerId = 6; + */ + public boolean hasDealerPlayerId() { + return ((bitField0_ & 0x00000020) == 0x00000020); + } + /** + * optional uint32 dealerPlayerId = 6; + */ + public int getDealerPlayerId() { + return dealerPlayerId_; + } + /** + * optional uint32 dealerPlayerId = 6; + */ + public Builder setDealerPlayerId(int value) { + bitField0_ |= 0x00000020; + dealerPlayerId_ = value; + + return this; + } + /** + * optional uint32 dealerPlayerId = 6; + */ + public Builder clearDealerPlayerId() { + bitField0_ = (bitField0_ & ~0x00000020); + dealerPlayerId_ = 0; + + return this; + } + // @@protoc_insertion_point(builder_scope:HandStartMessage) } From 8baecdf9e0f6f6dfaaf9c78ce34032b527aca6c0 Mon Sep 17 00:00:00 2001 From: lotodore Date: Sat, 28 Sep 2013 18:58:43 +0200 Subject: [PATCH 2/3] Send spectator list to joining players. --- src/net/common/servergamestate.cpp | 9 +++++++++ src/net/common/sessionmanager.cpp | 22 ++++++++++++++++++++++ src/net/sessionmanager.h | 1 + 3 files changed, 32 insertions(+) diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 7b9fa67b..a807c738 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -460,6 +460,15 @@ AbstractServerGameStateReceiving::AcceptNewSession(boost::shared_ptr ++player_i; } + // Send notifications for connected spectators to client. + PlayerDataList tmpSpectatorList(server->GetSessionManager().GetSpectatorDataList()); + PlayerDataList::iterator spectator_i = tmpSpectatorList.begin(); + PlayerDataList::iterator spectator_end = tmpSpectatorList.end(); + while (spectator_i != spectator_end) { + server->GetLobbyThread().GetSender().Send(session, CreateNetPacketSpectatorJoined(server->GetId(), *(*spectator_i))); + ++spectator_i; + } + // Send "Player Joined"/"Spectator Joined" to other fully connected clients. if (spectateOnly) { server->SendToAllPlayers(CreateNetPacketSpectatorJoined(server->GetId(), *session->GetPlayerData()), SessionData::Game | SessionData::Spectating | SessionData::SpectatorWaiting); diff --git a/src/net/common/sessionmanager.cpp b/src/net/common/sessionmanager.cpp index 56a7e7b0..bd8b65eb 100644 --- a/src/net/common/sessionmanager.cpp +++ b/src/net/common/sessionmanager.cpp @@ -161,6 +161,28 @@ SessionManager::GetPlayerDataList() const return playerList; } +PlayerDataList +SessionManager::GetSpectatorDataList() const +{ + PlayerDataList spectatorList; + boost::recursive_mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator session_i = m_sessionMap.begin(); + SessionMap::const_iterator session_end = m_sessionMap.end(); + + while (session_i != session_end) { + // Get all spectators of the game. + if (session_i->second->GetState() == SessionData::Spectating || session_i->second->GetState() == SessionData::SpectatorWaiting) { + boost::shared_ptr tmpPlayer(session_i->second->GetPlayerData()); + if (!tmpPlayer.get() || tmpPlayer->GetName().empty()) + throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0); + spectatorList.push_back(tmpPlayer); + } + ++session_i; + } + return spectatorList; +} + PlayerIdList SessionManager::GetPlayerIdList(int state) const { diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index ac3cd3df..8e90a544 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -59,6 +59,7 @@ public: boost::shared_ptr GetSessionByUniquePlayerId(unsigned uniqueId, bool initSessions = false) const; PlayerDataList GetPlayerDataList() const; + PlayerDataList GetSpectatorDataList() const; PlayerIdList GetPlayerIdList(int state) const; bool IsPlayerConnected(const std::string &playerName) const; bool IsPlayerConnected(unsigned uniqueId) const; From d82c9a510dc0949399a33ee43be5a6f04d436932 Mon Sep 17 00:00:00 2001 From: lotodore Date: Sun, 29 Sep 2013 13:15:37 +0200 Subject: [PATCH 3/3] Add spectator list during the game (when lobby messages are disabled). --- src/engine/game.cpp | 15 +++++++----- src/gamedata.h | 1 + src/net/clientthread.h | 3 +++ src/net/common/clientstate.cpp | 10 ++++++-- src/net/common/clientthread.cpp | 42 +++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/engine/game.cpp b/src/engine/game.cpp index e1582182..8d1fe4dc 100755 --- a/src/engine/game.cpp +++ b/src/engine/game.cpp @@ -220,8 +220,9 @@ void Game::startHand() boost::shared_ptr Game::getPlayerByUniqueId(unsigned id) { boost::shared_ptr tmpPlayer; - PlayerListIterator i = getSeatsList()->begin(); - PlayerListIterator end = getSeatsList()->end(); + PlayerList tmpList = getSeatsList(); + PlayerListIterator i = tmpList->begin(); + PlayerListIterator end = tmpList->end(); while (i != end) { if ((*i)->getMyUniqueID() == id) { tmpPlayer = *i; @@ -235,8 +236,9 @@ boost::shared_ptr Game::getPlayerByUniqueId(unsigned id) boost::shared_ptr Game::getPlayerByNumber(int number) { boost::shared_ptr tmpPlayer; - PlayerListIterator i = getSeatsList()->begin(); - PlayerListIterator end = getSeatsList()->end(); + PlayerList tmpList = getSeatsList(); + PlayerListIterator i = tmpList->begin(); + PlayerListIterator end = tmpList->end(); while (i != end) { if ((*i)->getMyID() == number) { tmpPlayer = *i; @@ -258,8 +260,9 @@ boost::shared_ptr Game::getCurrentPlayer() boost::shared_ptr Game::getPlayerByName(const std::string &name) { boost::shared_ptr tmpPlayer; - PlayerListIterator i = getSeatsList()->begin(); - PlayerListIterator end = getSeatsList()->end(); + PlayerList tmpList = getSeatsList(); + PlayerListIterator i = tmpList->begin(); + PlayerListIterator end = tmpList->end(); while (i != end) { if ((*i)->getMyName() == name) { tmpPlayer = *i; diff --git a/src/gamedata.h b/src/gamedata.h index a5e3e0d5..cb5a463a 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -102,6 +102,7 @@ struct GameInfo { unsigned adminPlayerId; PlayerIdList players; PlayerIdList spectators; + PlayerIdList spectatorsDuringGame; bool isPasswordProtected; }; diff --git a/src/net/clientthread.h b/src/net/clientthread.h index ae16614a..39de5407 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -218,6 +218,9 @@ protected: void ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId); void ModifyGameInfoAddSpectator(unsigned gameId, unsigned playerId); void ModifyGameInfoRemoveSpectator(unsigned gameId, unsigned playerId); + void ModifyGameInfoClearSpectatorsDuringGame(); + void ModifyGameInfoAddSpectatorDuringGame(unsigned playerId); + void ModifyGameInfoRemoveSpectatorDuringGame(unsigned playerId, int removeReason); void ClearGameInfoMap(); void StartPetition(unsigned petitionId, unsigned proposingPlayerId, unsigned kickPlayerId, int timeoutSec, int numVotesToKick); diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 25520963..a22620ce 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -631,7 +631,12 @@ AbstractClientStateReceiving::HandlePacket(boost::shared_ptr clien } else if (tmpPacket->GetMsg()->messagetype() == PokerTHMessage::Type_GameSpectatorJoinedMessage) { // Another spectator joined the network game. const GameSpectatorJoinedMessage &netSpectatorJoined = tmpPacket->GetMsg()->gamespectatorjoinedmessage(); - client->GetCallback().SignalNetClientSpectatorJoined(netSpectatorJoined.playerid(), client->GetPlayerName(netSpectatorJoined.playerid())); + // Request player info if needed. + PlayerInfo info; + if (!client->GetCachedPlayerInfo(netSpectatorJoined.playerid(), info)) { + client->RequestPlayerInfo(netSpectatorJoined.playerid()); + } + client->ModifyGameInfoAddSpectatorDuringGame(netSpectatorJoined.playerid()); } else if (tmpPacket->GetMsg()->messagetype() == PokerTHMessage::Type_GameSpectatorLeftMessage) { // A spectator left the network game. const GameSpectatorLeftMessage &netSpectatorLeft = tmpPacket->GetMsg()->gamespectatorleftmessage(); @@ -645,7 +650,7 @@ AbstractClientStateReceiving::HandlePacket(boost::shared_ptr clien removeReason = NTF_NET_REMOVED_ON_REQUEST; break; } - client->GetCallback().SignalNetClientSpectatorLeft(netSpectatorLeft.playerid(), client->GetPlayerName(netSpectatorLeft.playerid()), removeReason); + client->ModifyGameInfoRemoveSpectatorDuringGame(netSpectatorLeft.playerid(), removeReason); } else if (tmpPacket->GetMsg()->messagetype() == PokerTHMessage::Type_TimeoutWarningMessage) { const TimeoutWarningMessage &tmpTimeout = tmpPacket->GetMsg()->timeoutwarningmessage(); client->GetCallback().SignalNetClientShowTimeoutDialog((NetTimeoutReason)tmpTimeout.timeoutreason(), tmpTimeout.remainingseconds()); @@ -1252,6 +1257,7 @@ ClientStateWaitJoin::InternalHandlePacket(boost::shared_ptr client GameData tmpData; NetPacket::GetGameData(netJoinAck.gameinfo(), tmpData); client->SetGameData(tmpData); + client->ModifyGameInfoClearSpectatorsDuringGame(); // Player number is 0 on init. Will be set when the game starts. boost::shared_ptr playerData( diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index e396fbd0..775bce70 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -1454,6 +1454,48 @@ ClientThread::ModifyGameInfoRemoveSpectator(unsigned gameId, unsigned playerId) GetCallback().SignalNetClientGameListSpectatorLeft(gameId, playerId); } +void +ClientThread::ModifyGameInfoClearSpectatorsDuringGame() +{ + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(GetGameId()); + if (pos != m_gameInfoMap.end()) { + pos->second.spectatorsDuringGame.clear(); + } +} + +void +ClientThread::ModifyGameInfoAddSpectatorDuringGame(unsigned playerId) +{ + bool spectatorAdded = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(GetGameId()); + if (pos != m_gameInfoMap.end()) { + pos->second.spectatorsDuringGame.push_back(playerId); + spectatorAdded = true; + } + } + if (spectatorAdded) + GetCallback().SignalNetClientSpectatorJoined(playerId, GetPlayerName(playerId)); +} + +void +ClientThread::ModifyGameInfoRemoveSpectatorDuringGame(unsigned playerId, int removeReason) +{ + bool spectatorRemoved = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(GetGameId()); + if (pos != m_gameInfoMap.end()) { + pos->second.spectatorsDuringGame.remove(playerId); + spectatorRemoved = true; + } + } + if (spectatorRemoved) + GetCallback().SignalNetClientSpectatorLeft(playerId, GetPlayerName(playerId), removeReason); +} + void ClientThread::ClearGameInfoMap() {