Started error handling for vote kick.

This commit is contained in:
lotodore
2008-12-06 00:18:36 +00:00
parent 5bf83898d2
commit 2652625828
6 changed files with 113 additions and 39 deletions
+23 -2
View File
@@ -120,8 +120,10 @@ using namespace std;
#define NET_LEFT_OTHER_REASON 0xFFFF
// Reasons why ask kick was denied.
#define NET_ASK_KICK_DENIED_TEMPORARY 0x0000
#define NET_ASK_KICK_DENIED_OTHER_IN_PROGRESS 0x0001
#define NET_ASK_KICK_DENIED_INVALID_STATE 0x0000
#define NET_ASK_KICK_DENIED_TOO_FEW_PLAYERS 0x0001
#define NET_ASK_KICK_DENIED_TEMPORARY 0x0002
#define NET_ASK_KICK_DENIED_OTHER_IN_PROGRESS 0x0003
#define NET_ASK_KICK_DENIED_OTHER_REASON 0xFFFF
// Vote types
@@ -131,6 +133,7 @@ using namespace std;
// Reasons why vote to kick was denied.
#define NET_VOTE_KICK_DENIED_INVALID_PETITION 0x0000
#define NET_VOTE_KICK_DENIED_ALREADY_VOTED 0x0001
#define NET_VOTE_KICK_DENIED_IMPOSSIBLE 0x0002
#define NET_VOTE_KICK_DENIED_OTHER_REASON 0xFFFF
// Reasons for timeout warning
@@ -4485,6 +4488,12 @@ NetPacketAskKickPlayerDenied::SetData(const NetPacketAskKickPlayerDenied::Data &
tmpData->playerId = htonl(inData.playerId);
switch (inData.denyReason)
{
case KICK_DENIED_INVALID_STATE:
tmpData->denyReason = htons(NET_ASK_KICK_DENIED_INVALID_STATE);
break;
case KICK_DENIED_TOO_FEW_PLAYERS:
tmpData->denyReason = htons(NET_ASK_KICK_DENIED_TOO_FEW_PLAYERS);
break;
case KICK_DENIED_TEMPORARY:
tmpData->denyReason = htons(NET_ASK_KICK_DENIED_TEMPORARY);
break;
@@ -4508,6 +4517,12 @@ NetPacketAskKickPlayerDenied::GetData(NetPacketAskKickPlayerDenied::Data &outDat
outData.playerId = ntohl(tmpData->playerId);
switch (ntohs(tmpData->denyReason))
{
case NET_ASK_KICK_DENIED_INVALID_STATE:
outData.denyReason = KICK_DENIED_INVALID_STATE;
break;
case NET_ASK_KICK_DENIED_TOO_FEW_PLAYERS:
outData.denyReason = KICK_DENIED_TOO_FEW_PLAYERS;
break;
case NET_ASK_KICK_DENIED_TEMPORARY:
outData.denyReason = KICK_DENIED_TEMPORARY;
break;
@@ -4758,6 +4773,9 @@ NetPacketVoteKickPlayerDenied::SetData(const NetPacketVoteKickPlayerDenied::Data
case VOTE_DENIED_ALREADY_VOTED:
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_ALREADY_VOTED);
break;
case VOTE_DENIED_IMPOSSIBLE:
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_IMPOSSIBLE);
break;
default:
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_OTHER_REASON);
break;
@@ -4781,6 +4799,9 @@ NetPacketVoteKickPlayerDenied::GetData(NetPacketVoteKickPlayerDenied::Data &outD
case NET_VOTE_KICK_DENIED_ALREADY_VOTED:
outData.denyReason = VOTE_DENIED_ALREADY_VOTED;
break;
case NET_VOTE_KICK_DENIED_IMPOSSIBLE:
outData.denyReason = VOTE_DENIED_IMPOSSIBLE;
break;
default:
outData.denyReason = VOTE_DENIED_OTHER_REASON;
break;
+2 -16
View File
@@ -38,8 +38,6 @@ using namespace std;
//#define SERVER_TEST
#define SERVER_START_GAME_TIMEOUT_SEC 10
#ifdef SERVER_TEST
#define SERVER_DELAY_NEXT_HAND_SEC 0
#define SERVER_DELAY_NEXT_GAME_SEC 0
@@ -62,6 +60,7 @@ using namespace std;
#define SERVER_COMPUTER_ACTION_DELAY_SEC 2
#endif
#define SERVER_START_GAME_TIMEOUT_SEC 10
#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
@@ -204,20 +203,7 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server)
NetPacketAskKickPlayer::Data askKickData;
packet->ToNetPacketAskKickPlayer()->GetData(askKickData);
boost::shared_ptr<VoteKickData> voteData(server.InternalAskVoteKick(session.playerData->GetUniqueId(), askKickData.playerId));
if (voteData)
{
boost::shared_ptr<NetPacket> 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->initialNumVotesToKick;
static_cast<NetPacketStartKickPlayerPetition *>(startPetition.get())->SetData(startPetitionData);
server.SendToAllPlayers(startPetition, SessionData::Game);
// TODO notify first vote.
}
server.InternalAskVoteKick(session, askKickData.playerId, SERVER_VOTE_KICK_TIMEOUT_SEC);
}
}
else if (packet->ToNetPacketVoteKickPlayer())
+76 -16
View File
@@ -135,6 +135,7 @@ ServerGameThread::Main()
// Process current state.
GetState().Process(*this);
RemovePlayerLoop();
VoteKickLoop();
} while (!ShouldTerminate() && GetSessionManager().HasSessions());
} catch (const PokerTHException &e)
{
@@ -167,6 +168,19 @@ ServerGameThread::RemovePlayerLoop()
m_removePlayerList.clear();
}
void
ServerGameThread::VoteKickLoop()
{
/* boost::mutex::scoped_lock lock(m_voteKickMapMutex);
// Check the list whether the player is already being kicked.
VoteKickMap::iterator i = m_voteKickMap.begin();
VoteKickMap::iterator end = m_voteKickMap.end();
while (i != end)
{
++i;
}*/
}
void
ServerGameThread::InternalStartGame()
{
@@ -226,25 +240,71 @@ ServerGameThread::InternalKickPlayer(unsigned playerId)
MoveSessionToLobby(tmpSession, NTF_NET_REMOVED_KICKED);
}
boost::shared_ptr<VoteKickData>
ServerGameThread::InternalAskVoteKick(unsigned playerIdByWhom, unsigned playerIdWho)
void
ServerGameThread::InternalAskVoteKick(SessionWrapper byWhom, unsigned playerIdWho, unsigned timeoutSec)
{
// TODO: Check whether player is allowed to initiate vote.
// TODO: Check whether there are more than two players.
boost::shared_ptr<VoteKickData> voteData;
if (IsRunning())
if (IsRunning() && byWhom.playerData)
{
voteData.reset(new VoteKickData);
voteData->petitionId = m_curPetitionId++;
voteData->kickPlayerId = playerIdWho;
voteData->initialNumVotesToKick = static_cast<unsigned>(ceil(GetCurNumberOfPlayers() / 3. * 2.));
// Consider first vote.
voteData->numVotesInFavourOfKicking = 1;
voteData->votedPlayerIds.push_back(playerIdByWhom);
boost::mutex::scoped_lock lock(m_voteKickMapMutex);
m_voteKickMap.insert(VoteKickMap::value_type(voteData->petitionId, voteData));
size_t numPlayers = GetCurNumberOfPlayers();
if (numPlayers > 2)
{
// Lock the vote kick list.
boost::mutex::scoped_lock lock(m_voteKickMapMutex);
// Check the list whether the player is already being kicked.
VoteKickMap::const_iterator i = m_voteKickMap.begin();
VoteKickMap::const_iterator end = m_voteKickMap.end();
while (i != end)
{
if (i->second->kickPlayerId == playerIdWho)
break;
++i;
}
if (i == end)
{
// Initiate a vote kick.
unsigned playerIdByWhom = byWhom.playerData->GetUniqueId();
boost::shared_ptr<VoteKickData> voteData(new VoteKickData);
voteData->petitionId = m_curPetitionId++;
voteData->kickPlayerId = playerIdWho;
voteData->initialNumVotesToKick = static_cast<unsigned>(ceil(numPlayers / 3. * 2.));
// Consider first vote.
voteData->numVotesInFavourOfKicking = 1;
voteData->votedPlayerIds.push_back(playerIdByWhom);
m_voteKickMap.insert(VoteKickMap::value_type(voteData->petitionId, voteData));
lock.unlock(); // Do not block the list longer than necessary.
boost::shared_ptr<NetPacket> startPetition(new NetPacketStartKickPlayerPetition);
NetPacketStartKickPlayerPetition::Data startPetitionData;
startPetitionData.petitionId = voteData->petitionId;
startPetitionData.proposingPlayerId = playerIdByWhom;
startPetitionData.kickPlayerId = voteData->kickPlayerId;
startPetitionData.kickTimeoutSec = timeoutSec;
startPetitionData.numVotesNeededToKick = voteData->initialNumVotesToKick;
static_cast<NetPacketStartKickPlayerPetition *>(startPetition.get())->SetData(startPetitionData);
SendToAllPlayers(startPetition, SessionData::Game);
}
else
{
lock.unlock(); // Do not block the list longer than necessary.
InternalDenyAskVoteKick(byWhom, playerIdWho, KICK_DENIED_OTHER_IN_PROGRESS);
}
}
else
InternalDenyAskVoteKick(byWhom, playerIdWho, KICK_DENIED_TOO_FEW_PLAYERS);
}
return voteData;
else
InternalDenyAskVoteKick(byWhom, playerIdWho, KICK_DENIED_INVALID_STATE);
}
void
ServerGameThread::InternalDenyAskVoteKick(SessionWrapper byWhom, unsigned playerIdWho, DenyKickPlayerReason reason)
{
boost::shared_ptr<NetPacket> denyPetition(new NetPacketAskKickPlayerDenied);
NetPacketAskKickPlayerDenied::Data denyPetitionData;
denyPetitionData.playerId = playerIdWho;
denyPetitionData.denyReason = reason;
static_cast<NetPacketAskKickPlayerDenied *>(denyPetition.get())->SetData(denyPetitionData);
GetSender().Send(byWhom.sessionData, denyPetition);
}
void
+3 -1
View File
@@ -82,12 +82,14 @@ protected:
// Main function of the thread.
virtual void Main();
void RemovePlayerLoop();
void VoteKickLoop();
void InternalStartGame();
void ResetGame();
void InternalKickPlayer(unsigned playerId);
boost::shared_ptr<VoteKickData> InternalAskVoteKick(unsigned playerIdByWhom, unsigned playerIdWho);
void InternalAskVoteKick(SessionWrapper byWhom, unsigned playerIdWho, unsigned timeoutSec);
void InternalDenyAskVoteKick(SessionWrapper byWhom, unsigned playerIdWho, DenyKickPlayerReason reason);
void InternalVoteKick(unsigned petitionId, KickVote vote);
PlayerDataList GetFullPlayerDataList() const;