From 4149f780011e217d8312c1b635a49546b7e2ec26 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 1 Mar 2011 20:49:36 +0100 Subject: [PATCH] more buddy&ignore code, added missing file --- cockatrice/src/abstractclient.cpp | 2 + cockatrice/src/abstractclient.h | 5 +- cockatrice/src/localserverinterface.h | 2 + cockatrice/src/tab_userlists.cpp | 142 ++++++++++++++++++++++ cockatrice/src/tab_userlists.h | 46 ++++++++ cockatrice/src/userlist.cpp | 24 ++-- common/protocol.cpp | 11 ++ common/protocol.h | 11 ++ common/protocol_datastructures.h | 2 +- common/protocol_item_ids.h | 143 +++++++++++------------ common/protocol_items.cpp | 33 +++--- common/protocol_items.dat | 7 +- common/protocol_items.h | 43 +++---- common/server_protocolhandler.cpp | 30 +++-- common/server_protocolhandler.h | 8 +- servatrice/src/servatrice.h | 2 +- servatrice/src/serversocketinterface.cpp | 86 ++++++++++++++ servatrice/src/serversocketinterface.h | 3 + 18 files changed, 459 insertions(+), 141 deletions(-) create mode 100644 cockatrice/src/tab_userlists.cpp create mode 100644 cockatrice/src/tab_userlists.h diff --git a/cockatrice/src/abstractclient.cpp b/cockatrice/src/abstractclient.cpp index 627f6ed6..e5bc36a1 100644 --- a/cockatrice/src/abstractclient.cpp +++ b/cockatrice/src/abstractclient.cpp @@ -32,6 +32,8 @@ void AbstractClient::processProtocolItem(ProtocolItem *item) GenericEvent *genericEvent = qobject_cast(item); if (genericEvent) { switch (genericEvent->getItemId()) { + case ItemId_Event_AddToList: emit addToListEventReceived(qobject_cast(item)); break; + case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(qobject_cast(item)); break; case ItemId_Event_UserJoined: emit userJoinedEventReceived(qobject_cast(item)); break; case ItemId_Event_UserLeft: emit userLeftEventReceived(qobject_cast(item)); break; case ItemId_Event_ServerMessage: emit serverMessageEventReceived(qobject_cast(item)); break; diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index 94388d6e..5e13bf9d 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -12,7 +12,8 @@ class TopLevelProtocolItem; class CommandContainer; class RoomEvent; class GameEventContainer; -class Event_ListGames; +class Event_AddToList; +class Event_RemoveFromList; class Event_UserJoined; class Event_UserLeft; class Event_ServerMessage; @@ -40,6 +41,8 @@ signals: // Game events void gameEventContainerReceived(GameEventContainer *event); // Generic events + void addToListEventReceived(Event_AddToList *event); + void removeFromListEventReceived(Event_RemoveFromList *event); void userJoinedEventReceived(Event_UserJoined *event); void userLeftEventReceived(Event_UserLeft *event); void serverMessageEventReceived(Event_ServerMessage *event); diff --git a/cockatrice/src/localserverinterface.h b/cockatrice/src/localserverinterface.h index f88d4940..7adb5cb3 100644 --- a/cockatrice/src/localserverinterface.h +++ b/cockatrice/src/localserverinterface.h @@ -10,6 +10,8 @@ class LocalServerInterface : public Server_ProtocolHandler Q_OBJECT private: DeckList *getDeckFromDatabase(int /*deckId*/) { return 0; } + ResponseCode cmdAddToList(Command_AddToList * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } + ResponseCode cmdRemoveFromList(Command_RemoveFromList * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdDeckList(Command_DeckList * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdDeckNewDir(Command_DeckNewDir * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdDeckDelDir(Command_DeckDelDir * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } diff --git a/cockatrice/src/tab_userlists.cpp b/cockatrice/src/tab_userlists.cpp new file mode 100644 index 00000000..5c2e5ca1 --- /dev/null +++ b/cockatrice/src/tab_userlists.cpp @@ -0,0 +1,142 @@ +#include "tab_userlists.h" +#include "userlist.h" +#include "userinfobox.h" +#include "protocol_items.h" +#include "abstractclient.h" +#include +#include +#include + +TabUserLists::TabUserLists(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerInfo_User *userInfo, QWidget *parent) + : Tab(_tabSupervisor, parent), client(_client) +{ + allUsersList = new UserList(this, client, UserList::AllUsersList); + buddyList = new UserList(this, client, UserList::BuddyList); + ignoreList = new UserList(this, client, UserList::IgnoreList); + userInfoBox = new UserInfoBox(client, false); + userInfoBox->updateInfo(userInfo); + + connect(allUsersList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); + connect(buddyList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); + connect(ignoreList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); + + connect(client, SIGNAL(userJoinedEventReceived(Event_UserJoined *)), this, SLOT(processUserJoinedEvent(Event_UserJoined *))); + connect(client, SIGNAL(userLeftEventReceived(Event_UserLeft *)), this, SLOT(processUserLeftEvent(Event_UserLeft *))); + connect(client, SIGNAL(buddyListReceived(const QList &)), this, SLOT(buddyListReceived(const QList &))); + connect(client, SIGNAL(ignoreListReceived(const QList &)), this, SLOT(ignoreListReceived(const QList &))); + connect(client, SIGNAL(addToListEventReceived(Event_AddToList *)), this, SLOT(processAddToListEvent(Event_AddToList *))); + connect(client, SIGNAL(removeFromListEventReceived(Event_RemoveFromList *)), this, SLOT(processRemoveFromListEvent(Event_RemoveFromList *))); + + Command_ListUsers *cmd = new Command_ListUsers; + connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(processListUsersResponse(ProtocolResponse *))); + client->sendCommand(cmd); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(userInfoBox); + vbox->addWidget(allUsersList); + + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->addWidget(buddyList); + mainLayout->addWidget(ignoreList); + mainLayout->addLayout(vbox); + + setLayout(mainLayout); +} + +void TabUserLists::retranslateUi() +{ + allUsersList->retranslateUi(); + buddyList->retranslateUi(); + ignoreList->retranslateUi(); + userInfoBox->retranslateUi(); +} + +void TabUserLists::processListUsersResponse(ProtocolResponse *response) +{ + Response_ListUsers *resp = qobject_cast(response); + if (!resp) + return; + + const QList &respList = resp->getUserList(); + for (int i = 0; i < respList.size(); ++i) { + allUsersList->processUserInfo(respList[i], true); + ignoreList->setUserOnline(respList[i]->getName(), true); + buddyList->setUserOnline(respList[i]->getName(), true); + } + + allUsersList->sortItems(); + ignoreList->sortItems(); + buddyList->sortItems(); +} + +void TabUserLists::processUserJoinedEvent(Event_UserJoined *event) +{ + ServerInfo_User *info = event->getUserInfo(); + allUsersList->processUserInfo(info, true); + ignoreList->setUserOnline(info->getName(), true); + buddyList->setUserOnline(info->getName(), true); + + allUsersList->sortItems(); + ignoreList->sortItems(); + buddyList->sortItems(); + + emit userJoined(event->getUserInfo()->getName()); +} + +void TabUserLists::processUserLeftEvent(Event_UserLeft *event) +{ + QString userName = event->getUserName(); + if (allUsersList->deleteUser(userName)) { + ignoreList->setUserOnline(userName, false); + buddyList->setUserOnline(userName, false); + ignoreList->sortItems(); + buddyList->sortItems(); + + emit userLeft(userName); + } +} + +void TabUserLists::buddyListReceived(const QList &_buddyList) +{ + for (int i = 0; i < _buddyList.size(); ++i) + buddyList->processUserInfo(_buddyList[i], false); + buddyList->sortItems(); +} + +void TabUserLists::ignoreListReceived(const QList &_ignoreList) +{ + for (int i = 0; i < _ignoreList.size(); ++i) + ignoreList->processUserInfo(_ignoreList[i], false); + ignoreList->sortItems(); +} + +void TabUserLists::processAddToListEvent(Event_AddToList *event) +{ + ServerInfo_User *info = event->getUserInfo(); + bool online = allUsersList->userInList(info->getName()); + QString list = event->getList(); + UserList *userList = 0; + if (list == "buddy") + userList = buddyList; + else if (list == "ignore") + userList = ignoreList; + if (!userList) + return; + + userList->processUserInfo(info, online); + userList->sortItems(); +} + +void TabUserLists::processRemoveFromListEvent(Event_RemoveFromList *event) +{ + QString list = event->getList(); + QString user = event->getUserName(); + UserList *userList = 0; + if (list == "buddy") + userList = buddyList; + else if (list == "ignore") + userList = ignoreList; + if (!userList) + return; + userList->deleteUser(user); +} diff --git a/cockatrice/src/tab_userlists.h b/cockatrice/src/tab_userlists.h new file mode 100644 index 00000000..e345be46 --- /dev/null +++ b/cockatrice/src/tab_userlists.h @@ -0,0 +1,46 @@ +#ifndef TAB_USERLISTS_H +#define TAB_USERLISTS_H + +#include "tab.h" + +class AbstractClient; +class UserList; +class UserInfoBox; + +class Event_ListRooms; +class Event_UserJoined; +class Event_UserLeft; +class ProtocolResponse; +class ServerInfo_User; +class Event_AddToList; +class Event_RemoveFromList; + +class TabUserLists : public Tab { + Q_OBJECT +signals: + void openMessageDialog(const QString &userName, bool focus); + void userLeft(const QString &userName); + void userJoined(const QString &userName); +private slots: + void processListUsersResponse(ProtocolResponse *response); + void processUserJoinedEvent(Event_UserJoined *event); + void processUserLeftEvent(Event_UserLeft *event); + void buddyListReceived(const QList &_buddyList); + void ignoreListReceived(const QList &_ignoreList); + void processAddToListEvent(Event_AddToList *event); + void processRemoveFromListEvent(Event_RemoveFromList *event); +private: + AbstractClient *client; + UserList *allUsersList; + UserList *buddyList; + UserList *ignoreList; + UserInfoBox *userInfoBox; +public: + TabUserLists(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerInfo_User *userInfo, QWidget *parent = 0); + void retranslateUi(); + QString getTabText() const { return tr("User lists"); } + UserList *getBuddyList() const { return buddyList; } + UserList *getIgnoreList() const { return ignoreList; } +}; + +#endif diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index 39aaf4df..053acca7 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -3,6 +3,7 @@ #include "abstractclient.h" #include "pixmapgenerator.h" #include "userinfobox.h" +#include "protocol_items.h" #include #include #include @@ -90,7 +91,9 @@ void UserList::processUserInfo(ServerInfo_User *user, bool online) if (!item) { item = new UserListTWI; userTree->addTopLevelItem(item); - retranslateUi(); + if (online) + ++onlineCount; + updateCount(); } item->setData(0, Qt::UserRole, user->getUserLevel()); item->setIcon(0, QIcon(UserLevelPixmapGenerator::generatePixmap(12, user->getUserLevel()))); @@ -109,7 +112,10 @@ bool UserList::deleteUser(const QString &userName) { for (int i = 0; i < userTree->topLevelItemCount(); ++i) if (userTree->topLevelItem(i)->data(2, Qt::UserRole) == userName) { - delete userTree->takeTopLevelItem(i); + QTreeWidgetItem *item = userTree->takeTopLevelItem(i); + if (item->data(0, Qt::UserRole + 1).toBool()) + --onlineCount; + delete item; updateCount(); return true; } @@ -165,7 +171,7 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) QAction *aChat = new QAction(tr("Direct &chat"), this); QAction *aAddToBuddyList = new QAction(tr("Add to &buddy list"), this); QAction *aRemoveFromBuddyList = new QAction(tr("Remove from &buddy list"), this); - QAction *aAddToIgnoreList = new QAction(tr("Remove from &ignore list"), this); + QAction *aAddToIgnoreList = new QAction(tr("Add to &ignore list"), this); QAction *aRemoveFromIgnoreList = new QAction(tr("Remove from &ignore list"), this); QMenu *menu = new QMenu(this); @@ -191,18 +197,22 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) } else if (actionClicked == aChat) emit openMessageDialog(userName, true); else if (actionClicked == aAddToBuddyList) - emit addBuddy(userName); + client->sendCommand(new Command_AddToList("buddy", userName)); else if (actionClicked == aRemoveFromBuddyList) - emit removeBuddy(userName); + client->sendCommand(new Command_RemoveFromList("buddy", userName)); else if (actionClicked == aAddToIgnoreList) - emit addIgnore(userName); + client->sendCommand(new Command_AddToList("ignore", userName)); else if (actionClicked == aRemoveFromIgnoreList) - emit removeIgnore(userName); + client->sendCommand(new Command_RemoveFromList("ignore", userName)); delete menu; delete aUserName; delete aDetails; delete aChat; + delete aAddToBuddyList; + delete aRemoveFromBuddyList; + delete aAddToIgnoreList; + delete aRemoveFromIgnoreList; } bool UserList::userInList(const QString &userName) const diff --git a/common/protocol.cpp b/common/protocol.cpp index a883dc99..13719bfa 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -53,6 +53,7 @@ void ProtocolItem::initializeHash() registerSerializableItem("room_eventlist_games", Event_ListGames::newItem); registerSerializableItem("room_eventjoin_room", Event_JoinRoom::newItem); + registerSerializableItem("generic_eventadd_to_list", Event_AddToList::newItem); registerSerializableItem("generic_eventuser_joined", Event_UserJoined::newItem); registerSerializableItem("generic_eventlist_rooms", Event_ListRooms::newItem); registerSerializableItem("game_eventjoin", Event_Join::newItem); @@ -253,6 +254,7 @@ void ProtocolResponse::initializeHash() { responseHash.insert(QString(), RespNothing); responseHash.insert("ok", RespOk); + responseHash.insert("internal_error", RespInternalError); responseHash.insert("invalid_command", RespInvalidCommand); responseHash.insert("name_not_found", RespNameNotFound); responseHash.insert("login_needed", RespLoginNeeded); @@ -376,6 +378,15 @@ Event_ListGames::Event_ListGames(int _roomId, const QList &_g itemList.append(_gameList[i]); } +Event_AddToList::Event_AddToList(const QString &_list, ServerInfo_User *_userInfo) + : GenericEvent("add_to_list") +{ + if (!_userInfo) + _userInfo = new ServerInfo_User; + insertItem(_userInfo); + insertItem(new SerializableItem_String("list", _list)); +} + Event_UserJoined::Event_UserJoined(ServerInfo_User *_userInfo) : GenericEvent("user_joined") { diff --git a/common/protocol.h b/common/protocol.h index fda322ac..b72deb10 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -40,6 +40,7 @@ enum ItemId { ItemId_Event_RevealCards = ItemId_Other + 210, ItemId_Event_Join = ItemId_Other + 211, ItemId_Event_Ping = ItemId_Other + 212, + ItemId_Event_AddToList = ItemId_Other + 213, ItemId_Response_ListUsers = ItemId_Other + 300, ItemId_Response_GetUserInfo = ItemId_Other + 301, ItemId_Response_DeckList = ItemId_Other + 302, @@ -407,6 +408,16 @@ public: QList getGameList() const { return typecastItemList(); } }; +class Event_AddToList : public GenericEvent { + Q_OBJECT +public: + Event_AddToList(const QString &_list = QString(), ServerInfo_User *_userInfo = 0); + int getItemId() const { return ItemId_Event_AddToList; } + static SerializableItem *newItem() { return new Event_AddToList; } + ServerInfo_User *getUserInfo() const { return static_cast(itemMap.value("user")); } + QString getList() const { return static_cast(itemMap.value("list"))->getData(); } +}; + class Event_UserJoined : public GenericEvent { Q_OBJECT public: diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 045a4003..48ddb445 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -8,7 +8,7 @@ class DeckList; -enum ResponseCode { RespNothing, RespOk, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed, RespOnlyBuddies, RespUserLevelTooLow }; +enum ResponseCode { RespNothing, RespOk, RespInternalError, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed, RespOnlyBuddies, RespUserLevelTooLow }; // PrivateZone: Contents of the zone are always visible to the owner, // but not to anyone else. diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h index 2f486df2..f2907846 100644 --- a/common/protocol_item_ids.h +++ b/common/protocol_item_ids.h @@ -4,76 +4,75 @@ ItemId_Command_Login = 1002, ItemId_Command_Message = 1003, ItemId_Command_ListUsers = 1004, ItemId_Command_GetUserInfo = 1005, -ItemId_Command_AddBuddy = 1006, -ItemId_Command_RemoveBuddy = 1007, -ItemId_Command_AddIgnore = 1008, -ItemId_Command_RemoveIgnore = 1009, -ItemId_Command_DeckList = 1010, -ItemId_Command_DeckNewDir = 1011, -ItemId_Command_DeckDelDir = 1012, -ItemId_Command_DeckDel = 1013, -ItemId_Command_DeckDownload = 1014, -ItemId_Command_ListRooms = 1015, -ItemId_Command_JoinRoom = 1016, -ItemId_Command_LeaveRoom = 1017, -ItemId_Command_RoomSay = 1018, -ItemId_Command_JoinGame = 1019, -ItemId_Command_LeaveGame = 1020, -ItemId_Command_Say = 1021, -ItemId_Command_Shuffle = 1022, -ItemId_Command_Mulligan = 1023, -ItemId_Command_RollDie = 1024, -ItemId_Command_DrawCards = 1025, -ItemId_Command_UndoDraw = 1026, -ItemId_Command_FlipCard = 1027, -ItemId_Command_AttachCard = 1028, -ItemId_Command_CreateToken = 1029, -ItemId_Command_CreateArrow = 1030, -ItemId_Command_DeleteArrow = 1031, -ItemId_Command_SetCardAttr = 1032, -ItemId_Command_SetCardCounter = 1033, -ItemId_Command_IncCardCounter = 1034, -ItemId_Command_ReadyStart = 1035, -ItemId_Command_Concede = 1036, -ItemId_Command_IncCounter = 1037, -ItemId_Command_CreateCounter = 1038, -ItemId_Command_SetCounter = 1039, -ItemId_Command_DelCounter = 1040, -ItemId_Command_NextTurn = 1041, -ItemId_Command_SetActivePhase = 1042, -ItemId_Command_DumpZone = 1043, -ItemId_Command_StopDumpZone = 1044, -ItemId_Command_RevealCards = 1045, -ItemId_Event_Say = 1046, -ItemId_Event_Leave = 1047, -ItemId_Event_GameClosed = 1048, -ItemId_Event_Shuffle = 1049, -ItemId_Event_RollDie = 1050, -ItemId_Event_MoveCard = 1051, -ItemId_Event_FlipCard = 1052, -ItemId_Event_DestroyCard = 1053, -ItemId_Event_AttachCard = 1054, -ItemId_Event_CreateToken = 1055, -ItemId_Event_DeleteArrow = 1056, -ItemId_Event_SetCardAttr = 1057, -ItemId_Event_SetCardCounter = 1058, -ItemId_Event_SetCounter = 1059, -ItemId_Event_DelCounter = 1060, -ItemId_Event_SetActivePlayer = 1061, -ItemId_Event_SetActivePhase = 1062, -ItemId_Event_DumpZone = 1063, -ItemId_Event_StopDumpZone = 1064, -ItemId_Event_ServerMessage = 1065, -ItemId_Event_Message = 1066, -ItemId_Event_GameJoined = 1067, -ItemId_Event_UserLeft = 1068, -ItemId_Event_LeaveRoom = 1069, -ItemId_Event_RoomSay = 1070, -ItemId_Context_ReadyStart = 1071, -ItemId_Context_Concede = 1072, -ItemId_Context_DeckSelect = 1073, -ItemId_Context_UndoDraw = 1074, -ItemId_Context_MoveCard = 1075, -ItemId_Command_UpdateServerMessage = 1076, -ItemId_Other = 1077 +ItemId_Command_AddToList = 1006, +ItemId_Command_RemoveFromList = 1007, +ItemId_Command_DeckList = 1008, +ItemId_Command_DeckNewDir = 1009, +ItemId_Command_DeckDelDir = 1010, +ItemId_Command_DeckDel = 1011, +ItemId_Command_DeckDownload = 1012, +ItemId_Command_ListRooms = 1013, +ItemId_Command_JoinRoom = 1014, +ItemId_Command_LeaveRoom = 1015, +ItemId_Command_RoomSay = 1016, +ItemId_Command_JoinGame = 1017, +ItemId_Command_LeaveGame = 1018, +ItemId_Command_Say = 1019, +ItemId_Command_Shuffle = 1020, +ItemId_Command_Mulligan = 1021, +ItemId_Command_RollDie = 1022, +ItemId_Command_DrawCards = 1023, +ItemId_Command_UndoDraw = 1024, +ItemId_Command_FlipCard = 1025, +ItemId_Command_AttachCard = 1026, +ItemId_Command_CreateToken = 1027, +ItemId_Command_CreateArrow = 1028, +ItemId_Command_DeleteArrow = 1029, +ItemId_Command_SetCardAttr = 1030, +ItemId_Command_SetCardCounter = 1031, +ItemId_Command_IncCardCounter = 1032, +ItemId_Command_ReadyStart = 1033, +ItemId_Command_Concede = 1034, +ItemId_Command_IncCounter = 1035, +ItemId_Command_CreateCounter = 1036, +ItemId_Command_SetCounter = 1037, +ItemId_Command_DelCounter = 1038, +ItemId_Command_NextTurn = 1039, +ItemId_Command_SetActivePhase = 1040, +ItemId_Command_DumpZone = 1041, +ItemId_Command_StopDumpZone = 1042, +ItemId_Command_RevealCards = 1043, +ItemId_Event_Say = 1044, +ItemId_Event_Leave = 1045, +ItemId_Event_GameClosed = 1046, +ItemId_Event_Shuffle = 1047, +ItemId_Event_RollDie = 1048, +ItemId_Event_MoveCard = 1049, +ItemId_Event_FlipCard = 1050, +ItemId_Event_DestroyCard = 1051, +ItemId_Event_AttachCard = 1052, +ItemId_Event_CreateToken = 1053, +ItemId_Event_DeleteArrow = 1054, +ItemId_Event_SetCardAttr = 1055, +ItemId_Event_SetCardCounter = 1056, +ItemId_Event_SetCounter = 1057, +ItemId_Event_DelCounter = 1058, +ItemId_Event_SetActivePlayer = 1059, +ItemId_Event_SetActivePhase = 1060, +ItemId_Event_DumpZone = 1061, +ItemId_Event_StopDumpZone = 1062, +ItemId_Event_RemoveFromList = 1063, +ItemId_Event_ServerMessage = 1064, +ItemId_Event_Message = 1065, +ItemId_Event_GameJoined = 1066, +ItemId_Event_UserLeft = 1067, +ItemId_Event_LeaveRoom = 1068, +ItemId_Event_RoomSay = 1069, +ItemId_Context_ReadyStart = 1070, +ItemId_Context_Concede = 1071, +ItemId_Context_DeckSelect = 1072, +ItemId_Context_UndoDraw = 1073, +ItemId_Context_MoveCard = 1074, +ItemId_Command_UpdateServerMessage = 1075, +ItemId_Other = 1076 }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index 630d5c63..ffedf384 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -26,24 +26,16 @@ Command_GetUserInfo::Command_GetUserInfo(const QString &_userName) { insertItem(new SerializableItem_String("user_name", _userName)); } -Command_AddBuddy::Command_AddBuddy(const QString &_userName) - : Command("add_buddy") +Command_AddToList::Command_AddToList(const QString &_list, const QString &_userName) + : Command("add_to_list") { + insertItem(new SerializableItem_String("list", _list)); insertItem(new SerializableItem_String("user_name", _userName)); } -Command_RemoveBuddy::Command_RemoveBuddy(const QString &_userName) - : Command("remove_buddy") -{ - insertItem(new SerializableItem_String("user_name", _userName)); -} -Command_AddIgnore::Command_AddIgnore(const QString &_userName) - : Command("add_ignore") -{ - insertItem(new SerializableItem_String("user_name", _userName)); -} -Command_RemoveIgnore::Command_RemoveIgnore(const QString &_userName) - : Command("remove_ignore") +Command_RemoveFromList::Command_RemoveFromList(const QString &_list, const QString &_userName) + : Command("remove_from_list") { + insertItem(new SerializableItem_String("list", _list)); insertItem(new SerializableItem_String("user_name", _userName)); } Command_DeckList::Command_DeckList() @@ -386,6 +378,12 @@ Event_StopDumpZone::Event_StopDumpZone(int _playerId, int _zoneOwnerId, const QS insertItem(new SerializableItem_Int("zone_owner_id", _zoneOwnerId)); insertItem(new SerializableItem_String("zone", _zone)); } +Event_RemoveFromList::Event_RemoveFromList(const QString &_list, const QString &_userName) + : GenericEvent("remove_from_list") +{ + insertItem(new SerializableItem_String("list", _list)); + insertItem(new SerializableItem_String("user_name", _userName)); +} Event_ServerMessage::Event_ServerMessage(const QString &_message) : GenericEvent("server_message") { @@ -457,10 +455,8 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("cmdmessage", Command_Message::newItem); itemNameHash.insert("cmdlist_users", Command_ListUsers::newItem); itemNameHash.insert("cmdget_user_info", Command_GetUserInfo::newItem); - itemNameHash.insert("cmdadd_buddy", Command_AddBuddy::newItem); - itemNameHash.insert("cmdremove_buddy", Command_RemoveBuddy::newItem); - itemNameHash.insert("cmdadd_ignore", Command_AddIgnore::newItem); - itemNameHash.insert("cmdremove_ignore", Command_RemoveIgnore::newItem); + itemNameHash.insert("cmdadd_to_list", Command_AddToList::newItem); + itemNameHash.insert("cmdremove_from_list", Command_RemoveFromList::newItem); itemNameHash.insert("cmddeck_list", Command_DeckList::newItem); itemNameHash.insert("cmddeck_new_dir", Command_DeckNewDir::newItem); itemNameHash.insert("cmddeck_del_dir", Command_DeckDelDir::newItem); @@ -516,6 +512,7 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("game_eventset_active_phase", Event_SetActivePhase::newItem); itemNameHash.insert("game_eventdump_zone", Event_DumpZone::newItem); itemNameHash.insert("game_eventstop_dump_zone", Event_StopDumpZone::newItem); + itemNameHash.insert("generic_eventremove_from_list", Event_RemoveFromList::newItem); itemNameHash.insert("generic_eventserver_message", Event_ServerMessage::newItem); itemNameHash.insert("generic_eventmessage", Event_Message::newItem); itemNameHash.insert("generic_eventgame_joined", Event_GameJoined::newItem); diff --git a/common/protocol_items.dat b/common/protocol_items.dat index 941242ae..64175935 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -3,10 +3,8 @@ 0:message:s,user_name:s,text 0:list_users 0:get_user_info:s,user_name -0:add_buddy:s,user_name -0:remove_buddy:s,user_name -0:add_ignore:s,user_name -0:remove_ignore:s,user_name +0:add_to_list:s,list:s,user_name +0:remove_from_list:s,list:s,user_name 0:deck_list 0:deck_new_dir:s,path:s,dir_name 0:deck_del_dir:s,path @@ -62,6 +60,7 @@ 3:set_active_phase:i,phase 3:dump_zone:i,zone_owner_id:s,zone:i,number_cards 3:stop_dump_zone:i,zone_owner_id:s,zone +4:remove_from_list:s,list:s,user_name 4:server_message:s,message 4:message:s,sender_name:s,receiver_name:s,text 4:game_joined:i,game_id:s,game_description:i,player_id:b,spectator:b,spectators_can_talk:b,spectators_see_everything:b,resuming diff --git a/common/protocol_items.h b/common/protocol_items.h index d0783fe5..58264ff9 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -43,37 +43,23 @@ public: static SerializableItem *newItem() { return new Command_GetUserInfo; } int getItemId() const { return ItemId_Command_GetUserInfo; } }; -class Command_AddBuddy : public Command { +class Command_AddToList : public Command { Q_OBJECT public: - Command_AddBuddy(const QString &_userName = QString()); + Command_AddToList(const QString &_list = QString(), const QString &_userName = QString()); + QString getList() const { return static_cast(itemMap.value("list"))->getData(); }; QString getUserName() const { return static_cast(itemMap.value("user_name"))->getData(); }; - static SerializableItem *newItem() { return new Command_AddBuddy; } - int getItemId() const { return ItemId_Command_AddBuddy; } + static SerializableItem *newItem() { return new Command_AddToList; } + int getItemId() const { return ItemId_Command_AddToList; } }; -class Command_RemoveBuddy : public Command { +class Command_RemoveFromList : public Command { Q_OBJECT public: - Command_RemoveBuddy(const QString &_userName = QString()); + Command_RemoveFromList(const QString &_list = QString(), const QString &_userName = QString()); + QString getList() const { return static_cast(itemMap.value("list"))->getData(); }; QString getUserName() const { return static_cast(itemMap.value("user_name"))->getData(); }; - static SerializableItem *newItem() { return new Command_RemoveBuddy; } - int getItemId() const { return ItemId_Command_RemoveBuddy; } -}; -class Command_AddIgnore : public Command { - Q_OBJECT -public: - Command_AddIgnore(const QString &_userName = QString()); - QString getUserName() const { return static_cast(itemMap.value("user_name"))->getData(); }; - static SerializableItem *newItem() { return new Command_AddIgnore; } - int getItemId() const { return ItemId_Command_AddIgnore; } -}; -class Command_RemoveIgnore : public Command { - Q_OBJECT -public: - Command_RemoveIgnore(const QString &_userName = QString()); - QString getUserName() const { return static_cast(itemMap.value("user_name"))->getData(); }; - static SerializableItem *newItem() { return new Command_RemoveIgnore; } - int getItemId() const { return ItemId_Command_RemoveIgnore; } + static SerializableItem *newItem() { return new Command_RemoveFromList; } + int getItemId() const { return ItemId_Command_RemoveFromList; } }; class Command_DeckList : public Command { Q_OBJECT @@ -580,6 +566,15 @@ public: static SerializableItem *newItem() { return new Event_StopDumpZone; } int getItemId() const { return ItemId_Event_StopDumpZone; } }; +class Event_RemoveFromList : public GenericEvent { + Q_OBJECT +public: + Event_RemoveFromList(const QString &_list = QString(), const QString &_userName = QString()); + QString getList() const { return static_cast(itemMap.value("list"))->getData(); }; + QString getUserName() const { return static_cast(itemMap.value("user_name"))->getData(); }; + static SerializableItem *newItem() { return new Event_RemoveFromList; } + int getItemId() const { return ItemId_Event_RemoveFromList; } +}; class Event_ServerMessage : public GenericEvent { Q_OBJECT public: diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 8fb191b8..d45d11be 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -42,10 +42,12 @@ Server_ProtocolHandler::~Server_ProtocolHandler() } delete userInfo; - for (int i = 0; i < buddyList.size(); ++i) - delete buddyList[i]; - for (int i = 0; i < ignoreList.size(); ++i) - delete ignoreList[i]; + QMapIterator i(buddyList); + while (i.hasNext()) + delete i.next().value(); + QMapIterator j(ignoreList); + while (i.hasNext()) + delete i.next().value(); } void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game) @@ -138,6 +140,8 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm case ItemId_Command_Ping: return cmdPing(static_cast(command), cont); case ItemId_Command_Login: return cmdLogin(static_cast(command), cont); case ItemId_Command_Message: return cmdMessage(static_cast(command), cont); + case ItemId_Command_AddToList: return cmdAddToList(static_cast(command), cont); + case ItemId_Command_RemoveFromList: return cmdRemoveFromList(static_cast(command), cont); case ItemId_Command_DeckList: return cmdDeckList(static_cast(command), cont); case ItemId_Command_DeckNewDir: return cmdDeckNewDir(static_cast(command), cont); case ItemId_Command_DeckDelDir: return cmdDeckDelDir(static_cast(command), cont); @@ -237,8 +241,12 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage())); if (authState == PasswordRight) { - buddyList = server->getBuddyList(userInfo->getName()); - ignoreList = server->getIgnoreList(userInfo->getName()); + QList _buddyList = server->getBuddyList(userInfo->getName()); + for (int i = 0; i < _buddyList.size(); ++i) + buddyList.insert(_buddyList[i]->getName(), _buddyList[i]); + QList _ignoreList = server->getIgnoreList(userInfo->getName()); + for (int i = 0; i < _ignoreList.size(); ++i) + ignoreList.insert(_ignoreList[i]->getName(), _ignoreList[i]); // This might not scale very well. Use an extra QMap if it becomes a problem. const QList &serverGames = server->getGames(); @@ -256,11 +264,13 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain } QList _buddyList; - for (int i = 0; i < buddyList.size(); ++i) - _buddyList.append(new ServerInfo_User(buddyList[i])); + QMapIterator buddyIterator(buddyList); + while (buddyIterator.hasNext()) + _buddyList.append(new ServerInfo_User(buddyIterator.next().value())); QList _ignoreList; - for (int i = 0; i < ignoreList.size(); ++i) - _ignoreList.append(new ServerInfo_User(ignoreList[i])); + QMapIterator ignoreIterator(ignoreList); + while (ignoreIterator.hasNext()) + _ignoreList.append(new ServerInfo_User(ignoreIterator.next().value())); cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList)); return RespNothing; diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 8f9caaf6..d4da0ea7 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -27,7 +27,7 @@ protected: bool acceptsUserListChanges; bool acceptsRoomListChanges; ServerInfo_User *userInfo; - QList buddyList, ignoreList; + QMap buddyList, ignoreList; private: QList itemQueue; QDateTime lastCommandTime; @@ -38,6 +38,8 @@ private: ResponseCode cmdPing(Command_Ping *cmd, CommandContainer *cont); ResponseCode cmdLogin(Command_Login *cmd, CommandContainer *cont); ResponseCode cmdMessage(Command_Message *cmd, CommandContainer *cont); + virtual ResponseCode cmdAddToList(Command_AddToList *cmd, CommandContainer *cont) = 0; + virtual ResponseCode cmdRemoveFromList(Command_RemoveFromList *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckList(Command_DeckList *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckNewDir(Command_DeckNewDir *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckDelDir(Command_DeckDelDir *cmd, CommandContainer *cont) = 0; @@ -95,8 +97,8 @@ public: bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; } ServerInfo_User *getUserInfo() const { return userInfo; } void setUserInfo(ServerInfo_User *_userInfo) { userInfo = _userInfo; } - const QList &getBuddyList() const { return buddyList; } - const QList &getIgnoreList() const { return ignoreList; } + const QMap &getBuddyList() const { return buddyList; } + const QMap &getIgnoreList() const { return ignoreList; } const QDateTime &getLastCommandTime() const { return lastCommandTime; } void processCommandContainer(CommandContainer *cont); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 0ee0b032..3aad67c1 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -47,10 +47,10 @@ public: int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; } QString getDbPrefix() const { return dbPrefix; } void updateLoginMessage(); + ServerInfo_User *getUserData(const QString &name); protected: bool userExists(const QString &user); AuthenticationResult checkUserPassword(const QString &user, const QString &password); - ServerInfo_User *getUserData(const QString &name); QList getBuddyList(const QString &name); QList getIgnoreList(const QString &name); private: diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 99fb1bb1..48fa5501 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -97,6 +97,92 @@ void ServerSocketInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem delete item; } +int ServerSocketInterface::getUserIdInDB(const QString &name) const +{ + QSqlQuery query; + query.prepare("select id from " + servatrice->getDbPrefix() + "_users where name = :name"); + query.bindValue(":name", name); + if (!servatrice->execSqlQuery(query)) + return -1; + if (!query.next()) + return -1; + return query.value(0).toInt(); +} + +ResponseCode ServerSocketInterface::cmdAddToList(Command_AddToList *cmd, CommandContainer *cont) +{ + QString list = cmd->getList(); + QString user = cmd->getUserName(); + + if ((list != "buddy") && (list != "ignore")) + return RespContextError; + + if ((list == "buddy") && buddyList.contains(user)) + return RespContextError; + if ((list == "ignore") && ignoreList.contains(user)) + return RespContextError; + + int id1 = getUserIdInDB(userInfo->getName()); + int id2 = getUserIdInDB(user); + if (id2 < 0) + return RespNameNotFound; + if (id1 == id2) + return RespContextError; + + QSqlQuery query; + query.prepare("insert into " + servatrice->getDbPrefix() + "_" + list + "list (id_user1, id_user2) values(:id1, :id2)"); + query.bindValue(":id1", id1); + query.bindValue(":id2", id2); + if (!servatrice->execSqlQuery(query)) + return RespInternalError; + + ServerInfo_User *info = servatrice->getUserData(user); + if (list == "buddy") + buddyList.insert(info->getName(), info); + else if (list == "ignore") + ignoreList.insert(info->getName(), info); + + cont->enqueueItem(new Event_AddToList(list, new ServerInfo_User(info))); + return RespOk; +} + +ResponseCode ServerSocketInterface::cmdRemoveFromList(Command_RemoveFromList *cmd, CommandContainer *cont) +{ + QString list = cmd->getList(); + QString user = cmd->getUserName(); + + if ((list != "buddy") && (list != "ignore")) + return RespContextError; + + if ((list == "buddy") && !buddyList.contains(user)) + return RespContextError; + if ((list == "ignore") && !ignoreList.contains(user)) + return RespContextError; + + int id1 = getUserIdInDB(userInfo->getName()); + int id2 = getUserIdInDB(user); + if (id2 < 0) + return RespNameNotFound; + + QSqlQuery query; + query.prepare("delete from " + servatrice->getDbPrefix() + "_" + list + "list where id_user1 = :id1 and id_user2 = :id2"); + query.bindValue(":id1", id1); + query.bindValue(":id2", id2); + if (!servatrice->execSqlQuery(query)) + return RespInternalError; + + if (list == "buddy") { + delete buddyList.value(user); + buddyList.remove(user); + } else if (list == "ignore") { + delete ignoreList.value(user); + ignoreList.remove(user); + } + + cont->enqueueItem(new Event_RemoveFromList(list, user)); + return RespOk; +} + int ServerSocketInterface::getDeckPathId(int basePathId, QStringList path) { if (path.isEmpty()) diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index d496026e..dc347d93 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -43,7 +43,10 @@ private: QXmlStreamWriter *xmlWriter; QXmlStreamReader *xmlReader; TopLevelProtocolItem *topLevelItem; + int getUserIdInDB(const QString &name) const; + ResponseCode cmdAddToList(Command_AddToList *cmd, CommandContainer *cont); + ResponseCode cmdRemoveFromList(Command_RemoveFromList *cmd, CommandContainer *cont); int getDeckPathId(int basePathId, QStringList path); int getDeckPathId(const QString &path); bool deckListHelper(DeckList_Directory *folder);