22
33import com .faforever .client .domain .api .CoopMission ;
44import com .faforever .client .domain .api .CoopResult ;
5+ import com .faforever .client .domain .api .CoopScenario ;
56import com .faforever .client .domain .server .GameInfo ;
67import com .faforever .client .fx .ControllerTableCell ;
78import com .faforever .client .fx .FxApplicationThreadExecutor ;
89import com .faforever .client .fx .ImageViewHelper ;
910import com .faforever .client .fx .NodeController ;
1011import com .faforever .client .fx .ObservableConstant ;
12+ import com .faforever .client .fx .PlatformService ;
1113import com .faforever .client .fx .StringCell ;
1214import com .faforever .client .fx .StringListCell ;
1315import com .faforever .client .fx .WebViewConfigurer ;
5759import java .time .OffsetDateTime ;
5860import java .util .Collection ;
5961import java .util .List ;
62+ import java .util .Objects ;
6063import java .util .Optional ;
6164import java .util .Set ;
6265import java .util .function .Function ;
@@ -77,6 +80,7 @@ public class CoopController extends NodeController<Node> {
7780 private final ReplayService replayService ;
7881 private final GameService gameService ;
7982 private final CoopService coopService ;
83+ private final PlatformService platformService ;
8084 private final ImageViewHelper imageViewHelper ;
8185 private final NotificationService notificationService ;
8286 private final I18n i18n ;
@@ -89,6 +93,7 @@ public class CoopController extends NodeController<Node> {
8993 private final FilteredList <CoopResult > leaderboardFilteredList = new FilteredList <>(leaderboardUnFilteredList );
9094
9195 public GridPane coopRoot ;
96+ public ComboBox <CoopScenario > scenarioComboBox ;
9297 public ComboBox <CoopMission > missionComboBox ;
9398 public WebView descriptionWebView ;
9499 public Pane gameViewContainer ;
@@ -111,9 +116,13 @@ public class CoopController extends NodeController<Node> {
111116
112117 @ Override
113118 protected void onInitialize () {
114- missionComboBox .setCellFactory (param -> missionListCell ());
115- missionComboBox .setButtonCell (missionListCell ());
119+ scenarioComboBox .setCellFactory (param -> scenarioListCell ());
120+ scenarioComboBox .setButtonCell (scenarioListCell ());
121+ scenarioComboBox .getSelectionModel ().selectedItemProperty ().when (showing ).subscribe (this ::populateMissionList );
122+
116123 missionComboBox .getSelectionModel ().selectedItemProperty ().when (showing ).subscribe (this ::setSelectedMission );
124+ missionComboBox .setButtonCell (missionListCell ());
125+ missionComboBox .setCellFactory (param -> missionListCell ());
117126
118127 mapPreviewImageView .imageProperty ()
119128 .bind (missionComboBox .getSelectionModel ().selectedItemProperty ().map (CoopMission ::mapFolderName )
@@ -148,10 +157,10 @@ protected void onInitialize() {
148157 playerCountColumn .setCellFactory (param -> new StringCell <>(String ::valueOf ));
149158
150159 playerNamesColumn .setCellValueFactory (param -> ObservableConstant .valueOf (param .getValue ().replay ().teams ().values ()
151- .stream ()
152- .flatMap (Collection ::stream )
153- .collect (Collectors .joining (
154- i18n .get ("textSeparator" )))));
160+ .stream ()
161+ .flatMap (Collection ::stream )
162+ .collect (Collectors .joining (
163+ i18n .get ("textSeparator" )))));
155164
156165 playerNamesColumn .setCellFactory (param -> new StringCell <>(Function .identity ()));
157166
@@ -185,25 +194,32 @@ protected void onInitialize() {
185194 FilteredList <GameInfo > filteredItems = new FilteredList <>(gameService .getGames ());
186195 filteredItems .setPredicate (OPEN_COOP_GAMES_PREDICATE );
187196
188- coopService .getMissions ()
197+ coopService .getScenarios ()
189198 .collectList ()
190199 .map (FXCollections ::observableList )
191200 .publishOn (fxApplicationThreadExecutor .asScheduler ())
192- .subscribe (coopMaps -> {
193- missionComboBox .setItems (coopMaps );
201+ .subscribe (coopScenarios -> {
202+ scenarioComboBox .getItems ().addAll (coopScenarios );
203+
204+ List <CoopMission > coopMissions = coopScenarios .stream ()
205+ .map (CoopScenario ::maps )
206+ .filter (Objects ::nonNull )
207+ .flatMap (Collection ::stream )
208+ .toList ();
194209
195210 gamesTableController .initializeGameTable (filteredItems ,
196- mapFolderName -> coopMissionFromFolderName (coopMaps ,
211+ mapFolderName -> coopMissionFromFolderName (coopMissions ,
197212 mapFolderName ),
198213 false );
199214 gamesTableController .getMapPreviewColumn ().setVisible (false );
200215 gamesTableController .getRatingRangeColumn ().setVisible (false );
201216
217+ SingleSelectionModel <CoopScenario > selectionModel = scenarioComboBox .getSelectionModel ();
202218
203- SingleSelectionModel <CoopMission > selectionModel = missionComboBox .getSelectionModel ();
204219 if (selectionModel .isEmpty ()) {
205220 selectionModel .selectFirst ();
206221 }
222+
207223 }, throwable -> notificationService .addPersistentErrorNotification ("coop.couldNotLoad" ,
208224 throwable .getLocalizedMessage ()));
209225 }
@@ -232,22 +248,28 @@ private ListCell<Integer> numberOfPlayersCell() {
232248 }, fxApplicationThreadExecutor );
233249 }
234250
235- private ListCell <CoopMission > missionListCell () {
236- return new StringListCell <>(fxApplicationThreadExecutor , CoopMission ::name , mission -> {
251+ private ListCell <CoopScenario > scenarioListCell () {
252+ return new StringListCell <>(fxApplicationThreadExecutor , CoopScenario ::name , category -> {
237253 Label label = new Label ();
238254 Region iconRegion = new Region ();
239255 label .setGraphic (iconRegion );
240256 iconRegion .getStyleClass ().add (ThemeService .CSS_CLASS_ICON );
241- switch (mission . category ()) {
257+ switch (category . faction ()) {
242258 case AEON -> iconRegion .getStyleClass ().add (ThemeService .AEON_STYLE_CLASS );
243259 case CYBRAN -> iconRegion .getStyleClass ().add (ThemeService .CYBRAN_STYLE_CLASS );
244260 case UEF -> iconRegion .getStyleClass ().add (ThemeService .UEF_STYLE_CLASS );
261+ case SERAPHIM -> iconRegion .getStyleClass ().add (ThemeService .SERAPHIM_STYLE_CLASS );
262+ case CUSTOM -> iconRegion .getStyleClass ().add (ThemeService .WRENCH_STYLE_CLASS );
245263 default -> {
246264 return null ;
247265 }
248266 }
249267 return label ;
250- }, Pos .CENTER_LEFT , "coop-mission" );
268+ }, Pos .CENTER_LEFT , "coop-category" );
269+ }
270+
271+ private ListCell <CoopMission > missionListCell () {
272+ return new StringListCell <>(fxApplicationThreadExecutor , this ::getMissionConcatDisplayName , null , Pos .CENTER_LEFT , "coop-mission" );
251273 }
252274
253275 private void loadLeaderboard () {
@@ -274,11 +296,25 @@ private Set<String> getAllPlayerNamesFromTeams(CoopResult coopResult) {
274296 .collect (Collectors .toUnmodifiableSet ());
275297 }
276298
277-
278299 private CoopMission getSelectedMission () {
279300 return missionComboBox .getSelectionModel ().getSelectedItem ();
280301 }
281302
303+ private void populateMissionList (CoopScenario scenario ) {
304+ if (scenario == null ) {
305+ return ;
306+ }
307+
308+ List <CoopMission > missions = scenario .maps ();
309+ if (missions == null || missions .isEmpty ()) {
310+ missionComboBox .getItems ().clear ();
311+ return ;
312+ }
313+
314+ missionComboBox .getItems ().setAll (missions );
315+ missionComboBox .getSelectionModel ().select (0 );
316+ }
317+
282318 private void setSelectedMission (CoopMission mission ) {
283319 if (mission == null ) {
284320 return ;
@@ -297,10 +333,22 @@ public void onPlayButtonClicked() {
297333 COOP .getTechnicalName (), getSelectedMission ().mapFolderName (), Set .of ()));
298334 }
299335
336+ public void onWikiButtonClicked () {
337+ platformService .showDocument ("https://wiki.faforever.com/en/Development/Missions/Mission-Scripting" );
338+ }
339+
340+ public void onDiscordHyperLinkClicked () {
341+ platformService .showDocument ("https://discord.gg/ayzAVr9JUV" );
342+ }
343+
300344 public void onMapPreviewImageClicked () {
301345 Optional .ofNullable (mapPreviewImageView .getImage ()).ifPresent (PopupUtil ::showImagePopup );
302346 }
303347
348+ public String getMissionConcatDisplayName (CoopMission mission ) {
349+ return mission .name () + " - V" + mission .version ();
350+ }
351+
304352 @ Override
305353 public Node getRoot () {
306354 return coopRoot ;
0 commit comments