Commit 6bbc76af authored by Max-Wilhelm Bruker's avatar Max-Wilhelm Bruker
Browse files

Merge branch 'devel' into servernetwork

parents 50e53fbe b0378544
...@@ -4,5 +4,5 @@ message Command_ReplayDownload { ...@@ -4,5 +4,5 @@ message Command_ReplayDownload {
extend SessionCommand { extend SessionCommand {
optional Command_ReplayDownload ext = 1101; optional Command_ReplayDownload ext = 1101;
} }
optional sint32 game_id = 1 [default = -1]; optional sint32 replay_id = 1 [default = -1];
} }
import "session_commands.proto";
message Command_ReplayModifyMatch {
extend SessionCommand {
optional Command_ReplayModifyMatch ext = 1102;
}
optional sint32 game_id = 1 [default = -1];
optional bool do_not_hide = 2;
}
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;
}
...@@ -2,6 +2,8 @@ import "serverinfo_game.proto"; ...@@ -2,6 +2,8 @@ import "serverinfo_game.proto";
import "game_event_container.proto"; import "game_event_container.proto";
message GameReplay { message GameReplay {
optional ServerInfo_Game game_info = 1; optional uint64 replay_id = 1;
repeated GameEventContainer event_list = 2; optional ServerInfo_Game game_info = 2;
repeated GameEventContainer event_list = 3;
optional uint32 duration_seconds = 4;
} }
import "response.proto"; import "response.proto";
import "serverinfo_replay.proto"; import "serverinfo_replay_match.proto";
message Response_ReplayList { message Response_ReplayList {
extend Response { extend Response {
optional Response_ReplayList ext = 1100; optional Response_ReplayList ext = 1100;
} }
repeated ServerInfo_Replay replay_list = 1; repeated ServerInfo_ReplayMatch match_list = 1;
} }
message ServerInfo_Replay { message ServerInfo_Replay {
optional sint32 game_id = 1 [default = -1]; optional sint32 replay_id = 1 [default = -1];
optional string room_name = 2; optional string replay_name = 2;
optional uint32 time_started = 3; optional uint32 duration = 3;
optional uint32 length = 4;
optional string game_name = 5;
optional string replay_name = 6;
repeated string player_names = 7;
} }
import "serverinfo_replay.proto";
message ServerInfo_ReplayMatch {
repeated ServerInfo_Replay replay_list = 1;
optional sint32 game_id = 2 [default = -1];
optional string room_name = 3;
optional uint32 time_started = 4;
optional uint32 length = 5;
optional string game_name = 6;
repeated string player_names = 7;
optional bool do_not_hide = 8;
}
...@@ -18,6 +18,7 @@ message SessionCommand { ...@@ -18,6 +18,7 @@ message SessionCommand {
JOIN_ROOM = 1015; JOIN_ROOM = 1015;
REPLAY_LIST = 1100; REPLAY_LIST = 1100;
REPLAY_DOWNLOAD = 1101; REPLAY_DOWNLOAD = 1101;
REPLAY_MODIFY_MATCH = 1102;
} }
extensions 100 to max; extensions 100 to max;
} }
......
...@@ -11,6 +11,7 @@ message SessionEvent { ...@@ -11,6 +11,7 @@ message SessionEvent {
USER_JOINED = 1007; USER_JOINED = 1007;
USER_LEFT = 1008; USER_LEFT = 1008;
GAME_JOINED = 1009; GAME_JOINED = 1009;
REPLAY_ADDED = 1100;
} }
extensions 100 to max; extensions 100 to max;
} }
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <QDebug> #include <QDebug>
Server::Server(QObject *parent) Server::Server(QObject *parent)
: QObject(parent), serverMutex(QMutex::Recursive), nextGameId(0) : QObject(parent), serverMutex(QMutex::Recursive), nextGameId(0), nextReplayId(0)
{ {
} }
......
...@@ -28,6 +28,7 @@ public: ...@@ -28,6 +28,7 @@ public:
AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reason); AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reason);
const QMap<int, Server_Room *> &getRooms() { return rooms; } const QMap<int, Server_Room *> &getRooms() { return rooms; }
int getNextGameId() { return nextGameId++; } int getNextGameId() { return nextGameId++; }
int getNextReplayId() { return nextReplayId++; }
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; } const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
void addClient(Server_ProtocolHandler *player); void addClient(Server_ProtocolHandler *player);
...@@ -48,7 +49,7 @@ public: ...@@ -48,7 +49,7 @@ public:
virtual bool isInBuddyList(const QString &whoseList, const QString &who) { return false; } virtual bool isInBuddyList(const QString &whoseList, const QString &who) { return false; }
virtual bool isInIgnoreList(const QString &whoseList, const QString &who) { return false; } virtual bool isInIgnoreList(const QString &whoseList, const QString &who) { return false; }
virtual void storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const GameReplay &replay) { } virtual void storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replays) { }
protected: protected:
void prepareDestroy(); void prepareDestroy();
QList<Server_ProtocolHandler *> clients; QList<Server_ProtocolHandler *> clients;
...@@ -62,7 +63,7 @@ protected: ...@@ -62,7 +63,7 @@ protected:
virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0; virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0;
int getUsersCount() const; int getUsersCount() const;
int getGamesCount() const; int getGamesCount() const;
int nextGameId; int nextGameId, nextReplayId;
void addRoom(Server_Room *newRoom); void addRoom(Server_Room *newRoom);
}; };
......
...@@ -45,14 +45,16 @@ ...@@ -45,14 +45,16 @@
#include <QDebug> #include <QDebug>
Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room) Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room)
: 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), secondsElapsed(0), startTime(QDateTime::currentDateTime()), gameMutex(QMutex::Recursive) : 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)
{ {
replay = new GameReplay; currentReplay = new GameReplay;
currentReplay->set_replay_id(room->getServer()->getNextReplayId());
connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection); connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection);
addPlayer(_creator, false, false); addPlayer(_creator, false, false);
replay->mutable_game_info()->CopyFrom(getInfo());
currentReplay->mutable_game_info()->CopyFrom(getInfo());
if (room->getServer()->getGameShouldPing()) { if (room->getServer()->getGameShouldPing()) {
pingClock = new QTimer(this); pingClock = new QTimer(this);
...@@ -80,8 +82,12 @@ Server_Game::~Server_Game() ...@@ -80,8 +82,12 @@ Server_Game::~Server_Game()
gameMutex.unlock(); gameMutex.unlock();
room->roomMutex.unlock(); room->roomMutex.unlock();
room->getServer()->storeGameInformation(secondsElapsed, allPlayersEver, allSpectatorsEver, *replay); currentReplay->set_duration_seconds(secondsElapsed - startTimeOfThisGame);
delete replay; replayList.append(currentReplay);
room->getServer()->storeGameInformation(secondsElapsed, allPlayersEver, allSpectatorsEver, replayList);
for (int i = 0; i < replayList.size(); ++i)
delete replayList[i];
qDebug() << "Server_Game destructor: gameId=" << gameId; qDebug() << "Server_Game destructor: gameId=" << gameId;
} }
...@@ -176,9 +182,9 @@ void Server_Game::sendGameStateToPlayers() ...@@ -176,9 +182,9 @@ void Server_Game::sendGameStateToPlayers()
omniscientEvent.add_player_list()->CopyFrom(omniscientGameStateIterator.next()); omniscientEvent.add_player_list()->CopyFrom(omniscientGameStateIterator.next());
GameEventContainer *replayCont = prepareGameEvent(omniscientEvent, -1); GameEventContainer *replayCont = prepareGameEvent(omniscientEvent, -1);
replayCont->set_seconds_elapsed(secondsElapsed); replayCont->set_seconds_elapsed(secondsElapsed - startTimeOfThisGame);
replayCont->clear_game_id(); replayCont->clear_game_id();
replay->add_event_list()->CopyFrom(*replayCont); currentReplay->add_event_list()->CopyFrom(*replayCont);
delete replayCont; delete replayCont;
// If spectators are not omniscient, we need an additional getGameState call, otherwise we can use the data we used for the replay. // If spectators are not omniscient, we need an additional getGameState call, otherwise we can use the data we used for the replay.
...@@ -237,6 +243,28 @@ void Server_Game::doStartGameIfReady() ...@@ -237,6 +243,28 @@ void Server_Game::doStartGameIfReady()
player->setReadyStart(false); player->setReadyStart(false);
} }
if (firstGameStarted) {
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;
QListIterator<ServerInfo_Player> omniscientGameStateIterator(getGameState(0, true, true));
while (omniscientGameStateIterator.hasNext())
omniscientEvent.add_player_list()->CopyFrom(omniscientGameStateIterator.next());
GameEventContainer *replayCont = prepareGameEvent(omniscientEvent, -1);
replayCont->set_seconds_elapsed(0);
replayCont->clear_game_id();
currentReplay->add_event_list()->CopyFrom(*replayCont);
delete replayCont;
startTimeOfThisGame = secondsElapsed;
} else
firstGameStarted = true;
sendGameStateToPlayers(); sendGameStateToPlayers();
activePlayer = -1; activePlayer = -1;
...@@ -624,9 +652,9 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStor ...@@ -624,9 +652,9 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStor
p->sendGameEvent(*cont); p->sendGameEvent(*cont);
} }
if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) { if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) {
cont->set_seconds_elapsed(secondsElapsed); cont->set_seconds_elapsed(secondsElapsed - startTimeOfThisGame);
cont->clear_game_id(); cont->clear_game_id();
replay->add_event_list()->CopyFrom(*cont); currentReplay->add_event_list()->CopyFrom(*cont);
} }
delete cont; delete cont;
......
...@@ -59,10 +59,12 @@ private: ...@@ -59,10 +59,12 @@ private:
bool spectatorsCanTalk; bool spectatorsCanTalk;
bool spectatorsSeeEverything; bool spectatorsSeeEverything;
int inactivityCounter; int inactivityCounter;
int secondsElapsed; int startTimeOfThisGame, secondsElapsed;
bool firstGameStarted;
QDateTime startTime; QDateTime startTime;
QTimer *pingClock; QTimer *pingClock;
GameReplay *replay; QList<GameReplay *> replayList;
GameReplay *currentReplay;
signals: signals:
void sigStartGameIfReady(); void sigStartGameIfReady();
private slots: private slots:
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include "pb/command_deck_del.pb.h" #include "pb/command_deck_del.pb.h"
#include "pb/command_replay_list.pb.h" #include "pb/command_replay_list.pb.h"
#include "pb/command_replay_download.pb.h" #include "pb/command_replay_download.pb.h"
#include "pb/command_replay_modify_match.pb.h"
#include "pb/response.pb.h" #include "pb/response.pb.h"
#include "pb/response_login.pb.h" #include "pb/response_login.pb.h"
#include "pb/response_list_users.pb.h" #include "pb/response_list_users.pb.h"
...@@ -241,6 +242,7 @@ Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(co ...@@ -241,6 +242,7 @@ Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(co
case SessionCommand::DECK_DOWNLOAD: resp = cmdDeckDownload(sc.GetExtension(Command_DeckDownload::ext), rc); break; case SessionCommand::DECK_DOWNLOAD: resp = cmdDeckDownload(sc.GetExtension(Command_DeckDownload::ext), rc); break;
case SessionCommand::REPLAY_LIST: resp = cmdReplayList(sc.GetExtension(Command_ReplayList::ext), rc); break; case SessionCommand::REPLAY_LIST: resp = cmdReplayList(sc.GetExtension(Command_ReplayList::ext), rc); break;
case SessionCommand::REPLAY_DOWNLOAD: resp = cmdReplayDownload(sc.GetExtension(Command_ReplayDownload::ext), rc); break; case SessionCommand::REPLAY_DOWNLOAD: resp = cmdReplayDownload(sc.GetExtension(Command_ReplayDownload::ext), rc); break;
case SessionCommand::REPLAY_MODIFY_MATCH: resp = cmdReplayModifyMatch(sc.GetExtension(Command_ReplayModifyMatch::ext), rc); break;
case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc); break; case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc); break;
case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc); break; case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc); break;
case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc); break; case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc); break;
......
...@@ -41,6 +41,7 @@ class Command_DeckDownload; ...@@ -41,6 +41,7 @@ class Command_DeckDownload;
class Command_DeckUpload; class Command_DeckUpload;
class Command_ReplayList; class Command_ReplayList;
class Command_ReplayDownload; class Command_ReplayDownload;
class Command_ReplayModifyMatch;
class Command_ListRooms; class Command_ListRooms;
class Command_JoinRoom; class Command_JoinRoom;
class Command_LeaveRoom; class Command_LeaveRoom;
...@@ -123,6 +124,7 @@ private: ...@@ -123,6 +124,7 @@ private:
virtual Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc) = 0; virtual Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc) = 0;
virtual Response::ResponseCode cmdReplayList(const Command_ReplayList &cmd, ResponseContainer &rc) = 0; virtual Response::ResponseCode cmdReplayList(const Command_ReplayList &cmd, ResponseContainer &rc) = 0;
virtual Response::ResponseCode cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc) = 0; virtual Response::ResponseCode cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc) = 0;
virtual Response::ResponseCode cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer &rc) = 0;
Response::ResponseCode cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetUserInfo(const Command_GetUserInfo &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetUserInfo(const Command_GetUserInfo &cmd, ResponseContainer &rc);
Response::ResponseCode cmdListRooms(const Command_ListRooms &cmd, ResponseContainer &rc); Response::ResponseCode cmdListRooms(const Command_ListRooms &cmd, ResponseContainer &rc);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "main.h" #include "main.h"
#include "passwordhasher.h" #include "passwordhasher.h"
#include "pb/game_replay.pb.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_message.pb.h"
#include "pb/event_server_shutdown.pb.h" #include "pb/event_server_shutdown.pb.h"
#include "pb/event_connection_closed.pb.h" #include "pb/event_connection_closed.pb.h"
...@@ -203,6 +204,15 @@ bool Servatrice::openDatabase() ...@@ -203,6 +204,15 @@ bool Servatrice::openDatabase()
nextGameId = query.value(0).toInt() + 1; nextGameId = query.value(0).toInt() + 1;
qDebug() << "set nextGameId to " << nextGameId; 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; return true;
} }
...@@ -582,43 +592,32 @@ void Servatrice::statusUpdate() ...@@ -582,43 +592,32 @@ void Servatrice::statusUpdate()
execSqlQuery(query); execSqlQuery(query);
} }
void Servatrice::storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const GameReplay &replay) void Servatrice::storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replayList)
{ {
Server_Room *room = rooms.value(replay.game_info().room_id()); const ServerInfo_Game &gameInfo = replayList.first()->game_info();
const QStringList &allGameTypes = room->getGameTypes(); Server_Room *room = rooms.value(gameInfo.room_id());
QStringList gameTypes;
for (int i = replay.game_info().game_types_size() - 1; i >= 0; --i)
gameTypes.append(allGameTypes[replay.game_info().game_types(i)]);
QByteArray replayBlob; Event_ReplayAdded replayEvent;
const unsigned int size = replay.ByteSize(); ServerInfo_ReplayMatch *replayMatchInfo = replayEvent.mutable_match_info();
replayBlob.resize(size); replayMatchInfo->set_game_id(gameInfo.game_id());
replay.SerializeToArray(replayBlob.data(), size); 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());
QMutexLocker locker(&dbMutex); const QStringList &allGameTypes = room->getGameTypes();
if (!checkSql()) QStringList gameTypes;
return; for (int i = gameInfo.game_types_size() - 1; i >= 0; --i)
gameTypes.append(allGameTypes[gameInfo.game_types(i)]);
QSqlQuery query1;
query1.prepare("insert into " + dbPrefix + "_games (room_name, id, descr, creator_name, password, game_types, player_count, time_started, time_finished, replay) values (:id_room, :id_game, :descr, :creator_name, :password, :game_types, :player_count, date_sub(now(), interval :seconds second), now(), :replay)");
query1.bindValue(":room_name", room->getName());
query1.bindValue(":id_game", replay.game_info().game_id());
query1.bindValue(":descr", QString::fromStdString(replay.game_info().description()));
query1.bindValue(":creator_name", QString::fromStdString(replay.game_info().creator_info().name()));
query1.bindValue(":password", replay.game_info().with_password() ? 1 : 0);
query1.bindValue(":game_types", gameTypes.isEmpty() ? QString("") : gameTypes.join(", "));
query1.bindValue(":player_count", replay.game_info().max_players());
query1.bindValue(":seconds", secondsElapsed);
query1.bindValue(":replay", replayBlob);
if (!execSqlQuery(query1))
return;
QVariantList gameIds1, playerNames, gameIds2, userIds, replayNames; QVariantList gameIds1, playerNames, gameIds2, userIds, replayNames;
QSetIterator<QString> playerIterator(allPlayersEver); QSetIterator<QString> playerIterator(allPlayersEver);
while (playerIterator.hasNext()) { while (playerIterator.hasNext()) {
gameIds1.append(replay.game_info().game_id()); gameIds1.append(gameInfo.game_id());
playerNames.append(playerIterator.next()); const QString &playerName = playerIterator.next();
playerNames.append(playerName);
replayMatchInfo->add_player_names(playerName.toStdString());
} }
QSet<QString> allUsersInGame = allPlayersEver + allSpectatorsEver; QSet<QString> allUsersInGame = allPlayersEver + allSpectatorsEver;
QSetIterator<QString> allUsersIterator(allUsersInGame); QSetIterator<QString> allUsersIterator(allUsersInGame);
...@@ -626,17 +625,71 @@ void Servatrice::storeGameInformation(int secondsElapsed, const QSet<QString> &a ...@@ -626,17 +625,71 @@ void Servatrice::storeGameInformation(int secondsElapsed, const QSet<QString> &a
int id = getUserIdInDB(allUsersIterator.next()); int id = getUserIdInDB(allUsersIterator.next());
if (id == -1) if (id == -1)
continue; continue;
gameIds2.append(replay.game_info().game_id()); gameIds2.append(gameInfo.game_id());
userIds.append(id); userIds.append(id);
replayNames.append(QString::fromStdString(replay.game_info().description())); replayNames.append(QString::fromStdString(gameInfo.description()));
} }
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;
QSqlQuery query1;
query1.prepare("insert into " + dbPrefix + "_games (room_name, id, descr, creator_name, password, game_types, player_count, time_started, time_finished) values (:id_room, :id_game, :descr, :creator_name, :password, :game_types, :player_count, date_sub(now(), interval :seconds second), now())");
query1.bindValue(":room_name", room->getName());
query1.bindValue(":id_game", gameInfo.game_id());
query1.bindValue(":descr", QString::fromStdString(gameInfo.description()));
query1.bindValue(":creator_name", QString::fromStdString(gameInfo.creator_info().name()));
query1.bindValue(":password", gameInfo.with_password() ? 1 : 0);
query1.bindValue(":game_types", gameTypes.isEmpty() ? QString("") : gameTypes.join(", "));
query1.bindValue(":player_count", gameInfo.max_players());
query1.bindValue(":seconds", secondsElapsed);
if (!execSqlQuery(query1))
return;
QSqlQuery query2; QSqlQuery query2;
query2.prepare("insert into " + dbPrefix + "_games_players (id_game, player_name) values (:id_game, :player_name)"); query2.prepare("insert into " + dbPrefix + "_games_players (id_game, player_name) values (:id_game, :player_name)");
query2.bindValue(":id_game", gameIds1); query2.bindValue(":id_game", gameIds1);
query2.bindValue(":player_name", playerNames); query2.bindValue(":player_name", playerNames);
query2.execBatch(); query2.execBatch();
QSqlQuery replayQuery1;
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);
replayQuery1.execBatch();
QSqlQuery query3; QSqlQuery query3;
query3.prepare("insert into " + dbPrefix + "_replays_access (id_game, id_player, replay_name) values (:id_game, :id_player, :replay_name)"); query3.prepare("insert into " + dbPrefix + "_replays_access (id_game, id_player, replay_name) values (:id_game, :id_player, :replay_name)");
query3.bindValue(":id_game", gameIds2); query3.bindValue(":id_game", gameIds2);
......
...@@ -97,7 +97,7 @@ public: ...@@ -97,7 +97,7 @@ public:
void incTxBytes(quint64 num); void incTxBytes(quint64 num);
void incRxBytes(quint64 num); void incRxBytes(quint64 num);
int getUserIdInDB(const QString &name); int getUserIdInDB(const QString &name);
void storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const GameReplay &replay); void storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replays);
protected: protected:
int startSession(const QString &userName, const QString &address); int startSession(const QString &userName, const QString &address);
void endSession(int sessionId); void endSession(int sessionId);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "pb/command_deck_del.pb.h" #include "pb/command_deck_del.pb.h"
#include "pb/command_replay_list.pb.h" #include "pb/command_replay_list.pb.h"
#include "pb/command_replay_download.pb.h" #include "pb/command_replay_download.pb.h"
#include "pb/command_replay_modify_match.pb.h"
#include "pb/event_connection_closed.pb.h" #include "pb/event_connection_closed.pb.h"
#include "pb/event_server_message.pb.h" #include "pb/event_server_message.pb.h"
#include "pb/event_server_identification.pb.h" #include "pb/event_server_identification.pb.h"
...@@ -499,27 +500,40 @@ Response::ResponseCode ServerSocketInterface::cmdReplayList(const Command_Replay ...@@ -499,27 +500,40 @@ Response::ResponseCode ServerSocketInterface::cmdReplayList(const Command_Replay
servatrice->dbMutex.lock(); servatrice->dbMutex.lock();
QSqlQuery query1; QSqlQuery query1;
query1.prepare("select a.id_game, a.replay_name, b.room_name, b.time_started, b.time_finished, b.descr from cockatrice_replays_access a left join cockatrice_games b on b.id = a.id_game where a.id_player = :id_player"); query1.prepare("select a.id_game, a.replay_name, b.room_name, b.time_started, b.time_finished, b.descr, a.do_not_hide from cockatrice_replays_access a left join cockatrice_games b on b.id = a.id_game where a.id_player = :id_player and (a.do_not_hide = 1 or date_add(b.time_started, interval 14 day) > now())");
query1.bindValue(":id_player", userInfo->id()); query1.bindValue(":id_player", userInfo->id());
servatrice->execSqlQuery(query1); servatrice->execSqlQuery(query1);
while (query1.next()) { while (query1.next()) {
ServerInfo_Replay *replayInfo = re->add_replay_list(); ServerInfo_ReplayMatch *matchInfo = re->add_match_list();
const int gameId = query1.value(0).toInt(); const int gameId = query1.value(0).toInt();
replayInfo->set_game_id(gameId); matchInfo->set_game_id(gameId);
replayInfo->set_room_name(query1.value(2).toString().toStdString()); matchInfo->set_room_name(query1.value(2).toString().toStdString());
const int timeStarted = query1.value(3).toDateTime().toTime_t(); const int timeStarted = query1.value(3).toDateTime().toTime_t();
const int timeFinished = query1.value(4).toDateTime().toTime_t(); const int timeFinished = query1.value(4).toDateTime().toTime_t();
replayInfo->set_time_started(timeStarted); matchInfo->set_time_started(timeStarted);
replayInfo->set_length(timeFinished - timeStarted); matchInfo->set_length(timeFinished - timeStarted);
replayInfo->set_game_name(query1.value(5).toString().toStdString()); matchInfo->set_game_name(query1.value(5).toString().toStdString());
replayInfo->set_replay_name(query1.value(1).toString().toStdString()); const QString replayName = query1.value(1).toString();
matchInfo->set_do_not_hide(query1.value(6).toBool());
QSqlQuery query2; QSqlQuery query2;
query2.prepare("select player_name from cockatrice_games_players where id_game = :id_game"); query2.prepare("select player_name from cockatrice_games_players where id_game = :id_game");
query2.bindValue(":id_game", gameId); query2.bindValue(":id_game", gameId);
servatrice->execSqlQuery(query2); servatrice->execSqlQuery(query2);
while (query2.next()) while (query2.next())
replayInfo->add_player_names(query2.value(0).toString().toStdString()); matchInfo->add_player_names(query2.value(0).toString().toStdString());
QSqlQuery query3;
query3.prepare("select id, duration from " + servatrice->getDbPrefix() + "_replays where id_game = :id_game");
query3.bindValue(":id_game", gameId);
servatrice->execSqlQuery(query3);
while (query3.next()) {
ServerInfo_Replay *replayInfo = matchInfo->add_replay_list();
replayInfo->set_replay_id(query3.value(0).toInt());
replayInfo->set_replay_name(replayName.toStdString());
replayInfo->set_duration(query3.value(1).toInt());
}
} }
servatrice->dbMutex.unlock(); servatrice->dbMutex.unlock();
...@@ -535,8 +549,8 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDownload(const Command_Re ...@@ -535,8 +549,8 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDownload(const Command_Re
QMutexLocker dbLocker(&servatrice->dbMutex); QMutexLocker dbLocker(&servatrice->dbMutex);
QSqlQuery query1; QSqlQuery query1;
query1.prepare("select 1 from " + servatrice->getDbPrefix() + "_replays_access where id_game = :id_game and id_player = :id_player"); query1.prepare("select 1 from " + servatrice->getDbPrefix() + "_replays_access a left join " + servatrice->getDbPrefix() + "_replays b on a.id_game = b.id_game where b.id = :id_replay and a.id_player = :id_player");
query1.bindValue(":id_game", cmd.game_id()); query1.bindValue(":id_replay", cmd.replay_id());
query1.bindValue(":id_player", userInfo->id()); query1.bindValue(":id_player", userInfo->id());
if (!servatrice->execSqlQuery(query1)) if (!servatrice->execSqlQuery(query1))
return Response::RespInternalError; return Response::RespInternalError;
...@@ -544,8 +558,8 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDownload(const Command_Re ...@@ -544,8 +558,8 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDownload(const Command_Re
return Response::RespAccessDenied; return Response::RespAccessDenied;
QSqlQuery query2; QSqlQuery query2;
query2.prepare("select replay from " + servatrice->getDbPrefix() + "_games where id = :id_game"); query2.prepare("select replay from " + servatrice->getDbPrefix() + "_replays where id = :id_replay");
query2.bindValue(":id_game", cmd.game_id()); query2.bindValue(":id_replay", cmd.replay_id());
if (!servatrice->execSqlQuery(query2)) if (!servatrice->execSqlQuery(query2))
return Response::RespInternalError; return Response::RespInternalError;
if (!query2.next()) if (!query2.next())
...@@ -560,6 +574,22 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDownload(const Command_Re ...@@ -560,6 +574,22 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDownload(const Command_Re
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode ServerSocketInterface::cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer & /*rc*/)
{
if (authState != PasswordRight)
return Response::RespFunctionNotAllowed;
QMutexLocker dbLocker(&servatrice->dbMutex);
QSqlQuery query1;
query1.prepare("update " + servatrice->getDbPrefix() + "_replays_access set do_not_hide=:do_not_hide where id_player = :id_player and id_game = :id_game");
query1.bindValue(":id_player", userInfo->id());
query1.bindValue(":id_game", cmd.game_id());
query1.bindValue(":do_not_hide", cmd.do_not_hide());
return servatrice->execSqlQuery(query1) ? Response::RespOk : Response::RespNameNotFound;
}
// MODERATOR FUNCTIONS. // MODERATOR FUNCTIONS.
// May be called by admins and moderators. Permission is checked by the calling function. // May be called by admins and moderators. Permission is checked by the calling function.
......
...@@ -63,6 +63,7 @@ private: ...@@ -63,6 +63,7 @@ private:
Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc); Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayList(const Command_ReplayList &cmd, ResponseContainer &rc); Response::ResponseCode cmdReplayList(const Command_ReplayList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc); Response::ResponseCode cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer &rc);
Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc); Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc);
Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc); Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc);
Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc); Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment