diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index eaa6981a..0d1f7723 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -42,10 +42,10 @@ void MessageLogWidget::logJoin(Player *player) appendHtmlServerMessage(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); } -void MessageLogWidget::logLeave(Player *player) +void MessageLogWidget::logLeave(Player *player, QString reason) { soundEngine->playSound("player_leave"); - appendHtmlServerMessage(tr("%1 has left the game.").arg(sanitizeHtml(player->getName()))); + appendHtmlServerMessage(tr("%1 has left the game (%2).").arg(sanitizeHtml(player->getName()), sanitizeHtml(reason))); } void MessageLogWidget::logGameClosed() @@ -64,10 +64,10 @@ void MessageLogWidget::logJoinSpectator(QString name) appendHtmlServerMessage(tr("%1 is now watching the game.").arg(sanitizeHtml(name))); } -void MessageLogWidget::logLeaveSpectator(QString name) +void MessageLogWidget::logLeaveSpectator(QString name, QString reason) { soundEngine->playSound("spectator_leave"); - appendHtmlServerMessage(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name))); + appendHtmlServerMessage(tr("%1 is not watching the game any more (%2).").arg(sanitizeHtml(name), sanitizeHtml(reason))); } void MessageLogWidget::logDeckSelect(Player *player, QString deckHash, int sideboardSize) diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index da375928..e9b058d9 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -40,11 +40,11 @@ public slots: void logGameJoined(int gameId); void logReplayStarted(int gameId); void logJoin(Player *player); - void logLeave(Player *player); + void logLeave(Player *player, QString reason); void logGameClosed(); void logKicked(); void logJoinSpectator(QString name); - void logLeaveSpectator(QString name); + void logLeaveSpectator(QString name, QString reason); void logDeckSelect(Player *player, QString deckHash, int sideboardSize); void logReadyStart(Player *player); void logNotReadyStart(Player *player); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 49dd70e9..f7411559 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -891,12 +891,12 @@ void TabGame::eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, c messageLog->logSpectatorSay(QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()), QString::fromStdString(userInfo.privlevel()), QString::fromStdString(event.message())); } -void TabGame::eventSpectatorLeave(const Event_Leave & /*event*/, int eventPlayerId, const GameEventContext & /*context*/) +void TabGame::eventSpectatorLeave(const Event_Leave & event, int eventPlayerId, const GameEventContext & /*context*/) { QString playerName = "@" + QString::fromStdString(spectators.value(eventPlayerId).name()); if (sayEdit && autocompleteUserList.removeOne(playerName)) sayEdit->setCompletionList(autocompleteUserList); - messageLog->logLeaveSpectator(QString::fromStdString(spectators.value(eventPlayerId).name())); + messageLog->logLeaveSpectator(QString::fromStdString(spectators.value(eventPlayerId).name()), getLeaveReason(event.reason())); playerListWidget->removePlayer(eventPlayerId); spectators.remove(eventPlayerId); @@ -1042,7 +1042,26 @@ void TabGame::eventJoin(const Event_Join &event, int /*eventPlayerId*/, const Ga emitUserEvent(); } -void TabGame::eventLeave(const Event_Leave & /*event*/, int eventPlayerId, const GameEventContext & /*context*/) +QString TabGame::getLeaveReason(Event_Leave::LeaveReason reason) +{ + switch(reason) + { + case Event_Leave::USER_KICKED: + return tr("kicked by game host or moderator"); + break; + case Event_Leave::USER_LEFT: + return tr("player left the game"); + break; + case Event_Leave::USER_DISCONNECTED: + return tr("player disconnected from server"); + break; + case Event_Leave::OTHER: + default: + return tr("reason unknown"); + break; + } +} +void TabGame::eventLeave(const Event_Leave & event, int eventPlayerId, const GameEventContext & /*context*/) { Player *player = players.value(eventPlayerId, 0); if (!player) @@ -1052,7 +1071,7 @@ void TabGame::eventLeave(const Event_Leave & /*event*/, int eventPlayerId, const if(sayEdit && autocompleteUserList.removeOne(playerName)) sayEdit->setCompletionList(autocompleteUserList); - messageLog->logLeave(player); + messageLog->logLeave(player, getLeaveReason(event.reason())); playerListWidget->removePlayer(eventPlayerId); players.remove(eventPlayerId); emit playerRemoved(player); diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 631c5578..150f4b37 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -6,6 +6,7 @@ #include #include "tab.h" #include "pb/serverinfo_game.pb.h" +#include "pb/event_leave.pb.h" class AbstractClient; class CardDatabase; @@ -186,6 +187,7 @@ private: void createPlayAreaWidget(bool bReplay=false); void createDeckViewContainerWidget(bool bReplay=false); void createReplayDock(); + QString getLeaveReason(Event_Leave::LeaveReason reason); signals: void gameClosing(TabGame *tab); void playerAdded(Player *player); diff --git a/common/pb/event_leave.proto b/common/pb/event_leave.proto index c4a3740f..6e1ed871 100644 --- a/common/pb/event_leave.proto +++ b/common/pb/event_leave.proto @@ -5,4 +5,11 @@ message Event_Leave { extend GameEvent { optional Event_Leave ext = 1001; } + enum LeaveReason { + OTHER = 1; + USER_KICKED = 2; + USER_LEFT = 3; + USER_DISCONNECTED = 4; + } + optional LeaveReason reason = 1; } diff --git a/common/server_game.cpp b/common/server_game.cpp index 673bb300..87f5fcd3 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -471,7 +471,7 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, Respons createGameJoinedEvent(newPlayer, rc, false); } -void Server_Game::removePlayer(Server_Player *player) +void Server_Game::removePlayer(Server_Player *player, Event_Leave::LeaveReason reason) { room->getServer()->removePersistentPlayer(QString::fromStdString(player->getUserInfo()->name()), room->getId(), gameId, player->getPlayerId()); players.remove(player->getPlayerId()); @@ -479,7 +479,10 @@ void Server_Game::removePlayer(Server_Player *player) GameEventStorage ges; removeArrowsRelatedToPlayer(ges, player); unattachCards(ges, player); - ges.enqueueGameEvent(Event_Leave(), player->getPlayerId()); + + Event_Leave event; + event.set_reason(reason); + ges.enqueueGameEvent(event, player->getPlayerId()); ges.sendToGame(this); bool playerActive = activePlayer == player->getPlayerId(); @@ -585,7 +588,7 @@ bool Server_Game::kickPlayer(int playerId) playerToKick->sendGameEvent(*gec); delete gec; - removePlayer(playerToKick); + removePlayer(playerToKick, Event_Leave::USER_KICKED); return true; } diff --git a/common/server_game.h b/common/server_game.h index cf7eb086..606f2df2 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -29,6 +29,7 @@ #include "server_response_containers.h" #include "pb/response.pb.h" #include "pb/serverinfo_game.pb.h" +#include "pb/event_leave.pb.h" class QTimer; class GameEventContainer; @@ -103,7 +104,7 @@ public: Response::ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions); bool containsUser(const QString &userName) const; void addPlayer(Server_AbstractUserInterface *userInterface, ResponseContainer &rc, bool spectator, bool broadcastUpdate = true); - void removePlayer(Server_Player *player); + void removePlayer(Server_Player *player, Event_Leave::LeaveReason reason); void removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player); void unattachCards(GameEventStorage &ges, Server_Player *player); bool kickPlayer(int playerId); diff --git a/common/server_player.cpp b/common/server_player.cpp index d1413147..506c4aa8 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -616,7 +616,7 @@ Response::ResponseCode Server_Player::setCardAttrHelper(GameEventStorage &ges, c Response::ResponseCode Server_Player::cmdLeaveGame(const Command_LeaveGame & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage & /*ges*/) { - game->removePlayer(this); + game->removePlayer(this, Event_Leave::USER_LEFT); return Response::RespOk; } @@ -1715,7 +1715,7 @@ void Server_Player::setUserInterface(Server_AbstractUserInterface *_userInterfac void Server_Player::disconnectClient() { if (!(userInfo->user_level() & ServerInfo_User::IsRegistered) || spectator) - game->removePlayer(this); + game->removePlayer(this, Event_Leave::USER_DISCONNECTED); else setUserInterface(0); }