From 4895f2b4fd89184e7c594c0f9c5b42212db26e7c Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 29 Jan 2012 13:36:43 +0100 Subject: [PATCH] server code cleanup, changed in-game ping event to not use any bandwidth as long as nothing changes --- cockatrice/src/messagelogwidget.cpp | 1 - cockatrice/src/player.cpp | 7 -- cockatrice/src/player.h | 1 - cockatrice/src/playerlistwidget.cpp | 56 +++++---- cockatrice/src/playerlistwidget.h | 3 +- cockatrice/src/tab_game.cpp | 44 ++++--- cockatrice/src/tab_game.h | 4 + common/pb/CMakeLists.txt | 4 +- .../pb/context_connection_state_changed.proto | 7 ++ common/pb/context_ping_changed.proto | 7 ++ .../pb/event_connection_state_changed.proto | 8 -- common/pb/event_game_state_changed.proto | 1 + common/pb/event_ping.proto | 10 -- common/pb/game_event.proto | 2 - common/pb/game_event_context.proto | 2 + common/pb/serverinfo_playerproperties.proto | 1 + common/server_game.cpp | 52 ++++---- common/server_game.h | 2 +- common/server_player.cpp | 22 +++- common/server_player.h | 9 +- common/server_protocolhandler.cpp | 34 ++---- common/server_protocolhandler.h | 2 + common/server_response_containers.cpp | 114 +++++++++--------- common/server_response_containers.h | 99 +++------------ servatrice/src/server_logger.cpp | 2 +- servatrice/src/server_logger.h | 4 +- servatrice/src/serversocketinterface.cpp | 2 +- 27 files changed, 232 insertions(+), 268 deletions(-) create mode 100644 common/pb/context_connection_state_changed.proto create mode 100644 common/pb/context_ping_changed.proto delete mode 100644 common/pb/event_connection_state_changed.proto delete mode 100644 common/pb/event_ping.proto diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index c174e813..bcb6d853 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -762,7 +762,6 @@ void MessageLogWidget::containerProcessingDone() void MessageLogWidget::connectToPlayer(Player *player) { - connect(player, SIGNAL(logConnectionStateChanged(Player *, bool)), this, SLOT(logConnectionStateChanged(Player *, bool))); connect(player, SIGNAL(logSay(Player *, QString)), this, SLOT(logSay(Player *, QString))); connect(player, SIGNAL(logShuffle(Player *, CardZone *)), this, SLOT(logShuffle(Player *, CardZone *))); connect(player, SIGNAL(logRollDie(Player *, int, int)), this, SLOT(logRollDie(Player *, int, int))); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 795e7b6e..d9ef1657 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -41,7 +41,6 @@ #include "pb/serverinfo_zone.pb.h" #include "pb/context_move_card.pb.h" #include "pb/context_undo_draw.pb.h" -#include "pb/event_connection_state_changed.pb.h" #include "pb/event_game_say.pb.h" #include "pb/event_shuffle.pb.h" #include "pb/event_roll_die.pb.h" @@ -814,11 +813,6 @@ void Player::setCardAttrHelper(const GameEventContext &context, CardItem *card, } } -void Player::eventConnectionStateChanged(const Event_ConnectionStateChanged &event) -{ - emit logConnectionStateChanged(this, event.connected()); -} - void Player::eventGameSay(const Event_GameSay &event) { emit logSay(this, QString::fromStdString(event.message())); @@ -1159,7 +1153,6 @@ void Player::eventRevealCards(const Event_RevealCards &event) void Player::processGameEvent(GameEvent::GameEventType type, const GameEvent &event, const GameEventContext &context) { switch (type) { - case GameEvent::CONNECTION_STATE_CHANGED: eventConnectionStateChanged(event.GetExtension(Event_ConnectionStateChanged::ext)); break; case GameEvent::GAME_SAY: eventGameSay(event.GetExtension(Event_GameSay::ext)); break; case GameEvent::SHUFFLE: eventShuffle(event.GetExtension(Event_Shuffle::ext)); break; case GameEvent::ROLL_DIE: eventRollDie(event.GetExtension(Event_RollDie::ext)); break; diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 36705782..d3c7f6b1 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -77,7 +77,6 @@ class Player : public QObject, public QGraphicsItem { signals: void newCardAdded(AbstractCardItem *card); // Log events - void logConnectionStateChanged(Player *player, bool connectionState); void logSay(Player *player, QString message); void logShuffle(Player *player, CardZone *zone); void logRollDie(Player *player, int sides, int roll); diff --git a/cockatrice/src/playerlistwidget.cpp b/cockatrice/src/playerlistwidget.cpp index ea04668a..d6e9be1d 100644 --- a/cockatrice/src/playerlistwidget.cpp +++ b/cockatrice/src/playerlistwidget.cpp @@ -81,26 +81,40 @@ void PlayerListWidget::addPlayer(const ServerInfo_PlayerProperties &player) sortItems(1, Qt::AscendingOrder); } -void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties &prop) +void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties &prop, int playerId) { - QTreeWidgetItem *player = players.value(prop.player_id(), 0); + if (playerId == -1) + playerId = prop.player_id(); + + QTreeWidgetItem *player = players.value(playerId, 0); if (!player) return; - - player->setIcon(1, prop.spectator() ? spectatorIcon : playerIcon); - player->setData(1, Qt::UserRole, !prop.spectator()); - player->setData(2, Qt::UserRole, prop.conceded()); - player->setData(2, Qt::UserRole + 1, prop.ready_start()); - player->setIcon(2, gameStarted ? (prop.conceded() ? concededIcon : QIcon()) : (prop.ready_start() ? readyIcon : notReadyIcon)); - player->setData(3, Qt::UserRole, prop.user_info().user_level()); - player->setIcon(3, QIcon(UserLevelPixmapGenerator::generatePixmap(12, prop.user_info().user_level()))); - player->setText(4, QString::fromStdString(prop.user_info().name())); - const QString country = QString::fromStdString(prop.user_info().country()); - if (!country.isEmpty()) - player->setIcon(4, QIcon(CountryPixmapGenerator::generatePixmap(12, country))); - player->setData(4, Qt::UserRole, QString::fromStdString(prop.user_info().name())); - player->setData(4, Qt::UserRole + 1, prop.player_id()); - player->setText(5, QString::fromStdString(prop.deck_hash())); + + if (prop.has_spectator()) { + player->setIcon(1, prop.spectator() ? spectatorIcon : playerIcon); + player->setData(1, Qt::UserRole, !prop.spectator()); + } + if (prop.has_conceded()) + player->setData(2, Qt::UserRole, prop.conceded()); + if (prop.has_ready_start()) + player->setData(2, Qt::UserRole + 1, prop.ready_start()); + if (prop.has_conceded() && prop.has_ready_start()) + player->setIcon(2, gameStarted ? (prop.conceded() ? concededIcon : QIcon()) : (prop.ready_start() ? readyIcon : notReadyIcon)); + if (prop.has_user_info()) { + player->setData(3, Qt::UserRole, prop.user_info().user_level()); + player->setIcon(3, QIcon(UserLevelPixmapGenerator::generatePixmap(12, prop.user_info().user_level()))); + player->setText(4, QString::fromStdString(prop.user_info().name())); + const QString country = QString::fromStdString(prop.user_info().country()); + if (!country.isEmpty()) + player->setIcon(4, QIcon(CountryPixmapGenerator::generatePixmap(12, country))); + player->setData(4, Qt::UserRole, QString::fromStdString(prop.user_info().name())); + } + if (prop.has_player_id()) + player->setData(4, Qt::UserRole + 1, prop.player_id()); + if (prop.has_deck_hash()) + player->setText(5, QString::fromStdString(prop.deck_hash())); + if (prop.has_ping_seconds()) + player->setIcon(0, QIcon(PingPixmapGenerator::generatePixmap(12, prop.ping_seconds(), 10))); } void PlayerListWidget::removePlayer(int playerId) @@ -123,14 +137,6 @@ void PlayerListWidget::setActivePlayer(int playerId) } } -void PlayerListWidget::updatePing(int playerId, int pingTime) -{ - QTreeWidgetItem *twi = players.value(playerId, 0); - if (!twi) - return; - twi->setIcon(0, QIcon(PingPixmapGenerator::generatePixmap(12, pingTime, 10))); -} - void PlayerListWidget::setGameStarted(bool _gameStarted, bool resuming) { gameStarted = _gameStarted; diff --git a/cockatrice/src/playerlistwidget.h b/cockatrice/src/playerlistwidget.h index dc25404b..585e41dd 100644 --- a/cockatrice/src/playerlistwidget.h +++ b/cockatrice/src/playerlistwidget.h @@ -41,8 +41,7 @@ public: void addPlayer(const ServerInfo_PlayerProperties &player); void removePlayer(int playerId); void setActivePlayer(int playerId); - void updatePing(int playerId, int pingTime); - void updatePlayerProperties(const ServerInfo_PlayerProperties &prop); + void updatePlayerProperties(const ServerInfo_PlayerProperties &prop, int playerId = -1); void setGameStarted(bool _gameStarted, bool resuming); void showContextMenu(const QPoint &pos, const QModelIndex &index); }; diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index d5a9ed13..9e2a7c2a 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "tab_game.h" #include "tab_supervisor.h" #include "cardinfowidget.h" @@ -50,8 +51,9 @@ #include "pb/event_game_closed.pb.h" #include "pb/event_set_active_player.pb.h" #include "pb/event_set_active_phase.pb.h" -#include "pb/event_ping.pb.h" #include "pb/context_deck_select.pb.h" +#include "pb/context_connection_state_changed.pb.h" +#include "pb/context_ping_changed.pb.h" #include "get_pb_extension.h" ReadyStartButton::ReadyStartButton(QWidget *parent) @@ -208,6 +210,11 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client resuming(event.resuming()), currentPhase(-1) { + gameTimer = new QTimer(this); + gameTimer->setInterval(1000); + connect(gameTimer, SIGNAL(timeout()), this, SLOT(incrementGameTime())); + gameTimer->start(); + phasesToolbar = new PhasesToolbar; phasesToolbar->hide(); connect(phasesToolbar, SIGNAL(sendGameCommand(const ::google::protobuf::Message &, int)), this, SLOT(sendGameCommand(const ::google::protobuf::Message &, int))); @@ -361,6 +368,17 @@ void TabGame::closeRequest() actLeaveGame(); } +void TabGame::incrementGameTime() +{ + int seconds = ++secondsElapsed; + int minutes = seconds / 60; + seconds -= minutes * 60; + int hours = minutes / 60; + minutes -= hours * 60; + + timeElapsedLabel->setText(QString::number(hours).rightJustified(2, '0') + ":" + QString::number(minutes).rightJustified(2, '0') + ":" + QString::number(seconds).rightJustified(2, '0')); +} + void TabGame::adminLockChanged(bool lock) { bool v = !(spectator && !spectatorsCanTalk && lock); @@ -496,7 +514,6 @@ void TabGame::processGameEventContainer(const GameEventContainer &cont, Abstract case GameEvent::GAME_CLOSED: eventGameClosed(event.GetExtension(Event_GameClosed::ext), playerId, context); break; case GameEvent::SET_ACTIVE_PLAYER: eventSetActivePlayer(event.GetExtension(Event_SetActivePlayer::ext), playerId, context); break; case GameEvent::SET_ACTIVE_PHASE: eventSetActivePhase(event.GetExtension(Event_SetActivePhase::ext), playerId, context); break; - case GameEvent::PING: eventPing(event.GetExtension(Event_Ping::ext), playerId, context); break; default: { Player *player = players.value(playerId, 0); @@ -650,6 +667,9 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event, int /*e player->processCardAttachment(playerInfo); } } + + secondsElapsed = event.seconds_elapsed(); + if (event.game_started() && !started) { startGame(!gameStateKnown); if (gameStateKnown) @@ -669,7 +689,7 @@ void TabGame::eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged & Player *player = players.value(eventPlayerId, 0); if (!player) return; - playerListWidget->updatePlayerProperties(event.player_properties()); + playerListWidget->updatePlayerProperties(event.player_properties(), eventPlayerId); const GameEventContext::ContextType contextType = static_cast(getPbExtension(context)); switch (contextType) { @@ -697,6 +717,10 @@ void TabGame::eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged & messageLog->logDeckSelect(player, QString::fromStdString(context.GetExtension(Context_DeckSelect::ext).deck_hash())); break; } + case GameEventContext::CONNECTION_STATE_CHANGED: { + messageLog->logConnectionStateChanged(player, event.player_properties().ping_seconds() != -1); + break; + } default: ; } } @@ -809,20 +833,6 @@ void TabGame::eventSetActivePhase(const Event_SetActivePhase &event, int /*event emit userEvent(); } -void TabGame::eventPing(const Event_Ping &event, int /*eventPlayerId*/, const GameEventContext & /*context*/) -{ - const int pingListSize = event.ping_list_size(); - for (int i = 0; i < pingListSize; ++i) - playerListWidget->updatePing(event.ping_list(i).player_id(), event.ping_list(i).ping_time()); - - int seconds = event.seconds_elapsed(); - int minutes = seconds / 60; - seconds -= minutes * 60; - int hours = minutes / 60; - minutes -= hours * 60; - timeElapsedLabel->setText(QString::number(hours).rightJustified(2, '0') + ":" + QString::number(minutes).rightJustified(2, '0') + ":" + QString::number(seconds).rightJustified(2, '0')); -} - void TabGame::newCardAdded(AbstractCardItem *card) { connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfo, SLOT(setCard(AbstractCardItem *))); diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 43d7e19f..0efc922e 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -13,6 +13,7 @@ class DeckView; class GameScene; class CardInfoWidget; class MessageLogWidget; +class QTimer; class QSplitter; class QLabel; class QLineEdit; @@ -89,6 +90,8 @@ public: class TabGame : public Tab { Q_OBJECT private: + QTimer *gameTimer; + int secondsElapsed; QList clients; int gameId; QString gameDescription; @@ -152,6 +155,7 @@ signals: void containerProcessingDone(); void openMessageDialog(const QString &userName, bool focus); private slots: + void incrementGameTime(); void adminLockChanged(bool lock); void newCardAdded(AbstractCardItem *card); diff --git a/common/pb/CMakeLists.txt b/common/pb/CMakeLists.txt index 4ff832c8..f490f6db 100644 --- a/common/pb/CMakeLists.txt +++ b/common/pb/CMakeLists.txt @@ -41,15 +41,16 @@ SET(PROTO_FILES command_stop_dump_zone.proto command_undo_draw.proto context_concede.proto + context_connection_state_changed.proto context_deck_select.proto context_move_card.proto context_mulligan.proto + context_ping_changed.proto context_ready_start.proto context_undo_draw.proto event_add_to_list.proto event_attach_card.proto event_connection_closed.proto - event_connection_state_changed.proto event_create_arrow.proto event_create_counter.proto event_create_token.proto @@ -72,7 +73,6 @@ SET(PROTO_FILES event_list_games.proto event_list_rooms.proto event_move_card.proto - event_ping.proto event_player_properties_changed.proto event_remove_from_list.proto event_reveal_cards.proto diff --git a/common/pb/context_connection_state_changed.proto b/common/pb/context_connection_state_changed.proto new file mode 100644 index 00000000..d1f592ee --- /dev/null +++ b/common/pb/context_connection_state_changed.proto @@ -0,0 +1,7 @@ +import "game_event_context.proto"; + +message Context_ConnectionStateChanged { + extend GameEventContext { + optional Context_ConnectionStateChanged ext = 1007; + } +} diff --git a/common/pb/context_ping_changed.proto b/common/pb/context_ping_changed.proto new file mode 100644 index 00000000..8ea43c5f --- /dev/null +++ b/common/pb/context_ping_changed.proto @@ -0,0 +1,7 @@ +import "game_event_context.proto"; + +message Context_PingChanged { + extend GameEventContext { + optional Context_PingChanged ext = 1006; + } +} diff --git a/common/pb/event_connection_state_changed.proto b/common/pb/event_connection_state_changed.proto deleted file mode 100644 index 6e830d83..00000000 --- a/common/pb/event_connection_state_changed.proto +++ /dev/null @@ -1,8 +0,0 @@ -import "game_event.proto"; - -message Event_ConnectionStateChanged { - extend GameEvent { - optional Event_ConnectionStateChanged ext = 1006; - } - optional bool connected = 1; -} diff --git a/common/pb/event_game_state_changed.proto b/common/pb/event_game_state_changed.proto index 0bc957ad..a4055c02 100644 --- a/common/pb/event_game_state_changed.proto +++ b/common/pb/event_game_state_changed.proto @@ -9,4 +9,5 @@ message Event_GameStateChanged { optional bool game_started = 2; optional sint32 active_player_id = 3; optional sint32 active_phase = 4; + optional uint32 seconds_elapsed = 5; } diff --git a/common/pb/event_ping.proto b/common/pb/event_ping.proto deleted file mode 100644 index b787ffa4..00000000 --- a/common/pb/event_ping.proto +++ /dev/null @@ -1,10 +0,0 @@ -import "game_event.proto"; -import "serverinfo_playerping.proto"; - -message Event_Ping { - extend GameEvent { - optional Event_Ping ext = 1008; - } - optional uint32 seconds_elapsed = 1; - repeated ServerInfo_PlayerPing ping_list = 2; -} diff --git a/common/pb/game_event.proto b/common/pb/game_event.proto index 6d33f436..4c7e3e15 100644 --- a/common/pb/game_event.proto +++ b/common/pb/game_event.proto @@ -6,9 +6,7 @@ message GameEvent { GAME_HOST_CHANGED = 1003; KICKED = 1004; GAME_STATE_CHANGED = 1005; - CONNECTION_STATE_CHANGED = 1006; PLAYER_PROPERTIES_CHANGED = 1007; - PING = 1008; GAME_SAY = 1009; CREATE_ARROW = 2000; DELETE_ARROW = 2001; diff --git a/common/pb/game_event_context.proto b/common/pb/game_event_context.proto index f1787484..8dc9de68 100644 --- a/common/pb/game_event_context.proto +++ b/common/pb/game_event_context.proto @@ -6,6 +6,8 @@ message GameEventContext { UNDO_DRAW = 1003; MOVE_CARD = 1004; MULLIGAN = 1005; + PING_CHANGED = 1006; + CONNECTION_STATE_CHANGED = 1007; } extensions 100 to max; } diff --git a/common/pb/serverinfo_playerproperties.proto b/common/pb/serverinfo_playerproperties.proto index 05dff105..0e3dc135 100644 --- a/common/pb/serverinfo_playerproperties.proto +++ b/common/pb/serverinfo_playerproperties.proto @@ -7,4 +7,5 @@ message ServerInfo_PlayerProperties { optional bool conceded = 4; optional bool ready_start = 5; optional string deck_hash = 6; + optional sint32 ping_seconds = 7; } diff --git a/common/server_game.cpp b/common/server_game.cpp index a236df78..f751043d 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -26,12 +26,13 @@ #include "server_cardzone.h" #include "server_counter.h" #include "decklist.h" +#include "pb/context_connection_state_changed.pb.h" +#include "pb/context_ping_changed.pb.h" +#include "pb/event_player_properties_changed.pb.h" #include "pb/event_game_closed.pb.h" #include "pb/event_game_host_changed.pb.h" #include "pb/event_game_state_changed.pb.h" -#include "pb/event_connection_state_changed.pb.h" #include "pb/event_kicked.pb.h" -#include "pb/event_ping.pb.h" #include "pb/event_join.pb.h" #include "pb/event_leave.pb.h" #include "pb/event_delete_arrow.pb.h" @@ -77,9 +78,10 @@ Server_Game::~Server_Game() void Server_Game::pingClockTimeout() { QMutexLocker locker(&gameMutex); + ++secondsElapsed; - Event_Ping event; - event.set_seconds_elapsed(++secondsElapsed); + GameEventStorage ges; + ges.setGameEventContext(Context_PingChanged()); QList pingList; QMapIterator playerIterator(players); @@ -89,19 +91,28 @@ void Server_Game::pingClockTimeout() Server_Player *player = playerIterator.next().value(); if (!player->getSpectator()) ++playerCount; - int pingTime; - if (player->getProtocolHandler()) { - pingTime = player->getProtocolHandler()->getLastCommandTime(); - if (!player->getSpectator()) - allPlayersInactive = false; - } else - pingTime = -1; - ServerInfo_PlayerPing *pingInfo = event.add_ping_list(); - pingInfo->set_player_id(player->getPlayerId()); - pingInfo->set_ping_time(pingTime); + const int oldPingTime = player->getPingTime(); + player->playerMutex.lock(); + int newPingTime; + if (player->getProtocolHandler()) + newPingTime = player->getProtocolHandler()->getLastCommandTime(); + else + newPingTime = -1; + player->playerMutex.unlock(); + + if ((newPingTime != -1) && !player->getSpectator()) + allPlayersInactive = false; + + if ((abs(oldPingTime - newPingTime) > 1) || ((newPingTime == -1) && (oldPingTime != -1)) || ((newPingTime != -1) && (oldPingTime == -1))) { + player->setPingTime(newPingTime); + + Event_PlayerPropertiesChanged event; + event.mutable_player_properties()->set_ping_seconds(newPingTime); + ges.enqueueGameEvent(event, player->getPlayerId()); + } } - sendGameEventContainer(prepareGameEvent(event, -1)); + ges.sendToGame(this); const int maxTime = room->getServer()->getMaxGameInactivityTime(); if (allPlayersInactive) { @@ -165,6 +176,7 @@ void Server_Game::doStartGameIfReady() while (playerIterator.hasNext()) { Server_Player *player = playerIterator.next().value(); Event_GameStateChanged event; + event.set_seconds_elapsed(secondsElapsed); event.set_game_started(true); event.set_active_player_id(0); event.set_active_phase(0); @@ -229,6 +241,7 @@ void Server_Game::stopGameIfFinished() while (playerIterator.hasNext()) { Server_Player *player = playerIterator.next().value(); Event_GameStateChanged event; + event.set_seconds_elapsed(secondsElapsed); event.set_game_started(false); QListIterator gameStateIterator(getGameState(player)); while (gameStateIterator.hasNext()) @@ -438,15 +451,6 @@ void Server_Game::nextTurn() setActivePlayer(keys[listPos]); } -void Server_Game::postConnectionStatusUpdate(Server_Player *player, bool connectionStatus) -{ - QMutexLocker locker(&gameMutex); - - Event_ConnectionStateChanged event; - event.set_connected(connectionStatus); - sendGameEventContainer(prepareGameEvent(event, player->getPlayerId())); -} - QList Server_Game::getGameState(Server_Player *playerWhosAsking) const { QMutexLocker locker(&gameMutex); diff --git a/common/server_game.h b/common/server_game.h index ebe3ad8d..72c442e7 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -95,7 +95,7 @@ public: void setActivePlayer(int _activePlayer); void setActivePhase(int _activePhase); void nextTurn(); - void postConnectionStatusUpdate(Server_Player *player, bool connectionStatus); + int getSecondsElapsed() const { return secondsElapsed; } QList getGameState(Server_Player *playerWhosAsking) const; diff --git a/common/server_player.cpp b/common/server_player.cpp index a745f4f6..4c87e339 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -14,13 +14,15 @@ #include "pb/event_draw_cards.pb.h" #include "pb/event_destroy_card.pb.h" #include "pb/event_move_card.pb.h" +#include "pb/event_player_properties_changed.pb.h" #include "pb/event_set_card_attr.pb.h" +#include "pb/context_connection_state_changed.pb.h" #include "pb/context_move_card.pb.h" #include "pb/context_undo_draw.pb.h" #include Server_Player::Server_Player(Server_Game *_game, int _playerId, const ServerInfo_User &_userInfo, bool _spectator, Server_ProtocolHandler *_handler) - : game(_game), handler(_handler), userInfo(new ServerInfo_User(_userInfo)), deck(0), playerId(_playerId), spectator(_spectator), nextCardId(0), readyStart(false), conceded(false) + : game(_game), handler(_handler), userInfo(new ServerInfo_User(_userInfo)), deck(0), pingTime(0), playerId(_playerId), spectator(_spectator), nextCardId(0), readyStart(false), conceded(false) { } @@ -201,6 +203,7 @@ ServerInfo_PlayerProperties Server_Player::getProperties() result.set_ready_start(readyStart); if (deck) result.set_deck_hash(deck->getDeckHash().toStdString()); + result.set_ping_seconds(pingTime); return result; } @@ -585,3 +588,20 @@ void Server_Player::sendGameEvent(GameEventContainer *cont) if (handler) handler->sendProtocolItem(*cont); } + +void Server_Player::setProtocolHandler(Server_ProtocolHandler *_handler) +{ + playerMutex.lock(); + handler = _handler; + playerMutex.unlock(); + + pingTime = _handler ? 0 : -1; + + Event_PlayerPropertiesChanged event; + event.mutable_player_properties()->set_ping_seconds(pingTime); + + GameEventStorage ges; + ges.setGameEventContext(Context_ConnectionStateChanged()); + ges.enqueueGameEvent(event, playerId); + ges.sendToGame(game); +} diff --git a/common/server_player.h b/common/server_player.h index 4425e8cc..ca9ed40d 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -27,7 +27,6 @@ class GameEventStorage; class Server_Player : public Server_ArrowTarget { Q_OBJECT private: - mutable QMutex playerMutex; class MoveCardCompareFunctor; Server_Game *game; Server_ProtocolHandler *handler; @@ -37,6 +36,7 @@ private: QMap counters; QMap arrows; QList lastDrawList; + int pingTime; int playerId; bool spectator; int initialCards; @@ -44,11 +44,12 @@ private: bool readyStart; bool conceded; public: + mutable QMutex playerMutex; Server_Player(Server_Game *_game, int _playerId, const ServerInfo_User &_userInfo, bool _spectator, Server_ProtocolHandler *_handler); ~Server_Player(); void prepareDestroy(); Server_ProtocolHandler *getProtocolHandler() const { return handler; } - void setProtocolHandler(Server_ProtocolHandler *_handler) { playerMutex.lock(); handler = _handler; playerMutex.unlock(); } + void setProtocolHandler(Server_ProtocolHandler *_handler); void setPlayerId(int _id) { playerId = _id; } int getInitialCards() const { return initialCards; } @@ -66,7 +67,9 @@ public: const QMap &getZones() const { return zones; } const QMap &getCounters() const { return counters; } const QMap &getArrows() const { return arrows; } - + + int getPingTime() const { return pingTime; } + void setPingTime(int _pingTime) { pingTime = _pingTime; } ServerInfo_PlayerProperties getProperties(); int newCardId(); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 87f38c4f..0c0375be 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -114,12 +114,12 @@ void Server_ProtocolHandler::prepareDestroy() Server_Game *g = gameIterator.value().first; Server_Player *p = gameIterator.value().second; + g->gameMutex.lock(); if ((authState == UnknownUser) || p->getSpectator()) g->removePlayer(p); - else { + else p->setProtocolHandler(0); - g->postConnectionStatusUpdate(p, false); - } + g->gameMutex.unlock(); } gameListMutex.unlock(); @@ -220,6 +220,8 @@ Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(co num = fieldList[j]->number(); break; } + if (num != SessionCommand::PING) + emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((SessionCommand::SessionCommandType) num) { case SessionCommand::PING: resp = cmdPing(sc.GetExtension(Command_Ping::ext), rc); break; case SessionCommand::LOGIN: resp = cmdLogin(sc.GetExtension(Command_Login::ext), rc); break; @@ -267,6 +269,7 @@ Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const num = fieldList[j]->number(); break; } + emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((RoomCommand::RoomCommandType) num) { case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc); break; case RoomCommand::ROOM_SAY: resp = cmdRoomSay(sc.GetExtension(Command_RoomSay::ext), room, rc); break; @@ -309,6 +312,7 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const num = fieldList[j]->number(); break; } + emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((GameCommand::GameCommandType) num) { case GameCommand::KICK_FROM_GAME: resp = cmdKickFromGame(sc.GetExtension(Command_KickFromGame::ext), game, player, rc, ges); break; case GameCommand::LEAVE_GAME: resp = cmdLeaveGame(sc.GetExtension(Command_LeaveGame::ext), game, player, rc, ges); break; @@ -344,23 +348,7 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const if ((resp != Response::RespOk) && (resp != Response::RespNothing)) finalResponseCode = resp; } - GameEventContainer *contPrivate = new GameEventContainer; - GameEventContainer *contOthers = new GameEventContainer; - const QList &gameEventList = ges.getGameEventList(); - for (int i = 0; i < gameEventList.size(); ++i) { - const GameEvent &event = gameEventList[i]->getGameEvent(); - const GameEventStorageItem::EventRecipients recipients = gameEventList[i]->getRecipients(); - if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) - contPrivate->add_event_list()->CopyFrom(event); - if (recipients.testFlag(GameEventStorageItem::SendToOthers)) - contOthers->add_event_list()->CopyFrom(event); - } - if (ges.getGameEventContext()) { - contPrivate->mutable_context()->CopyFrom(*ges.getGameEventContext()); - contOthers->mutable_context()->CopyFrom(*ges.getGameEventContext()); - } - game->sendGameEventContainer(contPrivate, GameEventStorageItem::SendToPrivate, ges.getPrivatePlayerId()); - game->sendGameEventContainer(contOthers, GameEventStorageItem::SendToOthers, ges.getPrivatePlayerId()); + ges.sendToGame(game); return finalResponseCode; } @@ -383,6 +371,7 @@ Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer( num = fieldList[j]->number(); break; } + emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((ModeratorCommand::ModeratorCommandType) num) { case ModeratorCommand::BAN_FROM_SERVER: resp = cmdBanFromServer(sc.GetExtension(Command_BanFromServer::ext), rc); break; } @@ -411,6 +400,7 @@ Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(cons num = fieldList[j]->number(); break; } + emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((AdminCommand::AdminCommandType) num) { case AdminCommand::SHUTDOWN_SERVER: resp = cmdShutdownServer(sc.GetExtension(Command_ShutdownServer::ext), rc); break; case AdminCommand::UPDATE_SERVER_MESSAGE: resp = cmdUpdateServerMessage(sc.GetExtension(Command_UpdateServerMessage::ext), rc); break; @@ -539,7 +529,6 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd for (int j = 0; j < gamePlayers.size(); ++j) if (gamePlayers[j]->getUserInfo()->name() == userInfo->name()) { gamePlayers[j]->setProtocolHandler(this); - game->postConnectionStatusUpdate(gamePlayers[j], true); games.insert(game->getGameId(), QPair(game, gamePlayers[j])); Event_GameJoined event1; @@ -557,6 +546,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd QListIterator gameStateIterator(game->getGameState(gamePlayers[j])); while (gameStateIterator.hasNext()) event2.add_player_list()->CopyFrom(gameStateIterator.next()); + event2.set_seconds_elapsed(game->getSecondsElapsed()); event2.set_game_started(game->getGameStarted()); event2.set_active_player_id(game->getActivePlayer()); event2.set_active_phase(game->getActivePhase()); @@ -773,6 +763,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_Creat QListIterator gameStateIterator(game->getGameState(creator)); while (gameStateIterator.hasNext()) event2.add_player_list()->CopyFrom(gameStateIterator.next()); + event2.set_seconds_elapsed(0); event2.set_game_started(game->getGameStarted()); event2.set_active_player_id(game->getActivePlayer()); event2.set_active_phase(game->getActivePhase()); @@ -819,6 +810,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdJoinGame(const Command_JoinGam QListIterator gameStateIterator(g->getGameState(player)); while (gameStateIterator.hasNext()) event2.add_player_list()->CopyFrom(gameStateIterator.next()); + event2.set_seconds_elapsed(g->getSecondsElapsed()); event2.set_game_started(g->getGameStarted()); event2.set_active_player_id(g->getActivePlayer()); event2.set_active_phase(g->getActivePhase()); diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 8e11992b..f11a5187 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -169,6 +169,8 @@ private: Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc); private slots: void pingClockTimeout(); +signals: + void logDebugMessage(const QString &message, Server_ProtocolHandler *session); public: QMutex gameListMutex; diff --git a/common/server_response_containers.cpp b/common/server_response_containers.cpp index e68e2839..11778cff 100644 --- a/common/server_response_containers.cpp +++ b/common/server_response_containers.cpp @@ -1,74 +1,78 @@ -/* -Response_DeckDownload::Response_DeckDownload(int _cmdId, ResponseCode _responseCode, DeckList *_deck) - : ProtocolResponse(_cmdId, _responseCode, "deck_download") +#include "server_response_containers.h" +#include +#include "server_game.h" + +GameEventStorageItem::GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients) + : event(new GameEvent), recipients(_recipients) { - if (!_deck) - _deck = new DeckList; - insertItem(_deck); + event->GetReflection()->MutableMessage(event, _event.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_event); + event->set_player_id(_playerId); } -DeckList *Response_DeckDownload::getDeck() const +GameEventStorageItem::~GameEventStorageItem() { - return static_cast(itemMap.value("cockatrice_deck")); + delete event; } -Response_DeckUpload::Response_DeckUpload(int _cmdId, ResponseCode _responseCode, DeckList_File *_file) - : ProtocolResponse(_cmdId, _responseCode, "deck_upload") +GameEventStorage::GameEventStorage() + : gameEventContext(0) { - if (!_file) - _file = new DeckList_File; - insertItem(_file); } -*/ -/* -GameEventContainer::GameEventContainer(const QList &_eventList, int _gameId, GameEventContext *_context) - : ProtocolItem("container", "game_event") + +GameEventStorage::~GameEventStorage() { - insertItem(new SerializableItem_Int("game_id", _gameId)); + delete gameEventContext; + for (int i = 0; i < gameEventList.size(); ++i) + delete gameEventList[i]; +} + +void GameEventStorage::setGameEventContext(const ::google::protobuf::Message &_gameEventContext) +{ + delete gameEventContext; + gameEventContext = new GameEventContext; + gameEventContext->GetReflection()->MutableMessage(gameEventContext, _gameEventContext.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_gameEventContext); +} + +void GameEventStorage::enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients, int _privatePlayerId) +{ + gameEventList.append(new GameEventStorageItem(event, playerId, recipients)); + if (_privatePlayerId != -1) + privatePlayerId = _privatePlayerId; +} + +void GameEventStorage::sendToGame(Server_Game *game) +{ + if (gameEventList.isEmpty()) + return; - context = _context; - if (_context) - itemList.append(_context); - - eventList = _eventList; - for (int i = 0; i < _eventList.size(); ++i) - itemList.append(_eventList[i]); -} - -void GameEventContainer::extractData() -{ - for (int i = 0; i < itemList.size(); ++i) { - GameEvent *_event = dynamic_cast(itemList[i]); - GameEventContext *_context = dynamic_cast(itemList[i]); - if (_event) - eventList.append(_event); - else if (_context) - context = _context; + GameEventContainer *contPrivate = new GameEventContainer; + GameEventContainer *contOthers = new GameEventContainer; + for (int i = 0; i < gameEventList.size(); ++i) { + const GameEvent &event = gameEventList[i]->getGameEvent(); + const GameEventStorageItem::EventRecipients recipients = gameEventList[i]->getRecipients(); + if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) + contPrivate->add_event_list()->CopyFrom(event); + if (recipients.testFlag(GameEventStorageItem::SendToOthers)) + contOthers->add_event_list()->CopyFrom(event); } -} - -void GameEventContainer::setContext(GameEventContext *_context) -{ - for (int i = 0; i < itemList.size(); ++i) { - GameEventContext *temp = qobject_cast(itemList[i]); - if (temp) { - delete temp; - itemList.removeAt(i); - break; - } + if (gameEventContext) { + contPrivate->mutable_context()->CopyFrom(*gameEventContext); + contOthers->mutable_context()->CopyFrom(*gameEventContext); } - itemList.append(_context); - context = _context; + game->sendGameEventContainer(contPrivate, GameEventStorageItem::SendToPrivate, privatePlayerId); + game->sendGameEventContainer(contOthers, GameEventStorageItem::SendToOthers, privatePlayerId); } -void GameEventContainer::addGameEvent(GameEvent *event) +ResponseContainer::ResponseContainer() + : responseExtension(0) { - appendItem(event); - eventList.append(event); } -GameEventContainer *GameEventContainer::makeNew(GameEvent *event, int _gameId) +ResponseContainer::~ResponseContainer() { - return new GameEventContainer(QList() << event, _gameId); + delete responseExtension; + for (int i = 0; i < preResponseQueue.size(); ++i) + delete preResponseQueue[i].second; + for (int i = 0; i < postResponseQueue.size(); ++i) + delete postResponseQueue[i].second; } -*/ diff --git a/common/server_response_containers.h b/common/server_response_containers.h index 96513b8e..13fab1dc 100644 --- a/common/server_response_containers.h +++ b/common/server_response_containers.h @@ -1,21 +1,11 @@ -#ifndef PROTOCOL_H -#define PROTOCOL_H +#ifndef SERVER_RESPONSE_CONTAINERS_H +#define SERVER_RESPONSE_CONTAINERS_H -#include -#include -#include -#include -#include #include - -#include -#include #include "pb/server_message.pb.h" -class DeckList; -class GameEvent; -class GameEventContainer; -class GameEventContext; +namespace google { namespace protobuf { class Message; } } +class Server_Game; class GameEventStorageItem { public: @@ -25,16 +15,9 @@ private: GameEvent *event; EventRecipients recipients; public: - GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients) - : event(new GameEvent), recipients(_recipients) - { - event->GetReflection()->MutableMessage(event, _event.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_event); - event->set_player_id(_playerId); - } - ~GameEventStorageItem() - { - delete event; - } + GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients); + ~GameEventStorageItem(); + const GameEvent &getGameEvent() const { return *event; } EventRecipients getRecipients() const { return recipients; } }; @@ -46,32 +29,16 @@ private: QList gameEventList; int privatePlayerId; public: - GameEventStorage() - : gameEventContext(0) - { - } - ~GameEventStorage() - { - delete gameEventContext; - for (int i = 0; i < gameEventList.size(); ++i) - delete gameEventList[i]; - } + GameEventStorage(); + ~GameEventStorage(); - void setGameEventContext(const ::google::protobuf::Message &_gameEventContext) { - delete gameEventContext; - gameEventContext = new GameEventContext; - gameEventContext->GetReflection()->MutableMessage(gameEventContext, _gameEventContext.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_gameEventContext); - } + void setGameEventContext(const ::google::protobuf::Message &_gameEventContext); ::google::protobuf::Message *getGameEventContext() const { return gameEventContext; } const QList &getGameEventList() const { return gameEventList; } int getPrivatePlayerId() const { return privatePlayerId; } - void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int _privatePlayerId = -1) - { - gameEventList.append(new GameEventStorageItem(event, playerId, recipients)); - if (_privatePlayerId != -1) - privatePlayerId = _privatePlayerId; - } + void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int _privatePlayerId = -1); + void sendToGame(Server_Game *game); }; class ResponseContainer { @@ -79,15 +46,9 @@ private: ::google::protobuf::Message *responseExtension; QList > preResponseQueue, postResponseQueue; public: - ResponseContainer() : responseExtension(0) { } - ~ResponseContainer() - { - delete responseExtension; - for (int i = 0; i < preResponseQueue.size(); ++i) - delete preResponseQueue[i].second; - for (int i = 0; i < postResponseQueue.size(); ++i) - delete postResponseQueue[i].second; - } + ResponseContainer(); + ~ResponseContainer(); + void setResponseExtension(::google::protobuf::Message *_responseExtension) { responseExtension = _responseExtension; } ::google::protobuf::Message *getResponseExtension() const { return responseExtension; } void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); } @@ -96,34 +57,4 @@ public: const QList > &getPostResponseQueue() const { return postResponseQueue; } }; -/* - * XXX - * -class Response_DeckList : public ProtocolResponse { - Q_OBJECT -public: - Response_DeckList(int _cmdId = -1, ResponseCode _responseCode = RespOk, DeckList_Directory *_root = 0); - int getItemId() const { return ItemId_Response_DeckList; } - static SerializableItem *newItem() { return new Response_DeckList; } - DeckList_Directory *getRoot() const { return static_cast(itemMap.value("directory")); } -}; - -class Response_DeckDownload : public ProtocolResponse { - Q_OBJECT -public: - Response_DeckDownload(int _cmdId = -1, ResponseCode _responseCode = RespOk, DeckList *_deck = 0); - int getItemId() const { return ItemId_Response_DeckDownload; } - static SerializableItem *newItem() { return new Response_DeckDownload; } - DeckList *getDeck() const; -}; - -class Response_DeckUpload : public ProtocolResponse { - Q_OBJECT -public: - Response_DeckUpload(int _cmdId = -1, ResponseCode _responseCode = RespOk, DeckList_File *_file = 0); - int getItemId() const { return ItemId_Response_DeckUpload; } - static SerializableItem *newItem() { return new Response_DeckUpload; } - DeckList_File *getFile() const { return static_cast(itemMap.value("file")); } -}; -*/ #endif diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index d3e49a15..ff75d062 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -31,7 +31,7 @@ ServerLogger::~ServerLogger() flushBuffer(); } -void ServerLogger::logMessage(QString message, ServerSocketInterface *ssi) +void ServerLogger::logMessage(QString message, Server_ProtocolHandler *ssi) { if (!logFile) return; diff --git a/servatrice/src/server_logger.h b/servatrice/src/server_logger.h index 95bbba8d..f14c2980 100644 --- a/servatrice/src/server_logger.h +++ b/servatrice/src/server_logger.h @@ -9,7 +9,7 @@ class QSocketNotifier; class QFile; -class ServerSocketInterface; +class Server_ProtocolHandler; class ServerLogger : public QObject { Q_OBJECT @@ -18,7 +18,7 @@ public: ~ServerLogger(); static void hupSignalHandler(int unused); public slots: - void logMessage(QString message, ServerSocketInterface *ssi = 0); + void logMessage(QString message, Server_ProtocolHandler *ssi = 0); private slots: void handleSigHup(); void flushBuffer(); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 67e6fddc..ece22778 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -57,6 +57,7 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); connect(this, SIGNAL(outputBufferChanged()), this, SLOT(flushOutputBuffer()), Qt::QueuedConnection); + connect(this, SIGNAL(logDebugMessage(const QString &, Server_ProtocolHandler *)), logger, SLOT(logMessage(QString, Server_ProtocolHandler *))); Event_ServerIdentification identEvent; identEvent.set_server_name(servatrice->getServerName().toStdString()); @@ -125,7 +126,6 @@ void ServerSocketInterface::readClient() CommandContainer newCommandContainer; newCommandContainer.ParseFromArray(inputBuffer.data(), messageLength); - logger->logMessage(QString::fromStdString(newCommandContainer.ShortDebugString()), this); inputBuffer.remove(0, messageLength); messageInProgress = false;