Skip to content

Commit

Permalink
Avoid crash when min is greater than max
Browse files Browse the repository at this point in the history
  • Loading branch information
Sheikah45 committed Jun 8, 2024
1 parent dfa84c1 commit ba662be
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 47 deletions.
50 changes: 27 additions & 23 deletions src/main/java/com/faforever/client/game/GameService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.faforever.client.game;

import com.faforever.client.domain.server.GameInfo;
import com.faforever.client.domain.server.PlayerInfo;
import com.faforever.client.fx.FxApplicationThreadExecutor;
import com.faforever.client.fx.JavaFxUtil;
import com.faforever.client.mapstruct.GameMapper;
Expand All @@ -25,6 +26,7 @@
import reactor.core.publisher.Mono;
import reactor.function.TupleUtils;

import java.util.List;
import java.util.Optional;
import java.util.Set;

Expand All @@ -45,21 +47,20 @@ public class GameService implements InitializingBean {
private final ObservableMap<Integer, GameInfo> gameIdToGame = FXCollections.synchronizedObservableMap(
FXCollections.observableHashMap());
@Getter
private final ObservableList<GameInfo> games = JavaFxUtil.attachListToMap(FXCollections.synchronizedObservableList(
FXCollections.observableArrayList(
game -> new Observable[]{game.statusProperty(), game.teamsProperty(), game.titleProperty(), game.mapFolderNameProperty(), game.simModsProperty(), game.passwordProtectedProperty()})),
gameIdToGame);
private final ObservableList<GameInfo> games = JavaFxUtil.attachListToMap(
FXCollections.synchronizedObservableList(FXCollections.observableArrayList(game -> new Observable[]{
game.statusProperty(), game.teamsProperty(), game.titleProperty(), game.mapFolderNameProperty(),
game.simModsProperty(), game.passwordProtectedProperty()
})), gameIdToGame);

@Override
public void afterPropertiesSet() {
fafServerAccessor.getEvents(com.faforever.commons.lobby.GameInfo.class)
.flatMap(gameInfo -> gameInfo.getGames() == null ? Flux.just(
gameInfo) : Flux.fromIterable(gameInfo.getGames()))
.flatMap(gameInfo -> Mono.zip(Mono.just(gameInfo), Mono.justOrEmpty(getByUid(
gameInfo.getUid()))
.switchIfEmpty(
initializeGameBean(
gameInfo))))
.flatMap(gameInfo -> gameInfo.getGames() == null ? Flux.just(gameInfo) : Flux.fromIterable(
gameInfo.getGames()))
.flatMap(gameInfo -> Mono.zip(Mono.just(gameInfo), Mono.justOrEmpty(getByUid(gameInfo.getUid()))
.switchIfEmpty(
initializeGameBean(gameInfo))))
.publishOn(fxApplicationThreadExecutor.asScheduler())
.map(TupleUtils.function(gameMapper::update))
.doOnError(throwable -> log.error("Error processing game", throwable))
Expand Down Expand Up @@ -92,18 +93,21 @@ private Mono<GameInfo> initializeGameBean(com.faforever.commons.lobby.GameInfo g

private ChangeListener<Set<Integer>> generatePlayerChangeListener(GameInfo newGame) {
return (observable, oldValue, newValue) -> {
oldValue.stream()
.filter(player -> !newValue.contains(player))
.map(playerService::getPlayerByIdIfOnline)
.flatMap(Optional::stream)
.filter(player -> newGame.equals(player.getGame()))
.forEach(player -> player.setGame(null));

newValue.stream()
.filter(player -> !oldValue.contains(player))
.map(playerService::getPlayerByIdIfOnline)
.flatMap(Optional::stream)
.forEach(player -> player.setGame(newGame));
List<PlayerInfo> playersWhoLeftGame = oldValue.stream()
.filter(player -> !newValue.contains(player))
.map(playerService::getPlayerByIdIfOnline)
.flatMap(Optional::stream)
.filter(player -> newGame.equals(player.getGame()))
.toList();
List<PlayerInfo> playersWhoJoinedGame = newValue.stream()
.filter(player -> !oldValue.contains(player))
.map(playerService::getPlayerByIdIfOnline)
.flatMap(Optional::stream)
.toList();
fxApplicationThreadExecutor.execute(() -> {
playersWhoLeftGame.forEach(player -> player.setGame(null));
playersWhoJoinedGame.forEach(player -> player.setGame(newGame));
});
};
}

Expand Down
56 changes: 32 additions & 24 deletions src/main/java/com/faforever/client/game/GamesTableController.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,25 +120,34 @@ public void initializeGameTable(ObservableList<GameInfo> games, Function<String,

mapPreviewColumn.setCellFactory(param -> new MapPreviewTableCell(imageViewHelper));
mapPreviewColumn.setCellValueFactory(param -> param.getValue()
.mapFolderNameProperty()
.flatMap(mapFolderName -> Bindings.createObjectBinding(() -> mapService.loadPreview(mapFolderName, PreviewSize.SMALL), mapService.isInstalledBinding(mapFolderName)))
.flatMap(imageViewHelper::createPlaceholderImageOnErrorObservable)
.when(mapPreviewColumn.visibleProperty().and(showing)));
.mapFolderNameProperty()
.flatMap(mapFolderName -> Bindings.createObjectBinding(
() -> mapService.loadPreview(mapFolderName,
PreviewSize.SMALL),
mapService.isInstalledBinding(mapFolderName)))
.flatMap(
imageViewHelper::createPlaceholderImageOnErrorObservable)
.when(mapPreviewColumn.visibleProperty().and(showing)));

gameTitleColumn.setCellValueFactory(param -> param.getValue().titleProperty().when(showing));
gameTitleColumn.setCellFactory(param -> new StringCell<>(StringUtils::normalizeSpace));
playersColumn.setCellValueFactory(param -> param.getValue()
.maxPlayersProperty()
.flatMap(max -> param.getValue()
.numActivePlayersProperty()
.map(Number::intValue)
.map(active -> new PlayerFill(active, max.intValue())))
.when(showing));
.maxPlayersProperty()
.flatMap(max -> param.getValue()
.numActivePlayersProperty()
.map(Number::intValue)
.map(active -> new PlayerFill(active,
max.intValue())))
.when(showing));
playersColumn.setCellFactory(param -> playersCell());
ratingRangeColumn.setCellValueFactory(param -> param.getValue()
.ratingMaxProperty()
.flatMap(max -> param.getValue().ratingMinProperty().map(min -> new RatingRange(min, max)))
.when(ratingRangeColumn.visibleProperty().and(showing)));
.ratingMaxProperty()
.flatMap(max -> param.getValue()
.ratingMinProperty()
.map(
min -> min > max ? null : new RatingRange(
min, max)))
.when(ratingRangeColumn.visibleProperty().and(showing)));
ratingRangeColumn.setCellFactory(param -> ratingTableCell());
hostColumn.setCellValueFactory(param -> param.getValue().hostProperty().when(showing));
hostColumn.setCellFactory(param -> new HostTableCell(playerService, avatarService));
Expand All @@ -151,22 +160,20 @@ public void initializeGameTable(ObservableList<GameInfo> games, Function<String,
Duration.between(offsetDateTime, OffsetDateTime.now()))));

if (averageRatingColumn != null) {
averageRatingColumn.setCellValueFactory(param -> playerService.getAverageRatingPropertyForGame(param.getValue())
.when(showing));
averageRatingColumn.setCellFactory(param -> new DecimalCell<>(new DecimalFormat("0"), number -> Math.round(number / 100.0) * 100.0));
averageRatingColumn.setCellValueFactory(
param -> playerService.getAverageRatingPropertyForGame(param.getValue()).when(showing));
averageRatingColumn.setCellFactory(
param -> new DecimalCell<>(new DecimalFormat("0"), number -> Math.round(number / 100.0) * 100.0));
}

if (coopMissionNameProvider != null) {
coopMissionName.setCellFactory(param -> new StringCell<>(name -> name));
coopMissionName.setCellValueFactory(param -> param.getValue()
.mapFolderNameProperty()
.map(coopMissionNameProvider)
.when(showing));
coopMissionName.setCellValueFactory(
param -> param.getValue().mapFolderNameProperty().map(coopMissionNameProvider).when(showing));
}

selectedGameProperty().bind(gamesTable.selectionModelProperty()
.flatMap(TableViewSelectionModel::selectedItemProperty)
.when(showing));
selectedGameProperty().bind(
gamesTable.selectionModelProperty().flatMap(TableViewSelectionModel::selectedItemProperty).when(showing));

if (listenToFilterPreferences && coopMissionNameProvider == null) {
modsColumn.visibleProperty().bind(preferences.hideModdedGamesProperty().not().when(showing));
Expand Down Expand Up @@ -247,7 +254,8 @@ private TableCell<GameInfo, Boolean> passwordIndicatorColumn() {
}

private TableCell<GameInfo, PlayerFill> playersCell() {
return new StringCell<>(playerFill -> i18n.get("game.players.format", playerFill.getPlayers(), playerFill.getMaxPlayers()));
return new StringCell<>(
playerFill -> i18n.get("game.players.format", playerFill.getPlayers(), playerFill.getMaxPlayers()));
}

private TableCell<GameInfo, RatingRange> ratingTableCell() {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/faforever/client/game/NewGameInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,11 @@ public record NewGameInfo(
public NewGameInfo(String title, String password, String featuredModName, String map, Set<String> simMods) {
this(title, password, featuredModName, map, simMods, GameVisibility.PUBLIC, null, null, false);
}

public NewGameInfo {
if (ratingMin != null && ratingMax != null && ratingMin > ratingMax) {
throw new IllegalArgumentException(
"Min cannot be greater than min: min %d max %d".formatted(ratingMin, ratingMax));
}
}
}

0 comments on commit ba662be

Please sign in to comment.