From 1cfe551f1948c4b374cd92debbcdf5c55957d655 Mon Sep 17 00:00:00 2001 From: lotodore Date: Sun, 16 Nov 2008 22:57:11 +0000 Subject: [PATCH] More work on vote kick. Some network packets are exchanged, but still not functional. --- src/gamedata.h | 10 ++++++++++ src/gui/qt/gametable/gametableimpl.cpp | 10 ++++++++-- src/net/clientthread.h | 1 + src/net/common/clientstate.cpp | 6 ++++++ src/net/common/clientthread.cpp | 11 +++++++++++ src/net/common/servergamestate.cpp | 18 +++++++++++++++--- src/net/common/servergamethread.cpp | 23 ++++++++++++++++++++++- src/net/servergamethread.h | 6 ++++++ src/session.cpp | 7 +++++++ src/session.h | 1 + 10 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/gamedata.h b/src/gamedata.h index c0181255..465570fd 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -22,6 +22,7 @@ #define _GAMEDATA_H_ #include +#include #define SERVER_COMPUTER_PLAYER_NAME "Computer" @@ -87,5 +88,14 @@ struct StartData int numberOfPlayers; }; +struct VoteKickData +{ + unsigned petitionId; + unsigned kickPlayerId; + unsigned numVotesToKick; + boost::timers::portable::microsec_timer voteTimer; + std::list votedPlayerIds; +}; + #endif diff --git a/src/gui/qt/gametable/gametableimpl.cpp b/src/gui/qt/gametable/gametableimpl.cpp index 0271148a..b2d66175 100755 --- a/src/gui/qt/gametable/gametableimpl.cpp +++ b/src/gui/qt/gametable/gametableimpl.cpp @@ -3088,8 +3088,14 @@ void gameTableImpl::leaveCurrentNetworkGame() { void gameTableImpl::triggerVoteOnKick(int id) { - qDebug() << "vote for kick user: " << id; -// myStartWindow->getSession()->sendVoteKickSignal(id); + assert(myStartWindow->getSession()->getCurrentGame()); + int playerCount = static_cast(myStartWindow->getSession()->getCurrentGame()->getSeatsList()->size()); + if (id < playerCount) + { + PlayerListIterator pos = myStartWindow->getSession()->getCurrentGame()->getSeatsList()->begin(); + advance(pos, id); + myStartWindow->getSession()->startVoteKickPlayer((*pos)->getMyUniqueID()); + } } void gameTableImpl::startVoteOnKick(int playerId, int timeoutSec) diff --git a/src/net/clientthread.h b/src/net/clientthread.h index aec2dcc9..8f37743e 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -68,6 +68,7 @@ public: void SendJoinGame(unsigned gameId, const std::string &password); void SendCreateGame(const GameData &gameData, const std::string &name, const std::string &password); void SendResetTimeout(); + void SendAskKickPlayer(unsigned playerId); GameInfo GetGameInfo(unsigned gameId) const; PlayerInfo GetPlayerInfo(unsigned playerId) const; diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 47bb8669..42834ac3 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -769,6 +769,12 @@ AbstractClientStateReceiving::Process(ClientThread &client) tmpPacket->ToNetPacketGameListAdminChanged()->GetData(adminChangedData); client.UpdateGameInfoAdmin(adminChangedData.gameId, adminChangedData.newAdminplayerId); } + else if (tmpPacket->ToNetPacketStartKickPlayerPetition()) + { + NetPacketStartKickPlayerPetition::Data petitionData; + tmpPacket->ToNetPacketStartKickPlayerPetition()->GetData(petitionData); + // TODO + } else if (tmpPacket->ToNetPacketAvatarHeader()) { NetPacketAvatarHeader::Data headerData; diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index 853430b3..a5cb5bfa 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -253,6 +253,17 @@ ClientThread::SendResetTimeout() m_outPacketList.push_back(reset); } +void +ClientThread::SendAskKickPlayer(unsigned playerId) +{ + boost::shared_ptr ask(new NetPacketAskKickPlayer); + NetPacketAskKickPlayer::Data askData; + askData.playerId = playerId; + static_cast(ask.get())->SetData(askData); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(ask); +} + GameInfo ClientThread::GetGameInfo(unsigned gameId) const { diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index ed7d8331..618fd8ad 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -64,6 +64,7 @@ using namespace std; #define SERVER_GAME_ADMIN_WARNING_REMAINING_SEC 60 #define SERVER_GAME_ADMIN_TIMEOUT_SEC 300 // 5 min, MUST be > SERVER_GAME_ADMIN_WARNING_REMAINING_SEC +#define SERVER_VOTE_KICK_TIMEOUT_SEC 30 // Helper functions // TODO: these are hacks. @@ -198,13 +199,24 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) } else if (packet->ToNetPacketAskKickPlayer()) { - if (server.IsRunning()) + if (server.IsRunning() && session.playerData) { NetPacketAskKickPlayer::Data askKickData; packet->ToNetPacketAskKickPlayer()->GetData(askKickData); - // TODO start vote kick. - //askKickData.playerId + boost::shared_ptr voteData(server.InternalAskVoteKick(session.playerData->GetUniqueId(), askKickData.playerId)); + if (voteData) + { + boost::shared_ptr startPetition(new NetPacketStartKickPlayerPetition); + NetPacketStartKickPlayerPetition::Data startPetitionData; + startPetitionData.petitionId = voteData->petitionId; + startPetitionData.proposingPlayerId = session.playerData->GetUniqueId(); + startPetitionData.kickPlayerId = voteData->kickPlayerId; + startPetitionData.kickTimeoutSec = SERVER_VOTE_KICK_TIMEOUT_SEC; + startPetitionData.numVotesNeededToKick = voteData->numVotesToKick; + static_cast(startPetition.get())->SetData(startPetitionData); + server.GetSender().Send(session.sessionData, startPetition); + } } } // Chat text is always allowed. diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp index 10cc7617..65c45d60 100644 --- a/src/net/common/servergamethread.cpp +++ b/src/net/common/servergamethread.cpp @@ -37,7 +37,7 @@ using namespace std; ServerGameThread::ServerGameThread(ServerLobbyThread &lobbyThread, u_int32_t id, const string &name, const string &pwd, const GameData &gameData, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig) : m_adminPlayerId(adminPlayerId), m_lobbyThread(lobbyThread), m_gui(gui), m_gameData(gameData), m_id(id), m_name(name), m_password(pwd), m_playerConfig(playerConfig), - m_curState(NULL), m_gameNum(1), + m_curState(NULL), m_gameNum(1), m_curPetitionId(1), m_stateTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::manual_start), m_stateTimerFlag(0) { @@ -226,6 +226,27 @@ ServerGameThread::InternalKickPlayer(unsigned playerId) MoveSessionToLobby(tmpSession, NTF_NET_REMOVED_KICKED); } +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) + { + voteData.reset(new VoteKickData); + voteData->petitionId = m_curPetitionId++; + voteData->kickPlayerId = playerIdWho; + voteData->numVotesToKick = static_cast(ceil(GetCurNumberOfPlayers() / 3. * 2.)); + // Consider first vote. + voteData->numVotesToKick--; + voteData->votedPlayerIds.push_back(playerIdByWhom); + m_voteKickMap.insert(VoteKickMap::value_type(voteData->petitionId, voteData)); + } + return voteData; +} + PlayerDataList ServerGameThread::GetFullPlayerDataList() const { diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h index 3f6b0fd6..7f1e8bce 100644 --- a/src/net/servergamethread.h +++ b/src/net/servergamethread.h @@ -77,6 +77,7 @@ public: protected: typedef std::deque SessionQueue; + typedef std::map > VoteKickMap; // Main function of the thread. virtual void Main(); @@ -86,6 +87,7 @@ protected: void ResetGame(); void InternalKickPlayer(unsigned playerId); + boost::shared_ptr InternalAskVoteKick(unsigned playerIdByWhom, unsigned playerIdWho); PlayerDataList GetFullPlayerDataList() const; @@ -140,6 +142,9 @@ private: unsigned m_adminPlayerId; mutable boost::mutex m_adminPlayerIdMutex; + VoteKickMap m_voteKickMap; + mutable boost::mutex m_voteKickMapMutex; + ServerLobbyThread &m_lobbyThread; boost::shared_ptr m_receiver; GuiInterface &m_gui; @@ -153,6 +158,7 @@ private: ConfigFile *m_playerConfig; ServerGameState *m_curState; unsigned m_gameNum; + unsigned m_curPetitionId; boost::timers::portable::microsec_timer m_stateTimer; unsigned m_stateTimerFlag; diff --git a/src/session.cpp b/src/session.cpp index 4327c9cd..2d97292c 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -388,6 +388,13 @@ void Session::kickPlayer(const string &playerName) kickPlayer(playerId); } +void Session::startVoteKickPlayer(unsigned playerId) +{ + if (!myNetClient) + return; // only act if client is running. + myNetClient->SendAskKickPlayer(playerId); +} + 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 f8924662..64bb7a8c 100755 --- a/src/session.h +++ b/src/session.h @@ -80,6 +80,7 @@ public: void sendChatMessage(const std::string &message); void kickPlayer(unsigned playerId); void kickPlayer(const std::string &playerName); + void startVoteKickPlayer(unsigned playerId); void resetNetworkTimeout();