Started error handling for vote kick.
This commit is contained in:
@@ -821,13 +821,15 @@ Server Reply: Ask Kick Player Denied
|
|||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| Message Type = 114 | Message Length = 12 |
|
| Message Type = 114 | Message Length = 12 |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| Player ID |
|
| Player ID (who cannot be kicked) |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| Deny Reason | Reserved |
|
| Deny Reason | Reserved |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
Deny Reason:
|
Deny Reason:
|
||||||
0x0000: Another kick cannot be requested at this time.
|
0x0000: Invalid state. Vote kick is only possible when the game is running.
|
||||||
0x0001: Kick request is already in progress for this player.
|
0x0001: Kick not possible due to number of players.
|
||||||
|
0x0002: Another kick cannot be requested at this time.
|
||||||
|
0x0003: Kick request is already in progress for this player.
|
||||||
0xFFFF: Other reason.
|
0xFFFF: Other reason.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -68,7 +68,9 @@ enum PlayerActionCode
|
|||||||
|
|
||||||
enum DenyKickPlayerReason
|
enum DenyKickPlayerReason
|
||||||
{
|
{
|
||||||
KICK_DENIED_TEMPORARY = 0,
|
KICK_DENIED_INVALID_STATE = 0,
|
||||||
|
KICK_DENIED_TOO_FEW_PLAYERS,
|
||||||
|
KICK_DENIED_TEMPORARY,
|
||||||
KICK_DENIED_OTHER_IN_PROGRESS,
|
KICK_DENIED_OTHER_IN_PROGRESS,
|
||||||
KICK_DENIED_OTHER_REASON
|
KICK_DENIED_OTHER_REASON
|
||||||
};
|
};
|
||||||
@@ -83,6 +85,7 @@ enum DenyVoteReason
|
|||||||
{
|
{
|
||||||
VOTE_DENIED_INVALID_PETITION = 0,
|
VOTE_DENIED_INVALID_PETITION = 0,
|
||||||
VOTE_DENIED_ALREADY_VOTED,
|
VOTE_DENIED_ALREADY_VOTED,
|
||||||
|
VOTE_DENIED_IMPOSSIBLE,
|
||||||
VOTE_DENIED_OTHER_REASON
|
VOTE_DENIED_OTHER_REASON
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,10 @@ using namespace std;
|
|||||||
#define NET_LEFT_OTHER_REASON 0xFFFF
|
#define NET_LEFT_OTHER_REASON 0xFFFF
|
||||||
|
|
||||||
// Reasons why ask kick was denied.
|
// Reasons why ask kick was denied.
|
||||||
#define NET_ASK_KICK_DENIED_TEMPORARY 0x0000
|
#define NET_ASK_KICK_DENIED_INVALID_STATE 0x0000
|
||||||
#define NET_ASK_KICK_DENIED_OTHER_IN_PROGRESS 0x0001
|
#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
|
#define NET_ASK_KICK_DENIED_OTHER_REASON 0xFFFF
|
||||||
|
|
||||||
// Vote types
|
// Vote types
|
||||||
@@ -131,6 +133,7 @@ using namespace std;
|
|||||||
// Reasons why vote to kick was denied.
|
// Reasons why vote to kick was denied.
|
||||||
#define NET_VOTE_KICK_DENIED_INVALID_PETITION 0x0000
|
#define NET_VOTE_KICK_DENIED_INVALID_PETITION 0x0000
|
||||||
#define NET_VOTE_KICK_DENIED_ALREADY_VOTED 0x0001
|
#define NET_VOTE_KICK_DENIED_ALREADY_VOTED 0x0001
|
||||||
|
#define NET_VOTE_KICK_DENIED_IMPOSSIBLE 0x0002
|
||||||
#define NET_VOTE_KICK_DENIED_OTHER_REASON 0xFFFF
|
#define NET_VOTE_KICK_DENIED_OTHER_REASON 0xFFFF
|
||||||
|
|
||||||
// Reasons for timeout warning
|
// Reasons for timeout warning
|
||||||
@@ -4485,6 +4488,12 @@ NetPacketAskKickPlayerDenied::SetData(const NetPacketAskKickPlayerDenied::Data &
|
|||||||
tmpData->playerId = htonl(inData.playerId);
|
tmpData->playerId = htonl(inData.playerId);
|
||||||
switch (inData.denyReason)
|
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:
|
case KICK_DENIED_TEMPORARY:
|
||||||
tmpData->denyReason = htons(NET_ASK_KICK_DENIED_TEMPORARY);
|
tmpData->denyReason = htons(NET_ASK_KICK_DENIED_TEMPORARY);
|
||||||
break;
|
break;
|
||||||
@@ -4508,6 +4517,12 @@ NetPacketAskKickPlayerDenied::GetData(NetPacketAskKickPlayerDenied::Data &outDat
|
|||||||
outData.playerId = ntohl(tmpData->playerId);
|
outData.playerId = ntohl(tmpData->playerId);
|
||||||
switch (ntohs(tmpData->denyReason))
|
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:
|
case NET_ASK_KICK_DENIED_TEMPORARY:
|
||||||
outData.denyReason = KICK_DENIED_TEMPORARY;
|
outData.denyReason = KICK_DENIED_TEMPORARY;
|
||||||
break;
|
break;
|
||||||
@@ -4758,6 +4773,9 @@ NetPacketVoteKickPlayerDenied::SetData(const NetPacketVoteKickPlayerDenied::Data
|
|||||||
case VOTE_DENIED_ALREADY_VOTED:
|
case VOTE_DENIED_ALREADY_VOTED:
|
||||||
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_ALREADY_VOTED);
|
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_ALREADY_VOTED);
|
||||||
break;
|
break;
|
||||||
|
case VOTE_DENIED_IMPOSSIBLE:
|
||||||
|
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_IMPOSSIBLE);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_OTHER_REASON);
|
tmpData->denyReason = htons(NET_VOTE_KICK_DENIED_OTHER_REASON);
|
||||||
break;
|
break;
|
||||||
@@ -4781,6 +4799,9 @@ NetPacketVoteKickPlayerDenied::GetData(NetPacketVoteKickPlayerDenied::Data &outD
|
|||||||
case NET_VOTE_KICK_DENIED_ALREADY_VOTED:
|
case NET_VOTE_KICK_DENIED_ALREADY_VOTED:
|
||||||
outData.denyReason = VOTE_DENIED_ALREADY_VOTED;
|
outData.denyReason = VOTE_DENIED_ALREADY_VOTED;
|
||||||
break;
|
break;
|
||||||
|
case NET_VOTE_KICK_DENIED_IMPOSSIBLE:
|
||||||
|
outData.denyReason = VOTE_DENIED_IMPOSSIBLE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
outData.denyReason = VOTE_DENIED_OTHER_REASON;
|
outData.denyReason = VOTE_DENIED_OTHER_REASON;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ using namespace std;
|
|||||||
|
|
||||||
//#define SERVER_TEST
|
//#define SERVER_TEST
|
||||||
|
|
||||||
#define SERVER_START_GAME_TIMEOUT_SEC 10
|
|
||||||
|
|
||||||
#ifdef SERVER_TEST
|
#ifdef SERVER_TEST
|
||||||
#define SERVER_DELAY_NEXT_HAND_SEC 0
|
#define SERVER_DELAY_NEXT_HAND_SEC 0
|
||||||
#define SERVER_DELAY_NEXT_GAME_SEC 0
|
#define SERVER_DELAY_NEXT_GAME_SEC 0
|
||||||
@@ -62,6 +60,7 @@ using namespace std;
|
|||||||
#define SERVER_COMPUTER_ACTION_DELAY_SEC 2
|
#define SERVER_COMPUTER_ACTION_DELAY_SEC 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SERVER_START_GAME_TIMEOUT_SEC 10
|
||||||
#define SERVER_GAME_ADMIN_WARNING_REMAINING_SEC 60
|
#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_GAME_ADMIN_TIMEOUT_SEC 300 // 5 min, MUST be > SERVER_GAME_ADMIN_WARNING_REMAINING_SEC
|
||||||
#define SERVER_VOTE_KICK_TIMEOUT_SEC 30
|
#define SERVER_VOTE_KICK_TIMEOUT_SEC 30
|
||||||
@@ -204,20 +203,7 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server)
|
|||||||
NetPacketAskKickPlayer::Data askKickData;
|
NetPacketAskKickPlayer::Data askKickData;
|
||||||
packet->ToNetPacketAskKickPlayer()->GetData(askKickData);
|
packet->ToNetPacketAskKickPlayer()->GetData(askKickData);
|
||||||
|
|
||||||
boost::shared_ptr<VoteKickData> voteData(server.InternalAskVoteKick(session.playerData->GetUniqueId(), askKickData.playerId));
|
server.InternalAskVoteKick(session, askKickData.playerId, SERVER_VOTE_KICK_TIMEOUT_SEC);
|
||||||
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.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (packet->ToNetPacketVoteKickPlayer())
|
else if (packet->ToNetPacketVoteKickPlayer())
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ ServerGameThread::Main()
|
|||||||
// Process current state.
|
// Process current state.
|
||||||
GetState().Process(*this);
|
GetState().Process(*this);
|
||||||
RemovePlayerLoop();
|
RemovePlayerLoop();
|
||||||
|
VoteKickLoop();
|
||||||
} while (!ShouldTerminate() && GetSessionManager().HasSessions());
|
} while (!ShouldTerminate() && GetSessionManager().HasSessions());
|
||||||
} catch (const PokerTHException &e)
|
} catch (const PokerTHException &e)
|
||||||
{
|
{
|
||||||
@@ -167,6 +168,19 @@ ServerGameThread::RemovePlayerLoop()
|
|||||||
m_removePlayerList.clear();
|
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
|
void
|
||||||
ServerGameThread::InternalStartGame()
|
ServerGameThread::InternalStartGame()
|
||||||
{
|
{
|
||||||
@@ -226,25 +240,71 @@ ServerGameThread::InternalKickPlayer(unsigned playerId)
|
|||||||
MoveSessionToLobby(tmpSession, NTF_NET_REMOVED_KICKED);
|
MoveSessionToLobby(tmpSession, NTF_NET_REMOVED_KICKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<VoteKickData>
|
void
|
||||||
ServerGameThread::InternalAskVoteKick(unsigned playerIdByWhom, unsigned playerIdWho)
|
ServerGameThread::InternalAskVoteKick(SessionWrapper byWhom, unsigned playerIdWho, unsigned timeoutSec)
|
||||||
{
|
{
|
||||||
// TODO: Check whether player is allowed to initiate vote.
|
if (IsRunning() && byWhom.playerData)
|
||||||
// TODO: Check whether there are more than two players.
|
|
||||||
boost::shared_ptr<VoteKickData> voteData;
|
|
||||||
if (IsRunning())
|
|
||||||
{
|
{
|
||||||
voteData.reset(new VoteKickData);
|
size_t numPlayers = GetCurNumberOfPlayers();
|
||||||
voteData->petitionId = m_curPetitionId++;
|
if (numPlayers > 2)
|
||||||
voteData->kickPlayerId = playerIdWho;
|
{
|
||||||
voteData->initialNumVotesToKick = static_cast<unsigned>(ceil(GetCurNumberOfPlayers() / 3. * 2.));
|
// Lock the vote kick list.
|
||||||
// Consider first vote.
|
boost::mutex::scoped_lock lock(m_voteKickMapMutex);
|
||||||
voteData->numVotesInFavourOfKicking = 1;
|
// Check the list whether the player is already being kicked.
|
||||||
voteData->votedPlayerIds.push_back(playerIdByWhom);
|
VoteKickMap::const_iterator i = m_voteKickMap.begin();
|
||||||
boost::mutex::scoped_lock lock(m_voteKickMapMutex);
|
VoteKickMap::const_iterator end = m_voteKickMap.end();
|
||||||
m_voteKickMap.insert(VoteKickMap::value_type(voteData->petitionId, voteData));
|
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
|
void
|
||||||
|
|||||||
@@ -82,12 +82,14 @@ protected:
|
|||||||
// Main function of the thread.
|
// Main function of the thread.
|
||||||
virtual void Main();
|
virtual void Main();
|
||||||
void RemovePlayerLoop();
|
void RemovePlayerLoop();
|
||||||
|
void VoteKickLoop();
|
||||||
|
|
||||||
void InternalStartGame();
|
void InternalStartGame();
|
||||||
void ResetGame();
|
void ResetGame();
|
||||||
|
|
||||||
void InternalKickPlayer(unsigned playerId);
|
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);
|
void InternalVoteKick(unsigned petitionId, KickVote vote);
|
||||||
|
|
||||||
PlayerDataList GetFullPlayerDataList() const;
|
PlayerDataList GetFullPlayerDataList() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user