From a876a0bf5f7aae08dc001046f79265b7c31f1932 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 3 Mar 2012 18:10:16 +0100 Subject: [PATCH] tell logged in clients about new replays --- cockatrice/src/abstractclient.cpp | 2 + cockatrice/src/abstractclient.h | 2 + .../src/remotereplaylist_treewidget.cpp | 16 ++++++- cockatrice/src/remotereplaylist_treewidget.h | 4 +- cockatrice/src/tab_replays.cpp | 8 ++++ cockatrice/src/tab_replays.h | 5 ++- common/pb/CMakeLists.txt | 1 + common/pb/event_replay_added.proto | 9 ++++ common/pb/game_replay.proto | 7 +-- common/pb/session_event.proto | 1 + common/server.cpp | 2 +- common/server.h | 3 +- common/server_game.cpp | 2 + servatrice/src/servatrice.cpp | 44 +++++++++++++++++-- 14 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 common/pb/event_replay_added.proto diff --git a/cockatrice/src/abstractclient.cpp b/cockatrice/src/abstractclient.cpp index ce3cdfe8..8d27be49 100644 --- a/cockatrice/src/abstractclient.cpp +++ b/cockatrice/src/abstractclient.cpp @@ -14,6 +14,7 @@ #include "pb/event_user_joined.pb.h" #include "pb/event_user_left.pb.h" #include "pb/event_game_joined.pb.h" +#include "pb/event_replay_added.pb.h" #include "get_pb_extension.h" #include @@ -55,6 +56,7 @@ void AbstractClient::processProtocolItem(const ServerMessage &item) case SessionEvent::USER_JOINED: emit userJoinedEventReceived(event.GetExtension(Event_UserJoined::ext)); break; case SessionEvent::USER_LEFT: emit userLeftEventReceived(event.GetExtension(Event_UserLeft::ext)); break; case SessionEvent::GAME_JOINED: emit gameJoinedEventReceived(event.GetExtension(Event_GameJoined::ext)); break; + case SessionEvent::REPLAY_ADDED: emit replayAddedEventReceived(event.GetExtension(Event_ReplayAdded::ext)); break; } break; } diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index 86bd8266..3a1cbb9d 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -22,6 +22,7 @@ class Event_GameJoined; class Event_UserMessage; class Event_ConnectionClosed; class Event_ServerShutdown; +class Event_ReplayAdded; enum ClientStatus { StatusDisconnected, @@ -57,6 +58,7 @@ signals: void userInfoChanged(const ServerInfo_User &userInfo); void buddyListReceived(const QList &buddyList); void ignoreListReceived(const QList &ignoreList); + void replayAddedEventReceived(const Event_ReplayAdded &event); private: int nextCmdId; protected slots: diff --git a/cockatrice/src/remotereplaylist_treewidget.cpp b/cockatrice/src/remotereplaylist_treewidget.cpp index d978fe33..e8e4a5d1 100644 --- a/cockatrice/src/remotereplaylist_treewidget.cpp +++ b/cockatrice/src/remotereplaylist_treewidget.cpp @@ -13,7 +13,7 @@ RemoteReplayList_TreeModel::MatchNode::MatchNode(const ServerInfo_ReplayMatch &_ : RemoteReplayList_TreeModel::Node(QString::fromStdString(_matchInfo.game_name())), matchInfo(_matchInfo) { for (int i = 0; i < matchInfo.replay_list_size(); ++i) - append(new ReplayNode(matchInfo.replay_list(i))); + append(new ReplayNode(matchInfo.replay_list(i), this)); } RemoteReplayList_TreeModel::MatchNode::~MatchNode() @@ -200,6 +200,15 @@ void RemoteReplayList_TreeModel::refreshTree() client->sendCommand(pend); } +void RemoteReplayList_TreeModel::addMatchInfo(const ServerInfo_ReplayMatch &matchInfo) +{ + beginInsertRows(QModelIndex(), replayMatches.size(), replayMatches.size()); + replayMatches.append(new MatchNode(matchInfo)); + endInsertRows(); + + emit treeRefreshed(); +} + void RemoteReplayList_TreeModel::replayListFinished(const Response &r) { const Response_ReplayList &resp = r.GetExtension(Response_ReplayList::ext); @@ -236,3 +245,8 @@ ServerInfo_Replay const *RemoteReplayList_TreeWidget::getCurrentReplay() const { return treeModel->getReplay(proxyModel->mapToSource(selectionModel()->currentIndex())); } + +void RemoteReplayList_TreeWidget::addMatchInfo(const ServerInfo_ReplayMatch &matchInfo) +{ + treeModel->addMatchInfo(matchInfo); +} diff --git a/cockatrice/src/remotereplaylist_treewidget.h b/cockatrice/src/remotereplaylist_treewidget.h index 9c1567ea..299bf59e 100644 --- a/cockatrice/src/remotereplaylist_treewidget.h +++ b/cockatrice/src/remotereplaylist_treewidget.h @@ -39,7 +39,7 @@ private: MatchNode *parent; ServerInfo_Replay replayInfo; public: - ReplayNode(const ServerInfo_Replay &_replayInfo, MatchNode *_parent = 0) + ReplayNode(const ServerInfo_Replay &_replayInfo, MatchNode *_parent) : Node(QString::fromStdString(_replayInfo.replay_name())), parent(_parent), replayInfo(_replayInfo) { } MatchNode *getParent() const { return parent; } const ServerInfo_Replay &getReplayInfo() { return replayInfo; } @@ -67,6 +67,7 @@ public: void refreshTree(); ServerInfo_Replay const* getReplay(const QModelIndex &index) const; ServerInfo_ReplayMatch const* getReplayMatch(const QModelIndex &index) const; + void addMatchInfo(const ServerInfo_ReplayMatch &matchInfo); }; class RemoteReplayList_TreeWidget : public QTreeView { @@ -79,6 +80,7 @@ public: ServerInfo_Replay const *getCurrentReplay() const; ServerInfo_ReplayMatch const *getCurrentReplayMatch() const; void refreshTree(); + void addMatchInfo(const ServerInfo_ReplayMatch &matchInfo); }; #endif diff --git a/cockatrice/src/tab_replays.cpp b/cockatrice/src/tab_replays.cpp index bc430a10..5a9372ce 100644 --- a/cockatrice/src/tab_replays.cpp +++ b/cockatrice/src/tab_replays.cpp @@ -20,6 +20,7 @@ #include "pb/response.pb.h" #include "pb/response_replay_download.pb.h" #include "pb/command_replay_download.pb.h" +#include "pb/event_replay_added.pb.h" TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client) : Tab(_tabSupervisor), client(_client) @@ -90,6 +91,8 @@ TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client) retranslateUi(); setLayout(hbox); + + connect(client, SIGNAL(replayAddedEventReceived(const Event_ReplayAdded &)), this, SLOT(replayAddedEventReceived(const Event_ReplayAdded &))); } void TabReplays::retranslateUi() @@ -183,3 +186,8 @@ void TabReplays::downloadFinished(const Response &r) f.write((const char *) data.data(), data.size()); f.close(); } + +void TabReplays::replayAddedEventReceived(const Event_ReplayAdded &event) +{ + serverDirView->addMatchInfo(event.match_info()); +} diff --git a/cockatrice/src/tab_replays.h b/cockatrice/src/tab_replays.h index d564e531..70ea86eb 100644 --- a/cockatrice/src/tab_replays.h +++ b/cockatrice/src/tab_replays.h @@ -2,8 +2,8 @@ #define TAB_REPLAYS_H #include "tab.h" -#include "pb/response.pb.h" +class Response; class AbstractClient; class QTreeView; class QFileSystemModel; @@ -12,6 +12,7 @@ class QToolBar; class QGroupBox; class RemoteReplayList_TreeWidget; class GameReplay; +class Event_ReplayAdded; class TabReplays : public Tab { Q_OBJECT @@ -33,6 +34,8 @@ private slots: void actDownload(); void downloadFinished(const Response &r); + + void replayAddedEventReceived(const Event_ReplayAdded &event); signals: void openReplay(GameReplay *replay); public: diff --git a/common/pb/CMakeLists.txt b/common/pb/CMakeLists.txt index f60ca819..d5efd237 100644 --- a/common/pb/CMakeLists.txt +++ b/common/pb/CMakeLists.txt @@ -78,6 +78,7 @@ SET(PROTO_FILES event_move_card.proto event_player_properties_changed.proto event_remove_from_list.proto + event_replay_added.proto event_reveal_cards.proto event_roll_die.proto event_room_say.proto diff --git a/common/pb/event_replay_added.proto b/common/pb/event_replay_added.proto new file mode 100644 index 00000000..c3de2082 --- /dev/null +++ b/common/pb/event_replay_added.proto @@ -0,0 +1,9 @@ +import "session_event.proto"; +import "serverinfo_replay_match.proto"; + +message Event_ReplayAdded { + extend SessionEvent { + optional Event_ReplayAdded ext = 1100; + } + optional ServerInfo_ReplayMatch match_info = 1; +} diff --git a/common/pb/game_replay.proto b/common/pb/game_replay.proto index e3438e66..05bc67d0 100644 --- a/common/pb/game_replay.proto +++ b/common/pb/game_replay.proto @@ -2,7 +2,8 @@ import "serverinfo_game.proto"; import "game_event_container.proto"; message GameReplay { - optional ServerInfo_Game game_info = 1; - repeated GameEventContainer event_list = 2; - optional uint32 duration_seconds = 3; + optional uint64 replay_id = 1; + optional ServerInfo_Game game_info = 2; + repeated GameEventContainer event_list = 3; + optional uint32 duration_seconds = 4; } diff --git a/common/pb/session_event.proto b/common/pb/session_event.proto index f97778ab..a0b6254d 100644 --- a/common/pb/session_event.proto +++ b/common/pb/session_event.proto @@ -11,6 +11,7 @@ message SessionEvent { USER_JOINED = 1007; USER_LEFT = 1008; GAME_JOINED = 1009; + REPLAY_ADDED = 1100; } extensions 100 to max; } diff --git a/common/server.cpp b/common/server.cpp index 886fd9df..75633dc6 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -29,7 +29,7 @@ #include Server::Server(QObject *parent) - : QObject(parent), serverMutex(QMutex::Recursive), nextGameId(0) + : QObject(parent), serverMutex(QMutex::Recursive), nextGameId(0), nextReplayId(0) { } diff --git a/common/server.h b/common/server.h index b696190a..e05a67f2 100644 --- a/common/server.h +++ b/common/server.h @@ -28,6 +28,7 @@ public: AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reason); const QMap &getRooms() { return rooms; } int getNextGameId() { return nextGameId++; } + int getNextReplayId() { return nextReplayId++; } const QMap &getUsers() const { return users; } void addClient(Server_ProtocolHandler *player); @@ -62,7 +63,7 @@ protected: virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0; int getUsersCount() const; int getGamesCount() const; - int nextGameId; + int nextGameId, nextReplayId; void addRoom(Server_Room *newRoom); }; diff --git a/common/server_game.cpp b/common/server_game.cpp index 99887d78..ef2d152d 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -48,6 +48,7 @@ Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QS : QObject(), room(_room), hostId(0), creatorInfo(new ServerInfo_User(_creator->copyUserInfo(false))), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), startTimeOfThisGame(0), secondsElapsed(0), firstGameStarted(false), startTime(QDateTime::currentDateTime()), gameMutex(QMutex::Recursive) { currentReplay = new GameReplay; + currentReplay->set_replay_id(room->getServer()->getNextReplayId()); connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection); @@ -246,6 +247,7 @@ void Server_Game::doStartGameIfReady() currentReplay->set_duration_seconds(secondsElapsed - startTimeOfThisGame); replayList.append(currentReplay); currentReplay = new GameReplay; + currentReplay->set_replay_id(room->getServer()->getNextReplayId()); currentReplay->mutable_game_info()->CopyFrom(getInfo()); Event_GameStateChanged omniscientEvent; diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 3ec03785..df47803a 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -29,6 +29,7 @@ #include "main.h" #include "passwordhasher.h" #include "pb/game_replay.pb.h" +#include "pb/event_replay_added.pb.h" #include "pb/event_server_message.pb.h" #include "pb/event_server_shutdown.pb.h" #include "pb/event_connection_closed.pb.h" @@ -159,6 +160,15 @@ bool Servatrice::openDatabase() nextGameId = query.value(0).toInt() + 1; qDebug() << "set nextGameId to " << nextGameId; } + if (!nextReplayId) { + QSqlQuery query; + if (!query.exec("select max(id) from " + dbPrefix + "_replays")) + return false; + if (!query.next()) + return false; + nextReplayId = query.value(0).toInt() + 1; + qDebug() << "set nextReplayId to " << nextReplayId; + } return true; } @@ -544,6 +554,14 @@ void Servatrice::storeGameInformation(int secondsElapsed, const QSet &a Server_Room *room = rooms.value(gameInfo.room_id()); + Event_ReplayAdded replayEvent; + ServerInfo_ReplayMatch *replayMatchInfo = replayEvent.mutable_match_info(); + replayMatchInfo->set_game_id(gameInfo.game_id()); + replayMatchInfo->set_room_name(room->getName().toStdString()); + replayMatchInfo->set_time_started(QDateTime::currentDateTime().addSecs(-secondsElapsed).toTime_t()); + replayMatchInfo->set_length(secondsElapsed); + replayMatchInfo->set_game_name(gameInfo.description()); + const QStringList &allGameTypes = room->getGameTypes(); QStringList gameTypes; for (int i = gameInfo.game_types_size() - 1; i >= 0; --i) @@ -553,7 +571,9 @@ void Servatrice::storeGameInformation(int secondsElapsed, const QSet &a QSetIterator playerIterator(allPlayersEver); while (playerIterator.hasNext()) { gameIds1.append(gameInfo.game_id()); - playerNames.append(playerIterator.next()); + const QString &playerName = playerIterator.next(); + playerNames.append(playerName); + replayMatchInfo->add_player_names(playerName.toStdString()); } QSet allUsersInGame = allPlayersEver + allSpectatorsEver; QSetIterator allUsersIterator(allUsersInGame); @@ -566,18 +586,35 @@ void Servatrice::storeGameInformation(int secondsElapsed, const QSet &a replayNames.append(QString::fromStdString(gameInfo.description())); } - QVariantList replayGameIds, replayDurations, replayBlobs; + QVariantList replayIds, replayGameIds, replayDurations, replayBlobs; for (int i = 0; i < replayList.size(); ++i) { QByteArray blob; const unsigned int size = replayList[i]->ByteSize(); blob.resize(size); replayList[i]->SerializeToArray(blob.data(), size); + replayIds.append(QVariant((qulonglong) replayList[i]->replay_id())); replayGameIds.append(gameInfo.game_id()); replayDurations.append(replayList[i]->duration_seconds()); replayBlobs.append(blob); + + ServerInfo_Replay *replayInfo = replayMatchInfo->add_replay_list(); + replayInfo->set_replay_id(replayList[i]->replay_id()); + replayInfo->set_replay_name(gameInfo.description()); + replayInfo->set_duration(replayList[i]->duration_seconds()); } + SessionEvent *sessionEvent = Server_ProtocolHandler::prepareSessionEvent(replayEvent); + allUsersIterator.toFront(); + serverMutex.lock(); + while (allUsersIterator.hasNext()) { + Server_ProtocolHandler *userHandler = users.value(allUsersIterator.next()); + if (userHandler) + userHandler->sendProtocolItem(*sessionEvent); + } + serverMutex.unlock(); + delete sessionEvent; + QMutexLocker locker(&dbMutex); if (!checkSql()) return; @@ -602,7 +639,8 @@ void Servatrice::storeGameInformation(int secondsElapsed, const QSet &a query2.execBatch(); QSqlQuery replayQuery1; - replayQuery1.prepare("insert into " + dbPrefix + "_replays (id_game, duration, replay) values (:id_game, :duration, :replay)"); + replayQuery1.prepare("insert into " + dbPrefix + "_replays (id, id_game, duration, replay) values (:id_replay, :id_game, :duration, :replay)"); + replayQuery1.bindValue(":id_replay", replayIds); replayQuery1.bindValue(":id_game", replayGameIds); replayQuery1.bindValue(":duration", replayDurations); replayQuery1.bindValue(":replay", replayBlobs);