From b236fa9d62adf9c5940a567bd1c0169ce628201b Mon Sep 17 00:00:00 2001 From: lotodore Date: Tue, 25 Nov 2008 22:18:17 +0000 Subject: [PATCH] Vote kick kind of working. Only the forward case - no timeout, no error handling, no display update. --- docs/net_protocol.txt | 2 +- src/gamedata.h | 7 ++++- src/gui/qt/gametable/gametableimpl.cpp | 8 ++++-- src/gui/qt/gametable/gametableimpl.h | 2 +- src/gui/qt/guiwrapper.cpp | 2 +- src/net/clientthread.h | 6 +++++ src/net/common/clientstate.cpp | 3 ++- src/net/common/clientthread.cpp | 30 +++++++++++++++++++++ src/net/common/servergamestate.cpp | 19 +++++++++++--- src/net/common/servergamethread.cpp | 36 +++++++++++++++++++++++--- src/net/servergamethread.h | 1 + src/session.cpp | 7 +++++ src/session.h | 1 + 13 files changed, 109 insertions(+), 15 deletions(-) diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index accd4fd1..9f87f700 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -898,7 +898,7 @@ Server Notification: End Kick Player Petition 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 = 117 | Message Length = 16 | + | Message Type = 119 | Message Length = 16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Petition ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ diff --git a/src/gamedata.h b/src/gamedata.h index 465570fd..f49a4bdf 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -90,9 +90,14 @@ struct StartData struct VoteKickData { + VoteKickData() + : petitionId(0), kickPlayerId(0), initialNumVotesToKick(0), + numVotesInFavourOfKicking(0), numVotesAgainstKicking(0) {} unsigned petitionId; unsigned kickPlayerId; - unsigned numVotesToKick; + unsigned initialNumVotesToKick; + unsigned numVotesInFavourOfKicking; + unsigned numVotesAgainstKicking; boost::timers::portable::microsec_timer voteTimer; std::list votedPlayerIds; }; diff --git a/src/gui/qt/gametable/gametableimpl.cpp b/src/gui/qt/gametable/gametableimpl.cpp index 6fd9d5b2..56ad761a 100755 --- a/src/gui/qt/gametable/gametableimpl.cpp +++ b/src/gui/qt/gametable/gametableimpl.cpp @@ -2676,8 +2676,8 @@ void gameTableImpl::keyPressEvent ( QKeyEvent * event ) { else { keyUpDownChatCounter = 0; } //TESTING UNIT - if (event->key() == Qt::Key_M) { startVoteOnKick(3,60, 6); } - if (event->key() == Qt::Key_N) { endVoteOnKick(); } + //if (event->key() == Qt::Key_M) { startVoteOnKick(3,60, 6); } + //if (event->key() == Qt::Key_N) { endVoteOnKick(); } } void gameTableImpl::changePlayingMode() { @@ -3150,10 +3150,14 @@ void gameTableImpl::endVoteOnKick() void gameTableImpl::voteOnKickYes() { + changeVoteOnKickButtonsState(false); + myStartWindow->getSession()->voteKick(true); } void gameTableImpl::voteOnKickNo() { + changeVoteOnKickButtonsState(false); + myStartWindow->getSession()->voteKick(false); } void gameTableImpl::startVoteOnKickTimeout() diff --git a/src/gui/qt/gametable/gametableimpl.h b/src/gui/qt/gametable/gametableimpl.h index 55af186a..c9e7ba5c 100755 --- a/src/gui/qt/gametable/gametableimpl.h +++ b/src/gui/qt/gametable/gametableimpl.h @@ -282,7 +282,7 @@ public slots: void showMaximized (); void closeGameTable(); - void startVoteOnKick(unsigned int playerId, int timeoutSec, int numVotesNeededToKick); + void startVoteOnKick(unsigned playerId, int timeoutSec, int numVotesNeededToKick); void changeVoteOnKickButtonsState(bool showHide); void endVoteOnKick(); void voteOnKickYes(); diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index d18ca759..eca637b5 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -106,7 +106,7 @@ void GuiWrapper::startTimeoutAnimation(int playerNum, int timeoutSec) { myW->sig void GuiWrapper::stopTimeoutAnimation(int playerNum) { myW->signalStopTimeoutAnimation(playerNum); } void GuiWrapper::startVoteOnKick(unsigned playerId, int timeoutSec, int numVotesNeededToKick) { myW->signalStartVoteOnKick(playerId, timeoutSec, numVotesNeededToKick); } -void GuiWrapper::changeVoteOnKickButtonsState(bool showHide) { myW->changeVoteOnKickButtonsState(showHide); } +void GuiWrapper::changeVoteOnKickButtonsState(bool showHide) { myW->signalChangeVoteOnKickButtonsState(showHide); } void GuiWrapper::refreshVotesMonitor(int currentVotes, int numVotesNeededToKick) { myW->refreshVotesMonitor(currentVotes, numVotesNeededToKick); } void GuiWrapper::endVoteOnKick() { myW->signalEndVoteOnKick(); } diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 8f37743e..8bb91c29 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -69,6 +69,7 @@ public: void SendCreateGame(const GameData &gameData, const std::string &name, const std::string &password); void SendResetTimeout(); void SendAskKickPlayer(unsigned playerId); + void SendVoteKick(bool doKick); GameInfo GetGameInfo(unsigned gameId) const; PlayerInfo GetPlayerInfo(unsigned playerId) const; @@ -149,6 +150,8 @@ protected: void ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId); void ClearGameInfoMap(); + void StartPetition(unsigned petitionId, unsigned proposingPlayerId, unsigned kickPlayerId, int timeoutSec, int numVotesToKick); + void UpdateStatData(const ServerStats &stats); bool IsSessionEstablished() const; @@ -189,6 +192,9 @@ private: unsigned m_curGameId; mutable boost::mutex m_curGameIdMutex; + unsigned m_curPetitionId; + mutable boost::mutex m_curPetitionIdMutex; + AvatarDataMap m_tempAvatarMap; unsigned m_curGameNum; diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index adca1b24..69d98b32 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -773,7 +773,8 @@ AbstractClientStateReceiving::Process(ClientThread &client) { NetPacketStartKickPlayerPetition::Data petitionData; tmpPacket->ToNetPacketStartKickPlayerPetition()->GetData(petitionData); - client.GetGui().startVoteOnKick(petitionData.kickPlayerId, petitionData.kickTimeoutSec, petitionData.numVotesNeededToKick); + client.StartPetition(petitionData.petitionId, petitionData.proposingPlayerId, + petitionData.kickPlayerId, petitionData.kickTimeoutSec, petitionData.numVotesNeededToKick); } else if (tmpPacket->ToNetPacketAvatarHeader()) { diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index a5cb5bfa..57bfe4b9 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -264,6 +264,21 @@ ClientThread::SendAskKickPlayer(unsigned playerId) m_outPacketList.push_back(ask); } +void +ClientThread::SendVoteKick(bool doKick) +{ + boost::shared_ptr vote(new NetPacketVoteKickPlayer); + NetPacketVoteKickPlayer::Data voteData; + { + boost::mutex::scoped_lock lock(m_curPetitionIdMutex); + voteData.petitionId = m_curPetitionId; + } + voteData.vote = doKick ? KICK_VOTE_IN_FAVOUR : KICK_VOTE_AGAINST; + static_cast(vote.get())->SetData(voteData); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(vote); +} + GameInfo ClientThread::GetGameInfo(unsigned gameId) const { @@ -1007,6 +1022,21 @@ ClientThread::ClearGameInfoMap() m_gameInfoMap.clear(); } +void +ClientThread::StartPetition(unsigned petitionId, unsigned proposingPlayerId, unsigned kickPlayerId, int timeoutSec, int numVotesToKick) +{ + { + boost::mutex::scoped_lock lock(m_curPetitionIdMutex); + m_curPetitionId = petitionId; + } + GetGui().startVoteOnKick(kickPlayerId, timeoutSec, numVotesToKick); + if (GetGuiPlayerId() != kickPlayerId + && GetGuiPlayerId() != proposingPlayerId) + { + GetGui().changeVoteOnKickButtonsState(true); + } +} + void ClientThread::UpdateStatData(const ServerStats &stats) { diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index a548b556..33228c5a 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -153,7 +153,7 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) int retVal = MSG_SOCK_INTERNAL_PENDING; SessionWrapper session = server.GetSessionManager().Select(RECV_TIMEOUT_MSEC); - if (session.sessionData.get()) + if (session.sessionData) { boost::shared_ptr packet; try @@ -167,7 +167,7 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) } // Process packet if one was received. - if (packet.get()) + if (packet) { if (packet->IsClientActivity()) session.sessionData->ResetActivityTimer(); @@ -199,7 +199,7 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) } else if (packet->ToNetPacketAskKickPlayer()) { - if (server.IsRunning() && session.playerData) + if (session.playerData) { NetPacketAskKickPlayer::Data askKickData; packet->ToNetPacketAskKickPlayer()->GetData(askKickData); @@ -213,12 +213,23 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) startPetitionData.proposingPlayerId = session.playerData->GetUniqueId(); startPetitionData.kickPlayerId = voteData->kickPlayerId; startPetitionData.kickTimeoutSec = SERVER_VOTE_KICK_TIMEOUT_SEC; - startPetitionData.numVotesNeededToKick = voteData->numVotesToKick; + startPetitionData.numVotesNeededToKick = voteData->initialNumVotesToKick; static_cast(startPetition.get())->SetData(startPetitionData); server.SendToAllPlayers(startPetition, SessionData::Game); + // TODO notify first vote. } } } + else if (packet->ToNetPacketVoteKickPlayer()) + { + if (session.playerData) + { + NetPacketVoteKickPlayer::Data voteData; + packet->ToNetPacketVoteKickPlayer()->GetData(voteData); + + server.InternalVoteKick(voteData.petitionId, voteData.vote); + } + } // Chat text is always allowed. else if (packet->ToNetPacketSendChatText()) { diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp index 65c45d60..28369388 100644 --- a/src/net/common/servergamethread.cpp +++ b/src/net/common/servergamethread.cpp @@ -229,24 +229,52 @@ ServerGameThread::InternalKickPlayer(unsigned playerId) boost::shared_ptr ServerGameThread::InternalAskVoteKick(unsigned playerIdByWhom, unsigned playerIdWho) { - boost::mutex::scoped_lock lock(m_voteKickMapMutex); // TODO: Check whether player is allowed to initiate vote. // TODO: Check whether there are more than two players. boost::shared_ptr voteData; - if (m_game) + if (IsRunning()) { voteData.reset(new VoteKickData); voteData->petitionId = m_curPetitionId++; voteData->kickPlayerId = playerIdWho; - voteData->numVotesToKick = static_cast(ceil(GetCurNumberOfPlayers() / 3. * 2.)); + voteData->initialNumVotesToKick = static_cast(ceil(GetCurNumberOfPlayers() / 3. * 2.)); // Consider first vote. - voteData->numVotesToKick--; + voteData->numVotesInFavourOfKicking = 1; voteData->votedPlayerIds.push_back(playerIdByWhom); + boost::mutex::scoped_lock lock(m_voteKickMapMutex); m_voteKickMap.insert(VoteKickMap::value_type(voteData->petitionId, voteData)); } return voteData; } +void +ServerGameThread::InternalVoteKick(unsigned petitionId, KickVote vote) +{ + if (IsRunning()) + { + boost::mutex::scoped_lock lock(m_voteKickMapMutex); + VoteKickMap::iterator pos = m_voteKickMap.find(petitionId); + if (pos != m_voteKickMap.end()) + { + boost::shared_ptr curData(pos->second); + if (vote == KICK_VOTE_IN_FAVOUR) + { + curData->numVotesInFavourOfKicking++; + if (curData->numVotesInFavourOfKicking >= curData->initialNumVotesToKick) + { + // Perform kick. + InternalKickPlayer(curData->kickPlayerId); + } + } + else + curData->numVotesAgainstKicking++; + // TODO abort if no longer possible. + // TODO remove deprecated list entries. + // TODO error handling. + } + } +} + PlayerDataList ServerGameThread::GetFullPlayerDataList() const { diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h index 7f1e8bce..af723d0f 100644 --- a/src/net/servergamethread.h +++ b/src/net/servergamethread.h @@ -88,6 +88,7 @@ protected: void InternalKickPlayer(unsigned playerId); boost::shared_ptr InternalAskVoteKick(unsigned playerIdByWhom, unsigned playerIdWho); + void InternalVoteKick(unsigned petitionId, KickVote vote); PlayerDataList GetFullPlayerDataList() const; diff --git a/src/session.cpp b/src/session.cpp index 2d97292c..762e9b29 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -395,6 +395,13 @@ void Session::startVoteKickPlayer(unsigned playerId) myNetClient->SendAskKickPlayer(playerId); } +void Session::voteKick(bool doKick) +{ + if (!myNetClient) + return; // only act if client is running. + myNetClient->SendVoteKick(doKick); +} + bool Session::isNetworkClientRunning() const { // This, and every place which calls this, is a HACK. diff --git a/src/session.h b/src/session.h index 64bb7a8c..e69e788f 100755 --- a/src/session.h +++ b/src/session.h @@ -81,6 +81,7 @@ public: void kickPlayer(unsigned playerId); void kickPlayer(const std::string &playerName); void startVoteKickPlayer(unsigned playerId); + void voteKick(bool doKick); void resetNetworkTimeout();