Ejemplo n.º 1
0
void Server::externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId)
{
    // This function is always called from the main thread via signal/slot.

    try {
        ResponseContainer responseContainer(cont.cmd_id());
        Response::ResponseCode finalResponseCode = Response::RespOk;

        QReadLocker roomsLocker(&roomsLock);
        Server_Room *room = rooms.value(cont.room_id());
        if (!room) {
            qDebug() << "externalGameCommandContainerReceived: room id=" << cont.room_id() << "not found";
            throw Response::RespNotInRoom;
        }

        QReadLocker roomGamesLocker(&room->gamesLock);
        Server_Game *game = room->getGames().value(cont.game_id());
        if (!game) {
            qDebug() << "externalGameCommandContainerReceived: game id=" << cont.game_id() << "not found";
            throw Response::RespNotInRoom;
        }

        QMutexLocker gameLocker(&game->gameMutex);
        Server_Player *player = game->getPlayers().value(playerId);
        if (!player) {
            qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found";
            throw Response::RespNotInRoom;
        }

        GameEventStorage ges;
        for (int i = cont.game_command_size() - 1; i >= 0; --i) {
            const GameCommand &sc = cont.game_command(i);
            qDebug() << "[ISL]" << QString::fromStdString(sc.ShortDebugString());

            Response::ResponseCode resp = player->processGameCommand(sc, responseContainer, ges);

            if (resp != Response::RespOk)
                finalResponseCode = resp;
        }
        ges.sendToGame(game);

        if (finalResponseCode != Response::RespNothing) {
            player->playerMutex.lock();
            player->getUserInterface()->sendResponseContainer(responseContainer, finalResponseCode);
            player->playerMutex.unlock();
        }
    } catch (Response::ResponseCode code) {
        Response response;
        response.set_cmd_id(cont.cmd_id());
        response.set_response_code(code);

        sendIsl_Response(response, serverId, sessionId);
    }
}
Ejemplo n.º 2
0
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{
	if (authState == NotLoggedIn)
		return Response::RespLoginNeeded;
	
	QMap<int, QPair<int, int> > gameMap = getGames();
	if (!gameMap.contains(cont.game_id()))
		return Response::RespNotInRoom;
	const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id());
	
	QReadLocker roomsLocker(&server->roomsLock);
	Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first);
	if (!room)
		return Response::RespNotInRoom;
	
	QReadLocker roomGamesLocker(&room->gamesLock);
	Server_Game *game = room->getGames().value(cont.game_id());
	if (!game) {
		if (room->getExternalGames().contains(cont.game_id())) {
			server->sendIsl_GameCommand(cont,
			                            room->getExternalGames().value(cont.game_id()).server_id(),
			                            userInfo->session_id(),
			                            roomIdAndPlayerId.first,
			                            roomIdAndPlayerId.second
			                            );
			return Response::RespNothing;
		}
		return Response::RespNotInRoom;
	}
	
	QMutexLocker gameLocker(&game->gameMutex);
	Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second);
	if (!player)
		return Response::RespNotInRoom;
	
	GameEventStorage ges;
	Response::ResponseCode finalResponseCode = Response::RespOk;
	for (int i = cont.game_command_size() - 1; i >= 0; --i) {
		const GameCommand &sc = cont.game_command(i);
		logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString()));
		
		Response::ResponseCode resp = player->processGameCommand(sc, rc, ges);

		if (resp != Response::RespOk)
			finalResponseCode = resp;
	}
	ges.sendToGame(game);
	
	return finalResponseCode;
}
Ejemplo n.º 3
0
void Server_Game::removePlayer(Server_Player *player)
{
	room->getServer()->removePersistentPlayer(QString::fromStdString(player->getUserInfo()->name()), room->getId(), gameId, player->getPlayerId());
	players.remove(player->getPlayerId());
	
	GameEventStorage ges;
	removeArrowsRelatedToPlayer(ges, player);
	unattachCards(ges, player);
	ges.enqueueGameEvent(Event_Leave(), player->getPlayerId());
	ges.sendToGame(this);
	
	bool playerActive = activePlayer == player->getPlayerId();
	bool playerHost = hostId == player->getPlayerId();
	bool spectator = player->getSpectator();
	player->prepareDestroy();
	
	if (!getPlayerCount()) {
		gameClosed = true;
		deleteLater();
		return;
	} else if (!spectator) {
		if (playerHost) {
			int newHostId = -1;
			QMapIterator<int, Server_Player *> playerIterator(players);
			while (playerIterator.hasNext()) {
				Server_Player *p = playerIterator.next().value();
				if (!p->getSpectator()) {
					newHostId = p->getPlayerId();
					break;
				}
			}
			if (newHostId != -1) {
				hostId = newHostId;
				sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
			}
		}
		stopGameIfFinished();
		if (gameStarted && playerActive)
			nextTurn();
	}
	
	ServerInfo_Game gameInfo;
	gameInfo.set_room_id(room->getId());
	gameInfo.set_game_id(gameId);
	gameInfo.set_player_count(getPlayerCount());
	gameInfo.set_spectators_count(getSpectatorCount());
	emit gameInfoChanged(gameInfo);
}
Ejemplo n.º 4
0
void Server_Game::removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player)
{
	QMutexLocker locker(&gameMutex);
	
	// Remove all arrows of other players pointing to the player being removed or to one of his cards.
	// Also remove all arrows starting at one of his cards. This is necessary since players can create
	// arrows that start at another person's cards.
	QMapIterator<int, Server_Player *> playerIterator(players);
	while (playerIterator.hasNext()) {
		Server_Player *p = playerIterator.next().value();
		QList<Server_Arrow *> arrows = p->getArrows().values();
		QList<Server_Arrow *> toDelete;
		for (int i = 0; i < arrows.size(); ++i) {
			Server_Arrow *a = arrows[i];
			Server_Card *targetCard = qobject_cast<Server_Card *>(a->getTargetItem());
			if (targetCard) {
				if (targetCard->getZone()->getPlayer() == player)
					toDelete.append(a);
			} else if (static_cast<Server_Player *>(a->getTargetItem()) == player)
				toDelete.append(a);
			
			// Don't use else here! It has to happen regardless of whether targetCard == 0.
			if (a->getStartCard()->getZone()->getPlayer() == player)
				toDelete.append(a);
		}
		for (int i = 0; i < toDelete.size(); ++i) {
			Event_DeleteArrow event;
			event.set_arrow_id(toDelete[i]->getId());
			ges.enqueueGameEvent(event, p->getPlayerId());
			
			p->deleteArrow(toDelete[i]->getId());
		}
	}
}
Ejemplo n.º 5
0
void Server_Game::pingClockTimeout()
{
	QMutexLocker locker(&gameMutex);
	++secondsElapsed;
	
	GameEventStorage ges;
	ges.setGameEventContext(Context_PingChanged());
	
	QList<ServerInfo_PlayerPing *> pingList;
	QMapIterator<int, Server_Player *> playerIterator(players);
	bool allPlayersInactive = true;
	int playerCount = 0;
	while (playerIterator.hasNext()) {
		Server_Player *player = playerIterator.next().value();
		if (!player->getSpectator())
			++playerCount;
		
		const int oldPingTime = player->getPingTime();
		player->playerMutex.lock();
		int newPingTime;
		if (player->getUserInterface())
			newPingTime = player->getUserInterface()->getLastCommandTime();
		else
			newPingTime = -1;
		player->playerMutex.unlock();
		
		if ((newPingTime != -1) && !player->getSpectator())
			allPlayersInactive = false;
		
		if ((abs(oldPingTime - newPingTime) > 1) || ((newPingTime == -1) && (oldPingTime != -1)) || ((newPingTime != -1) && (oldPingTime == -1))) {
			player->setPingTime(newPingTime);
			
			Event_PlayerPropertiesChanged event;
			event.mutable_player_properties()->set_ping_seconds(newPingTime);
			ges.enqueueGameEvent(event, player->getPlayerId());
		}
	}
	ges.sendToGame(this);
	
	const int maxTime = room->getServer()->getMaxGameInactivityTime();
	if (allPlayersInactive) {
		if (((++inactivityCounter >= maxTime) && (maxTime > 0)) || (playerCount < maxPlayers))
			deleteLater();
	} else
		inactivityCounter = 0;
}
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{
    static QList<GameCommand::GameCommandType> antifloodCommandsWhiteList = QList<GameCommand::GameCommandType>()
        // draw/undo card draw (example: drawing 10 cards one by one from the deck)
        << GameCommand::DRAW_CARDS
        << GameCommand::UNDO_DRAW
        // create, delete arrows (example: targeting with 10 cards during an attack)
        << GameCommand::CREATE_ARROW
        << GameCommand::DELETE_ARROW
        // set card attributes (example: tapping 10 cards at once)
        << GameCommand::SET_CARD_ATTR
        // increment / decrement counter (example: -10 life points one by one)
        << GameCommand::INC_COUNTER
        // mulling lots of hands in a row
        << GameCommand::MULLIGAN
        // allows a user to sideboard without receiving flooding message
        << GameCommand::MOVE_CARD;

    if (authState == NotLoggedIn)
        return Response::RespLoginNeeded;

    QMap<int, QPair<int, int> > gameMap = getGames();
    if (!gameMap.contains(cont.game_id()))
        return Response::RespNotInRoom;
    const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id());

    QReadLocker roomsLocker(&server->roomsLock);
    Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first);
    if (!room)
        return Response::RespNotInRoom;

    QReadLocker roomGamesLocker(&room->gamesLock);
    Server_Game *game = room->getGames().value(cont.game_id());
    if (!game) {
        if (room->getExternalGames().contains(cont.game_id())) {
            server->sendIsl_GameCommand(cont,
                                        room->getExternalGames().value(cont.game_id()).server_id(),
                                        userInfo->session_id(),
                                        roomIdAndPlayerId.first,
                                        roomIdAndPlayerId.second
                                        );
            return Response::RespNothing;
        }
        return Response::RespNotInRoom;
    }

    QMutexLocker gameLocker(&game->gameMutex);
    Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second);
    if (!player)
        return Response::RespNotInRoom;

    int commandCountingInterval = server->getCommandCountingInterval();
    int maxCommandCountPerInterval = server->getMaxCommandCountPerInterval();
    GameEventStorage ges;
    Response::ResponseCode finalResponseCode = Response::RespOk;
    for (int i = cont.game_command_size() - 1; i >= 0; --i) {
        const GameCommand &sc = cont.game_command(i);
        logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString()));

        if (commandCountingInterval > 0) {
            int totalCount = 0;
            if (commandCountOverTime.isEmpty())
                commandCountOverTime.prepend(0);

            if(!antifloodCommandsWhiteList.contains((GameCommand::GameCommandType) getPbExtension(sc)))
                ++commandCountOverTime[0];

            for (int i = 0; i < commandCountOverTime.size(); ++i)
                totalCount += commandCountOverTime[i];

            if (totalCount > maxCommandCountPerInterval)
                return Response::RespChatFlood;
        }

        Response::ResponseCode resp = player->processGameCommand(sc, rc, ges);

        if (resp != Response::RespOk)
            finalResponseCode = resp;
    }
    ges.sendToGame(game);

    return finalResponseCode;
}