Search in sources :

Example 46 with Game

use of com.faforever.server.entity.Game in project faf-java-server by FAForever.

the class GameService method createGame.

/**
 * Creates a new, transient game with the specified options and tells the client to start the game process. The
 * player's current game is set to the new game.
 *
 * @return a future that will be completed as soon as the player's game has been started and is ready to be joined. Be
 * aware that there are various reasons for the game to never start (crash, disconnect, abort) so never wait without a
 * timeout.
 */
@Transactional(readOnly = true)
public CompletableFuture<Game> createGame(String title, String featuredModName, String mapFileName, String password, GameVisibility visibility, Integer minRating, Integer maxRating, Player player) {
    Game currentGame = player.getCurrentGame();
    if (currentGame != null && currentGame.getState() == GameState.INITIALIZING) {
        /* Apparently, the user's game crashed before it reached the lobby, leaving it in state INITIALIZING. One solution
      is to let the game time out, but as usual, that's not a good solution since no matter what timeout one chooses,
      there is always some drawback. Therefore, we don't timeout games but reset a player's game state when he tries
      to create a new game. Or when he logs out. */
        removePlayer(currentGame, player);
    }
    Requests.verify(currentGame == null, ErrorCode.ALREADY_IN_GAME);
    int gameId = this.lastGameId.incrementAndGet();
    Game game = new Game(gameId);
    game.setHost(player);
    modService.getFeaturedMod(featuredModName).map(game::setFeaturedMod).orElseThrow(() -> new RequestException(ErrorCode.INVALID_FEATURED_MOD, featuredModName));
    game.setTitle(title);
    mapService.findMap(mapFileName).ifPresent(game::setMapVersion);
    game.setMapName(mapFileName);
    game.setPassword(password);
    game.setGameVisibility(visibility);
    game.setMinRating(minRating);
    game.setMaxRating(maxRating);
    activeGamesById.put(game.getId(), game);
    counterService.increment(String.format(Metrics.GAMES_STATE_FORMAT, game.getState()));
    log.debug("Player '{}' created game '{}'", player, game);
    clientService.startGameProcess(game, player);
    player.setCurrentGame(game);
    changePlayerGameState(player, PlayerGameState.INITIALIZING);
    CompletableFuture<Game> gameJoinedFuture = new CompletableFuture<>();
    player.setGameFuture(gameJoinedFuture);
    return game.getJoinableFuture();
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) Game(com.faforever.server.entity.Game) RequestException(com.faforever.server.error.RequestException) Transactional(org.springframework.transaction.annotation.Transactional)

Example 47 with Game

use of com.faforever.server.entity.Game in project faf-java-server by FAForever.

the class GameService method updatePlayerOption.

/**
 * Updates an option value of a specific player. Only the host of a game is allowed to report such options and for
 * unstarted games, otherwise an exception will be thrown.
 *
 * @throws RequestException if the reporting player is not the host, or if the game is not in state {@link
 * GameState#OPEN}
 */
public void updatePlayerOption(Player reporter, int playerId, String key, Object value) {
    Game game = reporter.getCurrentGame();
    if (game == null) {
        // Since this is called repeatedly, throwing exceptions here would not be a good idea. Happens after restarts.
        log.warn("Received player option for player w/o game: {}", reporter);
        return;
    }
    Requests.verify(game.getState() == GameState.OPEN, ErrorCode.INVALID_GAME_STATE, game.getState(), GameState.OPEN);
    Requests.verify(Objects.equals(reporter.getCurrentGame().getHost(), reporter), ErrorCode.HOST_ONLY_OPTION, key);
    if (!game.getConnectedPlayers().containsKey(playerId)) {
        log.warn("Player '{}' reported option '{}' with value '{}' for unknown player '{}' in game '{}'", reporter, key, value, playerId, game);
        return;
    }
    log.trace("Updating option for player '{}' in game '{}': '{}' = '{}'", playerId, game.getId(), key, value);
    game.getPlayerOptions().computeIfAbsent(playerId, id -> new HashMap<>()).put(key, value);
    markDirty(game, DEFAULT_MIN_DELAY, DEFAULT_MAX_DELAY);
}
Also used : Arrays(java.util.Arrays) ProgrammingError(com.faforever.server.error.ProgrammingError) ModVersion(com.faforever.server.entity.ModVersion) BiFunction(java.util.function.BiFunction) ArmyResult(com.faforever.server.entity.ArmyResult) PlayerOfflineEvent(com.faforever.server.player.PlayerOfflineEvent) PlayerService(com.faforever.server.player.PlayerService) Metrics(com.faforever.server.stats.Metrics) Player(com.faforever.server.entity.Player) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) Map(java.util.Map) Pair(org.springframework.data.util.Pair) ArmyStatistics(com.faforever.server.stats.ArmyStatistics) ClientService(com.faforever.server.client.ClientService) CounterService(org.springframework.boot.actuate.metrics.CounterService) ConnectionAware(com.faforever.server.client.ConnectionAware) RatingService(com.faforever.server.rating.RatingService) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) EventListener(org.springframework.context.event.EventListener) ErrorCode(com.faforever.server.error.ErrorCode) Streams(com.google.common.collect.Streams) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) GameState(com.faforever.server.entity.GameState) MapService(com.faforever.server.map.MapService) Ladder1v1Rating(com.faforever.server.entity.Ladder1v1Rating) Slf4j(lombok.extern.slf4j.Slf4j) List(java.util.List) Requests(com.faforever.server.error.Requests) Stream(java.util.stream.Stream) DivisionService(com.faforever.server.ladder1v1.DivisionService) RatingType(com.faforever.server.rating.RatingType) Game(com.faforever.server.entity.Game) GlobalRating(com.faforever.server.entity.GlobalRating) Entry(java.util.Map.Entry) Optional(java.util.Optional) RequestException(com.faforever.server.error.RequestException) Joiner(com.google.common.base.Joiner) ModService(com.faforever.server.mod.ModService) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) FeaturedMod(com.faforever.server.entity.FeaturedMod) Validity(com.faforever.server.entity.Validity) Function(java.util.function.Function) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) VictoryCondition(com.faforever.server.entity.VictoryCondition) GameResponses(com.faforever.server.client.GameResponses) Service(org.springframework.stereotype.Service) ServerProperties(com.faforever.server.config.ServerProperties) Iterator(java.util.Iterator) FeaturedModFileVersion(com.faforever.server.game.GameResponse.FeaturedModFileVersion) EntityManager(javax.persistence.EntityManager) Consumer(java.util.function.Consumer) SimMod(com.faforever.server.game.GameResponse.SimMod) ContextRefreshedEvent(org.springframework.context.event.ContextRefreshedEvent) ArmyStatisticsService(com.faforever.server.stats.ArmyStatisticsService) PlayerOnlineEvent(com.faforever.server.player.PlayerOnlineEvent) GamePlayerStats(com.faforever.server.entity.GamePlayerStats) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Comparator(java.util.Comparator) Transactional(org.springframework.transaction.annotation.Transactional) Assert(org.springframework.util.Assert) Game(com.faforever.server.entity.Game) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 48 with Game

use of com.faforever.server.entity.Game in project faf-java-server by FAForever.

the class GameService method restoreGameSession.

/**
 * Associates the specified player with the specified game, if this player was previously part of the game and the
 * game is still running. This is requested by the client after it lost connection to the server.
 */
public void restoreGameSession(Player player, int gameId) {
    if (player.getCurrentGame() != null) {
        log.warn("Player '{}' requested game session restoration but is still associated with game '{}'", player, player.getCurrentGame());
        return;
    }
    Optional<Game> gameOptional = getActiveGame(gameId);
    Requests.verify(gameOptional.isPresent(), ErrorCode.CANT_RESTORE_GAME_DOESNT_EXIST);
    Game game = gameOptional.get();
    GameState gameState = game.getState();
    Requests.verify(gameState == GameState.OPEN || gameState == GameState.PLAYING, ErrorCode.CANT_RESTORE_GAME_DOESNT_EXIST);
    Requests.verify(game.getState() != GameState.PLAYING || game.getPlayerStats().containsKey(player.getId()), ErrorCode.CANT_RESTORE_GAME_NOT_PARTICIPANT);
    log.debug("Reassociating player '{}' with game '{}'", player, game);
    player.setGameFuture(CompletableFuture.completedFuture(game));
    addPlayer(game, player);
    changePlayerGameState(player, PlayerGameState.INITIALIZING);
    changePlayerGameState(player, PlayerGameState.LOBBY);
    if (gameState == GameState.PLAYING) {
        changePlayerGameState(player, PlayerGameState.LAUNCHING);
    }
}
Also used : Game(com.faforever.server.entity.Game) GameState(com.faforever.server.entity.GameState)

Example 49 with Game

use of com.faforever.server.entity.Game in project faf-java-server by FAForever.

the class GameService method updateAiOption.

/**
 * Updates an option value of a specific AI player. Only the host of a game is allowed to report such options,
 * otherwise an exception will be thrown.
 *
 * @throws RequestException if the reporting player is not the host
 */
public void updateAiOption(Player reporter, String aiName, String key, Object value) {
    Game game = reporter.getCurrentGame();
    if (game == null) {
        // Since this is called repeatedly, throwing exceptions here would not be a good idea. Happens after restarts.
        log.warn("Received AI option for player w/o game: {}", reporter);
        return;
    }
    Requests.verify(Objects.equals(reporter.getCurrentGame().getHost(), reporter), ErrorCode.HOST_ONLY_OPTION, key);
    if (!OPTION_ARMY.equals(key)) {
        log.trace("Ignoring option '{}' = '{}' for AI '{}' in game '{}' because only the option 'Army' is currently sent with the correct, final AI name", key, value, aiName, game.getId());
        return;
    }
    log.trace("Updating option for AI '{}' in game '{}': '{}' = '{}'", aiName, game.getId(), key, value);
    game.getAiOptions().computeIfAbsent(aiName, s -> new HashMap<>()).put(key, value);
    markDirty(game, DEFAULT_MIN_DELAY, DEFAULT_MAX_DELAY);
}
Also used : Arrays(java.util.Arrays) ProgrammingError(com.faforever.server.error.ProgrammingError) ModVersion(com.faforever.server.entity.ModVersion) BiFunction(java.util.function.BiFunction) ArmyResult(com.faforever.server.entity.ArmyResult) PlayerOfflineEvent(com.faforever.server.player.PlayerOfflineEvent) PlayerService(com.faforever.server.player.PlayerService) Metrics(com.faforever.server.stats.Metrics) Player(com.faforever.server.entity.Player) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) Map(java.util.Map) Pair(org.springframework.data.util.Pair) ArmyStatistics(com.faforever.server.stats.ArmyStatistics) ClientService(com.faforever.server.client.ClientService) CounterService(org.springframework.boot.actuate.metrics.CounterService) ConnectionAware(com.faforever.server.client.ConnectionAware) RatingService(com.faforever.server.rating.RatingService) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) EventListener(org.springframework.context.event.EventListener) ErrorCode(com.faforever.server.error.ErrorCode) Streams(com.google.common.collect.Streams) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) GameState(com.faforever.server.entity.GameState) MapService(com.faforever.server.map.MapService) Ladder1v1Rating(com.faforever.server.entity.Ladder1v1Rating) Slf4j(lombok.extern.slf4j.Slf4j) List(java.util.List) Requests(com.faforever.server.error.Requests) Stream(java.util.stream.Stream) DivisionService(com.faforever.server.ladder1v1.DivisionService) RatingType(com.faforever.server.rating.RatingType) Game(com.faforever.server.entity.Game) GlobalRating(com.faforever.server.entity.GlobalRating) Entry(java.util.Map.Entry) Optional(java.util.Optional) RequestException(com.faforever.server.error.RequestException) Joiner(com.google.common.base.Joiner) ModService(com.faforever.server.mod.ModService) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) FeaturedMod(com.faforever.server.entity.FeaturedMod) Validity(com.faforever.server.entity.Validity) Function(java.util.function.Function) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) VictoryCondition(com.faforever.server.entity.VictoryCondition) GameResponses(com.faforever.server.client.GameResponses) Service(org.springframework.stereotype.Service) ServerProperties(com.faforever.server.config.ServerProperties) Iterator(java.util.Iterator) FeaturedModFileVersion(com.faforever.server.game.GameResponse.FeaturedModFileVersion) EntityManager(javax.persistence.EntityManager) Consumer(java.util.function.Consumer) SimMod(com.faforever.server.game.GameResponse.SimMod) ContextRefreshedEvent(org.springframework.context.event.ContextRefreshedEvent) ArmyStatisticsService(com.faforever.server.stats.ArmyStatisticsService) PlayerOnlineEvent(com.faforever.server.player.PlayerOnlineEvent) GamePlayerStats(com.faforever.server.entity.GamePlayerStats) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Comparator(java.util.Comparator) Transactional(org.springframework.transaction.annotation.Transactional) Assert(org.springframework.util.Assert) Game(com.faforever.server.entity.Game) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 50 with Game

use of com.faforever.server.entity.Game in project faf-java-server by FAForever.

the class GameService method reportDesync.

/**
 * Increments the desync counter for a player's game. If the specified player is currently not in a game, this method
 * does nothing.
 */
public void reportDesync(Player reporter) {
    Game game = reporter.getCurrentGame();
    if (game == null) {
        log.warn("Desync reported by player w/o game: {}", reporter);
        return;
    }
    int desyncCount = game.getDesyncCounter().incrementAndGet();
    log.debug("Player '{}' increased desync count to '{}' for game: {}", reporter, desyncCount, game);
}
Also used : Game(com.faforever.server.entity.Game)

Aggregations

Game (com.faforever.server.entity.Game)96 Test (org.junit.Test)71 Player (com.faforever.server.entity.Player)26 FeaturedMod (com.faforever.server.entity.FeaturedMod)15 ModVersion (com.faforever.server.entity.ModVersion)12 ConnectionAware (com.faforever.server.client.ConnectionAware)11 Ladder1v1Rating (com.faforever.server.entity.Ladder1v1Rating)11 List (java.util.List)11 ClientService (com.faforever.server.client.ClientService)10 ServerProperties (com.faforever.server.config.ServerProperties)10 RequestException (com.faforever.server.error.RequestException)10 ModService (com.faforever.server.mod.ModService)10 VisibleForTesting (com.google.common.annotations.VisibleForTesting)10 Duration (java.time.Duration)10 Map (java.util.Map)10 Optional (java.util.Optional)10 Slf4j (lombok.extern.slf4j.Slf4j)10 Service (org.springframework.stereotype.Service)10 ArmyResult (com.faforever.server.entity.ArmyResult)9 GamePlayerStats (com.faforever.server.entity.GamePlayerStats)9