From 39fcabe921be14878d894b052fa23c56062d8d88 Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Sun, 16 Aug 2015 15:09:02 -0400 Subject: [PATCH 01/11] Allows moderators to promote users to mod and demote mod to user --- cockatrice/src/abstractclient.cpp | 3 ++ cockatrice/src/abstractclient.h | 2 + cockatrice/src/tab_supervisor.cpp | 18 ++++++-- cockatrice/src/tab_supervisor.h | 4 +- cockatrice/src/user_context_menu.cpp | 54 ++++++++++++++++++++++++ cockatrice/src/user_context_menu.h | 2 + common/pb/CMakeLists.txt | 2 + common/pb/admin_commands.proto | 10 +++++ common/pb/event_connection_closed.proto | 1 + common/pb/event_notify_user.proto | 14 ++++++ common/pb/response.proto | 1 + common/pb/response_adjust_mod.proto | 7 +++ common/pb/session_event.proto | 1 + servatrice/src/serversocketinterface.cpp | 53 +++++++++++++++++++++++ servatrice/src/serversocketinterface.h | 1 + 15 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 common/pb/event_notify_user.proto create mode 100644 common/pb/response_adjust_mod.proto diff --git a/cockatrice/src/abstractclient.cpp b/cockatrice/src/abstractclient.cpp index f2e8915b..6faf6b33 100644 --- a/cockatrice/src/abstractclient.cpp +++ b/cockatrice/src/abstractclient.cpp @@ -8,6 +8,7 @@ #include "pb/event_server_shutdown.pb.h" #include "pb/event_connection_closed.pb.h" #include "pb/event_user_message.pb.h" +#include "pb/event_notify_user.pb.h" #include "pb/event_list_rooms.pb.h" #include "pb/event_add_to_list.pb.h" #include "pb/event_remove_from_list.pb.h" @@ -40,6 +41,7 @@ AbstractClient::AbstractClient(QObject *parent) qRegisterMetaType("Event_ListRooms"); qRegisterMetaType("Event_GameJoined"); qRegisterMetaType("Event_UserMessage"); + qRegisterMetaType("Event_NotifyUser"); qRegisterMetaType("ServerInfo_User"); qRegisterMetaType >("QList"); qRegisterMetaType("Event_ReplayAdded"); @@ -75,6 +77,7 @@ void AbstractClient::processProtocolItem(const ServerMessage &item) case SessionEvent::SERVER_SHUTDOWN: emit serverShutdownEventReceived(event.GetExtension(Event_ServerShutdown::ext)); break; case SessionEvent::CONNECTION_CLOSED: emit connectionClosedEventReceived(event.GetExtension(Event_ConnectionClosed::ext)); break; case SessionEvent::USER_MESSAGE: emit userMessageEventReceived(event.GetExtension(Event_UserMessage::ext)); break; + case SessionEvent::NOTIFY_USER: emit notifyUserEventReceived(event.GetExtension(Event_NotifyUser::ext)); break; case SessionEvent::LIST_ROOMS: emit listRoomsEventReceived(event.GetExtension(Event_ListRooms::ext)); break; case SessionEvent::ADD_TO_LIST: emit addToListEventReceived(event.GetExtension(Event_AddToList::ext)); break; case SessionEvent::REMOVE_FROM_LIST: emit removeFromListEventReceived(event.GetExtension(Event_RemoveFromList::ext)); break; diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index df029a1e..939066bc 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -21,6 +21,7 @@ class Event_ServerMessage; class Event_ListRooms; class Event_GameJoined; class Event_UserMessage; +class Event_NotifyUser; class Event_ConnectionClosed; class Event_ServerShutdown; class Event_ReplayAdded; @@ -56,6 +57,7 @@ signals: void listRoomsEventReceived(const Event_ListRooms &event); void gameJoinedEventReceived(const Event_GameJoined &event); void userMessageEventReceived(const Event_UserMessage &event); + void notifyUserEventReceived(const Event_NotifyUser &event); void userInfoChanged(const ServerInfo_User &userInfo); void buddyListReceived(const QList &buddyList); void ignoreListReceived(const QList &ignoreList); diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index 47da8702..9bde53b2 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #include #include "tab_supervisor.h" #include "abstractclient.h" @@ -13,14 +16,12 @@ #include "pixmapgenerator.h" #include "userlist.h" #include "settingscache.h" -#include -#include -#include #include "pb/room_commands.pb.h" #include "pb/room_event.pb.h" #include "pb/game_event_container.pb.h" #include "pb/event_user_message.pb.h" +#include "pb/event_notify_user.pb.h" #include "pb/event_game_joined.pb.h" #include "pb/serverinfo_user.pb.h" #include "pb/serverinfo_room.pb.h" @@ -90,6 +91,7 @@ TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent) connect(client, SIGNAL(gameJoinedEventReceived(const Event_GameJoined &)), this, SLOT(gameJoined(const Event_GameJoined &))); connect(client, SIGNAL(userMessageEventReceived(const Event_UserMessage &)), this, SLOT(processUserMessageEvent(const Event_UserMessage &))); connect(client, SIGNAL(maxPingTime(int, int)), this, SLOT(updatePingTime(int, int))); + connect(client, SIGNAL(notifyUserEventReceived(const Event_NotifyUser &)), this, SLOT(processNotifyUserEvent(const Event_NotifyUser &))); retranslateUi(); } @@ -559,3 +561,13 @@ bool TabSupervisor::getAdminLocked() const return true; return tabAdmin->getLocked(); } + +void TabSupervisor::processNotifyUserEvent(const Event_NotifyUser &event) +{ + switch ((Event_NotifyUser::NotificationType) event.type()) { + case Event_NotifyUser::PROMOTED: QMessageBox::information(this, tr("Promotion"), tr("You have been promoted to moderator. Please log out and back in for changes to take effect.")); break; + default: ; + } + +} + diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index a29c316c..13722032 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -22,6 +22,7 @@ class RoomEvent; class GameEventContainer; class Event_GameJoined; class Event_UserMessage; +class Event_NotifyUser; class ServerInfo_Room; class ServerInfo_User; class GameReplay; @@ -105,6 +106,7 @@ private slots: void processRoomEvent(const RoomEvent &event); void processGameEventContainer(const GameEventContainer &cont); void processUserMessageEvent(const Event_UserMessage &event); + void processNotifyUserEvent(const Event_NotifyUser &event); }; -#endif +#endif \ No newline at end of file diff --git a/cockatrice/src/user_context_menu.cpp b/cockatrice/src/user_context_menu.cpp index 758f99e1..2925cd19 100644 --- a/cockatrice/src/user_context_menu.cpp +++ b/cockatrice/src/user_context_menu.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "user_context_menu.h" #include "tab_supervisor.h" #include "tab_userlists.h" @@ -31,6 +32,8 @@ UserContextMenu::UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *p aRemoveFromIgnoreList = new QAction(QString(), this); aKick = new QAction(QString(), this); aBan = new QAction(QString(), this); + aPromoteToMod = new QAction(QString(), this); + aDemoteFromMod = new QAction(QString(), this); retranslateUi(); } @@ -46,6 +49,8 @@ void UserContextMenu::retranslateUi() aRemoveFromIgnoreList->setText(tr("Remove from &ignore list")); aKick->setText(tr("Kick from &game")); aBan->setText(tr("Ban from &server")); + aPromoteToMod->setText(tr("&Promote user to moderator")); + aDemoteFromMod->setText(tr("Dem&ote user from moderator")); } void UserContextMenu::gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer) @@ -89,6 +94,27 @@ void UserContextMenu::banUser_processUserInfoResponse(const Response &r) dlg->show(); } +void UserContextMenu::adjustMod_processUserResponse(const Response &resp, const CommandContainer &commandContainer) +{ + + const Command_AdjustMod &cmd = commandContainer.admin_command(0).GetExtension(Command_AdjustMod::ext); + + if (resp.response_code() == Response::RespOk) { + if (cmd.should_be_mod()) { + QMessageBox::information(static_cast(parent()), tr("Success"), tr("Successfully promoted user.")); + } else { + QMessageBox::information(static_cast(parent()), tr("Success"), tr("Successfully demoted user.")); + } + + } else { + if (cmd.should_be_mod()) { + QMessageBox::information(static_cast(parent()), tr("Failed"), tr("Failed to promote user.")); + } else { + QMessageBox::information(static_cast(parent()), tr("Failed"), tr("Failed to demote user.")); + } + } +} + void UserContextMenu::banUser_dialogFinished() { BanDialog *dlg = static_cast(sender()); @@ -132,6 +158,14 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName if (!tabSupervisor->getAdminLocked()) { menu->addSeparator(); menu->addAction(aBan); + + menu->addSeparator(); + if (userLevel.testFlag(ServerInfo_User::IsModerator) && (tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsAdmin)) { + menu->addAction(aDemoteFromMod); + + } else if (userLevel.testFlag(ServerInfo_User::IsRegistered) && (tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsAdmin)) { + menu->addAction(aPromoteToMod); + } } bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name()); aDetails->setEnabled(online); @@ -143,6 +177,8 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName aRemoveFromIgnoreList->setEnabled(anotherUser); aKick->setEnabled(anotherUser); aBan->setEnabled(anotherUser); + aPromoteToMod->setEnabled(anotherUser); + aDemoteFromMod->setEnabled(anotherUser); QAction *actionClicked = menu->exec(pos); if (actionClicked == aDetails) { @@ -186,6 +222,7 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName } else if (actionClicked == aKick) { Command_KickFromGame cmd; cmd.set_player_id(playerId); + game->sendGameCommand(cmd); } else if (actionClicked == aBan) { Command_GetUserInfo cmd; @@ -193,7 +230,24 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName PendingCommand *pend = client->prepareSessionCommand(cmd); connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(banUser_processUserInfoResponse(Response))); + client->sendCommand(pend); + } else if (actionClicked == aPromoteToMod) { + Command_AdjustMod cmd; + cmd.set_user_name(userName.toStdString()); + cmd.set_should_be_mod(true); + // client->sendCommand(client->prepareAdminCommand(cmd)); + PendingCommand *pend = client->prepareAdminCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(adjustMod_processUserResponse(Response,CommandContainer))); + client->sendCommand(pend); + } else if (actionClicked == aDemoteFromMod) { + Command_AdjustMod cmd; + cmd.set_user_name(userName.toStdString()); + cmd.set_should_be_mod(false); + + // client->sendCommand(client->prepareAdminCommand(cmd)); + PendingCommand *pend = client->prepareAdminCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(adjustMod_processUserResponse(Response,CommandContainer))); client->sendCommand(pend); } diff --git a/cockatrice/src/user_context_menu.h b/cockatrice/src/user_context_menu.h index 9aeadfd4..dd0d1ed5 100644 --- a/cockatrice/src/user_context_menu.h +++ b/cockatrice/src/user_context_menu.h @@ -27,10 +27,12 @@ private: QAction *aAddToIgnoreList, *aRemoveFromIgnoreList; QAction *aKick; QAction *aBan; + QAction *aPromoteToMod, *aDemoteFromMod; signals: void openMessageDialog(const QString &userName, bool focus); private slots: void banUser_processUserInfoResponse(const Response &resp); + void adjustMod_processUserResponse(const Response &resp, const CommandContainer &commandContainer); void banUser_dialogFinished(); void gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer); public: diff --git a/common/pb/CMakeLists.txt b/common/pb/CMakeLists.txt index db5cd130..d58846c6 100644 --- a/common/pb/CMakeLists.txt +++ b/common/pb/CMakeLists.txt @@ -106,6 +106,7 @@ SET(PROTO_FILES event_user_joined.proto event_user_left.proto event_user_message.proto + event_notify_user.proto game_commands.proto game_event_container.proto game_event_context.proto @@ -127,6 +128,7 @@ SET(PROTO_FILES response_register.proto response_replay_download.proto response_replay_list.proto + response_adjust_mod.proto response.proto room_commands.proto room_event.proto diff --git a/common/pb/admin_commands.proto b/common/pb/admin_commands.proto index b23f745d..8e2757ae 100644 --- a/common/pb/admin_commands.proto +++ b/common/pb/admin_commands.proto @@ -3,6 +3,7 @@ message AdminCommand { UPDATE_SERVER_MESSAGE = 1000; SHUTDOWN_SERVER = 1001; RELOAD_CONFIG = 1002; + ADJUST_MOD = 1003; } extensions 100 to max; } @@ -26,3 +27,12 @@ message Command_ReloadConfig { optional Command_ReloadConfig ext = 1002; } } + +message Command_AdjustMod { + extend AdminCommand { + optional Command_AdjustMod ext = 1003; + } + required string user_name = 1; + required bool should_be_mod = 2; +} + diff --git a/common/pb/event_connection_closed.proto b/common/pb/event_connection_closed.proto index d5972aa4..c59a4f74 100644 --- a/common/pb/event_connection_closed.proto +++ b/common/pb/event_connection_closed.proto @@ -11,6 +11,7 @@ message Event_ConnectionClosed { BANNED = 4; USERNAMEINVALID = 5; USER_LIMIT_REACHED = 6; + DEMOTED = 7; } optional CloseReason reason = 1; optional string reason_str = 2; diff --git a/common/pb/event_notify_user.proto b/common/pb/event_notify_user.proto new file mode 100644 index 00000000..e300f45a --- /dev/null +++ b/common/pb/event_notify_user.proto @@ -0,0 +1,14 @@ +import "session_event.proto"; + +message Event_NotifyUser { + + enum NotificationType { + PROMOTED = 1; + } + + extend SessionEvent { + optional Event_NotifyUser ext = 1010; + } + optional NotificationType type = 1; + +} diff --git a/common/pb/response.proto b/common/pb/response.proto index ae4ff040..aa004006 100644 --- a/common/pb/response.proto +++ b/common/pb/response.proto @@ -49,6 +49,7 @@ message Response { DECK_UPLOAD = 1008; REGISTER = 1009; ACTIVATE = 1010; + ADJUST_MOD = 1011; REPLAY_LIST = 1100; REPLAY_DOWNLOAD = 1101; } diff --git a/common/pb/response_adjust_mod.proto b/common/pb/response_adjust_mod.proto new file mode 100644 index 00000000..e5dac6d8 --- /dev/null +++ b/common/pb/response_adjust_mod.proto @@ -0,0 +1,7 @@ +import "response.proto"; + +message Response_AdjustMod{ + extend Response { + optional Response_AdjustMod ext = 1011; + } +} diff --git a/common/pb/session_event.proto b/common/pb/session_event.proto index a7b14d00..1bfcbf88 100644 --- a/common/pb/session_event.proto +++ b/common/pb/session_event.proto @@ -12,6 +12,7 @@ message SessionEvent { USER_JOINED = 1007; USER_LEFT = 1008; GAME_JOINED = 1009; + NOTIFY_USER = 1010; REPLAY_ADDED = 1100; } extensions 100 to max; diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index db87c70d..a50ca128 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -49,6 +49,7 @@ #include "pb/event_server_identification.pb.h" #include "pb/event_add_to_list.pb.h" #include "pb/event_remove_from_list.pb.h" +#include "pb/event_notify_user.pb.h" #include "pb/response_deck_list.pb.h" #include "pb/response_deck_download.pb.h" #include "pb/response_deck_upload.pb.h" @@ -309,6 +310,7 @@ Response::ResponseCode ServerSocketInterface::processExtendedAdminCommand(int cm case AdminCommand::SHUTDOWN_SERVER: return cmdShutdownServer(cmd.GetExtension(Command_ShutdownServer::ext), rc); case AdminCommand::UPDATE_SERVER_MESSAGE: return cmdUpdateServerMessage(cmd.GetExtension(Command_UpdateServerMessage::ext), rc); case AdminCommand::RELOAD_CONFIG: return cmdReloadConfig(cmd.GetExtension(Command_ReloadConfig::ext), rc); + case AdminCommand::ADJUST_MOD: return cmdAdjustMod(cmd.GetExtension(Command_AdjustMod::ext), rc); default: return Response::RespFunctionNotAllowed; } } @@ -1000,3 +1002,54 @@ Response::ResponseCode ServerSocketInterface::cmdReloadConfig(const Command_Relo settingsCache->sync(); return Response::RespOk; } + +Response::ResponseCode ServerSocketInterface::cmdAdjustMod(const Command_AdjustMod &cmd, ResponseContainer & /*rc*/) { + + QString userName = QString::fromStdString(cmd.user_name()); + + if (cmd.should_be_mod()) { + logDebugMessage("Received admin command: promote user"); + QSqlQuery *query = sqlInterface->prepareQuery( + "update {prefix}_users set admin = :adminlevel where name = :username"); + query->bindValue(":adminlevel", 2); + query->bindValue(":username", userName); + if (!sqlInterface->execSqlQuery(query)) + return Response::RespInternalError; + + ServerSocketInterface *user = static_cast(server->getUsers().value(userName)); + Event_NotifyUser event; + event.set_type(Event_NotifyUser::PROMOTED); + SessionEvent *se = user->prepareSessionEvent(event); + user->sendProtocolItem(*se); + delete se; + + } else { + logDebugMessage("Received admin command: demote user"); + QSqlQuery *query = sqlInterface->prepareQuery("update {prefix}_users set admin = :adminlevel where name = :username"); + query->bindValue(":adminlevel", 0); + query->bindValue(":username", userName); + if (!sqlInterface->execSqlQuery(query)) + return Response::RespInternalError; + + QList userList; + ServerSocketInterface *user = static_cast(server->getUsers().value(userName)); + userList.append(user); + + if (!userList.isEmpty()) { + Event_ConnectionClosed event; + event.set_reason(Event_ConnectionClosed::DEMOTED); + event.set_reason_str("Your moderator status has been revoked."); + event.set_end_time(QDateTime::currentDateTime().toTime_t()); + for (int i = 0; i < userList.size(); ++i) { + SessionEvent *se = userList[i]->prepareSessionEvent(event); + userList[i]->sendProtocolItem(*se); + delete se; + QMetaObject::invokeMethod(userList[i], "prepareDestroy", Qt::QueuedConnection); + } + userList.clear(); + } + + } + + return Response::RespOk; +} \ No newline at end of file diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index ccec5519..a733c6b7 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -100,6 +100,7 @@ private: Response::ResponseCode cmdRegisterAccount(const Command_Register &cmd, ResponseContainer &rc); Response::ResponseCode cmdActivateAccount(const Command_Activate &cmd, ResponseContainer & /* rc */); Response::ResponseCode cmdReloadConfig(const Command_ReloadConfig &/* cmd */, ResponseContainer & /*rc*/); + Response::ResponseCode cmdAdjustMod(const Command_AdjustMod &cmd, ResponseContainer & /*rc*/); Response::ResponseCode processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc); Response::ResponseCode processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc); From 41b10308ba34f2b02a252393afa55ed070ac2186 Mon Sep 17 00:00:00 2001 From: Zach H Date: Sat, 15 Aug 2015 21:31:30 -0400 Subject: [PATCH 02/11] country to lower (fix win bug) --- cockatrice/src/dlg_edit_user.cpp | 2 +- cockatrice/src/dlg_register.cpp | 2 -- cockatrice/src/pixmapgenerator.cpp | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cockatrice/src/dlg_edit_user.cpp b/cockatrice/src/dlg_edit_user.cpp index b2702462..932dfa12 100644 --- a/cockatrice/src/dlg_edit_user.cpp +++ b/cockatrice/src/dlg_edit_user.cpp @@ -35,7 +35,7 @@ DlgEditUser::DlgEditUser(QWidget *parent, QString email, int gender, QString cou foreach(QString c, countries) { countryEdit->addItem(QPixmap(":/resources/countries/" + c + ".svg"), c); - if(c == country) + if (c == country) countryEdit->setCurrentIndex(i); ++i; diff --git a/cockatrice/src/dlg_register.cpp b/cockatrice/src/dlg_register.cpp index 54442f10..bda76b48 100644 --- a/cockatrice/src/dlg_register.cpp +++ b/cockatrice/src/dlg_register.cpp @@ -62,9 +62,7 @@ DlgRegister::DlgRegister(QWidget *parent) countryEdit->setCurrentIndex(0); QStringList countries = settingsCache->getCountries(); foreach(QString c, countries) - { countryEdit->addItem(QPixmap(":/resources/countries/" + c + ".svg"), c); - } realnameLabel = new QLabel(tr("Real name:")); realnameEdit = new QLineEdit(); diff --git a/cockatrice/src/pixmapgenerator.cpp b/cockatrice/src/pixmapgenerator.cpp index 0ff25f57..17d576c9 100644 --- a/cockatrice/src/pixmapgenerator.cpp +++ b/cockatrice/src/pixmapgenerator.cpp @@ -119,7 +119,7 @@ QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countr if (pmCache.contains(key)) return pmCache.value(key); - QSvgRenderer svg(QString(":/resources/countries/" + countryCode + ".svg")); + QSvgRenderer svg(QString(":/resources/countries/" + countryCode.toLower() + ".svg")); int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height()); QPixmap pixmap(width, height); pixmap.fill(Qt::transparent); From 6170c9037f08f0b14b0b7cc1818fd9d82e9b41dc Mon Sep 17 00:00:00 2001 From: Daenyth Date: Sun, 9 Aug 2015 16:18:58 -0400 Subject: [PATCH 03/11] Fix #1351 - Server ignores only-reg if in "none" auth mode. When in none auth mode, registered users don't exist; hence the setting makes the game impossible to join. Normally the setting would be greyed out when the user is unregistered, but commit 475c54bf introduced a new edge case where the stored setting would apply to the field even if the user is unregistered, making the setting possible to apply in no-reg mode. Regardless, any client could have done this, not just the default cockatrice. The server side fix should prevent all issues in the future. --- cockatrice/src/dlg_creategame.cpp | 8 +++++++- common/server.h | 1 + common/server_protocolhandler.cpp | 4 +++- servatrice/src/servatrice.h | 1 + 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index 2997779e..745c5ee5 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -114,7 +114,13 @@ DlgCreateGame::DlgCreateGame(TabRoom *_room, const QMap &_gameType descriptionEdit->setText(settingsCache->getGameDescription()); maxPlayersEdit->setValue(settingsCache->getMaxPlayers()); onlyBuddiesCheckBox->setChecked(settingsCache->getOnlyBuddies()); - onlyRegisteredCheckBox->setChecked(settingsCache->getOnlyRegistered()); + if (room && room->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) + { + onlyRegisteredCheckBox->setChecked(settingsCache->getOnlyRegistered()); + } else { + onlyBuddiesCheckBox->setEnabled(false); + onlyRegisteredCheckBox->setEnabled(false); + } spectatorsAllowedCheckBox->setChecked(settingsCache->getSpectatorsAllowed()); spectatorsNeedPasswordCheckBox->setChecked(settingsCache->getSpectatorsNeedPassword()); spectatorsCanTalkCheckBox->setChecked(settingsCache->getSpectatorsCanTalk()); diff --git a/common/server.h b/common/server.h index 46113a50..494ec534 100644 --- a/common/server.h +++ b/common/server.h @@ -55,6 +55,7 @@ public: void removeClient(Server_ProtocolHandler *player); virtual QString getLoginMessage() const { return QString(); } + virtual bool permitUnregisteredUsers() const { return true; } virtual bool getGameShouldPing() const { return false; } virtual bool getClientIdRequired() const { return false; } virtual bool getRegOnlyServer() const { return false; } diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 073a3d95..fdc6c1eb 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -636,7 +636,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_Creat if (description.size() > 60) description = description.left(60); - Server_Game *game = new Server_Game(copyUserInfo(false), gameId, description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), cmd.only_registered(), cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), room); + // When server doesn't permit registered users to exist, do not honor only-reg setting + bool onlyRegisteredUsers = cmd.only_registered() && (server->permitUnregisteredUsers()); + Server_Game *game = new Server_Game(copyUserInfo(false), gameId, description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), onlyRegisteredUsers, cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), room); game->addPlayer(this, rc, false, false); room->addGame(game); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 500df92c..4e4a74b2 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -136,6 +136,7 @@ public: bool initServer(); QString getServerName() const { return serverName; } QString getLoginMessage() const { QMutexLocker locker(&loginMessageMutex); return loginMessage; } + bool permitUnregisteredUsers() const { return authenticationMethod != AuthenticationNone; } bool getGameShouldPing() const { return true; } bool getClientIdRequired() const { return clientIdRequired; } bool getRegOnlyServer() const { return regServerOnly; } From 66f14c1168b0fc8929b9f8ea415ade1b3e745396 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 21 Aug 2015 23:03:15 -0400 Subject: [PATCH 04/11] Address PR feedback --- cockatrice/src/user_context_menu.cpp | 16 ++------- servatrice/src/serversocketinterface.cpp | 41 ++++++++++++------------ 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/cockatrice/src/user_context_menu.cpp b/cockatrice/src/user_context_menu.cpp index 2925cd19..9bf0f484 100644 --- a/cockatrice/src/user_context_menu.cpp +++ b/cockatrice/src/user_context_menu.cpp @@ -231,23 +231,13 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName PendingCommand *pend = client->prepareSessionCommand(cmd); connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(banUser_processUserInfoResponse(Response))); client->sendCommand(pend); - } else if (actionClicked == aPromoteToMod) { + } else if (actionClicked == aPromoteToMod || actionClicked == aDemoteFromMod) { Command_AdjustMod cmd; cmd.set_user_name(userName.toStdString()); - cmd.set_should_be_mod(true); + cmd.set_should_be_mod(actionClicked == aPromoteToMod); - // client->sendCommand(client->prepareAdminCommand(cmd)); PendingCommand *pend = client->prepareAdminCommand(cmd); - connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(adjustMod_processUserResponse(Response,CommandContainer))); - client->sendCommand(pend); - } else if (actionClicked == aDemoteFromMod) { - Command_AdjustMod cmd; - cmd.set_user_name(userName.toStdString()); - cmd.set_should_be_mod(false); - - // client->sendCommand(client->prepareAdminCommand(cmd)); - PendingCommand *pend = client->prepareAdminCommand(cmd); - connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(adjustMod_processUserResponse(Response,CommandContainer))); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(adjustMod_processUserResponse(Response, CommandContainer))); client->sendCommand(pend); } diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index a50ca128..84c1002d 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -19,6 +19,7 @@ ***************************************************************************/ #include +#include #include #include #include @@ -1008,47 +1009,45 @@ Response::ResponseCode ServerSocketInterface::cmdAdjustMod(const Command_AdjustM QString userName = QString::fromStdString(cmd.user_name()); if (cmd.should_be_mod()) { - logDebugMessage("Received admin command: promote user"); QSqlQuery *query = sqlInterface->prepareQuery( "update {prefix}_users set admin = :adminlevel where name = :username"); query->bindValue(":adminlevel", 2); query->bindValue(":username", userName); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)){ + logger->logMessage(QString::fromStdString("Failed to promote user %1: %2").arg(userName).arg(query->lastError().text())); return Response::RespInternalError; + } ServerSocketInterface *user = static_cast(server->getUsers().value(userName)); - Event_NotifyUser event; - event.set_type(Event_NotifyUser::PROMOTED); - SessionEvent *se = user->prepareSessionEvent(event); - user->sendProtocolItem(*se); - delete se; - + if (user) { + Event_NotifyUser event; + event.set_type(Event_NotifyUser::PROMOTED); + SessionEvent *se = user->prepareSessionEvent(event); + user->sendProtocolItem(*se); + delete se; + } } else { - logDebugMessage("Received admin command: demote user"); QSqlQuery *query = sqlInterface->prepareQuery("update {prefix}_users set admin = :adminlevel where name = :username"); query->bindValue(":adminlevel", 0); query->bindValue(":username", userName); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)){ + logger->logMessage(QString::fromStdString("Failed to demote user %1: %2").arg(userName).arg(query->lastError().text())); return Response::RespInternalError; + } - QList userList; ServerSocketInterface *user = static_cast(server->getUsers().value(userName)); - userList.append(user); - - if (!userList.isEmpty()) { + if (user) { Event_ConnectionClosed event; event.set_reason(Event_ConnectionClosed::DEMOTED); event.set_reason_str("Your moderator status has been revoked."); event.set_end_time(QDateTime::currentDateTime().toTime_t()); - for (int i = 0; i < userList.size(); ++i) { - SessionEvent *se = userList[i]->prepareSessionEvent(event); - userList[i]->sendProtocolItem(*se); - delete se; - QMetaObject::invokeMethod(userList[i], "prepareDestroy", Qt::QueuedConnection); - } - userList.clear(); + + SessionEvent *se = user->prepareSessionEvent(event); + user->sendProtocolItem(*se); + delete se; } + QMetaObject::invokeMethod(user, "prepareDestroy", Qt::QueuedConnection); } return Response::RespOk; From 34c78b31133ccbb487223f99b3be2c5fd0615479 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Sat, 22 Aug 2015 08:43:44 -0400 Subject: [PATCH 05/11] Use servatrice as docker entrypoint This lets you "docker run servatrice" and pass command line arguments --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8e77ae7e..581070cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ RUN apt-get update && apt-get install -y\ cmake\ git\ libprotobuf-dev\ + libqt5sql5-mysql\ libqt5svg5-dev\ libqt5webkit5-dev\ libsqlite3-dev\ @@ -37,4 +38,4 @@ WORKDIR /home/servatrice EXPOSE 4747 -CMD servatrice +ENTRYPOINT [ "servatrice" ] From b0630b81ca38754833ccb2f17d6ecf45dd0f7706 Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Sat, 22 Aug 2015 00:37:29 -0400 Subject: [PATCH 06/11] Log old session out of server if logging in from a second location --- cockatrice/src/window_main.cpp | 1 + common/pb/event_connection_closed.proto | 1 + common/server.cpp | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index a2edd199..1653e7f7 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -85,6 +85,7 @@ void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &even } case Event_ConnectionClosed::SERVER_SHUTDOWN: reasonStr = tr("Scheduled server shutdown."); break; case Event_ConnectionClosed::USERNAMEINVALID: reasonStr = tr("Invalid username."); break; + case Event_ConnectionClosed::LOGGEDINELSEWERE: reasonStr = tr("You have been logged out due to logging in at another location."); break; default: reasonStr = QString::fromStdString(event.reason_str()); } QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr)); diff --git a/common/pb/event_connection_closed.proto b/common/pb/event_connection_closed.proto index c59a4f74..c1c85ab5 100644 --- a/common/pb/event_connection_closed.proto +++ b/common/pb/event_connection_closed.proto @@ -12,6 +12,7 @@ message Event_ConnectionClosed { USERNAMEINVALID = 5; USER_LIMIT_REACHED = 6; DEMOTED = 7; + LOGGEDINELSEWERE = 8; } optional CloseReason reason = 1; optional string reason_str = 2; diff --git a/common/server.cpp b/common/server.cpp index 2fb064bc..c320ebba 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -30,6 +30,7 @@ #include "pb/event_user_left.pb.h" #include "pb/event_list_rooms.pb.h" #include "pb/session_event.pb.h" +#include "pb/event_connection_closed.pb.h" #include "pb/isl_message.pb.h" #include #include @@ -126,9 +127,17 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString // verify that new session would not cause problems with older existing session if (users.contains(name) || databaseInterface->userSessionExists(name)) { - qDebug("Login denied: would overwrite old session"); - databaseInterface->unlockSessionTables(); - return WouldOverwriteOldSession; + qDebug("Session already logged in, logging old session out"); + + Event_ConnectionClosed event; + event.set_reason(Event_ConnectionClosed::LOGGEDINELSEWERE); + event.set_reason_str("You have been logged out due to logging in at another location."); + event.set_end_time(QDateTime::currentDateTime().toTime_t()); + + SessionEvent *se = users.value(name)->prepareSessionEvent(event); + users.value(name)->sendProtocolItem(*se); + delete se; + } } else if (authState == UnknownUser) { // Change user name so that no two users have the same names, From ca82fd867a6746023bca557b5668a0f788afc236 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 22 Aug 2015 15:29:00 -0400 Subject: [PATCH 07/11] Option to opt-out of remember game settings --- cockatrice/src/dlg_creategame.cpp | 30 ++++++++++++++++++++---------- cockatrice/src/dlg_creategame.h | 1 + cockatrice/src/settingscache.cpp | 7 +++++++ cockatrice/src/settingscache.h | 3 +++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index 745c5ee5..0f8cea4f 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -21,6 +21,7 @@ void DlgCreateGame::sharedCtor() { + rememberGameSettings = new QCheckBox(tr("Re&member settings")); descriptionLabel = new QLabel(tr("&Description:")); descriptionEdit = new QLineEdit; descriptionLabel->setBuddy(descriptionEdit); @@ -38,6 +39,7 @@ void DlgCreateGame::sharedCtor() generalGrid->addWidget(descriptionEdit, 0, 1); generalGrid->addWidget(maxPlayersLabel, 1, 0); generalGrid->addWidget(maxPlayersEdit, 1, 1); + generalGrid->addWidget(rememberGameSettings, 2, 0); QVBoxLayout *gameTypeLayout = new QVBoxLayout; QMapIterator gameTypeIterator(gameTypes); @@ -111,6 +113,7 @@ DlgCreateGame::DlgCreateGame(TabRoom *_room, const QMap &_gameType { sharedCtor(); + rememberGameSettings->setChecked(settingsCache->getRememberGameSettings()); descriptionEdit->setText(settingsCache->getGameDescription()); maxPlayersEdit->setValue(settingsCache->getMaxPlayers()); onlyBuddiesCheckBox->setChecked(settingsCache->getOnlyBuddies()); @@ -126,6 +129,10 @@ DlgCreateGame::DlgCreateGame(TabRoom *_room, const QMap &_gameType spectatorsCanTalkCheckBox->setChecked(settingsCache->getSpectatorsCanTalk()); spectatorsSeeEverythingCheckBox->setChecked(settingsCache->getSpectatorsCanSeeEverything()); + if (!rememberGameSettings->isChecked()){ + actReset(); + } + clearButton = new QPushButton(tr("&Clear")); buttonBox->addButton(QDialogButtonBox::Cancel); buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole); @@ -140,6 +147,7 @@ DlgCreateGame::DlgCreateGame(const ServerInfo_Game &gameInfo, const QMapsetEnabled(false); descriptionEdit->setEnabled(false); maxPlayersEdit->setEnabled(false); passwordEdit->setEnabled(false); @@ -203,15 +211,6 @@ descriptionEdit->setFocus(); void DlgCreateGame::actOK() { - settingsCache->setGameDescription(descriptionEdit->text()); - settingsCache->setMaxPlayers(maxPlayersEdit->value()); - settingsCache->setOnlyBuddies(onlyBuddiesCheckBox->isChecked()); - settingsCache->setOnlyRegistered(onlyRegisteredCheckBox->isChecked()); - settingsCache->setSpectatorsAllowed(spectatorsAllowedCheckBox->isChecked()); - settingsCache->setSpectatorsNeedPassword(spectatorsNeedPasswordCheckBox->isChecked()); - settingsCache->setSpectatorsCanTalk(spectatorsCanTalkCheckBox->isChecked()); - settingsCache->setSpectatorsCanSeeEverything(spectatorsSeeEverythingCheckBox->isChecked()); - Command_CreateGame cmd; cmd.set_description(descriptionEdit->text().simplified().toStdString()); cmd.set_password(passwordEdit->text().toStdString()); @@ -233,7 +232,18 @@ void DlgCreateGame::actOK() } } - settingsCache->setGameTypes(gameTypes); + settingsCache->setRememberGameSettings(rememberGameSettings->isChecked()); + if (rememberGameSettings->isChecked()){ + settingsCache->setGameDescription(descriptionEdit->text()); + settingsCache->setMaxPlayers(maxPlayersEdit->value()); + settingsCache->setOnlyBuddies(onlyBuddiesCheckBox->isChecked()); + settingsCache->setOnlyRegistered(onlyRegisteredCheckBox->isChecked()); + settingsCache->setSpectatorsAllowed(spectatorsAllowedCheckBox->isChecked()); + settingsCache->setSpectatorsNeedPassword(spectatorsNeedPasswordCheckBox->isChecked()); + settingsCache->setSpectatorsCanTalk(spectatorsCanTalkCheckBox->isChecked()); + settingsCache->setSpectatorsCanSeeEverything(spectatorsSeeEverythingCheckBox->isChecked()); + settingsCache->setGameTypes(gameTypes); + } PendingCommand *pend = room->prepareRoomCommand(cmd); connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(checkResponse(Response))); room->sendRoomCommand(pend); diff --git a/cockatrice/src/dlg_creategame.h b/cockatrice/src/dlg_creategame.h index a0b168a1..a0c9521c 100644 --- a/cockatrice/src/dlg_creategame.h +++ b/cockatrice/src/dlg_creategame.h @@ -39,6 +39,7 @@ private: QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox, *spectatorsSeeEverythingCheckBox; QDialogButtonBox *buttonBox; QPushButton *clearButton; + QCheckBox *rememberGameSettings; void sharedCtor(); }; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 462001c6..a640e5f6 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -118,6 +118,7 @@ SettingsCache::SettingsCache() spectatorsNeedPassword = settings->value("game/spectatorsneedpassword", false).toBool(); spectatorsCanTalk = settings->value("game/spectatorscantalk", false).toBool(); spectatorsCanSeeEverything = settings->value("game/spectatorscanseeeverything", false).toBool(); + rememberGameSettings = settings->value("game/remembergamesettings", true).toBool(); clientID = settings->value("personal/clientid", "notset").toString(); QString file = getSettingsPath(); @@ -605,3 +606,9 @@ void SettingsCache::setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEv spectatorsCanSeeEverything = _spectatorsCanSeeEverything; settings->setValue("game/spectatorscanseeeverything", spectatorsCanSeeEverything); } + +void SettingsCache::setRememberGameSettings(const bool _rememberGameSettings) +{ + rememberGameSettings = _rememberGameSettings; + settings->setValue("game/remembergamesettings", rememberGameSettings); +} \ No newline at end of file diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index f8227efc..3670bc09 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -102,6 +102,7 @@ private: bool spectatorsNeedPassword; bool spectatorsCanTalk; bool spectatorsCanSeeEverything; + bool rememberGameSettings; int keepalive; QByteArray deckEditorLayoutState, deckEditorGeometry; QSize deckEditorFilterSize, deckEditorDeckSize, deckEditorCardSize; @@ -178,6 +179,7 @@ public: bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; } bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } bool getSpectatorsCanSeeEverything() const { return spectatorsCanSeeEverything; } + bool getRememberGameSettings() const { return rememberGameSettings; } int getKeepAlive() const { return keepalive; } void setClientID(QString clientID); QString getClientID() { return clientID; } @@ -257,6 +259,7 @@ public slots: void setSpectatorsNeedPassword(const bool _spectatorsNeedPassword); void setSpectatorsCanTalk(const bool _spectatorsCanTalk); void setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEverything); + void setRememberGameSettings(const bool _rememberGameSettings); }; extern SettingsCache *settingsCache; From b335bc5e7dcc78920f14001f6cad922f8de976b5 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sun, 23 Aug 2015 20:54:11 +0200 Subject: [PATCH 08/11] Translations: extracted new strings --- cockatrice/translations/cockatrice_en.ts | 1842 +++++++++++++++------- 1 file changed, 1306 insertions(+), 536 deletions(-) diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index c3fe23ab..93e4826b 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -4,17 +4,17 @@ AbstractCounter - + &Set counter... - + Set counter - + New value for counter '%1': @@ -22,86 +22,86 @@ AppearanceSettingsPage - + Zone background pictures - + Hand background: - + Stack background: - + Table background: - + Player info background: - + Card back: - + Card rendering - + Display card names on cards having a picture - + Scale cards on mouse over - + Hand layout - + Display hand horizontally (wastes space) - + Enable left justification - + Table grid layout - + Invert vertical coordinate - + Minimum player count for multi-column layout: - - - - - + + + + + Choose path @@ -119,86 +119,91 @@ - + + ban client I&D + + + + Ban type - + &permanent ban - + &temporary ban - + &Days: - + &Hours: - + &Minutes: - + Duration of the ban - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + Please enter the reason for the ban that will be visible to the banned person. - + &OK - + &Cancel - + Ban user from server - + Error - - You have to select a name-based or IP-based ban, or both. + + You have to select a name-based, IP-based, clientId based, or some combination of the three to place a ban. CardDatabase - + New sets found - + %1 new set(s) have been found in the card database. Do you want to enable them? @@ -234,17 +239,17 @@ This is only saved for moderators and cannot be seen by the banned person. CardFrame - + Image - + Description - + Both @@ -300,27 +305,32 @@ This is only saved for moderators and cannot be seen by the banned person. - + Name: - + Mana cost: - + + Color(s): + + + + Card type: - + P / T: - + Loyalty: @@ -584,12 +594,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Nothing is here... yet - + General @@ -597,17 +607,17 @@ This is only saved for moderators and cannot be seen by the banned person. DeckListModel - + Number - + Card - + Price @@ -629,42 +639,42 @@ This is only saved for moderators and cannot be seen by the banned person. DeckViewContainer - + Load local deck - + Load deck from server - + Ready to s&tart - + S&ideboard unlocked - + S&ideboard locked - + Load deck - + Error - + The selected file could not be loaded. @@ -709,38 +719,53 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - - - &Host: - - - &Port: - - - - - Player &name: - - - - - P&assword: + Previous Host + New Host + + + + + &Host: + + + + + Enter host name + + + + + &Port: + + + + + Player &name: + + + + + P&assword: + + + + &Save password - + A&uto connect at start - + Connect to server @@ -748,82 +773,87 @@ This is only saved for moderators and cannot be seen by the banned person. DlgCreateGame - + &Description: - + &Password: - + P&layers: - + Game type - + Only &buddies can join - + Only &registered users can join - + Joining restrictions - + &Spectators can watch - + Spectators &need a password to watch - + Spectators can see &hands - + Spectators can &chat - + Spectators - + + &Clear + + + + Create game - + Game information - + Error - + Server error. @@ -1188,7 +1218,7 @@ Make sure to enable the 'token set' in the 'Edit sets...' di DlgLoadDeckFromClipboard - + &Refresh @@ -1198,14 +1228,14 @@ Make sure to enable the 'token set' in the 'Edit sets...' di - - + + Error - - + + Invalid deck list. @@ -1221,67 +1251,93 @@ Make sure to enable the 'token set' in the 'Edit sets...' di DlgRegister - + &Host: - + &Port: - + Player &name: - + P&assword: - + + Password (again): + + + + Email: - + + Email (again): + + + + Pronouns: - + Neutral - + Masculine - + Feminine - + Undefined - + + + Registration Warning + + + + + Your passwords do not match, please try again. + + + + + Your email addresses do not match, please try again. + + + + Country: - + Real name: - + Register to server @@ -1289,19 +1345,19 @@ Make sure to enable the 'token set' in the 'Edit sets...' di DlgSettings - - - + + + Error - + Unknown Error loading card database - + Your card database is invalid. Cockatrice may not function correctly with an invalid database @@ -1312,7 +1368,7 @@ Would you like to change your database location setting? - + Your card database version is too old. This can cause problems loading card information or images @@ -1323,21 +1379,21 @@ Would you like to change your database location setting? - + File Error loading your card database. Would you like to change your database location setting? - + Your card database was loaded but contains no cards. Would you like to change your database location setting? - + Your card database did not finish loading Please file a ticket at http://github.com/Cockatrice/Cockatrice/issues with your cards.xml attached @@ -1346,7 +1402,7 @@ Would you like to change your database location setting? - + Unknown card database load status Please file a ticket at http://github.com/Cockatrice/Cockatrice/issues @@ -1355,50 +1411,55 @@ Would you like to change your database location setting? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User Interface - + Deck Editor - + Chat - + Sound + + + Shortcuts + + GameSelector @@ -1411,7 +1472,7 @@ Would you like to change your database location setting? - + Error @@ -1456,47 +1517,47 @@ Would you like to change your database location setting? - + Join game - + Password: - + Please join the respective room first. - + Games + + + &Filter games + + - Filter games + C&lear filter - Clear filter + C&reate - - Create + + &Join - - Join - - - - + J&oin as spectator @@ -1613,107 +1674,107 @@ Would you like to change your database location setting? GeneralSettingsPage - + Reset/Clear Downloaded Pictures - - - - - + + + + + Choose path - + Success - + Downloaded card pictures have been reset. - + Error - + One or more downloaded card pictures could not be cleared. - + Personal settings - + Language: - + Download card pictures on the fly - + Download card pictures from a custom URL - + Custom Card Download URL: - + Linking FAQ - + Paths - + Decks directory: - + Replays directory: - + Pictures directory: - + Card database: - + Token database: - + Picture cache size: - - + + English English @@ -1721,48 +1782,48 @@ Would you like to change your database location setting? MainWindow - + There are too many concurrent connections from your address. - + Scheduled server shutdown. - + Banned by moderator - + Expected end time: %1 - + This ban lasts indefinitely. - + Connection closed - + The server has terminated your connection. Reason: %1 - + Scheduled server shutdown - + The server is going to be restarted in %n minute(s). All running games will be lost. Reason for shutdown: %1 @@ -1772,449 +1833,473 @@ Reason for shutdown: %1 - + Number of players - + Please enter the number of players. - - + + Player %1 - + Load replay - + About Cockatrice - + Version %1 - + Translators: - + Project Manager: - - + + The server has reached its maximum user capacity, please check back later. + + + + + Invalid username. - - + + Success - + Registration accepted. Will now login. - + Account activation accepted. Will now login. - + Past Project Managers: - + Developers: - + Our Developers - + Help Develop! - + Recognition Page - + Help Translate! - + Support: - + Report an Issue - - - - - - - - - - + + + + + + + + + + + - - - + + + + Error - + Server timeout - + Incorrect username or password. Please check your authentication information and try again. - + There is already an active session using this user name. Please close that session first and re-login. - - + + You are banned until %1. - - + + You are banned indefinitely. - + This server requires user registration. Do you want to register now? + This server requires client ID's. Your client is either failing to generate an ID or you are running a modified client. +Please close and reopen your client to try again. + + + + + An internal error has occurred, please try closing and reopening your client and try again. If the error persists try updating your client to the most recent build and if need be contact your software provider. + + + + Account activation - - Your account has not been activated yet. - You need to provide the activation token received in the activation email - - - - - + Unknown login error: %1 - + + + +This usually means that your client version is out of date, and the server sent a reply your client doesn't understand. + + + + Your username must respect these rules: - + is %1 - %2 characters long - + can %1 contain lowercase characters - - - - + + + + NOT - + can %1 contain uppercase characters - + can %1 contain numeric characters - + can contain the following punctuation: %1 - + first character can %1 be a punctuation mark - + You may only use A-Z, a-z, 0-9, _, ., and - in your username. - - - - - + + + + + Registration denied - + Registration is currently disabled on this server - + There is already an existing account with the same user name. - + It's mandatory to specify a valid email address when registering. - + Too many registration attempts from your IP address. - + Password too short. - + Registration failed for a technical problem on the server. - Account activation failed + Unknown registration error: %1 - Socket error: %1 + Account activation failed + Socket error: %1 + + + + You are trying to connect to an obsolete server. Please downgrade your Cockatrice version or connect to a suitable server. Local version is %1, remote version is %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Registering to %1 as %2... - + Disconnected - + Connected, logging in at %1 - - Logged in as %1 at %2 - - - - + &Connect... - + &Disconnect - + Start &local game... - + &Watch replay... - + &Deck editor - + &Full screen - + &Register to server... - + &Settings... - - + + &Exit - + A&ctions - + &Cockatrice - + &About Cockatrice - + &Help - + Check for card updates... - + A card database update is already running. - + Unable to run the card database updater: - + The card database updater exited with an error: %1 - + Update completed successfully. Cockatrice will now reload the card database. - - + + Information - + Troubleshooting - + F.A.Q. - - failed to start. - - - - - crashed. - - - - - timed out. + + Your account has not been activated yet. +You need to provide the activation token received in the activation email - write error. + failed to start. + crashed. + + + + + timed out. + + + + + write error. + + + + read error. - + unknown error. @@ -3487,62 +3572,74 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Chat settings - + + Custom alert words + + + + Enable chat mentions - + + Enable mention completer + + + + In-game message macros - - Ignore unregistered users in main chat + + Ignore chat room messages sent by unregistered users - - Ignore chat room messages sent by unregistered users. + + Ignore private messages sent by unregistered users - - Ignore private messages sent by unregistered users. + + Enable desktop notifications for private messages - + + Separate words with a space, alphanumeric characters only + + + + + Invert text color - - Enable desktop notifications for private messages. - - - - + Enable desktop notification for mentions. - + + (Color is hexadecimal) - + Add message - + Message: @@ -3608,307 +3705,307 @@ Local version is %1, remote version is %2. Player - + &View library - + Move top cards to &graveyard... - + View &top cards of library... - + &View graveyard - + &View sideboard - + Player "%1" - - - - + + + + &Hand - + &Reveal hand to... - + Reveal r&andom card to... - + &Library - - - - + + + + &Graveyard - + &Sideboard - + Red - + Yellow - + Green - + View top cards of library - + Number of cards: - + &Draw card - + Reveal top cards of library - + Number of cards: (max. %1) - + &View exile - - - - + + + + &Exile - + Reveal t&op cards to... - + D&raw cards... - + Take &mulligan - + &Shuffle - + &Counters - + &Untap all permanents - + R&oll die... - + &Create token... - + C&reate another token - + S&ay - + &Move hand to... - - - - + + + + &Top of library - - - - + + + + &Bottom of library - + &Move graveyard to... - + &Move exile to... - + Reveal &library to... - + &Always reveal top card - + O&pen deck in deck editor - + &Undo last draw - + Play top card &face down - + Move top cards to &exile... - + Put top card on &bottom - + Put bottom card &in graveyard - + Cr&eate predefined token - + C&ard - + &All players - + &Play - + &Hide - + Play &Face Down - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Peek at card face - + &Clone - + Attac&h to card... @@ -3928,115 +4025,115 @@ Local version is %1, remote version is %2. - + &Decrease power - + I&ncrease toughness - + D&ecrease toughness - + In&crease power and toughness - + Dec&rease power and toughness - + Set &power and toughness... - + &Set annotation... - + &Add counter (%1) - + &Remove counter (%1) - + &Set counters (%1)... - + Draw cards - - - - + + + + Number: - + Move top cards to grave - + Move top cards to exile - + Roll die - + Number of sides: - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters - + Cr&eate related card @@ -4044,37 +4141,37 @@ Local version is %1, remote version is %2. QMenuBar - + Services - + Hide %1 - + Hide Others - + Show All - + Preferences... - + Quit %1 - + About %1 @@ -4082,7 +4179,7 @@ Local version is %1, remote version is %2. QObject - + Cockatrice replays (*.cor) @@ -4151,35 +4248,64 @@ Local version is %1, remote version is %2. RoomSelector - + Rooms - + Joi&n - + Room - + Description - + + Permissions + + + + Players - + Games + + + + Error + + + + + You do not have the proper permission to join this room. + + + + + Failed to join the room due to an unknown error. + + + + + SequenceEdit + + + Shortcut already in use + + SetsModel @@ -4230,37 +4356,37 @@ Local version is %1, remote version is %2. SoundSettingsPage - + Choose path - + Enable &sounds - + Path to sounds directory: - + Test system sound engine - + Sound settings - + Master volume requires QT5 - + Master volume @@ -4316,184 +4442,219 @@ Local version is %1, remote version is %2. TabDeckEditor - + &Print deck... - + &Close - + &Edit sets... - + Filters - + &Clear all filters - + Delete selected - + Deck &name: - + &Comments: - + Hash: - + &New deck - + &Load deck... - + &Save deck - + Save deck &as... - + Load deck from cl&ipboard... - + Save deck to clip&board - + &Analyze deck on deckstats.net - + Open custom image folder - + + Open custom sets folder + + + + Add card to &maindeck - + Add card to &sideboard - + &Deck Editor - + C&ard Database - + + Show/Hide card information + + + + + Show/Hide deck + + + + + Show/Hide filters + + + + + Reset layout + + + + + Card Info + + + + + Deck + + + + Welcome - + Hi! It seems like you're running this version of Cockatrice for the first time. All the sets in the card database have been enabled. Read more about changing the set order or disabling specific sets and consequent effects in the "Edit Sets" window. - + &Remove row - + &Increment number - + &Decrement number - + Edit &tokens... - + Deck: %1 - + Are you sure? - + The decklist has been modified. Do you want to save the changes? - + Load deck - - - + + + Error - + The deck could not be saved. - - + + The deck could not be saved. Please check that the directory is writable and try again. - + Save deck @@ -4590,97 +4751,97 @@ Please enter a name: TabGame - + &Phases - + &Game - + Next &phase - + Next &turn - + &Remove all local arrows - + Rotate View Cl&ockwise - + Rotate View Co&unterclockwise - + Game &information - + &Concede - + &Leave game - + C&lose replay - + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + You are flooding the game. Please wait a couple of seconds. - + You have been kicked out of the game. - + REPLAY @@ -4786,47 +4947,47 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + &Clear chat - + Chat Settings... - + mentioned you. - + Click to view - + You are flooding the chat. Please wait a couple of seconds. @@ -4842,15 +5003,25 @@ Please enter a name: TabSupervisor - + Are you sure? - + There are still open games. Are you sure you want to quit? + + + Promotion + + + + + You have been promoted to moderator. Please log out and back in for changes to take effect. + + TabUserLists @@ -4873,55 +5044,97 @@ Please enter a name: UserContextMenu - + User &details - + Private &chat - + Show this user's &games - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Kick from &game - + Ban from &server - + + &Promote user to moderator + + + + + Dem&ote user from moderator + + + + %1's games + + + + Success + + + + + Successfully promoted user. + + + + + Successfully demoted user. + + + + + + Failed + + + + + Failed to promote user. + + + + + Failed to demote user. + + UserInfoBox @@ -5090,42 +5303,42 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + Enable notifications in taskbar - + Notify in the taskbar for game events while you are spectating - + &Double-click cards to play them (instead of single-click) - + &Play all nonlands onto the stack (not the battlefield) by default - + Annotate card text on tokens - + Animation settings - + &Tap/untap animation @@ -5133,22 +5346,22 @@ Please enter a name: UserList - + Users connected to server: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 @@ -5207,7 +5420,7 @@ Please enter a name: - Disabled sets will still be used for loading images + Disabled sets will be used for loading images only if all the enabled sets failed @@ -5216,12 +5429,12 @@ Please enter a name: - + Success - + The sets database has been saved successfully. @@ -5249,4 +5462,561 @@ Please enter a name: + + shortcutsTab + + + Form + + + + + Main Window + + + + + Deck editor + + + + + Local gameplay + + + + + Watch replay + + + + + Connect + + + + + Register + + + + + Full screen + + + + + Settings + + + + + Check for card updates + + + + + Diconnect + + + + + Exit + + + + + Deck Editor + + + + + Analyze deck + + + + + Load deck (clipboard) + + + + + Clerar all filters + + + + + New deck + + + + + Clear one filter + + + + + Open custom folder + + + + + Close + + + + + Print deck + + + + + Edit sets + + + + + Delete card + + + + + Edit tokens + + + + + Reset layout + + + + + Add card + + + + + Save deck + + + + + Remove card + + + + + Save deck as + + + + + Load deck + + + + + Save deck (clipboard) + + + + + + Counters + + + + + Life + + + + + + + + + Set + + + + + + + + Add + + + + + + + + Remove + + + + + Red + + + + + Green + + + + + Yellow + + + + + Mainwindow / Deck editor + + + + + Power / toughness + + + + + Power and toughness + + + + + Add (+1/+1) + + + + + Remove (-1/-1) + + + + + Toughness + + + + + Remove (-0/-1) + + + + + Add (+0/+1) + + + + + Power + + + + + Remove (-1/-0) + + + + + Add (+1/+0) + + + + + Game Phases + + + + + Untap + + + + + Unkeep + + + + + + Draw + + + + + Main 1 + + + + + Start combat + + + + + Attack + + + + + Block + + + + + Damage + + + + + End combat + + + + + Main 2 + + + + + End + + + + + Next phase + + + + + Next turn + + + + + Player + + + + + Tap Card + + + + + Untap Card + + + + + Untap all + + + + + Toogle untap + + + + + Flip card + + + + + Peek card + + + + + Play card + + + + + Attach card + + + + + Unattach card + + + + + Clone card + + + + + Create token + + + + + Create another token + + + + + Set annotation + + + + + Phases / P/T / Player + + + + + Move card to + + + + + Bottom library + + + + + Top library + + + + + + Graveyard + + + + + + Exile + + + + + Hand + + + + + View + + + + + Library + + + + + Tops card of library + + + + + Sideboard + + + + + Close recent view + + + + + Pre-play + + + + + Load remote deck + + + + + Load local deck + + + + + Game play + + + + + Draw arrow + + + + + Leave game + + + + + Remove local arrows + + + + + Concede + + + + + Roll dice + + + + + Rotate view CW + + + + + Shuffle library + + + + + Rotate view CCW + + + + + Mulligan + + + + + Draw card + + + + + Draw cards + + + + + Undo draw + + + + + Always reveal top card + + + + + Draw / Move / View / Game play + + + From 8ffe31085507a7616a441eab9b36e7c46ef15810 Mon Sep 17 00:00:00 2001 From: Zach H Date: Sun, 23 Aug 2015 14:07:17 -0400 Subject: [PATCH 09/11] prevent bad flags --- cockatrice/src/dlg_register.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/src/dlg_register.h b/cockatrice/src/dlg_register.h index f0e2ecf2..c86f1217 100644 --- a/cockatrice/src/dlg_register.h +++ b/cockatrice/src/dlg_register.h @@ -19,7 +19,7 @@ public: QString getPassword() const { return passwordEdit->text(); } QString getEmail() const { return emailEdit->text(); } int getGender() const { return genderEdit->currentIndex() - 1; } - QString getCountry() const { return genderEdit->currentIndex() == 0 ? "" : countryEdit->currentText(); } + QString getCountry() const { return countryEdit->currentIndex() == 0 ? "" : countryEdit->currentText(); } QString getRealName() const { return realnameEdit->text(); } private slots: void actOk(); From a8727d5a5013c147d4af4c89a5029be6827ce35c Mon Sep 17 00:00:00 2001 From: Zach H Date: Sun, 23 Aug 2015 17:51:23 -0400 Subject: [PATCH 10/11] define URLs --- cockatrice/src/window_main.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 1653e7f7..219f1dbe 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -31,8 +31,7 @@ #include #include #if QT_VERSION < 0x050000 - // for Qt::escape() - #include + #include // for Qt::escape() #endif #include "main.h" @@ -47,7 +46,6 @@ #include "localclient.h" #include "settingscache.h" #include "tab_game.h" - #include "version_string.h" #include "pb/game_replay.pb.h" @@ -55,6 +53,14 @@ #include "pb/event_connection_closed.pb.h" #include "pb/event_server_shutdown.pb.h" +#define GITHUB_CONTRIBUTORS_URL "https://github.com/Cockatrice/Cockatrice/graphs/contributors?type=c" +#define GITHUB_CONTRIBUTE_URL "https://github.com/Cockatrice/Cockatrice#cockatrice" +#define GITHUB_TRANSLATOR_RECOGNIZE_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translators" +#define GITHUB_TRANSLATOR_FAQ_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ" +#define GITHUB_ISSUES_URL "https://github.com/Cockatrice/Cockatrice/issues" +#define GITHUB_TROUBLESHOOTING_URL "https://github.com/Cockatrice/Cockatrice/wiki/Troubleshooting" +#define GITHUB_FAQ_URL "https://github.com/Cockatrice/Cockatrice/wiki/Frequently-Asked-Questions" + const QString MainWindow::appName = "Cockatrice"; void MainWindow::updateTabMenu(const QList &newMenuList) @@ -71,7 +77,7 @@ void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &even client->disconnectFromServer(); QString reasonStr; switch (event.reason()) { - case Event_ConnectionClosed::USER_LIMIT_REACHED: reasonStr = tr("The server has reached its maximum user capacity, please check back later."); break; + case Event_ConnectionClosed::USER_LIMIT_REACHED: reasonStr = tr("The server has reached its maximum user capacity, please check back later."); break; case Event_ConnectionClosed::TOO_MANY_CONNECTIONS: reasonStr = tr("There are too many concurrent connections from your address."); break; case Event_ConnectionClosed::BANNED: { reasonStr = tr("Banned by moderator"); @@ -269,15 +275,15 @@ void MainWindow::actAbout() + "

" + tr("Project Manager:") + "
Gavin Bisesi

" + "" + tr("Past Project Managers:") + "
Max-Wilhelm Bruker
Marcus Schütz

" + "" + tr("Developers:") + "
" - + "" + tr("Our Developers") + "
" - + "" + tr("Help Develop!") + "

" + + "" + tr("Our Developers") + "
" + + "" + tr("Help Develop!") + "

" + "" + tr("Translators:") + "
" - + "" + tr("Recognition Page") + "
" - + "" + tr("Help Translate!") + "

" + + "" + tr("Recognition Page") + "
" + + "" + tr("Help Translate!") + "

" + "" + tr("Support:") + "
" - + "" + tr("Report an Issue") + "
" - + "" + tr("Troubleshooting") + "
" - + "" + tr("F.A.Q.") + "
" + + "" + tr("Report an Issue") + "
" + + "" + tr("Troubleshooting") + "
" + + "" + tr("F.A.Q.") + "
" )); } From 364df4daf04e6a01917d140f89eff1e249b5efc3 Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Mon, 24 Aug 2015 11:38:24 -0400 Subject: [PATCH 11/11] Extend the login protocol to send the client id (as optional) --- cockatrice/src/remoteclient.cpp | 2 ++ common/pb/session_commands.proto | 1 + 2 files changed, 3 insertions(+) diff --git a/cockatrice/src/remoteclient.cpp b/cockatrice/src/remoteclient.cpp index 96ee1eea..e149082b 100644 --- a/cockatrice/src/remoteclient.cpp +++ b/cockatrice/src/remoteclient.cpp @@ -12,6 +12,7 @@ #include "pb/event_server_identification.pb.h" #include "settingscache.h" #include "main.h" +#include "version_string.h" static const unsigned int protocolVersion = 14; @@ -112,6 +113,7 @@ void RemoteClient::doLogin() cmdLogin.set_user_name(userName.toStdString()); cmdLogin.set_password(password.toStdString()); cmdLogin.set_clientid(settingsCache->getClientID().toStdString()); + cmdLogin.set_clientver(VERSION_STRING); PendingCommand *pend = prepareSessionCommand(cmdLogin); connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(loginResponse(Response))); sendCommand(pend); diff --git a/common/pb/session_commands.proto b/common/pb/session_commands.proto index d5564f3e..22dad27d 100644 --- a/common/pb/session_commands.proto +++ b/common/pb/session_commands.proto @@ -44,6 +44,7 @@ message Command_Login { optional string user_name = 1; optional string password = 2; optional string clientid = 3; + optional string clientver = 4; } message Command_Message {