#include #include "rng_abstract.h" #include "server_protocolhandler.h" #include "protocol.h" #include "protocol_items.h" #include "server_room.h" #include "server_card.h" #include "server_arrow.h" #include "server_cardzone.h" #include "server_counter.h" #include "server_game.h" #include "server_player.h" #include "decklist.h" #include #include "pb/commands.pb.h" #include Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) : QObject(parent), server(_server), authState(PasswordWrong), acceptsUserListChanges(false), acceptsRoomListChanges(false), userInfo(0), sessionId(-1), timeRunning(0), lastDataReceived(0), gameListMutex(QMutex::Recursive) { connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); } Server_ProtocolHandler::~Server_ProtocolHandler() { } // This is essentially the destructor, but it needs to be called from the // child's destructor so that the server mutex does not get unlocked during // finalization. void Server_ProtocolHandler::prepareDestroy() { QMutexLocker locker(&server->serverMutex); qDebug("Server_ProtocolHandler::prepareDestroy"); server->removeClient(this); QMapIterator roomIterator(rooms); while (roomIterator.hasNext()) roomIterator.next().value()->removeClient(this); gameListMutex.lock(); QMapIterator > gameIterator(games); while (gameIterator.hasNext()) { gameIterator.next(); Server_Game *g = gameIterator.value().first; Server_Player *p = gameIterator.value().second; if ((authState == UnknownUser) || p->getSpectator()) g->removePlayer(p); else { p->setProtocolHandler(0); g->postConnectionStatusUpdate(p, false); } } gameListMutex.unlock(); delete userInfo; QMapIterator i(buddyList); while (i.hasNext()) delete i.next().value(); QMapIterator j(ignoreList); while (j.hasNext()) delete j.next().value(); } void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game) { qDebug() << "Server_ProtocolHandler::playerRemovedFromGame(): gameId =" << game->getGameId(); QMutexLocker locker(&gameListMutex); games.remove(game->getGameId()); } ResponseCode Server_ProtocolHandler::processSessionCommandContainer(CommandContainer *cont, BlaContainer *bla) { ResponseCode finalResponseCode = RespOk; for (int i = cont->session_command_size() - 1; i >= 0; --i) { ResponseCode resp; const SessionCommand &sc = cont->session_command(i); std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; sc.GetReflection()->ListFields(sc, &fieldList); int num = 0; for (unsigned int j = 0; j < fieldList.size(); ++j) if (fieldList[j]->number() >= 100) { num = fieldList[j]->number(); break; } switch ((SessionCommand::SessionCommandType) num) { case SessionCommand::PING: resp = cmdPing(sc.GetExtension(command_ping), cont); break; case SessionCommand::LOGIN: resp = cmdLogin(sc.GetExtension(command_login), cont, bla); break; case SessionCommand::MESSAGE: resp = cmdMessage(sc.GetExtension(command_message), cont, bla); break; case SessionCommand::ADD_TO_LIST: resp = cmdAddToList(sc.GetExtension(command_add_to_list), cont); break; case SessionCommand::REMOVE_FROM_LIST: resp = cmdRemoveFromList(sc.GetExtension(command_remove_from_list), cont); break; case SessionCommand::DECK_LIST: resp = cmdDeckList(sc.GetExtension(command_deck_list), cont); break; case SessionCommand::DECK_NEW_DIR: resp = cmdDeckNewDir(sc.GetExtension(command_deck_new_dir), cont); break; case SessionCommand::DECK_DEL_DIR: resp = cmdDeckDelDir(sc.GetExtension(command_deck_del_dir), cont); break; case SessionCommand::DECK_DEL: resp = cmdDeckDel(sc.GetExtension(command_deck_del), cont); break; case SessionCommand::DECK_UPLOAD: resp = cmdDeckUpload(sc.GetExtension(command_deck_upload), cont); break; case SessionCommand::DECK_DOWNLOAD: resp = cmdDeckDownload(sc.GetExtension(command_deck_download), cont); break; case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(command_get_games_of_user), cont, bla); break; case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(command_get_user_info), cont, bla); break; case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(command_list_rooms), cont, bla); break; case SessionCommand::JOIN_ROOM: resp = cmdJoinRoom(sc.GetExtension(command_join_room), cont, bla); break; case SessionCommand::LIST_USERS: resp = cmdListUsers(sc.GetExtension(command_list_users), cont, bla); break; } if ((resp != RespOk) && (resp != RespNothing)) finalResponseCode = resp; } return finalResponseCode; } ResponseCode Server_ProtocolHandler::processRoomCommandContainer(CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; Server_Room *room = rooms.value(cont->room_id(), 0); if (!room) return RespNotInRoom; QMutexLocker locker(&room->roomMutex); ResponseCode finalResponseCode = RespOk; for (int i = cont->room_command_size() - 1; i >= 0; --i) { ResponseCode resp; const RoomCommand &sc = cont->room_command(i); std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; sc.GetReflection()->ListFields(sc, &fieldList); int num = 0; for (unsigned int j = 0; j < fieldList.size(); ++j) if (fieldList[j]->number() >= 100) { num = fieldList[j]->number(); break; } switch ((RoomCommand::RoomCommandType) num) { case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(command_leave_room), cont, room); break; case RoomCommand::ROOM_SAY: resp = cmdRoomSay(sc.GetExtension(command_room_say), cont, room); break; case RoomCommand::CREATE_GAME: resp = cmdCreateGame(sc.GetExtension(command_create_game), cont, room); break; case RoomCommand::JOIN_GAME: resp = cmdJoinGame(sc.GetExtension(command_join_game), cont, room); break; } if ((resp != RespOk) && (resp != RespNothing)) finalResponseCode = resp; } return finalResponseCode; } ResponseCode Server_ProtocolHandler::processGameCommandContainer(CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; gameListMutex.lock(); if (!games.contains(cont->game_id())) { qDebug() << "invalid game"; return RespNotInRoom; } QPair gamePair = games.value(cont->game_id()); Server_Game *game = gamePair.first; Server_Player *player = gamePair.second; QMutexLocker locker(&game->gameMutex); gameListMutex.unlock(); ResponseCode finalResponseCode = RespOk; for (int i = cont->game_command_size() - 1; i >= 0; --i) { ResponseCode resp; const GameCommand &sc = cont->game_command(i); std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; sc.GetReflection()->ListFields(sc, &fieldList); int num = 0; for (unsigned int j = 0; j < fieldList.size(); ++j) if (fieldList[j]->number() >= 100) { num = fieldList[j]->number(); break; } switch ((GameCommand::GameCommandType) num) { case GameCommand::KICK_FROM_GAME: resp = cmdKickFromGame(sc.GetExtension(command_kick_from_game), cont, game, player, bla); break; case GameCommand::LEAVE_GAME: resp = cmdLeaveGame(sc.GetExtension(command_leave_game), cont, game, player, bla); break; case GameCommand::GAME_SAY: resp = cmdGameSay(sc.GetExtension(command_game_say), cont, game, player, bla); break; case GameCommand::SHUFFLE: resp = cmdShuffle(sc.GetExtension(command_shuffle), cont, game, player, bla); break; case GameCommand::MULLIGAN: resp = cmdMulligan(sc.GetExtension(command_mulligan), cont, game, player, bla); break; case GameCommand::ROLL_DIE: resp = cmdRollDie(sc.GetExtension(command_roll_die), cont, game, player, bla); break; case GameCommand::DRAW_CARDS: resp = cmdDrawCards(sc.GetExtension(command_draw_cards), cont, game, player, bla); break; case GameCommand::UNDO_DRAW: resp = cmdUndoDraw(sc.GetExtension(command_undo_draw), cont, game, player, bla); break; case GameCommand::FLIP_CARD: resp = cmdFlipCard(sc.GetExtension(command_flip_card), cont, game, player, bla); break; case GameCommand::ATTACH_CARD: resp = cmdAttachCard(sc.GetExtension(command_attach_card), cont, game, player, bla); break; case GameCommand::CREATE_TOKEN: resp = cmdCreateToken(sc.GetExtension(command_create_token), cont, game, player, bla); break; case GameCommand::CREATE_ARROW: resp = cmdCreateArrow(sc.GetExtension(command_create_arrow), cont, game, player, bla); break; case GameCommand::DELETE_ARROW: resp = cmdDeleteArrow(sc.GetExtension(command_delete_arrow), cont, game, player, bla); break; case GameCommand::SET_CARD_ATTR: resp = cmdSetCardAttr(sc.GetExtension(command_set_card_attr), cont, game, player, bla); break; case GameCommand::SET_CARD_COUNTER: resp = cmdSetCardCounter(sc.GetExtension(command_set_card_counter), cont, game, player, bla); break; case GameCommand::INC_CARD_COUNTER: resp = cmdIncCardCounter(sc.GetExtension(command_inc_card_counter), cont, game, player, bla); break; case GameCommand::READY_START: resp = cmdReadyStart(sc.GetExtension(command_ready_start), cont, game, player, bla); break; case GameCommand::CONCEDE: resp = cmdConcede(sc.GetExtension(command_concede), cont, game, player, bla); break; case GameCommand::INC_COUNTER: resp = cmdIncCounter(sc.GetExtension(command_inc_counter), cont, game, player, bla); break; case GameCommand::CREATE_COUNTER: resp = cmdCreateCounter(sc.GetExtension(command_create_counter), cont, game, player, bla); break; case GameCommand::SET_COUNTER: resp = cmdSetCounter(sc.GetExtension(command_set_counter), cont, game, player, bla); break; case GameCommand::DEL_COUNTER: resp = cmdDelCounter(sc.GetExtension(command_del_counter), cont, game, player, bla); break; case GameCommand::NEXT_TURN: resp = cmdNextTurn(sc.GetExtension(command_next_turn), cont, game, player, bla); break; case GameCommand::SET_ACTIVE_PHASE: resp = cmdSetActivePhase(sc.GetExtension(command_set_active_phase), cont, game, player, bla); break; case GameCommand::DUMP_ZONE: resp = cmdDumpZone(sc.GetExtension(command_dump_zone), cont, game, player, bla); break; case GameCommand::STOP_DUMP_ZONE: resp = cmdStopDumpZone(sc.GetExtension(command_stop_dump_zone), cont, game, player, bla); break; case GameCommand::REVEAL_CARDS: resp = cmdRevealCards(sc.GetExtension(command_reveal_cards), cont, game, player, bla); break; case GameCommand::MOVE_CARD: resp = cmdMoveCard(sc.GetExtension(command_move_card), cont, game, player, bla); break; case GameCommand::SET_SIDEBOARD_PLAN: resp = cmdSetSideboardPlan(sc.GetExtension(command_set_sideboard_plan), cont, game, player, bla); break; case GameCommand::DECK_SELECT: resp = cmdDeckSelect(sc.GetExtension(command_deck_select), cont, game, player, bla); break; } if ((resp != RespOk) && (resp != RespNothing)) finalResponseCode = resp; } return finalResponseCode; } ResponseCode Server_ProtocolHandler::processModeratorCommandContainer(CommandContainer *cont, BlaContainer *bla) { if (!(userInfo->getUserLevel() & ServerInfo_User::IsModerator)) return RespLoginNeeded; ResponseCode finalResponseCode = RespOk; for (int i = cont->moderator_command_size() - 1; i >= 0; --i) { ResponseCode resp; const ModeratorCommand &sc = cont->moderator_command(i); std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; sc.GetReflection()->ListFields(sc, &fieldList); int num = 0; for (unsigned int j = 0; j < fieldList.size(); ++j) if (fieldList[j]->number() >= 100) { num = fieldList[j]->number(); break; } switch ((ModeratorCommand::ModeratorCommandType) num) { case ModeratorCommand::BAN_FROM_SERVER: resp = cmdBanFromServer(sc.GetExtension(command_ban_from_server), cont); break; } if ((resp != RespOk) && (resp != RespNothing)) finalResponseCode = resp; } return finalResponseCode; } ResponseCode Server_ProtocolHandler::processAdminCommandContainer(CommandContainer *cont, BlaContainer *bla) { if (!(userInfo->getUserLevel() & ServerInfo_User::IsAdmin)) return RespLoginNeeded; ResponseCode finalResponseCode = RespOk; for (int i = cont->admin_command_size() - 1; i >= 0; --i) { ResponseCode resp; const AdminCommand &sc = cont->admin_command(i); std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; sc.GetReflection()->ListFields(sc, &fieldList); int num = 0; for (unsigned int j = 0; j < fieldList.size(); ++j) if (fieldList[j]->number() >= 100) { num = fieldList[j]->number(); break; } switch ((AdminCommand::AdminCommandType) num) { case AdminCommand::SHUTDOWN_SERVER: resp = cmdShutdownServer(sc.GetExtension(command_shutdown_server), cont); break; case AdminCommand::UPDATE_SERVER_MESSAGE: resp = cmdUpdateServerMessage(sc.GetExtension(command_update_server_message), cont); break; } if ((resp != RespOk) && (resp != RespNothing)) finalResponseCode = resp; } return finalResponseCode; } void Server_ProtocolHandler::processCommandContainer(CommandContainer *cont) { lastDataReceived = timeRunning; BlaContainer *bla = new BlaContainer; ResponseCode finalResponseCode; if (cont->game_command_size()) { finalResponseCode = processGameCommandContainer(cont, bla); } else if (cont->room_command_size()) { finalResponseCode = processRoomCommandContainer(cont, bla); } else if (cont->session_command_size()) { finalResponseCode = processSessionCommandContainer(cont, bla); } else if (cont->moderator_command_size()) { finalResponseCode = processModeratorCommandContainer(cont, bla); } else if (cont->admin_command_size()) { finalResponseCode = processAdminCommandContainer(cont, bla); } ProtocolResponse *pr = bla->getResponse(); if (!pr) pr = new ProtocolResponse(cont->cmd_id(), finalResponseCode); gameListMutex.lock(); GameEventContainer *gQPublic = bla->getGameEventQueuePublic(); if (gQPublic) { QPair gamePlayerPair = games.value(gQPublic->getGameId()); if (gamePlayerPair.first) { GameEventContainer *gQPrivate = bla->getGameEventQueuePrivate(); GameEventContainer *gQOmniscient = bla->getGameEventQueueOmniscient(); if (gQPrivate) { int privatePlayerId = bla->getPrivatePlayerId(); Server_Player *privatePlayer; if (privatePlayerId == -1) privatePlayer = gamePlayerPair.second; else privatePlayer = gamePlayerPair.first->getPlayer(privatePlayerId); if (gQOmniscient) { gamePlayerPair.first->sendGameEventContainer(gQPublic, privatePlayer, true); gamePlayerPair.first->sendGameEventContainerOmniscient(gQOmniscient, privatePlayer); } else gamePlayerPair.first->sendGameEventContainer(gQPublic, privatePlayer); privatePlayer->sendProtocolItem(gQPrivate); } else gamePlayerPair.first->sendGameEventContainer(gQPublic); } } gameListMutex.unlock(); const QList &iQ = bla->getItemQueue(); for (int i = 0; i < iQ.size(); ++i) sendProtocolItem(iQ[i]); sendProtocolItem(pr); while (!itemQueue.isEmpty()) sendProtocolItem(itemQueue.takeFirst()); // if (cont->getReceiverMayDelete()) delete cont; } void Server_ProtocolHandler::pingClockTimeout() { int interval = server->getMessageCountingInterval(); if (interval > 0) { messageSizeOverTime.prepend(0); if (messageSizeOverTime.size() > server->getMessageCountingInterval()) messageSizeOverTime.removeLast(); messageCountOverTime.prepend(0); if (messageCountOverTime.size() > server->getMessageCountingInterval()) messageCountOverTime.removeLast(); } if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime()) deleteLater(); ++timeRunning; } void Server_ProtocolHandler::enqueueProtocolItem(ProtocolItem *item) { itemQueue.append(item); } QPair Server_ProtocolHandler::getGame(int gameId) const { if (games.contains(gameId)) return games.value(gameId); return QPair(0, 0); } ResponseCode Server_ProtocolHandler::cmdPing(const Command_Ping & /*cmd*/, CommandContainer * /*cont*/) { return RespOk; } ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, CommandContainer *cont, BlaContainer *bla) { QString userName = QString::fromStdString(cmd.user_name()).simplified(); if (userName.isEmpty() || (userInfo != 0)) return RespContextError; authState = server->loginUser(this, userName, QString::fromStdString(cmd.password())); if (authState == PasswordWrong) return RespWrongPassword; if (authState == WouldOverwriteOldSession) return RespWouldOverwriteOldSession; ProtocolItem *serverMessage = new Event_ServerMessage(server->getLoginMessage()); if (getCompressionSupport()) serverMessage->setCompressed(true); enqueueProtocolItem(serverMessage); QList _buddyList, _ignoreList; if (authState == PasswordRight) { buddyList = server->getBuddyList(userInfo->getName()); QMapIterator buddyIterator(buddyList); while (buddyIterator.hasNext()) _buddyList.append(new ServerInfo_User(buddyIterator.next().value())); ignoreList = server->getIgnoreList(userInfo->getName()); QMapIterator ignoreIterator(ignoreList); while (ignoreIterator.hasNext()) _ignoreList.append(new ServerInfo_User(ignoreIterator.next().value())); } server->serverMutex.lock(); QList gameList; QMapIterator roomIterator(server->getRooms()); QMutexLocker gameListLocker(&gameListMutex); while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); room->roomMutex.lock(); QMapIterator gameIterator(room->getGames()); while (gameIterator.hasNext()) { Server_Game *game = gameIterator.next().value(); QMutexLocker gameLocker(&game->gameMutex); const QList &gamePlayers = game->getPlayers().values(); for (int j = 0; j < gamePlayers.size(); ++j) if (gamePlayers[j]->getUserInfo()->getName() == userInfo->getName()) { gamePlayers[j]->setProtocolHandler(this); game->postConnectionStatusUpdate(gamePlayers[j], true); games.insert(game->getGameId(), QPair(game, gamePlayers[j])); enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), game->getHostId(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), true)); enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(gamePlayers[j])), game->getGameId())); break; } } room->roomMutex.unlock(); } server->serverMutex.unlock(); ProtocolResponse *resp = new Response_Login(cont->cmd_id(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList); if (getCompressionSupport()) resp->setCompressed(true); bla->setResponse(resp); return RespNothing; } ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message &cmd, CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; QString receiver = QString::fromStdString(cmd.user_name()); Server_ProtocolHandler *userHandler = server->getUsers().value(receiver); qDebug() << "cmdMessage: recv=" << receiver << (userHandler == 0 ? "not found" : "found"); if (!userHandler) return RespNameNotFound; if (userHandler->getIgnoreList().contains(userInfo->getName())) return RespInIgnoreList; QString message = QString::fromStdString(cmd.message()); bla->enqueueItem(new Event_Message(userInfo->getName(), receiver, message)); userHandler->sendProtocolItem(new Event_Message(userInfo->getName(), receiver, message)); return RespOk; } ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; server->serverMutex.lock(); if (!server->getUsers().contains(QString::fromStdString(cmd.user_name()))) return RespNameNotFound; QList roomList; QList gameList; QMapIterator roomIterator(server->getRooms()); while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); room->roomMutex.lock(); roomList.append(room->getInfo(false, true)); gameList << room->getGamesOfUser(QString::fromStdString(cmd.user_name())); room->roomMutex.unlock(); } server->serverMutex.unlock(); ProtocolResponse *resp = new Response_GetGamesOfUser(cont->cmd_id(), RespOk, roomList, gameList); if (getCompressionSupport()) resp->setCompressed(true); bla->setResponse(resp); return RespNothing; } ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetUserInfo &cmd, CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; QString userName = QString::fromStdString(cmd.user_name()); ServerInfo_User *result; if (userName.isEmpty()) result = new ServerInfo_User(userInfo); else { Server_ProtocolHandler *handler = server->getUsers().value(userName); if (!handler) return RespNameNotFound; result = new ServerInfo_User(handler->getUserInfo(), true, userInfo->getUserLevel() & ServerInfo_User::IsModerator); } bla->setResponse(new Response_GetUserInfo(cont->cmd_id(), RespOk, result)); return RespNothing; } ResponseCode Server_ProtocolHandler::cmdListRooms(const Command_ListRooms & /*cmd*/, CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; QList eventRoomList; QMapIterator roomIterator(server->getRooms()); while (roomIterator.hasNext()) eventRoomList.append(roomIterator.next().value()->getInfo(false)); bla->enqueueItem(new Event_ListRooms(eventRoomList)); acceptsRoomListChanges = true; return RespOk; } ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoom &cmd, CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; if (rooms.contains(cmd.room_id())) return RespContextError; Server_Room *r = server->getRooms().value(cmd.room_id(), 0); if (!r) return RespNameNotFound; QMutexLocker serverLocker(&server->serverMutex); QMutexLocker roomLocker(&r->roomMutex); r->addClient(this); rooms.insert(r->getId(), r); enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage())); ServerInfo_Room *info = r->getInfo(true); if (getCompressionSupport()) info->setCompressed(true); bla->setResponse(new Response_JoinRoom(cont->cmd_id(), RespOk, info)); return RespNothing; } ResponseCode Server_ProtocolHandler::cmdListUsers(const Command_ListUsers & /*cmd*/, CommandContainer *cont, BlaContainer *bla) { if (authState == PasswordWrong) return RespLoginNeeded; QList resultList; QMapIterator userIterator = server->getUsers(); while (userIterator.hasNext()) resultList.append(new ServerInfo_User(userIterator.next().value()->getUserInfo(), false)); acceptsUserListChanges = true; ProtocolResponse *resp = new Response_ListUsers(cont->cmd_id(), RespOk, resultList); if (getCompressionSupport()) resp->setCompressed(true); bla->setResponse(resp); return RespNothing; } ResponseCode Server_ProtocolHandler::cmdLeaveRoom(const Command_LeaveRoom & /*cmd*/, CommandContainer * /*cont*/, Server_Room *room) { rooms.remove(room->getId()); room->removeClient(this); return RespOk; } ResponseCode Server_ProtocolHandler::cmdRoomSay(const Command_RoomSay &cmd, CommandContainer * /*cont*/, Server_Room *room) { QString msg = QString::fromStdString(cmd.message()); if (server->getMessageCountingInterval() > 0) { int totalSize = 0, totalCount = 0; if (messageSizeOverTime.isEmpty()) messageSizeOverTime.prepend(0); messageSizeOverTime[0] += msg.size(); for (int i = 0; i < messageSizeOverTime.size(); ++i) totalSize += messageSizeOverTime[i]; if (messageCountOverTime.isEmpty()) messageCountOverTime.prepend(0); ++messageCountOverTime[0]; for (int i = 0; i < messageCountOverTime.size(); ++i) totalCount += messageCountOverTime[i]; if ((totalSize > server->getMaxMessageSizePerInterval()) || (totalCount > server->getMaxMessageCountPerInterval())) return RespChatFlood; } msg.replace(QChar('\n'), QChar(' ')); room->say(this, msg); return RespOk; } ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, CommandContainer * /*cont*/, Server_Room *room) { if (authState == PasswordWrong) return RespLoginNeeded; if (server->getMaxGamesPerUser() > 0) if (room->getGamesCreatedByUser(userInfo->getName()) >= server->getMaxGamesPerUser()) return RespContextError; QList gameTypes; for (int i = cmd.game_type_ids_size() - 1; i >= 0; --i) gameTypes.append(cmd.game_type_ids(i)); QString description = QString::fromStdString(cmd.description()); if (description.size() > 60) description = description.left(60); Server_Game *game = room->createGame(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(), this); Server_Player *creator = game->getPlayers().values().first(); QMutexLocker gameListLocker(&gameListMutex); games.insert(game->getGameId(), QPair(game, creator)); sendProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); sendProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId())); game->gameMutex.unlock(); return RespOk; } ResponseCode Server_ProtocolHandler::cmdJoinGame(const Command_JoinGame &cmd, CommandContainer * /*cont*/, Server_Room *room) { if (authState == PasswordWrong) return RespLoginNeeded; QMutexLocker gameListLocker(&gameListMutex); if (games.contains(cmd.game_id())) return RespContextError; Server_Game *g = room->getGames().value(cmd.game_id()); if (!g) return RespNameNotFound; QMutexLocker locker(&g->gameMutex); ResponseCode result = g->checkJoin(userInfo, QString::fromStdString(cmd.password()), cmd.spectator(), cmd.override_restrictions()); if (result == RespOk) { Server_Player *player = g->addPlayer(this, cmd.spectator()); games.insert(cmd.game_id(), QPair(g, player)); enqueueProtocolItem(new Event_GameJoined(cmd.game_id(), g->getDescription(), g->getHostId(), player->getPlayerId(), cmd.spectator(), g->getSpectatorsCanTalk(), g->getSpectatorsSeeEverything(), false)); enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(g->getGameStarted(), g->getActivePlayer(), g->getActivePhase(), g->getGameState(player)), cmd.game_id())); } return result; } ResponseCode Server_ProtocolHandler::cmdLeaveGame(const Command_LeaveGame & /*cmd*/, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { game->removePlayer(player); return RespOk; } ResponseCode Server_ProtocolHandler::cmdKickFromGame(const Command_KickFromGame &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if ((game->getHostId() != player->getPlayerId()) && !(userInfo->getUserLevel() & ServerInfo_User::IsModerator)) return RespFunctionNotAllowed; if (!game->kickPlayer(cmd.player_id())) return RespNameNotFound; return RespOk; } ResponseCode Server_ProtocolHandler::cmdDeckSelect(const Command_DeckSelect &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; DeckList *deck; if (cmd.deck_id() == -1) { // if (!cmd->getDeck()) // return RespInvalidData; // deck = new DeckList(cmd->getDeck()); } else { try { deck = getDeckFromDatabase(cmd.deck_id()); } catch(ResponseCode r) { return r; } } player->setDeck(deck); game->sendGameEvent(new Event_PlayerPropertiesChanged(player->getPlayerId(), player->getProperties()), new Context_DeckSelect(deck->getDeckHash())); bla->setResponse(new Response_DeckDownload(cont->cmd_id(), RespOk, new DeckList(deck))); return RespNothing; } ResponseCode Server_ProtocolHandler::cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (player->getReadyStart()) return RespContextError; DeckList *deck = player->getDeck(); if (!deck) return RespContextError; QList sideboardPlan; for (int i = 0; i < cmd.move_list_size(); ++i) { const MoveCard_ToZone &temp = cmd.move_list(i); sideboardPlan.append(new MoveCardToZone(QString::fromStdString(temp.card_name()), QString::fromStdString(temp.start_zone()), QString::fromStdString(temp.target_zone()))); } deck->setCurrentSideboardPlan(sideboardPlan); for (int i = 0; i < sideboardPlan.size(); ++i) delete sideboardPlan[i]; // TEMPORARY HACK return RespOk; } ResponseCode Server_ProtocolHandler::cmdConcede(const Command_Concede & /*cmd*/, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; player->setConceded(true); game->removeArrowsToPlayer(player); player->clearZones(); game->sendGameEvent(new Event_PlayerPropertiesChanged(player->getPlayerId(), player->getProperties()), new Context_Concede); game->stopGameIfFinished(); if (game->getGameStarted() && (game->getActivePlayer() == player->getPlayerId())) game->nextTurn(); return RespOk; } ResponseCode Server_ProtocolHandler::cmdReadyStart(const Command_ReadyStart &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!player->getDeck() || game->getGameStarted()) return RespContextError; if (player->getReadyStart() == cmd.ready()) return RespContextError; player->setReadyStart(cmd.ready()); game->sendGameEvent(new Event_PlayerPropertiesChanged(player->getPlayerId(), player->getProperties()), new Context_ReadyStart); game->startGameIfReady(); return RespOk; } ResponseCode Server_ProtocolHandler::cmdGameSay(const Command_GameSay &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator() && !game->getSpectatorsCanTalk() && !(userInfo->getUserLevel() & ServerInfo_User::IsModerator)) return RespFunctionNotAllowed; game->sendGameEvent(new Event_Say(player->getPlayerId(), QString::fromStdString(cmd.message()))); return RespOk; } ResponseCode Server_ProtocolHandler::cmdShuffle(const Command_Shuffle & /*cmd*/, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; player->getZones().value("deck")->shuffle(); game->sendGameEvent(new Event_Shuffle(player->getPlayerId())); return RespOk; } ResponseCode Server_ProtocolHandler::cmdMulligan(const Command_Mulligan & /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_CardZone *hand = player->getZones().value("hand"); int number = (hand->cards.size() <= 1) ? player->getInitialCards() : hand->cards.size() - 1; Server_CardZone *deck = player->getZones().value("deck"); while (!hand->cards.isEmpty()) { CardToMove *cardToMove = new CardToMove; cardToMove->set_card_id(hand->cards.first()->getId()); player->moveCard(bla, hand, QList() << cardToMove, deck, 0, 0, false); delete cardToMove; } deck->shuffle(); bla->enqueueGameEventPrivate(new Event_Shuffle(player->getPlayerId()), game->getGameId()); bla->enqueueGameEventOmniscient(new Event_Shuffle(player->getPlayerId()), game->getGameId()); bla->enqueueGameEventPublic(new Event_Shuffle(player->getPlayerId()), game->getGameId()); player->drawCards(bla, number); if (number == player->getInitialCards()) number = -1; bla->getGameEventQueuePrivate()->setContext(new Context_Mulligan(number)); bla->getGameEventQueuePublic()->setContext(new Context_Mulligan(number)); bla->getGameEventQueueOmniscient()->setContext(new Context_Mulligan(number)); return RespOk; } ResponseCode Server_ProtocolHandler::cmdRollDie(const Command_RollDie &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (player->getConceded()) return RespContextError; game->sendGameEvent(new Event_RollDie(player->getPlayerId(), cmd.sides(), rng->getNumber(1, cmd.sides()))); return RespOk; } ResponseCode Server_ProtocolHandler::cmdDrawCards(const Command_DrawCards &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; return player->drawCards(bla, cmd.number()); } ResponseCode Server_ProtocolHandler::cmdUndoDraw(const Command_UndoDraw & /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; return player->undoDraw(bla); } ResponseCode Server_ProtocolHandler::cmdMoveCard(const Command_MoveCard &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; QList cardsToMove; for (int i = 0; i < cmd.cards_to_move_size(); ++i) cardsToMove.append(&cmd.cards_to_move(i)); return player->moveCard(bla, QString::fromStdString(cmd.start_zone()), cardsToMove, cmd.target_player_id(), QString::fromStdString(cmd.target_zone()), cmd.x(), cmd.y()); } ResponseCode Server_ProtocolHandler::cmdFlipCard(const Command_FlipCard &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_CardZone *zone = player->getZones().value(QString::fromStdString(cmd.zone())); if (!zone) return RespNameNotFound; if (!zone->hasCoords()) return RespContextError; Server_Card *card = zone->getCard(cmd.card_id()); if (!card) return RespNameNotFound; const bool faceDown = cmd.face_down(); if (faceDown == card->getFaceDown()) return RespContextError; card->setFaceDown(faceDown); bla->enqueueGameEventPrivate(new Event_FlipCard(player->getPlayerId(), zone->getName(), card->getId(), card->getName(), faceDown), game->getGameId()); bla->enqueueGameEventPublic(new Event_FlipCard(player->getPlayerId(), zone->getName(), card->getId(), card->getName(), faceDown), game->getGameId()); return RespOk; } ResponseCode Server_ProtocolHandler::cmdAttachCard(const Command_AttachCard &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_CardZone *startzone = player->getZones().value(QString::fromStdString(cmd.start_zone())); if (!startzone) return RespNameNotFound; Server_Card *card = startzone->getCard(cmd.card_id()); if (!card) return RespNameNotFound; int playerId = cmd.target_player_id(); Server_Player *targetPlayer = 0; Server_CardZone *targetzone = 0; Server_Card *targetCard = 0; if (playerId != -1) { targetPlayer = game->getPlayer(cmd.target_player_id()); if (!targetPlayer) return RespNameNotFound; } else if (!card->getParentCard()) return RespContextError; if (targetPlayer) targetzone = targetPlayer->getZones().value(QString::fromStdString(cmd.target_zone())); if (targetzone) { // This is currently enough to make sure cards don't get attached to a card that is not on the table. // Possibly a flag will have to be introduced for this sometime. if (!targetzone->hasCoords()) return RespContextError; targetCard = targetzone->getCard(cmd.target_card_id()); if (targetCard) if (targetCard->getParentCard()) return RespContextError; } if (!startzone->hasCoords()) return RespContextError; // Get all arrows pointing to or originating from the card being attached and delete them. QMapIterator playerIterator(game->getPlayers()); while (playerIterator.hasNext()) { Server_Player *p = playerIterator.next().value(); QList arrows = p->getArrows().values(); QList toDelete; for (int i = 0; i < arrows.size(); ++i) { Server_Arrow *a = arrows[i]; Server_Card *tCard = qobject_cast(a->getTargetItem()); if ((tCard == card) || (a->getStartCard() == card)) toDelete.append(a); } for (int i = 0; i < toDelete.size(); ++i) { bla->enqueueGameEventPrivate(new Event_DeleteArrow(p->getPlayerId(), toDelete[i]->getId()), game->getGameId()); bla->enqueueGameEventPublic(new Event_DeleteArrow(p->getPlayerId(), toDelete[i]->getId()), game->getGameId()); p->deleteArrow(toDelete[i]->getId()); } } if (targetCard) { // Unattach all cards attached to the card being attached. // Make a copy of the list because its contents change during the loop otherwise. QList attachedList = card->getAttachedCards(); for (int i = 0; i < attachedList.size(); ++i) attachedList[i]->getZone()->getPlayer()->unattachCard(bla, attachedList[i]); if (targetzone->isColumnStacked(targetCard->getX(), targetCard->getY())) { CardToMove *cardToMove = new CardToMove; cardToMove->set_card_id(targetCard->getId()); targetPlayer->moveCard(bla, targetzone, QList() << cardToMove, targetzone, targetzone->getFreeGridColumn(-2, targetCard->getY(), targetCard->getName()), targetCard->getY(), targetCard->getFaceDown()); delete cardToMove; } card->setParentCard(targetCard); card->setCoords(-1, card->getY()); bla->enqueueGameEventPrivate(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId()); bla->enqueueGameEventPublic(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId()); startzone->fixFreeSpaces(bla); } else player->unattachCard(bla, card); return RespOk; } ResponseCode Server_ProtocolHandler::cmdCreateToken(const Command_CreateToken &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_CardZone *zone = player->getZones().value(QString::fromStdString(cmd.zone())); if (!zone) return RespNameNotFound; QString cardName = QString::fromStdString(cmd.card_name()); int x = cmd.x(); int y = cmd.y(); if (zone->hasCoords()) x = zone->getFreeGridColumn(x, y, cardName); if (x < 0) x = 0; if (y < 0) y = 0; Server_Card *card = new Server_Card(cardName, player->newCardId(), x, y); card->moveToThread(player->thread()); card->setPT(QString::fromStdString(cmd.pt())); card->setColor(QString::fromStdString(cmd.color())); card->setAnnotation(QString::fromStdString(cmd.annotation())); card->setDestroyOnZoneChange(cmd.destroy_on_zone_change()); zone->insertCard(card, x, y); game->sendGameEvent(new Event_CreateToken(player->getPlayerId(), zone->getName(), card->getId(), card->getName(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), x, y)); return RespOk; } ResponseCode Server_ProtocolHandler::cmdCreateArrow(const Command_CreateArrow &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_Player *startPlayer = game->getPlayer(cmd.start_player_id()); Server_Player *targetPlayer = game->getPlayer(cmd.target_player_id()); if (!startPlayer || !targetPlayer) return RespNameNotFound; QString startZoneName = QString::fromStdString(cmd.start_zone()); Server_CardZone *startZone = startPlayer->getZones().value(startZoneName); QString targetZoneName = QString::fromStdString(cmd.target_zone()); bool playerTarget = targetZoneName.isEmpty(); Server_CardZone *targetZone = 0; if (!playerTarget) targetZone = targetPlayer->getZones().value(targetZoneName); if (!startZone || (!targetZone && !playerTarget)) return RespNameNotFound; if (startZone->getType() != PublicZone) return RespContextError; Server_Card *startCard = startZone->getCard(cmd.start_card_id()); if (!startCard) return RespNameNotFound; Server_Card *targetCard = 0; if (!playerTarget) { if (targetZone->getType() != PublicZone) return RespContextError; targetCard = targetZone->getCard(cmd.target_card_id()); } Server_ArrowTarget *targetItem; if (playerTarget) targetItem = targetPlayer; else targetItem = targetCard; if (!targetItem) return RespNameNotFound; QMapIterator arrowIterator(player->getArrows()); while (arrowIterator.hasNext()) { Server_Arrow *temp = arrowIterator.next().value(); if ((temp->getStartCard() == startCard) && (temp->getTargetItem() == targetItem)) return RespContextError; } Server_Arrow *arrow = new Server_Arrow(player->newArrowId(), startCard, targetItem, cmd.arrow_color()); player->addArrow(arrow); game->sendGameEvent(new Event_CreateArrows(player->getPlayerId(), QList() << new ServerInfo_Arrow( arrow->getId(), startPlayer->getPlayerId(), startZoneName, startCard->getId(), targetPlayer->getPlayerId(), targetZoneName, cmd.target_card_id(), cmd.arrow_color() ))); return RespOk; } ResponseCode Server_ProtocolHandler::cmdDeleteArrow(const Command_DeleteArrow &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; if (!player->deleteArrow(cmd.arrow_id())) return RespNameNotFound; game->sendGameEvent(new Event_DeleteArrow(player->getPlayerId(), cmd.arrow_id())); return RespOk; } ResponseCode Server_ProtocolHandler::cmdSetCardAttr(const Command_SetCardAttr &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; return player->setCardAttrHelper(bla, QString::fromStdString(cmd.zone()), cmd.card_id(), QString::fromStdString(cmd.attr_name()), QString::fromStdString(cmd.attr_value())); } ResponseCode Server_ProtocolHandler::cmdSetCardCounter(const Command_SetCardCounter &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_CardZone *zone = player->getZones().value(QString::fromStdString(cmd.zone())); if (!zone) return RespNameNotFound; if (!zone->hasCoords()) return RespContextError; Server_Card *card = zone->getCard(cmd.card_id()); if (!card) return RespNameNotFound; card->setCounter(cmd.counter_id(), cmd.counter_value()); bla->enqueueGameEventPrivate(new Event_SetCardCounter(player->getPlayerId(), zone->getName(), card->getId(), cmd.counter_id(), cmd.counter_value()), game->getGameId()); bla->enqueueGameEventPublic(new Event_SetCardCounter(player->getPlayerId(), zone->getName(), card->getId(), cmd.counter_id(), cmd.counter_value()), game->getGameId()); return RespOk; } ResponseCode Server_ProtocolHandler::cmdIncCardCounter(const Command_IncCardCounter &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_CardZone *zone = player->getZones().value(QString::fromStdString(cmd.zone())); if (!zone) return RespNameNotFound; if (!zone->hasCoords()) return RespContextError; Server_Card *card = zone->getCard(cmd.card_id()); if (!card) return RespNameNotFound; int newValue = card->getCounter(cmd.counter_id()) + cmd.counter_delta(); card->setCounter(cmd.counter_id(), newValue); bla->enqueueGameEventPrivate(new Event_SetCardCounter(player->getPlayerId(), zone->getName(), card->getId(), cmd.counter_id(), newValue), game->getGameId()); bla->enqueueGameEventPublic(new Event_SetCardCounter(player->getPlayerId(), zone->getName(), card->getId(), cmd.counter_id(), newValue), game->getGameId()); return RespOk; } ResponseCode Server_ProtocolHandler::cmdIncCounter(const Command_IncCounter &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; const QMap counters = player->getCounters(); Server_Counter *c = counters.value(cmd.counter_id(), 0); if (!c) return RespNameNotFound; c->setCount(c->getCount() + cmd.delta()); game->sendGameEvent(new Event_SetCounter(player->getPlayerId(), c->getId(), c->getCount())); return RespOk; } ResponseCode Server_ProtocolHandler::cmdCreateCounter(const Command_CreateCounter &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_Counter *c = new Server_Counter(player->newCounterId(), QString::fromStdString(cmd.counter_name()), cmd.counter_color(), cmd.radius(), cmd.value()); player->addCounter(c); game->sendGameEvent(new Event_CreateCounters(player->getPlayerId(), QList() << new ServerInfo_Counter(c->getId(), c->getName(), c->getColor(), c->getRadius(), c->getCount()))); return RespOk; } ResponseCode Server_ProtocolHandler::cmdSetCounter(const Command_SetCounter &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_Counter *c = player->getCounters().value(cmd.counter_id(), 0);; if (!c) return RespNameNotFound; c->setCount(cmd.value()); game->sendGameEvent(new Event_SetCounter(player->getPlayerId(), c->getId(), c->getCount())); return RespOk; } ResponseCode Server_ProtocolHandler::cmdDelCounter(const Command_DelCounter &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; if (!player->deleteCounter(cmd.counter_id())) return RespNameNotFound; game->sendGameEvent(new Event_DelCounter(player->getPlayerId(), cmd.counter_id())); return RespOk; } ResponseCode Server_ProtocolHandler::cmdNextTurn(const Command_NextTurn & /*cmd*/, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; game->nextTurn(); return RespOk; } ResponseCode Server_ProtocolHandler::cmdSetActivePhase(const Command_SetActivePhase &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; if (game->getActivePlayer() != player->getPlayerId()) return RespContextError; game->setActivePhase(cmd.phase()); return RespOk; } ResponseCode Server_ProtocolHandler::cmdDumpZone(const Command_DumpZone &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (!game->getGameStarted()) return RespGameNotStarted; Server_Player *otherPlayer = game->getPlayer(cmd.player_id()); if (!otherPlayer) return RespNameNotFound; Server_CardZone *zone = otherPlayer->getZones().value(QString::fromStdString(cmd.zone_name())); if (!zone) return RespNameNotFound; if (!((zone->getType() == PublicZone) || (player == otherPlayer))) return RespContextError; int numberCards = cmd.number_cards(); QList respCardList; for (int i = 0; (i < zone->cards.size()) && (i < numberCards || numberCards == -1); ++i) { Server_Card *card = zone->cards[i]; QString displayedName = card->getFaceDown() ? QString() : card->getName(); if (zone->getType() == HiddenZone) respCardList.append(new ServerInfo_Card(i, displayedName)); else { QList cardCounterList; QMapIterator cardCounterIterator(card->getCounters()); while (cardCounterIterator.hasNext()) { cardCounterIterator.next(); cardCounterList.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); } int attachPlayerId = -1; QString attachZone; int attachCardId = -1; if (card->getParentCard()) { attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); attachZone = card->getParentCard()->getZone()->getName(); attachCardId = card->getParentCard()->getId(); } respCardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterList, attachPlayerId, attachZone, attachCardId)); } } if (zone->getType() == HiddenZone) { zone->setCardsBeingLookedAt(numberCards); game->sendGameEvent(new Event_DumpZone(player->getPlayerId(), otherPlayer->getPlayerId(), zone->getName(), numberCards)); } bla->setResponse(new Response_DumpZone(cont->cmd_id(), RespOk, new ServerInfo_Zone(zone->getName(), zone->getType(), zone->hasCoords(), numberCards < zone->cards.size() ? zone->cards.size() : numberCards, respCardList))); return RespNothing; } ResponseCode Server_ProtocolHandler::cmdStopDumpZone(const Command_StopDumpZone &cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_Player *otherPlayer = game->getPlayer(cmd.player_id()); if (!otherPlayer) return RespNameNotFound; Server_CardZone *zone = otherPlayer->getZones().value(QString::fromStdString(cmd.zone_name())); if (!zone) return RespNameNotFound; if (zone->getType() == HiddenZone) { zone->setCardsBeingLookedAt(0); game->sendGameEvent(new Event_StopDumpZone(player->getPlayerId(), cmd.player_id(), zone->getName())); } return RespOk; } ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_RevealCards &cmd, CommandContainer *cont, Server_Game *game, Server_Player *player, BlaContainer *bla) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; if (player->getConceded()) return RespContextError; Server_Player *otherPlayer = 0; if (cmd.player_id() != -1) { otherPlayer = game->getPlayer(cmd.player_id()); if (!otherPlayer) return RespNameNotFound; } Server_CardZone *zone = player->getZones().value(QString::fromStdString(cmd.zone_name())); if (!zone) return RespNameNotFound; QList cardsToReveal; if (cmd.card_id() == -1) cardsToReveal = zone->cards; else if (cmd.card_id() == -2) { if (zone->cards.isEmpty()) return RespContextError; cardsToReveal.append(zone->cards.at(rng->getNumber(0, zone->cards.size() - 1))); } else { Server_Card *card = zone->getCard(cmd.card_id()); if (!card) return RespNameNotFound; cardsToReveal.append(card); } QList respCardListPrivate, respCardListOmniscient; for (int i = 0; i < cardsToReveal.size(); ++i) { Server_Card *card = cardsToReveal[i]; QList cardCounterListPrivate, cardCounterListOmniscient; QMapIterator cardCounterIterator(card->getCounters()); while (cardCounterIterator.hasNext()) { cardCounterIterator.next(); cardCounterListPrivate.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); cardCounterListOmniscient.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); } int attachPlayerId = -1; QString attachZone; int attachCardId = -1; if (card->getParentCard()) { attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); attachZone = card->getParentCard()->getZone()->getName(); attachCardId = card->getParentCard()->getId(); } if (cmd.player_id() != -1) respCardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListPrivate, attachPlayerId, attachZone, attachCardId)); respCardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListOmniscient, attachPlayerId, attachZone, attachCardId)); } if (cmd.player_id() == -1) bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), -1, respCardListOmniscient), game->getGameId()); else { bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId()), game->getGameId()); bla->enqueueGameEventPrivate(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListPrivate), game->getGameId(), otherPlayer->getPlayerId()); bla->enqueueGameEventOmniscient(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListOmniscient), game->getGameId()); } return RespOk; }