Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
ServerBrowserMenuUI.c
Go to the documentation of this file.
1/*
2Main class for server browser menu handling
3Handles cooperation of varios components for server searching, joning, mods handling, etc.
4*/
5
8typedef ScriptInvokerBase<ScriptInvokerRoomMethod> ScriptInvokerRoom;
9
11{
12 // Server list feedback strings
13 const string TAG_DETAILS_FALLBACK_SEACHING = "Searching";
14 const string TAG_DETAILS_FALLBACK_EMPTY = "Empty";
15 const string TAG_MESSAGE_SEARCHING = "SEARCHING";
16 const string TAG_MESSAGE_CONNECTING = "CONNECTING";
17
18 const int SERVER_LIST_VIEW_SIZE = 32;
19 const int ROOM_CONTENT_LOAD_DELAY = 500;
20 const int ROOM_REFRESH_RATE = 10 * 1000;
21
22 // This should be the same value as in High latency filter in {4F6F41C387ADC14E}Configs/ServerBrowser/ServerBrowserFilterSet.conf
23 // TODO: unify with the value set in filters
24 static const int HIGH_PING_SERVER_THRESHOLD = 200;
25
26 protected bool m_bHostedServers;
27
28 // Widget class reference
30
31 // Server list entry for user interactions
33
34 // Widget handlers
39
40 // States
41 protected SCR_EListMenuWidgetFocus m_eFocusedWidgetState = SCR_EListMenuWidgetFocus.LIST;
42
43 // Skip the details dialog on double click
44 protected bool m_bQuickJoin = true;
45
46 // Lobby Rooms handling
47 protected ref array<Room> m_aRooms = {};
48 protected ref array<Room> m_aDirectFoundRooms = {};
49
51
53
54 // Privileges
56
57 // Search callbacks
61
62 // Supposedly used for direct join process
64
65 // Room data refresh
67 protected bool m_bFirstRoomLoad = true;
69 protected int m_iTotalNumberOfRooms;
70
71 // Managers
75
76 // Joinign
79
80 protected ref RoomJoinData m_JoinData = new RoomJoinData();
81
82 // Filter parameters
85
86 // Server mod content
87 protected ref array<ref SCR_WorkshopItem> m_aRequiredMods = {};
88 protected ref array<ref SCR_WorkshopItemActionDownload> m_aUnrelatedDownloads = {};
89
90 // Message components
93
94 protected bool m_bIsWaitingForBackend = false;
95
96 // Reconnecting to last played server
98 protected ref SCR_GetRoomsIds m_SearchIds = new SCR_GetRoomsIds();
99
100 protected ref array<ref SCR_FilterEntry> m_aFiltersToSelect = {};
101
102 // Script invokers
104
105 // Entry Actions
106 protected EInputDeviceType m_eLastInputType;
107 protected bool m_bWasEntrySelected;
108
109 // Cache last clicked entry to trigger the correct dialog after the double click window
112
115
116 // Joining process state
119
120 protected int m_iSelectedTab = 0;
121
122 protected bool m_WaitingForModContent = false;
123
124 //------------------------------------------------------------------------------------------------
125 // --- OVERRIDES ---
126 //------------------------------------------------------------------------------------------------
127 //------------------------------------------------------------------------------------------------
129 override void OnMenuOpen()
130 {
131 m_Lobby = GetGame().GetBackendApi().GetClientLobby();
132
133 // Items preloading
134 WorkshopApi workshopApi = GetGame().GetBackendApi().GetWorkshop();
135 if (workshopApi && workshopApi.NeedAddonsScan())
136 workshopApi.ScanOfflineItems();
137
138 // Find widgets
139 m_Widgets.FindAllWidgets(GetRootWidget());
140
141 // Accessing handlers
145
147
148 // Setup list and message
150 Messages_ShowMessage(TAG_MESSAGE_SEARCHING);
151 else
152 Messages_ShowMessage(TAG_MESSAGE_CONNECTING, true);
153
155 m_ScrollableList.ShowEmptyRooms();
156
157 // Setup Actions
160 m_ActionsComponent.GetOnAction().Insert(OnActionTriggered);
161
163
164 SwitchFocus(SCR_EListMenuWidgetFocus.SORTING);
165
166 GetGame().OnUserSettingsChangedInvoker().Insert(FilterCrossplayCheck);
167
168 GetGame().GetGameBlocklist().UpdateBlockList();
169
170 // Hide news menu button (top right corner) on PS
171 if (GetGame().GetPlatformService().GetLocalPlatformKind() == PlatformKind.PSN)
172 {
173 Widget newsButton = GetRootWidget().FindAnyWidget("NewsButton");
174 if (newsButton)
175 {
176 newsButton.SetVisible(false);
177 newsButton.SetEnabled(false);
178 }
179 }
180
181 super.OnMenuOpen();
182 }
183
184 //------------------------------------------------------------------------------------------------
185 override void OnMenuHide()
186 {
187 super.OnMenuHide();
188
189 //SCR_AnalyticsApplication.GetInstance().CloseMultiplayerMenu();
190 }
191
192 //------------------------------------------------------------------------------------------------
193 override void OnMenuOpened()
194 {
195 // Kick errors
199
200 super.OnMenuOpened();
201
202 Refresh();
203 }
204
205 //------------------------------------------------------------------------------------------------
206 override void OnMenuFocusGained()
207 {
208 // Focus back on the host button
210 GetGame().GetCallqueue().Call(FocusWidget, m_Widgets.m_wHostNewServerButton);
211 else
212 SwitchFocus(SCR_EListMenuWidgetFocus.LIST, true);
213
214 super.OnMenuFocusGained();
215
217 m_ActionsComponent.ActivateActions();
218 }
219
220 //------------------------------------------------------------------------------------------------
222 override void OnMenuClose()
223 {
224 // Kick errors
228
230
231 // Clearing handlers
232 if (m_TabView)
233 m_TabView.GetOnChanged().Remove(OnTabViewSwitch);
234
235 // Store filter parameters
236 m_Lobby.StoreParams();
237
238 // Remove callbacks
240
241 m_ScrollableList.GetOnSetPage().Remove(CallOnServerListSetPage);
242
244
245 // Save filter
246 m_FilterPanel.Save();
247
248 GetGame().OnUserSettingsChangedInvoker().Remove(FilterCrossplayCheck);
249
250 super.OnMenuClose();
251 }
252
253 //------------------------------------------------------------------------------------------------
255 override void OnMenuUpdate(float tDelta)
256 {
257 super.OnMenuUpdate(tDelta);
258
259 // Run actions after backend initialization
262
263 // Scroll list update
265 m_ScrollableList.UpdateScroll();
266
268 EInputDeviceType inputDeviceType = GetGame().GetInputManager().GetLastUsedInputDevice();
269 bool isEntrySelected = GetSelectedEntry();
270 bool shouldUpdateButtons = inputDeviceType != m_eLastInputType || isEntrySelected != m_bWasEntrySelected;
271 if (shouldUpdateButtons)
273
274 m_eLastInputType = inputDeviceType;
275 m_bWasEntrySelected = isEntrySelected;
276 }
277
278 //------------------------------------------------------------------------------------------------
279 override void OnMenuShow()
280 {
281 super.OnMenuShow();
282
284 m_ActionsComponent.ActivateActions();
285
286 //SCR_AnalyticsApplication.GetInstance().OpenMultiplayerMenu();
287 }
288
289 //------------------------------------------------------------------------------------------------
290 // --- INPUTS ---
291 //------------------------------------------------------------------------------------------------
292 //------------------------------------------------------------------------------------------------
293 protected void UpdateNavigationButtons()
294 {
295 if (!m_Widgets)
296 return;
297
299 bool versionMismatch, unjoinable;
300 bool enabled = entry && entry.GetIsEnabled(versionMismatch, unjoinable);
301 bool visible = entry && GetGame().GetInputManager().GetLastUsedInputDevice() != EInputDeviceType.MOUSE;
302
303 if (m_Widgets.m_JoinButton)
304 m_Widgets.m_JoinButton.SetVisible(visible && !unjoinable, false);
305
306 if (m_Widgets.m_DetailsButton)
307 m_Widgets.m_DetailsButton.SetVisible(visible && !unjoinable, false);
308
309 if (m_Widgets.m_FavoritesButton)
310 m_Widgets.m_FavoritesButton.SetVisible(visible && enabled, false);
311
312 if (!enabled || !visible)
313 return;
314
315 Room room = entry.GetRoomInfo();
316 if (!room)
317 return;
318
319 if (m_Widgets.m_FavoritesButton)
320 m_Widgets.m_FavoritesButton.SetLabel(UIConstants.GetFavoriteLabel(room.IsFavorite()));
321 }
322
323 //------------------------------------------------------------------------------------------------
324 protected void OnActionTriggered(string action, float multiplier)
325 {
327
329 if (GetGame().GetInputManager().GetLastUsedInputDevice() != EInputDeviceType.MOUSE)
330 return;
331
332 switch (action)
333 {
334 case UIConstants.MENU_ACTION_DOUBLE_CLICK: OnServerEntryClickInteraction(multiplier); break;
335 case SCR_ScenarioUICommon.ACTION_SERVER_DETAILS: OnActionDetails(); break;
336 case UIConstants.MENU_ACTION_FAVORITE: OnActionFavorite(); break;
337 }
338 }
339
340 //------------------------------------------------------------------------------------------------
344 {
345 Refresh();
346 }
347
348 //------------------------------------------------------------------------------------------------
349 protected void Refresh()
350 {
351 PrintDebug("m_RejoinRoom: " + m_RejoinRoom, "OnActionRefresh");
352
353 // Try negotiate missing MP privilege
354 // kuceramar: I dont think this needs to be there anymore as the check is happening before this is opened but lets check later-
355 if (!SocialComponent.IsMultiplayerAllowed())
356 {
357 Messages_ShowMessage("MISSING_PRIVILEGE_MP");
358 return;
359 }
360
361 // Clear list
362 m_CallbackScroll.SetOnSuccess(OnScrollSuccess);
364
365 // Setup list loading
367 {
368 m_ScrollableList.MoveToTop();
369 m_ScrollableList.ShowEmptyRooms();
370 m_ScrollableList.ShowScrollbar(false);
371 }
372
374
375 // Start loading
377 SearchRooms();
378 else
379 GetGame().GetCallqueue().CallLater(SearchRooms, ROOM_CONTENT_LOAD_DELAY, false);
380
382 Messages_ShowMessage(TAG_MESSAGE_SEARCHING);
383 else
384 Messages_ShowMessage(TAG_MESSAGE_CONNECTING, true);
385
387 m_ServerScenarioDetails.SetDefaultScenario(TAG_DETAILS_FALLBACK_SEACHING);
388 }
389
390 //------------------------------------------------------------------------------------------------
394 {
395 MultiplayerDialogUI multiplayerDialog = m_Dialogs.CreateManualJoinDialog();
396
397 if (!multiplayerDialog)
398 return;
399
400 // Ip handling
401 multiplayerDialog.m_OnConfirm.Clear();
402 multiplayerDialog.m_OnConfirm.Insert(JoinActions_DirectJoin);
403
404 // Cancel
405 multiplayerDialog.m_OnCancel.Clear();
406 }
407
408 //------------------------------------------------------------------------------------------------
412 {
413 if (!m_FilterPanel)
414 return;
415
416 SCR_EListMenuWidgetFocus focus = SCR_EListMenuWidgetFocus.FILTERING;
417 if (m_FilterPanel.GetFilterListBoxShown())
418 focus = SCR_EListMenuWidgetFocus.LIST;
419
420 // Set focus
421 m_FilterPanel.ShowFilterListBox(focus == SCR_EListMenuWidgetFocus.FILTERING);
422 SwitchFocus(focus);
423 }
424
425 //------------------------------------------------------------------------------------------------
429 {
430 Close();
431 }
432
433 //------------------------------------------------------------------------------------------------
435 protected void OnActionFavorite()
436 {
438 return;
439
440 m_SelectedServerEntry.SetFavorite(!m_SelectedServerEntry.IsFavorite());
441 }
442
443 //------------------------------------------------------------------------------------------------
445 protected void OnActionDetails()
446 {
448 if (!entry)
449 return;
450
451 m_bQuickJoin = false;
452
453 // Join
454 Room room = entry.GetRoomInfo();
455 if (room && room.Joinable())
457 }
458
459 //------------------------------------------------------------------------------------------------
460 protected void OnServerEntryClickInteraction(float multiplier)
461 {
463
465 return;
466
467 switch (Math.Floor(multiplier))
468 {
469 case 1: OnServerEntryClick(m_ClickedEntry); break;
471 }
472
473 m_ClickedEntry = null;
474 }
475
476 //------------------------------------------------------------------------------------------------
479 {
480 if (entry != m_SelectedServerEntry)
481 return;
482
483 m_bQuickJoin = true;
484
485 // Join
486 if (entry && entry.GetRoomInfo() && entry.GetRoomInfo().Joinable())
488 }
489
490 //------------------------------------------------------------------------------------------------
491 protected void OnEntryMouseButton(string tag)
492 {
494 }
495
496 //------------------------------------------------------------------------------------------------
497 protected void OnJoinButton()
498 {
500 }
501
502 //------------------------------------------------------------------------------------------------
505 {
508 if (entry != m_SelectedServerEntry)
510
512 m_bQuickJoin = GetGame().GetInputManager().GetLastUsedInputDevice() != EInputDeviceType.MOUSE;
513
514 // Join
515 if (entry.GetRoomInfo() && entry.GetRoomInfo().Joinable())
517
518 //TODO: handle edge case in which we ask for the details while downloading another version of a required mod, make sure the shown download size is correct
519 }
520
521 //------------------------------------------------------------------------------------------------
522 // --- SERVICE CHECK ---
523 //------------------------------------------------------------------------------------------------
524 //------------------------------------------------------------------------------------------------
527 {
529 return;
530
531 // Call room search or find last server
532 string lastId = m_Lobby.GetPreviousRoomId();
533
534 if (!m_Lobby.IsPingAvailable())
535 return;
536
538 Refresh();
539
540 // Clear error msg
542
543 // Stop waiting for backend
545 }
546
547 //------------------------------------------------------------------------------------------------
548 protected void CheckBackendState()
549 {
551 {
553 GetGame().GetCallqueue().Remove(ConnectionTimeout);
555 }
556 }
557
558 //------------------------------------------------------------------------------------------------
559 protected void ShowTimeoutDialog()
560 {
561 Messages_ShowMessage("NO_CONNECTION");
562 if (m_Dialogs)
563 {
564 m_Dialogs.DisplayDialog(EJoinDialogState.BACKEND_TIMEOUT);
565 m_Dialogs.GetOnConfirm().Clear();
566 m_Dialogs.GetOnConfirm().Insert(OnConnectionTimeoutDialogConfirm);
567 }
568 }
569 //------------------------------------------------------------------------------------------------
571 protected void ConnectionTimeout()
572 {
574 {
576 }
578
580 }
581
582 //------------------------------------------------------------------------------------------------
584 {
585 m_Dialogs.GetOnConfirm().Remove(OnConnectionTimeoutDialogConfirm);
586
588 Messages_ShowMessage(TAG_MESSAGE_SEARCHING);
589 else
590 Messages_ShowMessage(TAG_MESSAGE_CONNECTING, true);
591 }
592
593 //------------------------------------------------------------------------------------------------
595 {
596 GetGame().GetCallqueue().Remove(ConnectionTimeout);
597 }
598
599 //------------------------------------------------------------------------------------------------
600 // --- ROOMS ---
601 //------------------------------------------------------------------------------------------------
602 //------------------------------------------------------------------------------------------------
605 protected void OnRoomsFound(array<Room> rooms = null)
606 {
607 // Load rooms
608 ClientLobbyApi lobby = GetGame().GetBackendApi().GetClientLobby();
609
610 if (rooms)
611 {
612 // Direct join rooms
613 lobby.Target(rooms);
614 }
615 else
616 {
617 // Room from search
618 lobby.Rooms(m_aRooms);
619 //TODO: [BUG] On trunk, switching to Community Tab returns an empty rooms array even if there are rooms?!
620
621 if (m_aRooms.IsEmpty())
622 PrintDebug("No room found", "OnRoomsFound");
623 }
624
625
627
628 // Move to top in list
629 if (m_ScrollableList && (m_ScrollableList.IsListFocused() || m_bFirstRoomLoad))
630 m_ScrollableList.FocusFirstAvailableEntry();
631
633 {
634 m_ScrollableList.SetIsListFocused(true);
635 m_bFirstRoomLoad = false;
636 }
637
638 m_ScrollableList.ShowScrollbar(true);
639
640 int currentRoomsCount = m_Lobby.TotalRoomCount();
641 if (currentRoomsCount > m_iTotalNumberOfRooms)
642 m_iTotalNumberOfRooms = currentRoomsCount;
643
644 // Items Found Message
645 if (m_FilterPanel)
646 m_FilterPanel.SetItemsFoundMessage(m_Lobby.TotalRoomCount(), m_iTotalNumberOfRooms, m_Lobby.TotalRoomCount() != m_iTotalNumberOfRooms);
647 }
648
649 //------------------------------------------------------------------------------------------------
650 protected void DisplayRooms(array<Room> rooms = null)
651 {
652 // Don't display if missing MP privilege
653 if (!SocialComponent.IsMultiplayerAllowed())
654 return;
655
656 // Check list
658 {
659 PrintDebug("Missing important component references!", "DisplayRooms");
660 return;
661 }
662
663 // Mods filter when UGC not enabled
665 if (!addonMgr)
666 {
667 PrintDebug("Could not find addon mngr to verify ugc privilege", "DisplayRooms");
668 return;
669 }
670
671 if (m_ParamsFilter.IsModdedFilterSelected() && !addonMgr.GetUgcPrivilege())
672 {
673 Messages_ShowMessage("MISSING_PRIVILEGE_UGC");
674
675 // Negotatiate UGC privilege
677
678 SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
679 if (m_FilterPanel)
680 m_FilterPanel.ShowFilterListBox(false);
681
682 return;
683 }
684
685 int roomCount = m_Lobby.TotalRoomCount();
686
687 // Display no rooms found
688 if (roomCount < 1)
689 {
690 // Setup list
691 m_ScrollableList.SetRooms(rooms, 0, true);
692 m_ScrollableList.ShowEmptyRooms();
693
695 m_ServerScenarioDetails.SetDefaultScenario(TAG_DETAILS_FALLBACK_EMPTY);
696
697 // Show filters
698 if (!m_FilterPanel.GetFilterListBoxShown())
699 SwitchFocus(SCR_EListMenuWidgetFocus.FILTERING);
700 if (m_FilterPanel)
701 m_FilterPanel.ShowFilterListBox(true);
702
703 // Show message
704 Messages_ShowMessage("NO_FILTERED_SERVERS");
705
706 return;
707 }
708
709 // Display rooms
710 // Set rooms to fill server list
711 m_ScrollableList.SetRooms(m_aRooms, m_Lobby.TotalRoomCount(), true);
712
713 // Hide message
715
716 if (m_FilterPanel && !m_FilterPanel.GetFilterListBoxShown())
717 SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
718 }
719
720 //------------------------------------------------------------------------------------------------
722 protected void OnRoomAutoRefresh(BackendCallback callback)
723 {
725
726 m_Dialogs.UpdateServerFullDialog();
727 }
728
729 // --- Search Rooms ---
730 // First search to get the total number of servers
731 //------------------------------------------------------------------------------------------------
732 protected void SearchRooms()
733 {
734 //TODO: query for filtered first, then independently query for total number, in order to reduce load time at start
735
736 // Start loading and show loading feedback
738 m_ModsManager.Clear();
739
741 {
743 return;
744 }
745
746 // Callback
747 ref BackendCallback searchCallback = new BackendCallback;
748
749 // Invoker actions
750 searchCallback.SetOnSuccess(OnSearchAllRooms);
751 searchCallback.SetOnError(OnSearchAllRooms);
752
753 m_CallbackLastSearch = searchCallback;
754
756 m_Lobby.SearchRooms(params, searchCallback);
757 }
758
759 //------------------------------------------------------------------------------------------------
760 protected void OnSearchAllRooms()
761 {
763
764 // Total number of active servers
765 m_iTotalNumberOfRooms = m_Lobby.TotalRoomCount();
766
768 }
769
770 // Searches to get the filtered servers to display
771 //------------------------------------------------------------------------------------------------
772 protected void SearchRoomsFiltered()
773 {
775 m_Lobby.SetViewSize(m_ScrollableList.GetPageEntriesCount() * 2);
776 else
777 m_Lobby.SetViewSize(SERVER_LIST_VIEW_SIZE);
778
779 // Callback
780 ref BackendCallback searchCallback = new BackendCallback;
781
782 // Invoker actions
783 searchCallback.SetOnSuccess(OnSearchRoomsSuccess);
784 searchCallback.SetOnError(OnSearchRoomsFail);
785
786 m_CallbackLastSearch = searchCallback;
787
788 m_Lobby.SearchRooms(m_ParamsFilter, searchCallback);
789 }
790
791 //------------------------------------------------------------------------------------------------
792 protected void OnSearchRoomsSuccess(BackendCallback callback)
793 {
794 PrintDebug(string.Format("Success - servers found: %1", m_Lobby.TotalRoomCount()), "OnSearchRoomsSuccess");
795
796 // Display rooms
797 OnRoomsFound();
799
800 PrintDebug("AFTER - m_RejoinRoom: " + m_RejoinRoom, "OnSearchRoomsSuccess");
801 }
802
803 //------------------------------------------------------------------------------------------------
804 protected void OnSearchRoomsFail(BackendCallback callback)
805 {
806 // Handle timeout
807 if (callback.GetRestResult() == ERestResult.EREST_ERROR_TIMEOUT)
808 {
810 PrintDebug("time out!", "OnSearchRoomsTimeOut");
811 return;
812 }
813
814 PrintDebug(string.Format("Room search fail - code: %1 | restCode: %2 | apiCode: %3", callback.GetHttpCode(), callback.GetRestResult(), callback.GetApiCode()), "OnSearchRoomsFail");
816
817 // Run again if failed ping
818 if (m_bFirstRoomLoad && m_ParamsFilter.GetSortOrder() == m_ParamsFilter.SORT_PING)
819 {
820 Refresh();
821 return;
822 }
823
824 Messages_ShowMessage("BACKEND_SERVICE_FAIL");
825 }
826
827 //------------------------------------------------------------------------------------------------
829 protected void SetupParams(ClientLobbyApi lobby)
830 {
831 FilteredServerParams params = FilteredServerParams.Cast(lobby.GetParameters());
832 if (!params)
833 {
834 // Default filter setup
835 string strParams = lobby.GetStrParams();
836 if (!strParams.IsEmpty())
837 {
838 m_ParamsFilter.ExpandFromRAW(strParams);
839 lobby.ClearParams();
840 }
841 }
842 else
843 {
844 // Restore previous filter setup
846 }
847
848 // Reset search
849 m_ParamsFilter.SetSearch(string.Empty);
850
852 }
853
854 //------------------------------------------------------------------------------------------------
856 protected void SetupFilteringUI(FilteredServerParams filterParams)
857 {
858 // Tabview
860 {
861 m_TabView.ShowTab(m_iSelectedTab, true, false);
862 }
863
864 if (m_FilterPanel)
865 {
866 bool show = m_FilterPanel.AnyFilterButtonsVisible();
867 m_FilterPanel.ShowFilterListBox(show, show);
868 }
869 }
870
871 //------------------------------------------------------------------------------------------------
873 protected void SetupCallbacks()
874 {
875 // Loading
876 SCR_MenuLoadingComponent.m_OnMenuOpening.Insert(OnOpeningByLoadComponent);
877
878 // Server list
879 m_ScrollableList.GetOnSetPage().Insert(CallOnServerListSetPage);
880 }
881
882 //------------------------------------------------------------------------------------------------
883 protected void SetupRefreshCallback()
884 {
887 m_Lobby.SetRefreshRate(ROOM_REFRESH_RATE);
888 m_Lobby.SetRefreshCallback(m_CallbackAutoRefresh);
889 }
890
891 //------------------------------------------------------------------------------------------------
892 protected void ClearRefreshCallback()
893 {
895 }
896
897 //------------------------------------------------------------------------------------------------
898 // --- ENTRIES ---
899 //------------------------------------------------------------------------------------------------
900 //------------------------------------------------------------------------------------------------
902 {
904 if (!serverEntry || !m_ModsManager)
905 return;
906
907 Room room = serverEntry.GetRoomInfo();
908 if (!room)
909 {
911 return;
912 }
913
914 serverEntry.m_OnClick.Insert(OnEntryMouseClick);
915
916 // Update visuals
917 if (m_SelectedServerEntry == serverEntry)
918 return;
919
920 DisplayFavoriteAction(room.IsFavorite());
922
923 m_SelectedServerEntry = serverEntry;
924
925 m_ModsManager.Clear();
926 m_SelectedServerEntry.SetModsManager(m_ModsManager);
927
928 ReceiveRoomContent(room, true);
929 }
930
931 //------------------------------------------------------------------------------------------------
933 {
935
936 serverEntry.m_OnClick.Remove(OnEntryMouseClick);
937 }
938
939 //------------------------------------------------------------------------------------------------
944
945 //------------------------------------------------------------------------------------------------
946 protected void ReceiveRoomContent(notnull Room room, bool receiveMods)
947 {
949 return;
950
951 GetGame().GetCallqueue().Remove(ReceiveRoomContent_Mods);
952
954 m_ServerScenarioDetails.DisplayRoomData(room, receiveMods);
955
956 // Allow check only if client is authorized to join server
957 if (!room.IsAuthorized())
958 return;
959
960 // Check room mods count
961 array<Dependency> roomMod = {};
962 room.GetItems(roomMod);
963
964 // Show mod count immidiatelly
965 if (!roomMod.IsEmpty() && m_ServerScenarioDetails)
966 m_ServerScenarioDetails.DisplayModsCount(roomMod.Count());
967
968 // Receive mod data only if currently view is focused
969 if (room.IsDownloadListLoaded())
970 {
972 return;
973 }
974 else
975 {
976 // Load mods after short delay - to prevent spamming mods receive request with fast server selecting
977 GetGame().GetCallqueue().CallLater(ReceiveRoomContent_Mods, ROOM_CONTENT_LOAD_DELAY, false, room);
979 }
980 }
981
982 //------------------------------------------------------------------------------------------------
986 {
987 // Load scenario
988 m_ModsManager.GetOnGetScenario().Insert(OnLoadingScenario);
989 m_ModsManager.ReceiveRoomScenario(room);
990 }
991
992 //------------------------------------------------------------------------------------------------
995 protected void ReceiveRoomContent_Mods(Room room)
996 {
997 if (!m_ModsManager)
998 return;
999
1000 m_ModsManager.GetOnGetAllDependencies().Insert(OnLoadingDependencyList);
1001 m_ModsManager.ReceiveRoomMods(room);
1002
1003 m_WaitingForModContent = false;
1004 }
1005
1006 //------------------------------------------------------------------------------------------------
1007 // --- SETUP ---
1008 //------------------------------------------------------------------------------------------------
1010 protected void SetupHandlers()
1011 {
1012 // Tab view
1013 m_TabView = SCR_TabViewComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_TAB_VIEW, SCR_TabViewComponent));
1014 if (m_TabView)
1015 {
1016 m_TabView.GetOnChanged().Insert(OnTabViewSwitch);
1017 OnTabViewSwitch(null, null, m_TabView.GetShownTab());
1018
1020 m_TabView.AddTab("", "#AR-Workshop_ButtonHost");
1021 }
1022
1023 // Filter panel
1024 m_FilterPanel = SCR_FilterPanelComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_FILTER, SCR_FilterPanelComponent));
1025 if (m_FilterPanel)
1026 {
1027 // Invoker
1028 m_FilterPanel.GetOnFilterPanelToggled().Insert(OnFilterPanelToggle);
1029 m_FilterPanel.GetOnFilterChanged().Insert(OnChangeFilter);
1030
1031 // Attempt load previous filter setup
1032 m_FilterPanel.TryLoad();
1033 m_ParamsFilter.SetFilters(m_FilterPanel.GetFilter());
1034
1036 }
1037
1038 // Sorting header
1039 SCR_SortHeaderComponent sortBar = SCR_SortHeaderComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_SERVER_HEADER, SCR_SortHeaderComponent));
1040 if (sortBar)
1041 {
1042 sortBar.m_OnChanged.Insert(OnChangeSort);
1043
1044 // Initial sort
1045 // todo move default sorting values out of here, it can be set in layout file now
1046 sortBar.SetCurrentSortElement(3, ESortOrder.DESCENDING);
1047 }
1048
1049 // Search edit box
1050 SCR_EditBoxComponent searchEditBox = SCR_EditBoxSearchComponent.Cast(m_Widgets.FindHandlerReference(m_Widgets.m_wSearchEditBox, m_Widgets.WIDGET_SEARCH, SCR_EditBoxSearchComponent));
1051 if (searchEditBox)
1052 searchEditBox.m_OnConfirm.Insert(OnSearchEditBoxConfirm);
1053
1054 // Server list and scroll --------------------
1055 m_ScrollableList = SCR_PooledServerListComponent.Cast(m_Widgets.FindHandlerReference(
1056 null, m_Widgets.WIDGET_SCROLLABLE_LIST, SCR_PooledServerListComponent
1057 ));
1058
1059 // Add callbacks
1060 array<SCR_ServerBrowserEntryComponent> entries = m_ScrollableList.GetRoomEntries();
1061
1062 foreach (SCR_ServerBrowserEntryComponent entry : entries)
1063 {
1064 // Set invoker actions
1065 entry.GetOnFocus().Insert(OnServerEntryFocusEnter);
1066 entry.GetOnFocusLost().Insert(OnServerEntryFocusLeave);
1067 entry.GetOnFavorite().Insert(OnRoomEntrySetFavorite);
1068 entry.GetOnMouseInteractionButtonClicked().Insert(OnEntryMouseButton);
1069 }
1070
1071 // Detail screen
1073 null, m_Widgets.WIDGET_SERVER_SCENARIO_DETAILS_PANEL, SCR_ServerScenarioDetailsPanelComponent
1074 ));
1075
1076 // Bacis setup and hide
1078 m_ServerScenarioDetails.SetModsManager(m_ModsManager);
1079
1080 // Messages
1081 m_SimpleMessageWrap = SCR_SimpleMessageComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_MESSAGE_WRAP, SCR_SimpleMessageComponent));
1082 m_SimpleMessageList = SCR_SimpleMessageComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_MESSAGE_LIST, SCR_SimpleMessageComponent));
1084 m_SimpleMessageList.SetVisible(false);
1085
1086
1087 // Navigation buttons
1088 m_Widgets.m_JoinButton.m_OnActivated.Insert(OnJoinButton);
1089 m_Widgets.m_DetailsButton.m_OnActivated.Insert(OnActionDetails);
1090 m_Widgets.m_FavoritesButton.m_OnActivated.Insert(OnActionFavorite);
1091 }
1092
1093 //------------------------------------------------------------------------------------------------
1097 protected void FilterCrossplayCheck()
1098 {
1099 if (!m_FilterPanel)
1100 return;
1101
1102 SCR_FilterSet filterSet = m_FilterPanel.GetFilter();
1103 if (!filterSet)
1104 return;
1105
1106 SCR_FilterCategory crossPlay = filterSet.FindFilterCategory("Crossplay");
1107 if (!crossPlay)
1108 return;
1109
1110 // Cross play privilege missing
1111 bool isCrossEnabled = GetGame().IsCrossPlayEnabled();
1112
1113 if (crossPlay.m_wCategoryTitleWidget)
1114 crossPlay.m_wCategoryTitleWidget.SetVisible(isCrossEnabled);
1115
1116 SCR_FilterEntry enabled = crossPlay.FindFilter("CrossplayEnabled");
1117 if (enabled)
1118 {
1119 //This sets an actual filter value for filtering servers
1120 enabled.SetSelected(false);
1121
1122 if (enabled.m_FilterComponent)
1123 {
1124 enabled.m_FilterComponent.SetVisible(isCrossEnabled);
1125 enabled.m_FilterComponent.SetEnabled(isCrossEnabled);
1126 }
1127
1128 //This sets only visualisation of widget
1129 m_FilterPanel.SelectFilter(enabled, false, false);
1130 }
1131
1132 SCR_FilterEntry disabled = crossPlay.FindFilter("CrossPlayDisabled");
1133 if (disabled)
1134 {
1135 //This sets an actual filter value for filtering servers
1136 disabled.SetSelected(!isCrossEnabled);
1137
1138 if (disabled.m_FilterComponent)
1139 {
1140 disabled.m_FilterComponent.SetVisible(isCrossEnabled);
1141 disabled.m_FilterComponent.SetEnabled(isCrossEnabled);
1142 }
1143
1144 //This sets only visualisation of widget
1145 m_FilterPanel.SelectFilter(disabled, !isCrossEnabled, false);
1146 }
1147
1148 Refresh();
1149 }
1150
1151 //------------------------------------------------------------------------------------------------
1153 protected void SwitchFocus(SCR_EListMenuWidgetFocus focus, bool force = false)
1154 {
1155 if (m_eFocusedWidgetState == focus && !force)
1156 return;
1157
1158 Widget focusTarget;
1159
1160 switch(focus)
1161 {
1162 case SCR_EListMenuWidgetFocus.LIST:
1163 {
1165 focusTarget = m_SelectedServerEntry.GetRootWidget();
1166 else if (m_ScrollableList)
1167 focusTarget = m_ScrollableList.FirstAvailableEntry();
1168
1169 break;
1170 }
1171
1172 case SCR_EListMenuWidgetFocus.FILTERING:
1173 {
1174 focusTarget = m_FilterPanel.GetWidgets().m_FilterButton;
1175 break;
1176 }
1177
1178 case SCR_EListMenuWidgetFocus.SORTING:
1179 {
1180 focusTarget = m_Widgets.m_wSortSessionFavorite;
1181 break;
1182 }
1183 }
1184
1185 m_eFocusedWidgetState = focus;
1186
1187 if (!focusTarget || !focusTarget.IsVisible())
1188 {
1189 // Fallback
1190 focusTarget = m_Widgets.m_wSortSessionFavorite;
1191 m_eFocusedWidgetState = SCR_EListMenuWidgetFocus.SORTING;
1192 }
1193
1194 GetGame().GetWorkspace().SetFocusedWidget(focusTarget);
1195 }
1196
1197 //------------------------------------------------------------------------------------------------
1200 void ActivateFilter(string filterName, bool enabled, bool processFilters = true)
1201 {
1202 // Setup filter
1203 SCR_FilterEntry filter = new SCR_FilterEntry;
1204 filter.m_sInternalName = filterName;
1205 filter.SetSelected(true);
1206
1207 // Register filter
1208 m_aFiltersToSelect.Insert(filter);
1209
1210 // Activate filter if possible
1211 if (processFilters)
1213 }
1214
1215 //------------------------------------------------------------------------------------------------
1217 {
1218 // Filters array check
1219 if (!m_aFiltersToSelect || m_aFiltersToSelect.IsEmpty())
1220 return;
1221
1222 // Filter panel check
1224 return;
1225
1226 // Get filter set
1227 ref SCR_FilterSet filterSet = m_FilterPanel.GetFilter();
1228 if (!filterSet)
1229 return;
1230
1231 // Check and enable each filter
1232 foreach (SCR_FilterEntry filter : m_aFiltersToSelect)
1233 {
1234 if (!filter)
1235 continue;
1236
1237 // Find filter to select
1238 SCR_FilterEntry targetFilter = filterSet.FindFilter(filter.m_sInternalName);
1239
1240 // Set select if is found
1241 if (targetFilter && targetFilter.GetSelected() != filter.GetSelected())
1242 {
1243 targetFilter.SetSelected(filter.GetSelected());
1244 m_FilterPanel.SelectFilter(targetFilter, filter.GetSelected());
1245 }
1246 }
1247
1248 // Clear filters
1249 m_aFiltersToSelect.Clear();
1250
1251 // Filter
1252 m_ParamsFilter.SetFilters(filterSet);
1253 Refresh();
1254 }
1255
1256 //------------------------------------------------------------------------------------------------
1258 protected void FocusWidget(Widget w)
1259 {
1260 GetGame().GetWorkspace().SetFocusedWidget(w);
1261 }
1262
1263 //------------------------------------------------------------------------------------------------
1264 protected void CallOnServerListSetPage(int page)
1265 {
1266 GetGame().GetCallqueue().Remove(OnServerListSetPage);
1267 GetGame().GetCallqueue().CallLater(OnServerListSetPage, ROOM_CONTENT_LOAD_DELAY, false, page);
1268 }
1269
1270 //------------------------------------------------------------------------------------------------
1271 // --- MESSAGES ---
1272 //------------------------------------------------------------------------------------------------
1273 //------------------------------------------------------------------------------------------------
1276 protected void Messages_ShowMessage(string messageTag, bool showWrap = false)
1277 {
1278 // Check message component references
1279 if (!m_Widgets.m_wPanelEmpty || !m_SimpleMessageWrap || !m_SimpleMessageList)
1280 {
1281 string msg = string.Format("Missing ref - WrapLayout: %1 Wrap: %2, List: %3", m_Widgets.m_wPanelEmpty, m_SimpleMessageWrap, m_SimpleMessageList);
1282 PrintDebug(msg, "Messages_ShowMessage");
1283 return;
1284 }
1285
1286 // Show menu content
1287 if (m_Widgets.m_wContent)
1288 m_Widgets.m_wContent.SetVisible(!showWrap);
1289
1290 m_Widgets.m_wPanelEmpty.SetVisible(showWrap);
1291
1292 // Fill the messages with content
1293 m_SimpleMessageWrap.SetContentFromPreset(messageTag);
1294 m_SimpleMessageList.SetContentFromPreset(messageTag);
1295
1296 // Display messages
1297 m_SimpleMessageWrap.SetVisible(showWrap);
1298 m_SimpleMessageList.SetVisible(!showWrap);
1299
1300 // Hide footer buttons during full layout mode
1301 if (m_Widgets.m_RefreshButton)
1302 m_Widgets.m_RefreshButton.SetVisible(!showWrap, false);
1303
1304 if (m_Widgets.m_DirectJoinButton)
1305 m_Widgets.m_DirectJoinButton.SetVisible(!showWrap, false);
1306
1307 if (m_Widgets.m_FilterButton)
1308 m_Widgets.m_FilterButton.SetVisible(!showWrap, false);
1309 }
1310
1311 //------------------------------------------------------------------------------------------------
1313 protected void Messages_Hide()
1314 {
1315 Widget wrapLayout = m_Widgets.m_wPanelEmpty;
1316
1317 // Check message component references
1318 if (!wrapLayout || !m_SimpleMessageWrap || !m_SimpleMessageList)
1319 {
1320 string msg = string.Format("Missing ref - WrapLayout: %1 Wrap: %2, List: %3", wrapLayout, m_SimpleMessageWrap, m_SimpleMessageList);
1321 PrintDebug(msg, "Messages_Hide");
1322 return;
1323 }
1324
1325 // Hide
1326 m_SimpleMessageWrap.SetVisible(false);
1327 m_SimpleMessageList.SetVisible(false);
1328
1329 wrapLayout.SetVisible(false);
1330
1331 if (m_Widgets.m_wContent)
1332 m_Widgets.m_wContent.SetVisible(true);
1333 }
1334
1335 //------------------------------------------------------------------------------------------------
1336 // --- CALLBACKS ---
1337 //------------------------------------------------------------------------------------------------
1340 protected void OnOpeningByLoadComponent(int menuPreset)
1341 {
1342 // Check menu opening
1343 if (menuPreset == ChimeraMenuPreset.ServerBrowserMenu)
1344 return;
1345 }
1346
1347 //------------------------------------------------------------------------------------------------
1349 protected void OnChangeSort(SCR_SortHeaderComponent sortHeader)
1350 {
1351 if (!m_ParamsFilter)
1352 return;
1353
1354 // Reload data
1355 bool sortAscending = sortHeader.GetSortOrderAscending();
1356 string sortElementName = sortHeader.GetSortElementName();
1357 m_ParamsFilter.SetSorting(sortElementName, sortAscending);
1358
1359 Refresh();
1360
1361 //SCR_AnalyticsApplication.GetInstance().MultiplayerMenuSetSorting(sortElementName);
1362 }
1363
1364 //------------------------------------------------------------------------------------------------
1366 protected void OnTabViewSwitch(SCR_TabViewComponent tabView, Widget w, int id)
1367 {
1368 // Default setup
1369 m_ParamsFilter.SetRecentlyPlayedFilter(false);
1370 m_Widgets.m_wHostNewServerButton.SetVisible(false);
1371
1372 // with id == SCR_EServerBrowserTabs.ALL, nothing is forced
1373 bool onlyFavorite = id == SCR_EServerBrowserTabs.FAVORITES;
1374 bool onlyOfficial = id == SCR_EServerBrowserTabs.OFFICIAL;
1375 bool onlyCommunity = id == SCR_EServerBrowserTabs.COMMUNITY;
1376 bool onlyRecent = id == SCR_EServerBrowserTabs.RECENT;
1377 bool onlyOwned = id == SCR_EServerBrowserTabs.HOST;
1378
1379 // limit to Official or Community
1380 m_ParamsFilter.SetOfficialFilter(onlyOfficial);
1381 m_ParamsFilter.SetCommunityFilter(onlyCommunity);
1382
1383 // limit to Favorite
1384 m_ParamsFilter.SetFavoriteFilter(onlyFavorite);
1385
1386 // limit to recent
1387 m_ParamsFilter.SetRecentlyPlayedFilter(onlyRecent);
1388
1389 // limit to owned (hosting widgets)
1390 m_ParamsFilter.SetOwnedOnly(onlyOwned);
1391 m_Widgets.m_wHostNewServerButton.SetVisible(onlyOwned);
1392 m_Widgets.m_wHostNewServerButton.SetEnabled(onlyOwned);
1393 if( onlyOwned )
1394 {
1395 // Call focus later to prevent override from auto widget focus
1396 GetGame().GetCallqueue().CallLater(FocusWidget, 0, false, m_Widgets.m_wHostNewServerButton);
1397 }
1398 m_bHostedServers = onlyOwned;
1399
1400 // Set tab filter json
1402
1403 Refresh();
1404
1405 Widget focus = GetGame().GetWorkspace().GetFocusedWidget();
1406 if (!m_FilterPanel || !m_FilterPanel.GetFilterListBoxShown() || !focus || !focus.IsVisible())
1407 SwitchFocus(SCR_EListMenuWidgetFocus.LIST, true);
1408
1409 //SCR_AnalyticsApplication.GetInstance().MultiplayerMenuSetTab(id);
1410 }
1411
1412 // --- Filters ---
1413 //------------------------------------------------------------------------------------------------
1414 protected void OnFilterPanelToggle(bool show)
1415 {
1416 if (!m_FilterPanel)
1417 return;
1418
1419 if (show || m_Lobby.TotalRoomCount() == 0)
1420 SwitchFocus(SCR_EListMenuWidgetFocus.FILTERING); // Focus back to server list
1421 else
1422 SwitchFocus(SCR_EListMenuWidgetFocus.LIST); // Focus back to last entry
1423
1424 //SCR_AnalyticsApplication.GetInstance().MultiplayerMenuUseFilterOn();
1425 }
1426
1427 //------------------------------------------------------------------------------------------------
1430 protected void OnChangeFilter(SCR_FilterEntry filter)
1431 {
1432 // Set filter and refresh
1433 m_ParamsFilter.SetFilters(m_FilterPanel.GetFilter());
1434 Refresh();
1435
1436 // Is crossplay filter
1437 if (!GetGame().IsCrossPlayEnabled() && filter.GetCategory().m_sInternalName == "Crossplay")
1438 {
1440 Refresh();
1441 }
1442
1443 //SCR_AnalyticsApplication.GetInstance().MultiplayerMenuSetFilter(filter.GetCategory().m_sInternalName, filter.m_sInternalName);
1444 }
1445
1446 // --- Scrolling ---
1447 //------------------------------------------------------------------------------------------------
1449 protected void OnScrollError(BackendCallback callback)
1450 {
1451 if (callback.GetRestResult() == ERestResult.EREST_ERROR_TIMEOUT)
1452 {
1453 PrintDebug("Scroll timeout!", "OnScrollResponse");
1454 return;
1455 }
1456 PrintDebug("Scroll error!", "OnScrollResponse");
1457 }
1458
1459 //------------------------------------------------------------------------------------------------
1460 protected void OnScrollSuccess(BackendCallback callback)
1461 {
1462 // Check if loaded room should display details
1463 bool loadedRoomFocused = false;
1465 loadedRoomFocused = true;
1466
1467 // Update rooms
1468 m_Lobby.Rooms(m_aRooms);
1469
1470 if (m_aRooms.IsEmpty())
1471 {
1472 PrintDebug("No room found", "OnScrollSuccess");
1473
1474 if (m_Lobby.TotalRoomCount() > 0)
1475 {
1476 if (m_ScrollableList)
1477 CallOnServerListSetPage(m_ScrollableList.GetCurrentPage());
1478 else
1479 Refresh();
1480 }
1481 }
1482
1483 m_ScrollableList.UpdateLoadedPage();
1484
1486
1487 // Focus on new room
1488 if (loadedRoomFocused)
1489 {
1490 Room room = m_SelectedServerEntry.GetRoomInfo();
1491 if (room)
1492 ReceiveRoomContent(room, true);
1493 }
1494 }
1495
1496 //------------------------------------------------------------------------------------------------
1498 protected void OnServerListSetPage(int page)
1499 {
1500 // Check list
1501 if (!m_ScrollableList)
1502 return;
1503
1504 // Get entries count
1505 int entriesC = m_ScrollableList.GetPageEntriesCount();
1506 int pos = entriesC * page;
1507
1508 // Setup scroll callback
1509 m_CallbackScroll.SetOnSuccess(OnScrollSuccess);
1510 m_CallbackScroll.SetOnError(OnScrollError);
1511
1512 array<Room> rooms = {};
1513 m_Lobby.Rooms(rooms);
1514 m_Lobby.Scroll(pos, m_CallbackScroll);
1515 }
1516
1517 // --- Search ---
1518 //------------------------------------------------------------------------------------------------
1520 protected void OnSearchEditBoxConfirm(SCR_EditBoxComponent editBox, string sInput)
1521 {
1522 m_ParamsFilter.SetSearch(sInput);
1523 Refresh();
1524
1525 //SCR_AnalyticsApplication.GetInstance().MultiplayerMenuUseSearch();
1526 }
1527
1528 // --- Favoriting ---
1529 //------------------------------------------------------------------------------------------------
1531 protected void OnRoomEntrySetFavorite(SCR_ListMenuEntryComponent entry, bool favorite)
1532 {
1534 if(!serverEntry)
1535 return;
1536
1537 Room roomClicked = serverEntry.GetRoomInfo();
1538 if (!roomClicked)
1539 return;
1540
1541 int roomId = m_aRooms.Find(roomClicked);
1542 if (roomId < 0)
1543 return;
1544
1545 roomClicked.SetFavorite(favorite, m_CallbackFavorite);
1546
1547 // Setup callback
1548 m_CallbackFavorite.SetRoom(roomClicked);
1551
1552 //SCR_AnalyticsApplication.GetInstance().MultiplayerMenuUseFavorite();
1553 }
1554
1555 //------------------------------------------------------------------------------------------------
1557 {
1558 if (callback.GetRoom())
1559 {
1560 DisplayFavoriteAction(callback.GetRoom().IsFavorite());
1561 m_OnFavoritesResponse.Invoke();
1562 }
1563
1564 // Clear
1565 m_CallbackFavorite.SetRoom(null);
1566 }
1567
1568 //------------------------------------------------------------------------------------------------
1570 {
1571 if (callback.GetRestResult() == ERestResult.EREST_ERROR_TIMEOUT)
1572 {
1573 PrintDebug("Timeout!", "OnRoomSetFavoriteResponse");
1574 }
1575 else
1576 {
1577 PrintDebug("Error!", "OnRoomSetFavoriteResponse");
1578 }
1579
1580 // Clear
1581 m_CallbackFavorite.SetRoom(null);
1582 }
1583
1584 //------------------------------------------------------------------------------------------------
1586 protected void DisplayFavoriteAction(bool isFavorite)
1587 {
1588 if (m_Widgets && m_Widgets.m_FavoritesButton && m_SelectedServerEntry)
1589 m_Widgets.m_FavoritesButton.SetLabel(UIConstants.GetFavoriteLabel(isFavorite));
1590 }
1591
1592 // --- Reconnect ---
1593 //------------------------------------------------------------------------------------------------
1596 {
1599
1600 // Find
1601 string lastId = m_Lobby.GetPreviousRoomId();
1603 }
1604
1605 //------------------------------------------------------------------------------------------------
1608 protected void OnLoadingScenario(Room room)
1609 {
1610 // Remove action
1611 m_ModsManager.GetOnGetScenario().Remove(OnLoadingScenario);
1612
1613 if (!room)
1614 return;
1615
1616 // Get scenario item
1617 MissionWorkshopItem scenarioItem = room.HostScenario();
1618
1619 // Hide scneario img if scenario if modded client can't see UGC
1620 Dependency scenarioMod = room.HostScenarioMod();
1621 bool hideScenario = scenarioMod && !SCR_AddonManager.GetInstance().GetUgcPrivilege();
1622
1623 // Display room and scenario data
1625 {
1626 // Hide scenario image
1627 m_ServerScenarioDetails.SetHideScenarioImg(hideScenario);
1628
1629 if (scenarioItem)
1630 m_ServerScenarioDetails.SetScenario(scenarioItem);
1631 else
1632 m_ServerScenarioDetails.DisplayDefaultScenarioImage();
1633 }
1634
1636 if (m_Dialogs)
1637 {
1638 m_Dialogs.UpdateRoomDetailsScenarioImage(scenarioItem);
1639 m_Dialogs.UpdateServerFullScenarioImage(scenarioItem);
1640 }
1641 }
1642
1643 //------------------------------------------------------------------------------------------------
1650
1651 //------------------------------------------------------------------------------------------------
1652 // --- HELPERS ---
1653 //------------------------------------------------------------------------------------------------
1656 protected bool CanJoinRoom(Room room)
1657 {
1658 if (!room)
1659 {
1660 PrintDebug("No room found for can join room check", "CanJoinRoom");
1661 return false;
1662 }
1663
1664 // Room to client version check
1665 bool versionMatch = ClientRoomVersionMatch(room);
1666
1667 //TODO: check platform restriction
1668
1669 return versionMatch && !m_ModsManager.HasBlockedMods() && room.Joinable();
1670 }
1671
1672 //------------------------------------------------------------------------------------------------
1673 protected bool ClientRoomVersionMatch(Room room)
1674 {
1675 if (!room)
1676 return false;
1677
1678 string clientV = GetGame().GetBuildVersion();
1679 string roomV = room.GameVersion();
1680
1681
1682 return (clientV == roomV);
1683 }
1684
1685 //------------------------------------------------------------------------------------------------
1687 {
1688 Widget w = WidgetManager.GetWidgetUnderCursor();
1689
1690 if (!w)
1691 return null;
1692
1694 }
1695
1696 //------------------------------------------------------------------------------------------------
1698 {
1699 // We are not over a line, use currently focused line
1700 Widget wfocused = GetGame().GetWorkspace().GetFocusedWidget();
1702 if (wfocused)
1703 comp = SCR_ServerBrowserEntryComponent.Cast(wfocused.FindHandler(SCR_ServerBrowserEntryComponent));
1704
1705 EInputDeviceType inputDevice = GetGame().GetInputManager().GetLastUsedInputDevice();
1706 bool isCursorOnInnerButton = m_SelectedServerEntry && m_SelectedServerEntry.IsInnerButtonInteraction();
1707
1708 if (inputDevice == EInputDeviceType.MOUSE && (GetEntryUnderCursor() || isCursorOnInnerButton))
1709 return m_SelectedServerEntry;
1710
1711 return comp;
1712 }
1713
1714 //------------------------------------------------------------------------------------------------
1715 protected void ClearScenarioFilters()
1716 {
1717 if (!m_ParamsFilter)
1718 return;
1719
1720 m_ParamsFilter.SetScenarioId("");
1721 m_ParamsFilter.SetHostedScenarioModId("");
1722 }
1723
1724 //------------------------------------------------------------------------------------------------
1725 protected void SetMenuHeader(string header)
1726 {
1728 if (menuHeader)
1729 menuHeader.SetTitle(header);
1730 }
1731
1732 //------------------------------------------------------------------------------------------------
1733 // --- API ---
1734 //------------------------------------------------------------------------------------------------
1735 //------------------------------------------------------------------------------------------------
1736 void FilterScenarioId(string scenarioId)
1737 {
1738 if (m_ParamsFilter)
1739 m_ParamsFilter.SetScenarioId(scenarioId);
1740 }
1741
1742 //------------------------------------------------------------------------------------------------
1743 void FilterHostedScenarioModId(string scenarioModId)
1744 {
1745 if (m_ParamsFilter)
1746 m_ParamsFilter.SetHostedScenarioModId(scenarioModId);
1747 }
1748
1749 //------------------------------------------------------------------------------------------------
1751 {
1752 if (m_Widgets && m_Widgets.m_HostButton)
1753 m_Widgets.m_HostButton.SetScenario(scenario);
1754 }
1755
1756 //------------------------------------------------------------------------------------------------
1759 {
1760 ServerBrowserMenuUI sb = ServerBrowserMenuUI.Cast(GetGame().GetMenuManager().OpenMenu(ChimeraMenuPreset.ServerBrowserMenu));
1761 if (!sb)
1762 return;
1763
1764 // Scenario id
1765 string scenarioId = mission.Id();
1766 sb.FilterScenarioId(scenarioId);
1767
1768 // Modded
1769 string modId = "";
1770 WorkshopItem owner = mission.GetOwner();
1771 if (owner)
1772 modId = owner.Id();
1773
1774 if (modId != string.Empty)
1775 sb.FilterHostedScenarioModId(modId);
1776
1777 sb.SetMenuHeader(mission.Name());
1778 sb.SetFilteredScenario(mission);
1779 //SCR_MenuLoadingComponent.SaveLastMenu(ChimeraMenuPreset.ServerBrowserMenu);
1780 }
1781
1782 //------------------------------------------------------------------------------------------------
1784 {
1785 //TODO: unify this check with the value in the filters
1786 return room && room.GetPing() >= HIGH_PING_SERVER_THRESHOLD;
1787 }
1788
1789 //------------------------------------------------------------------------------------------------
1790 //------------------------------------------------------------------------------------------------
1791 // <>-----<> ROOM JOINING PROCESS <>-----<>
1792 //------------------------------------------------------------------------------------------------
1793 //------------------------------------------------------------------------------------------------
1794
1795 // --- TRIGGERS ---
1796 // --- Entry interaction ---
1797 //------------------------------------------------------------------------------------------------
1799 protected void JoinActions_Join()
1800 {
1801 // Prevent join if no entry selected
1803 {
1804 PrintDebug("Quick join is not possible because there is no selected server", "JoinActions_Join");
1805 return;
1806 }
1807
1808 // Join
1810
1811 GameSessionStorage.s_Data["m_iRejoinAttempt"] = "0";
1812 }
1813
1814 // --- Manual Connect ---
1815 //------------------------------------------------------------------------------------------------
1816 // Action for finding server on direct join
1817 protected void JoinActions_DirectJoin(string params, EDirectJoinFormats format, bool publicNetwork)
1818 {
1819 JoinProcess_FindRoom(params, format, publicNetwork);
1820 GameSessionStorage.s_Data["m_iRejoinAttempt"] = "0";
1821 }
1822
1823 //------------------------------------------------------------------------------------------------
1825 protected void JoinProcess_FindRoom(string params, EDirectJoinFormats format, bool publicNetwork)
1826 {
1828
1829 // Format
1830 switch (format)
1831 {
1832 // IP:PORT
1833 case EDirectJoinFormats.IP_PORT:
1834 {
1835 m_DirectJoinParams.SetHostAddress(params);
1836 break;
1837 }
1838
1839 // Direct join code
1840 case EDirectJoinFormats.JOIN_CODE:
1841 {
1842 m_DirectJoinParams.SetJoinCode(params);
1843 break;
1844 }
1845
1846 // Invalid format
1847 case EDirectJoinFormats.INVALID:
1848 {
1849 PrintDebug("Invalid format of direct join", "JoinProcess_FindRoom");
1850 return;
1851 }
1852 }
1853
1854 // Set room search
1855 m_DirectJoinParams.SetUsePlayerLimit(false);
1857
1858 // Setup join dialog
1860 if (m_Dialogs)
1861 m_Dialogs.DisplayDialog(EJoinDialogState.SEARCHING_SERVER);
1862
1863 // Set invokers
1866 }
1867
1868 //------------------------------------------------------------------------------------------------
1871 {
1872 GetGame().GetBackendApi().GetClientLobby().Target(m_aDirectFoundRooms);
1873 if (m_aDirectFoundRooms.IsEmpty())
1874 {
1875 PrintDebug("No room found through direct join!", "JoinProcess_OnFindRoomSuccess");
1877 return;
1878 }
1879
1880 if (m_aDirectFoundRooms.Count() == 1)
1881 {
1882 // Check content of specific server
1883 m_ModsManager.Clear();
1884
1886 }
1887 else
1888 {
1889 // Show multiple rooms in list - fallback logic, shouldn't happend in relased game
1891 }
1892
1893 // Clear direct join callback
1895 }
1896
1897 //------------------------------------------------------------------------------------------------
1900 {
1901 if (m_Dialogs)
1902 m_Dialogs.DisplayDialog(EJoinDialogState.SERVER_NOT_FOUND);
1903
1905 }
1906
1907 //------------------------------------------------------------------------------------------------
1909 {
1910 m_CallbackSearchTarget.SetOnSuccess(null);
1911 m_CallbackSearchTarget.SetOnError(null);
1912 }
1913
1914 // --- Reconnect ---
1915 //------------------------------------------------------------------------------------------------
1917 protected void JoinProcess_FindRoomById(string id, BackendCallback callback)
1918 {
1919 // Setup ID
1920 m_SearchIds.ClearIds();
1921 m_SearchIds.RegisterId(id);
1922
1923 // Search
1924 m_Lobby.GetRoomsByIds(m_SearchIds, callback);
1925 callback.SetOnSuccess(JoinProcess_OnFindRoomByIdResponse);
1926 callback.SetOnError(JoinProcess_OnFindRoomFail);
1927
1928 // Setup join dialog
1930 if (m_Dialogs)
1931 m_Dialogs.DisplayDialog(EJoinDialogState.SEARCHING_SERVER);
1932 }
1933
1934 //------------------------------------------------------------------------------------------------
1937 {
1939
1940 // No rooms received
1941 if (m_aDirectFoundRooms.IsEmpty())
1942 {
1944 return;
1945 }
1946
1947 // Get first room
1950 }
1951
1952 // --- Process ---
1953 //------------------------------------------------------------------------------------------------
1955 void JoinProcess_Init(Room roomToJoin)
1956 {
1958 return;
1959
1960 // Cleanup just to be sure
1962
1963 // Setup room
1964 m_JoinProcessTargetRoom = roomToJoin;
1965
1966 // Setup join dialog
1968
1969 //this case shouldnt happen as filter cannot be changed when crossplay is disabled
1970 if (m_JoinProcessTargetRoom.IsCrossPlatform() && !GetGame().IsCrossPlayEnabled())
1971 {
1972 //i dont think we have different dialog?
1973 //m_Dialogs.DisplayDialog(EJoinDialogState.MOD_UGC_PRIVILEGE_MISSING);
1974 return;
1975 }
1976
1977 //Quick Join: Next step check version
1978 if (m_bQuickJoin)
1980 //Single click Join: Next step check password
1981 else
1983 }
1984
1985 //------------------------------------------------------------------------------------------------
1989 {
1990 // Chekc match
1991 bool versionsMatch = ClientRoomVersionMatch(m_JoinProcessTargetRoom);
1992
1993#ifdef SB_DEBUG
1994#else
1995 // Stop join process with error dialog with wrong version
1996 if (!versionsMatch)
1997 {
1999 m_Dialogs.DisplayDialog(EJoinDialogState.VERSION_MISMATCH);
2000 return;
2001 }
2002#endif
2003
2004 // Check room password protection
2006 }
2007
2008 //------------------------------------------------------------------------------------------------
2011 {
2013 {
2014 m_Dialogs.DisplayDialog(EJoinDialogState.HIGH_PING_SERVER);
2015 m_Dialogs.GetOnConfirm().Insert(OnHighPingServerWarningDialogConfirm);
2016
2017 return;
2018 }
2019
2021 }
2022
2023 //------------------------------------------------------------------------------------------------
2029
2030 //------------------------------------------------------------------------------------------------
2033 {
2034 // Skip password if using direct join code or is invited
2035 bool skipPassword;
2036
2037 if (m_Lobby.GetInviteRoom() == m_JoinProcessTargetRoom || m_RejoinRoom)
2038 skipPassword = m_JoinProcessTargetRoom.IsAuthorized();
2039
2040 // Next step if no password protection
2041 if (!m_JoinProcessTargetRoom.PasswordProtected() || skipPassword)
2042 {
2044 return;
2045 }
2046
2047 m_PasswordVerification.GetOnVerified().Insert(OnPasswordVerified);
2048 m_PasswordVerification.GetOnFailVerification().Clear();
2049 m_PasswordVerification.GetOnFailVerification().Insert(OnRejoinAuthorizationFailed);
2050 m_PasswordVerification.CheckRejoinAuthorization(m_JoinProcessTargetRoom);
2051 }
2052
2053 //------------------------------------------------------------------------------------------------
2054 protected void OnRejoinAuthorizationFailed(string message)
2055 {
2056 m_PasswordVerification.GetOnFailVerification().Remove(OnRejoinAuthorizationFailed);
2057
2058 m_Dialogs.CloseCurrentDialog();
2060 GetGame().GetCallqueue().CallLater(JoinProcess_PasswordDialogOpen);
2061 }
2062
2063 //------------------------------------------------------------------------------------------------
2065 {
2066 m_Dialogs.DisplayDialog(EJoinDialogState.PASSWORD_REQUIRED);
2067 m_Dialogs.GetOnCancel().Insert(JoinProcess_PasswordClearInvokers);
2068
2069 m_PasswordVerification.SetupDialog(m_Dialogs.GetCurrentDialog(), m_JoinProcessTargetRoom);
2070 m_PasswordVerification.GetOnVerified().Insert(OnPasswordVerified);
2071 m_PasswordVerification.GetOnFailVerification().Insert(OnPasswordFailVerification);
2072 }
2073
2074 //------------------------------------------------------------------------------------------------
2076 protected void OnPasswordVerified()
2077 {
2079
2081 {
2082 #ifdef WORKBENCH
2083 Print("ServerBrowserMenuUI - OnPasswordVerified() - NULL ROOM");
2084 #endif
2085
2086 return;
2087 }
2088
2090
2092 }
2093
2094 //------------------------------------------------------------------------------------------------
2096 protected void OnPasswordFailVerification(string message)
2097 {
2098 m_Dialogs.DisplayDialog(EJoinDialogState.PASSWORD_REQUIRED);
2099 m_PasswordVerification.SetupDialog(m_Dialogs.GetCurrentDialog(), m_JoinProcessTargetRoom, message);
2100 }
2101
2102 //------------------------------------------------------------------------------------------------
2104 {
2105 m_PasswordVerification.GetOnVerified().Remove(OnPasswordVerified);
2106 m_PasswordVerification.GetOnFailVerification().Remove(OnPasswordFailVerification);
2107 m_Dialogs.GetOnCancel().Remove(JoinProcess_PasswordClearInvokers);
2108 }
2109
2110 //------------------------------------------------------------------------------------------------
2112 {
2113 GameBlocklist bl = GetGame().GetGameBlocklist();
2114 bl.OnGetBlockedPlayersInRoomInvoker.Insert(JoinProcess_OnCheckedBlockedPlayersInRoom);
2115 bl.CheckBlockedPlayersInRoom(m_JoinProcessTargetRoom);
2116 }
2117
2118 //------------------------------------------------------------------------------------------------
2119 // The GameBlocklist.s_OnCheckedBlockedPlayersInRoomInvoker might return rooms different than the join target,
2120 // as the GameBlocklist can process multiple request at a time, and thus return multiple of these invokers.
2121 protected void JoinProcess_OnCheckedBlockedPlayersInRoom(Room checkedRoom, array<BlockedRoomPlayer> blockedPlayers)
2122 {
2123 if (checkedRoom != m_JoinProcessTargetRoom)
2124 return;
2125
2126 GetGame().GetGameBlocklist().OnGetBlockedPlayersInRoomInvoker.Remove(JoinProcess_OnCheckedBlockedPlayersInRoom);
2127
2128 if (!blockedPlayers || blockedPlayers.IsEmpty())
2129 {
2131 return;
2132 }
2133
2134 m_Dialogs.CreateBlockedPlayersWarningDialog(blockedPlayers);
2135 m_Dialogs.GetOnConfirm().Insert(JoinProcess_ShowJoinDetailsDialog);
2136 }
2137
2138 //------------------------------------------------------------------------------------------------
2140 {
2141 m_Dialogs.GetOnConfirm().Remove(JoinProcess_ShowJoinDetailsDialog);
2142
2143 // Skip the dialog on double click
2144 if (m_bQuickJoin)
2145 {
2147 return;
2148 }
2149
2151 }
2152
2153 //------------------------------------------------------------------------------------------------
2155 {
2156 // Create details dialog
2157 array<ref SCR_WorkshopItem> items = {};
2158 array<Dependency> dependencies = {};
2159 m_JoinProcessTargetRoom.GetItems(dependencies);
2160
2161 if (m_ModsManager.GetRoomItemsScripted().Count() == dependencies.Count())
2162 items = m_ModsManager.GetRoomItemsScripted();
2163
2164 SCR_ServerDetailsDialog serverDetails = m_Dialogs.CreateServerDetailsDialog(m_JoinProcessTargetRoom, items, m_OnFavoritesResponse);
2166 serverDetails.m_OnFavorites.Insert(OnActionFavorite);
2167
2168 bool loaded = m_JoinProcessTargetRoom.IsDownloadListLoaded();
2169
2170 if (!dependencies.IsEmpty())
2171 {
2172 //Fill with last loaded mod list
2173 if (!m_JoinProcessTargetRoom.IsDownloadListLoaded())
2174 m_ModsManager.GetOnGetAllDependencies().Insert(OnServerDetailModsLoaded);
2175 else
2177 }
2178 else
2179 {
2180 // Fill with emtpy data
2181 m_Dialogs.FillRoomDetailsMods({});
2182 }
2183
2184 m_Dialogs.GetCurrentDialog().m_OnConfirm.Insert(JoinProcess_LoadModContent);
2185 m_Dialogs.GetCurrentDialog().m_OnClose.Insert(OnServerDetailsClosed);
2186 }
2187
2188 //------------------------------------------------------------------------------------------------
2190 protected void OnServerDetailModsLoaded(Room room)
2191 {
2192 m_Dialogs.FillRoomDetailsMods(m_ModsManager.GetRoomItemsScripted(), m_ModsManager);
2193 m_ModsManager.GetOnGetAllDependencies().Remove(OnServerDetailModsLoaded);
2194 }
2195
2196 //------------------------------------------------------------------------------------------------
2198 {
2199 m_ModsManager.GetOnGetAllDependencies().Remove(OnServerDetailModsLoaded);
2200 }
2201
2202 //------------------------------------------------------------------------------------------------
2206 {
2207 // Check mods use privilege - UGC privilege
2209 array<Dependency> deps = {};
2210
2211 m_JoinProcessTargetRoom.GetItems(deps);
2212
2213 if (!mgr.GetUgcPrivilege() && !deps.IsEmpty())
2214 {
2215 m_Dialogs.DisplayDialog(EJoinDialogState.MOD_UGC_PRIVILEGE_MISSING);
2216
2217 // Negotatiate UGC privilege
2220 return;
2221 }
2222
2223 // Show state of mods if all loaded
2225 }
2226
2227 //------------------------------------------------------------------------------------------------
2229 protected void OnLoadingDependencyList(Room room)
2230 {
2231 // Remove data receiving actions
2232 m_ModsManager.GetOnGetAllDependencies().Remove(OnLoadingDependencyList);
2233
2234 array<ref SCR_WorkshopItem> updated = m_ModsManager.GetRoomItemsUpdated();
2235 array<ref SCR_WorkshopItem> outdated = m_ModsManager.GetRoomItemsToUpdate();
2236
2237 // setup of server detail
2238 bool modsUpdated = outdated.IsEmpty();
2239
2241 m_ServerScenarioDetails.DisplayMods();
2242
2244 }
2245
2246 //------------------------------------------------------------------------------------------------
2248 {
2249 m_ModListFailDialog = null;
2250
2252 }
2253
2254 //------------------------------------------------------------------------------------------------
2261
2262 //------------------------------------------------------------------------------------------------
2264 {
2265 // Show state of mods if all loaded
2266 if (m_JoinProcessTargetRoom.IsDownloadListLoaded())
2267 {
2269 return;
2270 }
2271
2272 // Show mods loading dialog
2273 m_Dialogs.DisplayDialog(EJoinDialogState.CHECKING_CONTENT);
2274
2275 // Set wait for loading
2276 m_ModsManager.GetOnGetAllDependencies().Insert(JoinProcess_CheckModContent);
2277 m_ModsManager.GetOnModsFail().Insert(JoinProcess_OnModCheckFailed);
2278 m_ModsManager.GetOnDependenciesLoadingPrevented().Insert(OnDependenciesLoadingPrevented);
2279
2280 m_ModsManager.ReceiveRoomMods(m_JoinProcessTargetRoom);
2281 }
2282
2283 //------------------------------------------------------------------------------------------------
2285 {
2286 m_Dialogs.CloseCurrentDialog();
2287 OnModListFail();
2288
2289 m_ModsManager.GetOnGetAllDependencies().Remove(JoinProcess_CheckModContent);
2290 m_ModsManager.GetOnModsFail().Remove(JoinProcess_OnModCheckFailed);
2291 m_ModsManager.GetOnDependenciesLoadingPrevented().Remove(OnDependenciesLoadingPrevented);
2292 }
2293
2294 //------------------------------------------------------------------------------------------------
2297 protected void OnModListFail()
2298 {
2300 return;
2301
2302 m_ModListFailDialog = SCR_CommonDialogs.CreateRequestErrorDialog();
2304 }
2305
2306 //------------------------------------------------------------------------------------------------
2307 protected void OnDependenciesLoadingPrevented(array<ref SCR_WorkshopItem> dependencies)
2308 {
2309 m_Dialogs.CloseCurrentDialog();
2311 }
2312
2313 //------------------------------------------------------------------------------------------------
2317 {
2318 m_Dialogs.CloseCurrentDialog();
2319
2320 // Remove mods check actions
2321 m_ModsManager.GetOnGetAllDependencies().Remove(JoinProcess_CheckModContent);
2322 m_ModsManager.GetOnModsFail().Remove(JoinProcess_OnModCheckFailed);
2323 m_ModsManager.GetOnDependenciesLoadingPrevented().Remove(OnDependenciesLoadingPrevented);
2324
2325 // Restricted content check
2326 array<ref SCR_WorkshopItem> items = m_ModsManager.GetRoomItemsScripted();
2327
2328 array<ref SCR_WorkshopItem> restricedMods = SCR_AddonManager.SelectItemsOr(items, EWorkshopItemQuery.RESTRICTED);
2329 bool restricted = restricedMods.Count() > 0;
2330
2331 // Stop join if there are restricted mods
2332 if (restricted)
2333 {
2334 SCR_ReportedAddonsDialog dialog = m_ModsManager.DisplayRestrictedAddonsList();
2336 return;
2337 }
2338
2340 }
2341
2342 //------------------------------------------------------------------------------------------------
2345 {
2346 array<ref SCR_WorkshopItem> items = m_ModsManager.GetRoomItemsScripted();
2348
2349 if (!m_aUnrelatedDownloads.IsEmpty())
2351 else
2353 }
2354
2355 //------------------------------------------------------------------------------------------------
2356 // Display a dialog asking for unrelated download stop confirmation (this includes wrong versions of required mods)
2358 {
2359 m_Dialogs.DisplayJoinDownloadsWarning(m_aUnrelatedDownloads, SCR_EJoinDownloadsConfirmationDialogType.UNRELATED);
2361 }
2362
2363 //------------------------------------------------------------------------------------------------
2364 // Pause existing downloads that are unrelated to the specific server we want to join
2366 {
2368
2369 // Display filler dialog
2370 m_Dialogs.DisplayDialog(EJoinDialogState.UNRELATED_DOWNLOADS_CANCELING);
2371
2372 // Stop downloads
2374 {
2375 download.Cancel();
2376 }
2377
2378 //TODO: pause downloads instead of clearing them, and allow the player to resume them once out of multiplayer games
2379 //TODO: give the option to keep downloading while playing multiplayer?
2380
2382 }
2383
2384 //------------------------------------------------------------------------------------------------
2385 //Check if all unrelated downloads have been stopped. Recursive
2387 {
2388 array<ref SCR_WorkshopItem> items = m_ModsManager.GetRoomItemsScripted();
2389 array<ref SCR_WorkshopItemActionDownload> downloads = SCR_DownloadManager.GetInstance().GetUnrelatedDownloads(items);
2390 if (!downloads.IsEmpty())
2391 {
2393 return;
2394 }
2395
2396 GetGame().GetCallqueue().Call(JoinProcess_CheckRequiredDownloads);
2397 }
2398
2399 //------------------------------------------------------------------------------------------------
2401 {
2402 m_Dialogs.CloseCurrentDialog();
2403
2404 // Get necessary downloads
2405 array<ref SCR_WorkshopItem> items = m_ModsManager.GetRoomItemsScripted();
2406 m_aRequiredMods = SCR_AddonManager.SelectItemsBasic(items, EWorkshopItemQuery.NOT_LOCAL_VERSION_MATCH_DEPENDENCY);
2407 if (!m_aRequiredMods.IsEmpty())
2408 {
2410 return;
2411 }
2412
2414 }
2415
2416 //------------------------------------------------------------------------------------------------
2417 // Start downloading necessary mods for the server
2427
2428 //------------------------------------------------------------------------------------------------
2436
2437 //------------------------------------------------------------------------------------------------
2439 {
2440 m_Dialogs.GetOnDownloadComplete().Remove(JoinProcess_PrepareFinalJoinRequest);
2441
2443 }
2444
2445 //------------------------------------------------------------------------------------------------
2446 // We need to wait a frame before performing the next check due to how the DownloadManager handles it's queue
2448 {
2449 GetGame().GetCallqueue().Call(JoinProcess_CheckRunningDownloads);
2450 }
2451
2453 //------------------------------------------------------------------------------------------------
2455 {
2456 m_Dialogs.CloseCurrentDialog();
2457
2458 int nCompleted, nTotal;
2460
2461 if (nTotal <= 0)
2462 {
2464 return;
2465 }
2466
2468 m_Dialogs.GetOnConfirm().Insert(OnInterruptDownloadConfirm);
2469 }
2470
2471 //------------------------------------------------------------------------------------------------
2473 {
2474 m_Dialogs.GetOnConfirm().Remove(OnInterruptDownloadConfirm);
2475
2477 {
2478 PrintDebug("Missing m_JoinProcessTargetRoom!", "OnInteruptDownloadConfirm");
2479 return;
2480 }
2481
2482 // TODO: pause and cache instead of canceling
2483 // Cancel downloading
2485
2487 }
2488
2489 //------------------------------------------------------------------------------------------------
2490 // Join ...Finally!
2491 protected void JoinProcess_Join()
2492 {
2493 m_Dialogs.CloseCurrentDialog();
2494 m_Dialogs.DisplayDialog(EJoinDialogState.JOIN);
2495
2496 // Add join callbacks
2500
2501 // Join server
2503 }
2504
2505 //------------------------------------------------------------------------------------------------
2509 {
2510 // Connect - gathers mods needed and calls for a reload
2511 if (!GameStateTransitions.RequestConnectViaRoom(m_Lobby.GetJoinRoom()))
2512 return; // Transition is not guaranteed
2513
2514 // Save menu to reopen
2515 SCR_MenuLoadingComponent.SaveLastMenu(ChimeraMenuPreset.ServerBrowserMenu);
2516
2517 GetGame().GetMenuManager().CloseAllMenus();
2518 GetGame().GetBackendApi().GetWorkshop().Cleanup();
2519
2521 }
2522
2523 //------------------------------------------------------------------------------------------------
2524 // This also includes being placed in joining queue
2526 {
2527 ERestResult apiCode = callback.GetApiCode();
2528
2529 // TODO: Backend - callback on Queue is called twice and apiCode is 0 - ignore such callback
2530 if (!apiCode)
2531 return;
2532
2533 // Timeout handle
2534 if (callback.GetRestResult() == ERestResult.EREST_ERROR_TIMEOUT)
2535 {
2537 m_Dialogs.CloseCurrentDialog();
2538 SCR_CommonDialogs.CreateTimeoutOkDialog();
2539 return;
2540 }
2541
2542 m_Dialogs.CloseCurrentDialog();
2543
2544 SCR_EJoinFailUI result = SCR_EJoinFailUI.GENERIC;
2545
2546 if (apiCode == EApiCode.EACODE_ERROR_MP_ROOM_QUEUE_JOIN)
2547 result = SCR_EJoinFailUI.ENQUEUED;
2548 else if (apiCode == EApiCode.EACODE_ERROR_MP_ROOM_QUEUE_FULL)
2549 result = SCR_EJoinFailUI.SERVER_FULL_QUEUE_FULL;
2550 else if (apiCode == EApiCode.EACODE_ERROR_MP_ROOM_IS_FULL)
2551 result = SCR_EJoinFailUI.SERVER_FULL_QUEUE_DISABLED;
2552 else if (!m_JoinData.scope.IsEmpty())
2553 result = SCR_EJoinFailUI.BANNED;
2554
2555 switch (result)
2556 {
2557 // QUEUE: provide a dialog with queue info and setup callbacks for queue results
2558 case SCR_EJoinFailUI.ENQUEUED:
2559 {
2560 Room joinRoom = m_Lobby.GetJoinRoom();
2561 if (!joinRoom)
2562 break;
2563
2564 SCR_ServerFullDialog dialog = m_Dialogs.CreateServerFullDialog();
2565 if (!dialog)
2566 break;
2567
2569
2570 dialog.Init(joinRoom, result, joinRoom.HostScenario());
2572
2573 // Callback
2577
2578 joinRoom.SetQueueBackendCallback(m_CallbackQueue);
2579
2580 // Remove auto refresh callback, as it is not needed while in queue
2582 break;
2583 }
2584
2585 // Provide a warning dialog that allows to reattempt joining
2586 case SCR_EJoinFailUI.SERVER_FULL_QUEUE_FULL:
2587 case SCR_EJoinFailUI.SERVER_FULL_QUEUE_DISABLED:
2588 {
2589 SCR_ServerFullDialog dialog = m_Dialogs.CreateServerFullDialog();
2590 if (dialog)
2591 {
2593
2595 dialog.GetOnFavorite().Insert(OnActionFavorite);
2596 }
2597
2600 break;
2601 }
2602
2603 // Provide an error dialog with ban info
2604 case SCR_EJoinFailUI.BANNED:
2605 {
2606 m_Dialogs.DisplayJoinBan(m_JoinData);
2609 break;
2610 }
2611
2612 // Provide a generic error dialog
2613 default:
2614 {
2615 m_Dialogs.DisplayJoinFail(apiCode);
2618 break;
2619 }
2620 }
2621 }
2622
2623 //------------------------------------------------------------------------------------------------
2625 {
2626 m_Lobby.GetJoinRoom().LeaveJoinQueue();
2627 m_Dialogs.CloseCurrentDialog();
2628
2630
2631 // Restore auto refresh callback
2633 }
2634
2635 //------------------------------------------------------------------------------------------------
2637 {
2638 EApiCode apiCode = callback.GetApiCode();
2639
2640 // TODO: Backend - callback on Queue is called twice and apiCode is 0 - ignore such callback
2641 if (!apiCode)
2642 return;
2643
2644 // Still waiting in queue, update the dialog
2645 if (apiCode == EApiCode.EACODE_ERROR_MP_ROOM_QUEUE_WAIT)
2646 {
2647 m_Dialogs.UpdateServerFullDialog();
2648 return;
2649 }
2650
2651 // Out of queue, joining failed
2652 m_Dialogs.CloseCurrentDialog();
2653 m_Dialogs.DisplayJoinFail(apiCode);
2655
2656 // Restore auto refresh callback
2658 }
2659
2660 //------------------------------------------------------------------------------------------------
2662 protected void JoinProcess_Clear()
2663 {
2665
2666 //m_CallbackJoin = null;
2667 //m_CallbackQueue = null;
2668
2669 m_Lobby.ClearInviteRoom();
2670
2671 // Clear mods manager callbacks
2672 m_ModsManager.GetOnGetAllDependencies().Clear();
2673 m_ModsManager.GetOnModsFail().Clear();
2674 m_ModsManager.GetOnDependenciesLoadingPrevented().Clear();
2675 m_ModsManager.GetOnGetScenario().Clear();
2676
2677 // Clear dialog
2678 m_Dialogs.GetOnConfirm().Clear();
2679 m_Dialogs.GetOnCancel().Clear();
2680 m_Dialogs.GetOnJoinProcessCancel().Clear();
2681 m_Dialogs.GetOnDownloadComplete().Clear();
2682
2683 // TODO: remove specific subscriptions instead of clearing!
2684
2685 GetGame().GetGameBlocklist().OnGetBlockedPlayersInRoomInvoker.Remove(JoinProcess_OnCheckedBlockedPlayersInRoom);
2686 }
2687
2688 //------------------------------------------------------------------------------------------------
2690 protected void SetupJoinDialogs()
2691 {
2692 // Check dialog
2693 if (!m_Dialogs)
2694 return;
2695
2696 // Setup basics
2697 m_Dialogs.SetModManager(m_ModsManager);
2699
2700 // Invokers
2701 m_Dialogs.GetOnDownloadComplete().Clear();
2702 m_Dialogs.GetOnJoinProcessCancel().Insert(JoinProcess_Clear);
2703
2704 m_CallbackLastSearch = null;
2705 }
2706
2707 //------------------------------------------------------------------------------------------------
2708 // --- PRIVILEGES HANDLING ---
2709 //------------------------------------------------------------------------------------------------
2710 //------------------------------------------------------------------------------------------------
2711
2712 //------------------------------------------------------------------------------------------------
2714 {
2715 // Sucessful
2716 if (privilege == UserPrivilege.MULTIPLAYER_GAMEPLAY && result == UserPrivilegeResult.ALLOWED)
2717 Refresh();
2718
2720 }
2721
2722 //------------------------------------------------------------------------------------------------
2724 {
2725 // Sucessful
2726 if (privilege == UserPrivilege.CROSS_PLAY && result == UserPrivilegeResult.ALLOWED)
2727 Refresh();
2728
2730 }
2731
2732 //------------------------------------------------------------------------------------------------
2733 // --- STATIC ---
2734 //------------------------------------------------------------------------------------------------
2735 //------------------------------------------------------------------------------------------------
2737 {
2740
2742 SocialComponent.RequestMultiplayerPrivilege(m_CallbackGetMPPrivilege);
2743 }
2744
2745 //------------------------------------------------------------------------------------------------
2747 {
2748 if (privilege == UserPrivilege.MULTIPLAYER_GAMEPLAY && result != UserPrivilegeResult.ALLOWED)
2749 SCR_ConfigurableDialogUi.CreateFromPreset(SCR_CommonDialogs.DIALOGS_CONFIG, "mp_you_dont_have_the_right");
2750 else if (m_MissionToFilter)
2752 else
2753 GetGame().GetMenuManager().OpenMenu(ChimeraMenuPreset.ServerBrowserMenu);
2754
2755 m_MissionToFilter = null;
2757 }
2758
2759 //------------------------------------------------------------------------------------------------
2761 {
2764
2765 m_MissionToFilter = mission;
2767 SocialComponent.RequestMultiplayerPrivilege(m_CallbackGetMPPrivilege);
2768 }
2769
2770 //------------------------------------------------------------------------------------------------
2771 // --- DEBUG ---
2772 //------------------------------------------------------------------------------------------------
2773 //------------------------------------------------------------------------------------------------
2775 protected void PrintDebug(string msg, string functionName = string.Empty)
2776 {
2777 #ifdef SB_DEBUG
2778 //Setup function format
2779 string fncStr = string.Empty;
2780 if (functionName != string.Empty)
2781 fncStr = string.Format(" Fnc: %1()", functionName);
2782
2783 // Display message
2784 PrintFormat("[ServerBrowserMenuUI]%1 -- Msg: %2", fncStr, msg);
2785 #endif
2786 }
2787}
2788
2789//------------------------------------------------------------------------------------------------
2791class SCR_GetRoomsIds extends GetRoomsIds
2792{
2793 protected ref array<string> roomIds = {};
2794
2795 //------------------------------------------------------------------------------------------------
2796 void RegisterId(string id)
2797 {
2798 roomIds.Insert(id);
2799 RegV("roomIds");
2800 }
2801
2802 //------------------------------------------------------------------------------------------------
2804 {
2805 roomIds.Clear();
2806 }
2807}
2808
2817
2818enum SCR_EServerBrowserTabs
2819{
2820 ALL = 0,
2825 HOST
2826}
AddonBuildInfoTool id
ChimeraMenuPreset
Menu presets.
bool IsPlatformGameConsole()
Definition game.c:1357
ArmaReforgerScripted GetGame()
Definition game.c:1398
EDirectJoinFormats
PlatformKind
Definition PlatformKind.c:8
EWorkshopItemQuery
InputManager GetInputManager()
Widget GetRootWidget()
@ RECENT
Definition SCR_PlayMenu.c:5
@ COMMUNITY
ScriptInvokerBase< ScriptInvokerVoidMethod > ScriptInvokerVoid
SCR_EJoinDownloadsConfirmationDialogType
Enum for confirmation dialogs that guide the player through the download processes required to join t...
proto native void Close()
ScriptInvokerBase< ScriptInvokerRoomMethod > ScriptInvokerRoom
void ClearIds()
enum SCR_EJoinFailUI OFFICIAL
func ScriptInvokerRoomMethod
@ SERVER_FULL_QUEUE_DISABLED
@ SERVER_FULL_QUEUE_FULL
ServerBrowserMenuUI roomIds
Overrided GetRoomsIds class to manipulation in script.
enum SCR_EJoinFailUI FAVORITES
void RegisterId(string id)
UserPrivilege
UserPrivilegeResult
Server search filtering.
GameSessionStorage is used to store data for whole lifetime of game executable run....
Definition Math.c:13
Definition Room.c:13
ref ScriptInvoker m_OnUgcPrivilegeResult
void NegotiateUgcPrivilegeAsync()
static array< ref SCR_WorkshopItem > SelectItemsBasic(array< ref SCR_WorkshopItem > items, EWorkshopItemQuery query)
bool GetUgcPrivilege()
Returns immediate value of UserPrivilege.USER_GEN_CONTENT.
static array< ref SCR_WorkshopItem > SelectItemsOr(array< ref SCR_WorkshopItem > items, EWorkshopItemQuery query)
static SCR_AddonManager GetInstance()
static SCR_ConfigurableDialogUi CreateFromPreset(ResourceName presetsResourceName, string tag, SCR_ConfigurableDialogUi customDialogObj=null)
Creates a dialog from preset.
static SCR_CoreMenuHeaderComponent FindComponentInHierarchy(notnull Widget root)
void GetDownloadQueueState(out int nCompleted, out int nTotal)
Might get delayed by a frame! Just use it for UI.
static SCR_DownloadManager GetInstance()
array< ref SCR_WorkshopItemActionDownload > GetDownloadQueue()
array< ref SCR_WorkshopItemActionDownload > DownloadItems(array< ref SCR_WorkshopItem > items)
array< ref SCR_WorkshopItemActionDownload > GetUnrelatedDownloads(array< ref SCR_WorkshopItem > requiredItems)
ref ScriptInvoker m_OnConfirm
Widget m_wCategoryTitleWidget
SCR_FilterEntry FindFilter(string internalName)
Finds a filter by internal name.
bool GetSelected(bool defaultValue=false)
Returns the selected flag.
SCR_FilterCategory GetCategory()
Returns the category of this filter.
void SetSelected(bool newValue)
Sets the selected flag, doesn't do anything special.
SCR_FilterCategory FindFilterCategory(string internalName)
Finds a filter category by its internal name.
static void SetReconnectEnabled(bool enabled)
static ScriptInvokerVoid GetOnCancel()
static ScriptInvokerVoid GetOnReconnect()
static void Clear()
static SCR_MenuActionsComponent FindComponent(Widget w)
Pooled scrollable list with server entries handling.
Show list of reported mods and provide option to cancel reports.
Scripted room callback specific for single room.
This component handles server entry and visiualization of server data.
Room GetRoomInfo()
bool GetIsEnabled(out bool versionMismatch, out bool unjoinable)
ScriptInvokerRoom GetOnRetryFullServerJoin()
void Init(Room room, SCR_EJoinFailUI mode, MissionWorkshopItem scenario, ScriptInvokerVoid onFavoritesResponse=null)
ScriptInvokerVoid GetOnLeaveQueueRequest()
ScriptInvokerVoid GetOnFavorite()
static const int CONNECTION_CHECK_EXPIRE_TIME
bool GetSortOrderAscending()
True when sort order is ASCENDING.
void SetCurrentSortElement(int id, ESortOrder order, bool useDefaultSortOrder=false, bool invokeOnChanged=true)
void WaitingForRunningBackend()
Start looking for servers once backend is runnig.
void OnServerEntryFocusEnter(SCR_ScriptedWidgetComponent entry)
void SwitchFocus(SCR_EListMenuWidgetFocus focus, bool force=false)
Switch focus.
void OnActionBack()
Bind action for leaving menu.
void OnActionManualConnect()
Bind action for opening dialog with manual connect to ip.
ref array< ref SCR_FilterEntry > m_aFiltersToSelect
void ReceiveRoomContent_Scenario(Room room)
void ActivateFilter(string filterName, bool enabled, bool processFilters=true)
SCR_ConfigurableDialogUi m_ModListFailDialog
void FilterScenarioId(string scenarioId)
void OnActionFilter()
Bind action for switching to filter component.
SCR_ServerBrowserEntryComponent GetSelectedEntry()
void JoinProcess_CheckUnrelatedDownloadsCanceling()
void JoinProcess_CheckModContent(Room room)
ref SCR_ScriptPlatformRequestCallback m_CallbackGetPrivilege
void OnRoomEntrySetFavorite(SCR_ListMenuEntryComponent entry, bool favorite)
Favoriting server.
void OnPasswordVerified()
On successfull room password verification continue to cotent handling.
void OnServerEntryFocusLeave(SCR_ScriptedWidgetComponent entry)
void JoinActions_DirectJoin(string params, EDirectJoinFormats format, bool publicNetwork)
override void OnMenuOpened()
SCR_MenuActionsComponent m_ActionsComponent
void CallOnServerListSetPage(int page)
void OnRoomSetFavoriteError(SCR_RoomCallback callback)
void SetupParams(ClientLobbyApi lobby)
Restore filtering parameters in UI.
ref BackendCallback m_CallbackQueue
void OnRejoinAuthorizationFailed(string message)
ref BackendCallback m_CallbackSearchPreviousRoom
void JoinProcess_Clear()
Call this to kill joining process at any stage.
void OnRejoinCancel()
Call this on rejoin dialog cancel.
static void TryOpenServerBrowser()
ref array< ref SCR_WorkshopItemActionDownload > m_aUnrelatedDownloads
void OnLoadingScenario(Room room)
void OnServerEntryClick(notnull SCR_ServerBrowserEntryComponent entry)
Join to the room on double click on server entry.
ref SCR_ServerBrowserDialogManager m_Dialogs
void OnChangeFilter(SCR_FilterEntry filter)
void OnCrossPlayPrivilegeResult(UserPrivilege privilege, UserPrivilegeResult result)
SCR_PooledServerListComponent m_ScrollableList
void SetupCallbacks()
General callbacks setup.
override void OnMenuOpen()
Opening menu - do server browser setup - TODO@wernerjak - cleanup open.
ref BackendCallback m_CallbackJoin
void JoinProcess_PrepareFinalJoinRequest(Room roomToJoin)
void OnFilterPanelToggle(bool show)
ref SCR_RoomPasswordVerification m_PasswordVerification
void OnLoadingDependencyList(Room room)
Call this when mods list is received.
void ReceiveRoomContent(notnull Room room, bool receiveMods)
void JoinProcess_OnFindRoomFail()
Call this if room wasn't found because of error or time out.
void OnChangeSort(SCR_SortHeaderComponent sortHeader)
Set focus to last filtering element.
ref BackendCallback m_CallbackLastSearch
void OnMPPrivilegeResult(UserPrivilege privilege, UserPrivilegeResult result)
static void TryOpenServerBrowserWithScenarioFilter(MissionWorkshopItem mission)
void JoinProcess_OnFindRoomSuccess()
Call this when room is found.
ref ScriptInvokerVoid m_OnFavoritesResponse
SCR_ServerBrowserEntryComponent GetEntryUnderCursor()
void OnOpeningByLoadComponent(int menuPreset)
void OnSearchRoomsSuccess(BackendCallback callback)
void OnServerListSetPage(int page)
Call this actions when server list page is changed.
ref array< Room > m_aRooms
ref RoomJoinData m_JoinData
void JoinProcess_CheckRunningDownloads()
Final step: display a warning dialog if there are still downloads running, as these will be stopped (...
void JoinProcess_Init(Room roomToJoin)
Initialize joining process to specific room.
ref ServerBrowserMenuWidgets m_Widgets
void OnLastRoomReconnectConfirm()
Confirm action to find new server.
void JoinProcess_OnFindRoomByIdResponse(BackendCallback callback)
Reaction for rooms found by id response success.
static ref SCR_ScriptPlatformRequestCallback m_CallbackGetMPPrivilege
void ConnectionTimeout()
Fail wating for backend if takes too long.
void OnActionTriggered(string action, float multiplier)
SCR_FilterPanelComponent m_FilterPanel
void OnTabViewSwitch(SCR_TabViewComponent tabView, Widget w, int id)
Set tab filters on switching tab view.
void OnPasswordFailVerification(string message)
On room password verication fail restart attemp.
ref FilteredServerParams m_DirectJoinParams
void OnModListFailDialogClose(SCR_ConfigurableDialogUi dialog)
void OnRoomsFound(array< Room > rooms=null)
void OnDependenciesLoadingPrevented(array< ref SCR_WorkshopItem > dependencies)
void JoinProcess_FindRoomById(string id, BackendCallback callback)
Specific call for id search.
void JoinProcess_OnJoinFail(BackendCallback callback)
ref BackendCallback m_CallbackAutoRefresh
void JoinProcess_FindRoom(string params, EDirectJoinFormats format, bool publicNetwork)
Initialize joining process to specific room.
void DisplayFavoriteAction(bool isFavorite)
Based on given boolean favorite nav button is displaying eather add or remove favorite.
SCR_TabViewComponent m_TabView
ref SCR_GetRoomsIds m_SearchIds
void FilterHostedScenarioModId(string scenarioModId)
static bool IsServerPingAboveThreshold(Room room)
override void OnMenuClose()
Closing menu - clearing server browser data.
ref array< ref SCR_WorkshopItem > m_aRequiredMods
void OnActionFavorite()
Action for favoriting server.
void SetFilteredScenario(MissionWorkshopItem scenario)
void OnRoomSetFavoriteResponse(SCR_RoomCallback callback)
void OnEntryMouseButton(string tag)
void JoinProcess_CheckRoomPasswordProtected()
Check if room requires password to join.
void Platform_OnUgcPrivilegeResult(bool result)
void FocusWidget(Widget w)
Separated focus function for later call.
EInputDeviceType m_eLastInputType
ref array< Room > m_aDirectFoundRooms
SCR_SimpleMessageComponent m_SimpleMessageList
void OnEntryMouseClick(SCR_ScriptedWidgetComponent button)
void OnSearchRoomsFail(BackendCallback callback)
ref BackendCallback m_CallbackScroll
void OnActionRefresh()
Bind action for refreshing server list.
ref SCR_RoomModsManager m_ModsManager
void JoinProcess_CheckUnrelatedDownloads()
Display a warning dialog if there are unrelated downloads running, as these will be stopped.
SCR_ServerBrowserEntryComponent m_ClickedEntry
void OnServerEntryClickInteraction(float multiplier)
void JoinProcess_CheckHighPing()
Display a warning dialog if the player chose to join a server with high ping.
void Messages_ShowMessage(string messageTag, bool showWrap=false)
override void OnMenuUpdate(float tDelta)
Updating menu - continuous menu hanling.
void JoinProcess_OnCheckedBlockedPlayersInRoom(Room checkedRoom, array< BlockedRoomPlayer > blockedPlayers)
void OnScrollSuccess(BackendCallback callback)
bool ClientRoomVersionMatch(Room room)
void OnServerEntryDoubleClick(SCR_ServerBrowserEntryComponent entry)
Join to the room on double click on server entry.
void OnActionDetails()
Action for server details.
static void ServerBrowserOnPrivilegeResult(UserPrivilege privilege, UserPrivilegeResult result)
void OnRoomAutoRefresh(BackendCallback callback)
Call this once new room data are fetched.
void JoinProcess_OnQueueJoinFail(BackendCallback callback)
SCR_EListMenuWidgetFocus m_eFocusedWidgetState
void SetupFilteringUI(FilteredServerParams filterParams)
Apply filter setup on each ui filtering widget - restoring filter UI states.
ref BackendCallback m_CallbackSearchTarget
override void OnMenuFocusGained()
void JoinProcess_StopDownloadingUnrelatedMods()
void ReceiveRoomContent_Mods(Room room)
void JoinActions_Join()
Action for joining to selected server.
ref SCR_RoomCallback m_CallbackFavorite
void Messages_Hide()
Hide both message widgets.
static MissionWorkshopItem m_MissionToFilter
void PrintDebug(string msg, string functionName=string.Empty)
Custom debug print displayed with -scrDefine=SB_DEBUG argument.
void SetupHandlers()
Getting reference for all server widget elements.
void SetMenuHeader(string header)
void OnSearchEditBoxConfirm(SCR_EditBoxComponent editBox, string sInput)
Fetch new servers on confirming search string.
SCR_ServerBrowserEntryComponent m_SelectedServerEntry
void OnServerDetailsClosed(SCR_ConfigurableDialogUi dialog)
SCR_SimpleMessageComponent m_SimpleMessageWrap
static void OpenWithScenarioFilter(MissionWorkshopItem mission)
Set to find server by mission workshop item.
void OnServerDetailModsLoaded(Room room)
Call this to fill details mods list.
void OnScrollError(BackendCallback callback)
Call this when scroll returns error server response.
SCR_ServerScenarioDetailsPanelComponent m_ServerScenarioDetails
void JoinProcess_DisplayUnrelatedDownloadsWarning()
ref FilteredServerParams m_ParamsFilter
void SetupJoinDialogs()
Open joining dialog in default state.
void JoinProcess_OnJoinSuccess(BackendCallback callback)
void DisplayRooms(array< Room > rooms=null)
Workshop Api instance.
Definition WorkshopApi.c:14
Workshop Item instance.
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
@ GENERIC
Default entity type (inherited from GenericEntity).
@ ALL
Everything except general switch.
Definition EntityEvent.c:37
EApiCode
Definition EApiCode.c:13
ERestResult
States and result + error code produced by RestApi.
Definition ERestResult.c:14
void MenuBindAttribute(string menuItemName="")
Definition menuManager.c:34