Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
ServerBrowserMenuUI.c
Go to the documentation of this file.
1 /*
2 Main class for server browser menu handling
3 Handles cooperation of varios components for server searching, joning, mods handling, etc.
4 */
5 
6 void ScriptInvokerRoomMethod(Room room);
8 typedef 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_bWaitForRefresh;
27  protected bool m_bHostedServers;
28 
29  // Widget class reference
30  protected ref ServerBrowserMenuWidgets m_Widgets = new ServerBrowserMenuWidgets();
31 
32  // Server list handling
33  protected SCR_ServerBrowserEntryComponent m_ServerEntry;
34 
35  // Widget handlers
36  protected SCR_TabViewComponent m_TabView;
37  protected SCR_SortHeaderComponent m_SortBar;
38  protected SCR_EditBoxComponent m_SearchEditBox;
39  protected SCR_FilterPanelComponent m_FilterPanel;
40  protected SCR_PooledServerListComponent m_ScrollableList;
41  protected SCR_ServerScenarioDetailsPanelComponent m_ServerScenarioDetails;
42  protected SCR_CoreMenuHeaderComponent m_MenuHeader;
43 
44  // States
45  protected Widget m_wFirstServerEntry;
46  protected SCR_EListMenuWidgetFocus m_iFocusedWidgetState = SCR_EListMenuWidgetFocus.LIST;
47 
48  // Skip the details dialog on double click
49  protected bool m_bQuickJoin = true;
50 
51  // Lobby Rooms handling
52  protected Room m_RoomToJoin;
53  protected ref array<Room> m_aRooms = {};
54  protected ref array<Room> m_aDirectFoundRooms = {};
55 
56  protected WorkshopApi m_WorkshopApi;
57  protected ClientLobbyApi m_Lobby;
58  protected SCR_ConfigurableDialogUi m_ModListFailDialog;
59 
60  // Privileges
61  protected ref SCR_ScriptPlatformRequestCallback m_CallbackGetPrivilege;
62 
63  // Search callbacks
64  protected ref ServerBrowserCallback m_CallbackLastSearch;
65  protected ref SCR_BackendCallback m_CallbackScroll = new SCR_BackendCallback();
66  protected ref SCR_RoomCallback m_CallbackFavorite = new SCR_RoomCallback();
67 
68  protected ref OnDirectJoinCallback m_CallbackSearchTarget = new OnDirectJoinCallback();
69 
70  // Room data refresh
71  protected ref ServerBrowserCallback m_CallbackAutoRefresh = new ServerBrowserCallback();
72  protected bool m_bFirstRoomLoad = true;
73  protected bool m_bForceUnfilteredRequest;
74  protected int m_iTotalNumberOfRooms;
75 
76  // Joining
77  protected ref ServerBrowserCallback m_CallbackJoin = new ServerBrowserCallback();
78  protected ref SCR_ServerBrowserDialogManager m_Dialogs = new SCR_ServerBrowserDialogManager();
79 
80  protected ref RoomJoinData m_JoinData = new RoomJoinData();
81  protected ref SCR_RoomPasswordVerification m_PasswordVerification = new SCR_RoomPasswordVerification();
82 
83  // Filter parameters
84  protected ref FilteredServerParams m_ParamsFilter = new FilteredServerParams();
85  protected ref FilteredServerParams m_DirectJoinParams;
86 
87  // Server mod content
88  protected ref SCR_RoomModsManager m_ModsManager = new SCR_RoomModsManager();
89  protected ref array<ref SCR_WorkshopItem> m_aRequiredMods = {};
90  protected ref array<ref SCR_WorkshopItemActionDownload> m_aUnrelatedDownloads = {};
91  protected SCR_DownloadManager m_DownloadManager;
92 
93  // Dependencies arrays for pasing updated & outdated server mod dependecies
94  protected MissionWorkshopItem m_RoomScenario;
95 
96  // Message components
97  protected SCR_SimpleMessageComponent m_SimpleMessageWrap;
98  protected SCR_SimpleMessageComponent m_SimpleMessageList;
99 
100  protected bool m_bIsWaitingForBackend = true;
101 
102  // Reconnecting to last played server
103  protected ref ServerBrowserCallback m_CallbackSearchPreviousRoom = new ServerBrowserCallback();
104  protected ref SCR_GetRoomsIds m_SearchIds = new SCR_GetRoomsIds();
105  protected Room m_RejoinRoom;
106 
107  protected ref array<ref SCR_FilterEntry> m_aFiltersToSelect = {};
108  protected bool m_bIsCheckingSpecificfilter;
109 
110  // Script invokers
111  ref ScriptInvoker m_OnAutoRefresh = new ScriptInvoker();
112  ref ScriptInvoker m_OnScenarioLoad = new ScriptInvoker();
113 
114  protected ref ScriptInvokerVoid m_OnFavoritesResponse = new ScriptInvokerVoid();
115 
116  // Entry Actions
117  protected EInputDeviceType m_eLastInputType;
118  protected bool m_bWasEntrySelected;
119  protected SCR_ServerBrowserEntryComponent m_ClickedEntry; // Cache last clicked entry to trigger the correct dialog after the double click window
120  protected SCR_MenuActionsComponent m_ActionsComponent;
121 
122  //------------------------------------------------------------------------------------------------
123  // OVERRIDES
124  //------------------------------------------------------------------------------------------------
125  //------------------------------------------------------------------------------------------------
127  override void OnMenuOpen()
128  {
129  // Workshop setup
130  m_WorkshopApi = GetGame().GetBackendApi().GetWorkshop();
131  m_Lobby = GetGame().GetBackendApi().GetClientLobby();
132 
133  // Items preloading
134  if (m_WorkshopApi.NeedScan())
135  m_WorkshopApi.ScanOfflineItems();
136 
137  // Find widgets
138  m_Widgets.FindAllWidgets(GetRootWidget());
139 
140  // Accessing handlers
141  SetupHandlers();
142  SetupCallbacks();
143  m_CallbackAutoRefresh.m_OnSuccess.Insert(OnRoomAutoRefresh);
144 
145  SetupParams(m_Lobby);
146 
147  // Setup list and message
148  if (SCR_ServicesStatusHelper.IsBackendReady())
149  Messages_ShowMessage(TAG_MESSAGE_SEARCHING);
150  else
151  Messages_ShowMessage(TAG_MESSAGE_CONNECTING, true);
152 
153  if (m_ScrollableList)
154  m_ScrollableList.ShowEmptyRooms();
155 
156  // Setup Actions
157  m_ActionsComponent = SCR_MenuActionsComponent.FindComponent(GetRootWidget());
158  if (m_ActionsComponent)
159  m_ActionsComponent.GetOnAction().Insert(OnActionTriggered);
160 
161  UpdateNavigationButtons();
162 
163  SwitchFocus(SCR_EListMenuWidgetFocus.SORTING);
164 
165  super.OnMenuOpen();
166  }
167 
168  //------------------------------------------------------------------------------------------------
169  override void OnMenuOpened()
170  {
171  // Kick errors
172  SCR_KickDialogs.SetReconnectEnabled(true);
173  SCR_KickDialogs.GetOnReconnect().Insert(OnLastRoomReconnectConfirm);
174  SCR_KickDialogs.GetOnCancel().Insert(OnRejoinCancel);
175 
176  super.OnMenuOpened();
177 
178  Refresh();
179  }
180 
181  //------------------------------------------------------------------------------------------------
182  override void OnMenuFocusGained()
183  {
184  // Focus back on the host button
185  if (m_bHostedServers)
186  GetGame().GetCallqueue().CallLater(FocusWidget, 0, false, m_Widgets.m_wHostNewServerButton);
187  else
188  SwitchFocus(SCR_EListMenuWidgetFocus.LIST, true);
189 
190  super.OnMenuFocusGained();
191 
192  if (m_ActionsComponent)
193  m_ActionsComponent.ActivateActions();
194  }
195 
196  //------------------------------------------------------------------------------------------------
198  override void OnMenuClose()
199  {
200  // Kick errors
201  SCR_KickDialogs.SetReconnectEnabled(false);
202  SCR_KickDialogs.GetOnReconnect().Remove(OnLastRoomReconnectConfirm);
203  SCR_KickDialogs.GetOnCancel().Remove(OnRejoinCancel);
204 
205  ClearScenarioFilters();
206 
207  // Clearing handlers
208  if (m_TabView)
209  m_TabView.GetOnChanged().Remove(OnTabViewSwitch);
210 
211  // Store filter parameters
212  m_Lobby.StoreParams();
213 
214  // Remove callbacks
215  m_Lobby.SetRefreshCallback(null);
216 
217  m_ScrollableList.GetOnSetPage().Remove(CallOnServerListSetPage);
218  m_CallbackAutoRefresh.m_OnSuccess.Clear();
219 
220  ClearConnectionTimeoutWaiting();
221 
222  // Save filter
223  m_FilterPanel.Save();
224 
225  super.OnMenuClose();
226  }
227 
228  //------------------------------------------------------------------------------------------------
230  override protected void OnMenuUpdate(float tDelta)
231  {
232  super.OnMenuUpdate(tDelta);
233 
234  // Run actions after backend initialization
235  if (m_bIsWaitingForBackend)
236  WaitingForRunningBackend();
237 
238  // Scroll list update
239  if (m_ScrollableList)
240  m_ScrollableList.UpdateScroll();
241 
243  EInputDeviceType inputDeviceType = GetGame().GetInputManager().GetLastUsedInputDevice();
244  bool isEntrySelected = GetSelectedEntry();
245  bool shouldUpdateButtons = inputDeviceType != m_eLastInputType || isEntrySelected != m_bWasEntrySelected;
246 
247  if (shouldUpdateButtons)
248  UpdateNavigationButtons();
249 
250  m_eLastInputType = inputDeviceType;
251  m_bWasEntrySelected = isEntrySelected;
252  }
253 
254  //------------------------------------------------------------------------------------------------
255  override void OnMenuShow()
256  {
257  super.OnMenuShow();
258 
259  if (m_ActionsComponent)
260  m_ActionsComponent.ActivateActions();
261  }
262 
263  //------------------------------------------------------------------------------------------------
264  // INPUTS
265  //------------------------------------------------------------------------------------------------
266  //------------------------------------------------------------------------------------------------
267  protected void UpdateNavigationButtons()
268  {
269  if (!m_Widgets)
270  return;
271 
272  SCR_ServerBrowserEntryComponent entry = GetSelectedEntry();
273  bool versionMismatch, unjoinable;
274  bool enabled = entry && entry.GetIsEnabled(versionMismatch, unjoinable);
275  bool visible = entry && GetGame().GetInputManager().GetLastUsedInputDevice() != EInputDeviceType.MOUSE;
276 
277  if (m_Widgets.m_JoinButton)
278  m_Widgets.m_JoinButton.SetVisible(visible && !unjoinable, false);
279 
280  if (m_Widgets.m_DetailsButton)
281  m_Widgets.m_DetailsButton.SetVisible(visible && !unjoinable, false);
282 
283  if (m_Widgets.m_FavoritesButton)
284  m_Widgets.m_FavoritesButton.SetVisible(visible && enabled, false);
285 
286  if (!enabled || !visible)
287  return;
288 
289  Room room = entry.GetRoomInfo();
290  if (!room)
291  return;
292 
293  if (m_Widgets.m_FavoritesButton)
294  m_Widgets.m_FavoritesButton.SetLabel(GetFavoriteLabel(room.IsFavorite()));
295  }
296 
297  //------------------------------------------------------------------------------------------------
298  protected void OnActionTriggered(string action, float multiplier)
299  {
301 
303  if (GetGame().GetInputManager().GetLastUsedInputDevice() != EInputDeviceType.MOUSE)
304  return;
305 
306  switch (action)
307  {
308  case "MenuSelectDouble": OnServerEntryClickInteraction(multiplier); break;
309  case "MenuServerDetails": OnActionDetails(); break;
310  case "MenuFavourite": OnActionFavorite(); break;
311  }
312  }
313 
314  //------------------------------------------------------------------------------------------------
316  [MenuBindAttribute()]
317  void OnActionRefresh()
318  {
319  m_bForceUnfilteredRequest = true;
320  Refresh();
321  }
322 
323  //------------------------------------------------------------------------------------------------
324  void Refresh()
325  {
326  PrintDebug("m_RejoinRoom: " + m_RejoinRoom, "OnActionRefresh");
327 
328  // Try negotiate missing MP privilege
329  if (!GetGame().GetPlatformService().GetPrivilege(UserPrivilege.MULTIPLAYER_GAMEPLAY))
330  {
331  Messages_ShowMessage("MISSING_PRIVILEGE_MP");
332  //NegotiateMPPrivilegeAsync();
333  NegotiatePrivilegeAsync(UserPrivilege.MULTIPLAYER_GAMEPLAY);
334  return;
335  }
336 
337  // Clear list
338  //m_CallbackScroll.m_OnSuccess.Remove(OnScrollSuccess);
339  m_CallbackScroll.GetEventOnResponse().Remove(OnScrollResponse);
340 
341  // Setup list loading
342  if (m_ScrollableList)
343  {
344  m_ScrollableList.MoveToTop();
345  m_ScrollableList.ShowEmptyRooms();
346  m_ScrollableList.ShowScrollbar(false);
347  }
348 
349  CheckBackendState();
350 
351  // Remove callbacks
352  m_Lobby.SetRefreshCallback(null);
353 
354  // Start loading
355  if (m_bFirstRoomLoad)
356  SearchRooms();
357  else
358  GetGame().GetCallqueue().CallLater(SearchRooms, ROOM_CONTENT_LOAD_DELAY, false);
359 
360  if (SCR_ServicesStatusHelper.IsBackendReady())
361  Messages_ShowMessage(TAG_MESSAGE_SEARCHING);
362  else
363  Messages_ShowMessage(TAG_MESSAGE_CONNECTING, true);
364 
365  if (m_ServerScenarioDetails)
366  m_ServerScenarioDetails.SetDefaultScenario(TAG_DETAILS_FALLBACK_SEACHING);
367  }
368 
369  //------------------------------------------------------------------------------------------------
371  [MenuBindAttribute()]
372  void OnActionManualConnect()
373  {
374  MultiplayerDialogUI multiplayerDialog = m_Dialogs.CreateManualJoinDialog();
375 
376  if (!multiplayerDialog)
377  return;
378 
379  // Ip handling
380  multiplayerDialog.m_OnConfirm.Clear();
381  multiplayerDialog.m_OnConfirm.Insert(JoinActions_DirectJoin);
382 
383  // Cancel
384  multiplayerDialog.m_OnCancel.Clear();
385  multiplayerDialog.m_OnCancel.Insert(OnDirectJoinCancel);
386  }
387 
388  //------------------------------------------------------------------------------------------------
390  [MenuBindAttribute()]
391  void OnActionFilter()
392  {
393  if (!m_FilterPanel)
394  return;
395 
396  SCR_EListMenuWidgetFocus focus = SCR_EListMenuWidgetFocus.FILTERING;
397  if (m_FilterPanel.GetFilterListBoxShown())
398  focus = SCR_EListMenuWidgetFocus.LIST;
399 
400  // Set focus
401  m_FilterPanel.ShowFilterListBox(focus == SCR_EListMenuWidgetFocus.FILTERING);
402  SwitchFocus(focus);
403  }
404 
405  //------------------------------------------------------------------------------------------------
407  [MenuBindAttribute()]
408  void OnActionBack()
409  {
410  Close();
411  }
412 
413  //------------------------------------------------------------------------------------------------
415  void OnActionFavorite()
416  {
417  if (!m_ServerEntry)
418  {
419  Debug.Error("No entry selected.");
420  return;
421  }
422  m_ServerEntry.SetFavorite(!m_ServerEntry.IsFavorite());
423  }
424 
425  //------------------------------------------------------------------------------------------------
427  void OnActionDetails()
428  {
429  SCR_ServerBrowserEntryComponent entry = GetSelectedEntry();
430  if (!entry)
431  return;
432 
433  m_bQuickJoin = false;
434 
435  // Join
436  Room room = entry.GetRoomInfo();
437  if (room && room.Joinable())
438  JoinActions_Join();
439  }
440 
441  //------------------------------------------------------------------------------------------------
442  protected void OnServerEntryClickInteraction(float multiplier)
443  {
445 
446  SCR_ServerBrowserEntryComponent entry = m_ClickedEntry;
447  if (!entry || !GetEntryUnderCursor())
448  return;
449 
450  switch (Math.Floor(multiplier))
451  {
452  case 1: OnServerEntryClick(entry); break;
453  case 2: OnServerEntryDoubleClick(entry); break;
454  }
455 
456  m_ClickedEntry = null;
457  }
458 
459  //------------------------------------------------------------------------------------------------
461  protected void OnServerEntryDoubleClick(SCR_ServerBrowserEntryComponent entry)
462  {
463  if (entry != m_ServerEntry)
464  OnServerEntryFocusEnter(entry);
465 
466  m_bQuickJoin = true;
467 
468  // Join
469  if (entry && entry.GetRoomInfo() && entry.GetRoomInfo().Joinable())
470  JoinActions_Join();
471  }
472 
473  //------------------------------------------------------------------------------------------------
474  protected void OnEntryMouseButton(string tag)
475  {
476  OnServerEntryDoubleClick(GetSelectedEntry());
477  }
478 
479  //------------------------------------------------------------------------------------------------
480  protected void OnJoinButton()
481  {
482  OnServerEntryClick(GetSelectedEntry());
483  }
484 
485  //------------------------------------------------------------------------------------------------
487  protected void OnServerEntryClick(notnull SCR_ServerBrowserEntryComponent entry)
488  {
491  if (entry != m_ServerEntry)
492  OnServerEntryFocusEnter(entry);
493 
494  m_RoomToJoin = entry.GetRoomInfo();
495 
497  m_bQuickJoin = GetGame().GetInputManager().GetLastUsedInputDevice() != EInputDeviceType.MOUSE;
498 
499  // Join
500  if (entry.GetRoomInfo() && entry.GetRoomInfo().Joinable())
501  JoinActions_Join();
502 
503  //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
504  }
505 
506  //------------------------------------------------------------------------------------------------
507  // Service check
508  //------------------------------------------------------------------------------------------------
509  //------------------------------------------------------------------------------------------------
511  protected void WaitingForRunningBackend()
512  {
513  if (!IsBackendReady())
514  return;
515 
516  // Call room search or find last server
517  string lastId = m_Lobby.GetPreviousRoomId();
518 
519  if (!m_Lobby.IsPingAvailable())
520  return;
521 
522  ClearConnectionTimeoutWaiting();
523  Refresh();
524 
525  // Clear error msg
526  SCR_KickDialogs.Clear();
527 
528  // Stop waiting for backend
529  m_bIsWaitingForBackend = false;
530  }
531 
532  //------------------------------------------------------------------------------------------------
533  protected bool IsBackendReady()
534  {
535  auto ba = GetGame().GetBackendApi();
536  return ba.IsActive() && ba.IsAuthenticated();
537  }
538 
539  //------------------------------------------------------------------------------------------------
540  protected void CheckBackendState()
541  {
542  if (!IsBackendReady())
543  {
544  m_bIsWaitingForBackend = true;
545  GetGame().GetCallqueue().Remove(ConnectionTimeout);
546  GetGame().GetCallqueue().CallLater(ConnectionTimeout, SCR_ServicesStatusHelper.CONNECTION_CHECK_EXPIRE_TIME);
547  }
548  }
549 
550  //------------------------------------------------------------------------------------------------
551  protected void ShowTimeoutDialog()
552  {
553  Messages_ShowMessage("NO_CONNECTION");
554  if (m_Dialogs)
555  {
556  m_Dialogs.DisplayDialog(EJoinDialogState.BACKEND_TIMEOUT);
557  m_Dialogs.GetOnConfirm().Clear();
558  m_Dialogs.GetOnConfirm().Insert(OnConnectionTimeoutDialogConfirm);
559  }
560  }
561  //------------------------------------------------------------------------------------------------
563  protected void ConnectionTimeout()
564  {
565  if (!IsBackendReady())
566  {
567  ShowTimeoutDialog();
568  }
569  ClearConnectionTimeoutWaiting();
570 
571  m_bIsWaitingForBackend = false;
572  }
573 
574  //------------------------------------------------------------------------------------------------
575  protected void OnConnectionTimeoutDialogConfirm()
576  {
577  m_Dialogs.GetOnConfirm().Remove(OnConnectionTimeoutDialogConfirm);
578 
579  if (SCR_ServicesStatusHelper.IsBackendReady())
580  Messages_ShowMessage(TAG_MESSAGE_SEARCHING);
581  else
582  Messages_ShowMessage(TAG_MESSAGE_CONNECTING, true);
583  }
584 
585  //------------------------------------------------------------------------------------------------
586  protected void ClearConnectionTimeoutWaiting()
587  {
588  GetGame().GetCallqueue().Remove(ConnectionTimeout);
589  }
590 
591  //------------------------------------------------------------------------------------------------
594  protected void OnRoomsFound(array<Room> rooms = null)
595  {
596  // Load rooms
597  ClientLobbyApi lobby = GetGame().GetBackendApi().GetClientLobby();
598 
599  if (rooms)
600  {
601  // Direct join rooms
602  lobby.Target(rooms);
603  }
604  else
605  {
606  // Room from search
607  lobby.Rooms(m_aRooms);
608  //TODO: [BUG] On trunk, switching to Community Tab returns an empty rooms array even if there are rooms?!
609 
610  if (m_aRooms.IsEmpty())
611  {
612  PrintDebug("No room found", "OnRoomsFound");
613  }
614  }
615 
616  // Setup room data refresh
617  lobby.SetRefreshCallback(m_CallbackAutoRefresh);
618  lobby.SetRefreshRate(ROOM_REFRESH_RATE);
619 
620  DisplayRooms(m_aRooms);
621 
622  // Move to top in list
623  if (m_ScrollableList)
624  {
625  if (m_ScrollableList.IsListFocused() || m_bFirstRoomLoad)
626  {
627  m_ScrollableList.FocusFirstAvailableEntry();
628  }
629  }
630 
631  if (m_bFirstRoomLoad)
632  {
633  m_ScrollableList.SetIsListFocused(true);
634  m_bFirstRoomLoad = false;
635  }
636 
637  m_ScrollableList.ShowScrollbar(true);
638 
639  int currentRoomsCount = m_Lobby.TotalRoomCount();
640  if (currentRoomsCount > m_iTotalNumberOfRooms)
641  m_iTotalNumberOfRooms = currentRoomsCount;
642 
643  // Items Found Message
644  if (m_FilterPanel)
645  m_FilterPanel.SetItemsFoundMessage(m_Lobby.TotalRoomCount(), m_iTotalNumberOfRooms, m_Lobby.TotalRoomCount() != m_iTotalNumberOfRooms);
646  }
647 
648  //------------------------------------------------------------------------------------------------
649  protected void DisplayRooms(array<Room> rooms = null)
650  {
651  // Don't display if missing MP privilege
652  if (!GetGame().GetPlatformService().GetPrivilege(UserPrivilege.MULTIPLAYER_GAMEPLAY))
653  {
654  return;
655  }
656 
657  // Check list
658  if (!m_ScrollableList || !m_ServerScenarioDetails)
659  {
660  PrintDebug("Missing important component references!", "DisplayRooms");
661  return;
662  }
663 
664  // Check addons
665  SCR_AddonManager addonMgr = SCR_AddonManager.GetInstance();
666 
667  if (!addonMgr)
668  {
669  PrintDebug("Could not find addon mngr to verify ugc privilege", "DisplayRooms");
670  return;
671  }
672 
673  // Modds filter when UGC not enabled
674  if (m_ParamsFilter.IsModdedFilterSelected() && !addonMgr.GetUgcPrivilege())
675  {
676  Messages_ShowMessage("MISSING_PRIVILEGE_UGC");
677 
678  // Negotatiate UGC privilege
679  addonMgr.m_OnUgcPrivilegeResult.Insert(Platform_OnUgcPrivilegeResult);
680  addonMgr.NegotiateUgcPrivilegeAsync();
681 
682  SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
683  if (m_FilterPanel)
684  m_FilterPanel.ShowFilterListBox(false);
685 
686  return;
687  }
688 
689  int roomCount = m_Lobby.TotalRoomCount();
690 
691  // Display no rooms found
692  if (roomCount == 0)
693  {
694  // Setup list
695  m_ScrollableList.SetRooms(rooms, 0, true);
696  m_ScrollableList.ShowEmptyRooms();
697 
698  if (m_ServerScenarioDetails)
699  m_ServerScenarioDetails.SetDefaultScenario(TAG_DETAILS_FALLBACK_EMPTY);
700 
701  // Show filters
702  if (!m_FilterPanel.GetFilterListBoxShown())
703  SwitchFocus(SCR_EListMenuWidgetFocus.FILTERING);
704  if (m_FilterPanel)
705  m_FilterPanel.ShowFilterListBox(true);
706 
707  // Show message
708  Messages_ShowMessage("NO_FILTERED_SERVERS");
709 
710  return;
711  }
712 
713  // Display rooms
714  // Set rooms to fill server list
715  m_ScrollableList.SetRooms(m_aRooms, m_Lobby.TotalRoomCount(), true);
716 
717  // Hide message
718  Messages_Hide();
719 
720  if (m_FilterPanel && !m_FilterPanel.GetFilterListBoxShown())
721  SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
722  }
723 
724  //------------------------------------------------------------------------------------------------
725  // LOBBY ROOMS HANDLING
726  //------------------------------------------------------------------------------------------------
727  //------------------------------------------------------------------------------------------------
729  protected void OnRoomAutoRefresh(ServerBrowserCallback callback)
730  {
731  m_Lobby.SetRefreshRate(ROOM_REFRESH_RATE);
732  DisplayRooms(m_aRooms);
733 
734  m_bWaitForRefresh = false;
735 
736  m_OnAutoRefresh.Invoke();
737  }
738 
739  // ---- SEARCH ROOMS ----
740  // First search to get the total number of servers
741  //------------------------------------------------------------------------------------------------
742  protected void SearchRooms()
743  {
744  //TODO: query for filtered first, then independently query for total number, in order to reduce load time at start
745 
746  // Start loading and show loading feedback
747  m_ServerEntry = null;
748  m_ModsManager.Clear();
749 
750  // Remove callbacks
751  m_Lobby.SetRefreshCallback(null);
752 
753  if (!m_bFirstRoomLoad && !m_bForceUnfilteredRequest)
754  {
755  SearchRoomsFiltered();
756  return;
757  }
758 
759  // Callback
760  ref ServerBrowserCallback searchCallback = new ServerBrowserCallback;
761 
762  // Invoker actions
763  searchCallback.m_OnSuccess.Insert(OnSearchAllRoomsSuccess);
764  searchCallback.m_OnFail.Insert(OnSearchAllRoomsFail);
765  searchCallback.m_OnTimeOut.Insert(OnSearchAllRoomsTimeOut);
766 
767  m_CallbackLastSearch = searchCallback;
768 
770  m_Lobby.SearchRooms(params, searchCallback);
771  }
772 
773  //------------------------------------------------------------------------------------------------
774  protected void OnSearchAllRoomsSuccess(ServerBrowserCallback callback)
775  {
776  OnSearchAllRooms();
777  }
778 
779  //------------------------------------------------------------------------------------------------
780  protected void OnSearchAllRoomsFail(ServerBrowserCallback callback, int code, int restCode, int apiCode)
781  {
782  OnSearchAllRooms();
783  }
784 
785  //------------------------------------------------------------------------------------------------
786  protected void OnSearchAllRoomsTimeOut()
787  {
788  OnSearchAllRooms();
789  }
790 
791  //------------------------------------------------------------------------------------------------
792  protected void OnSearchAllRooms()
793  {
794  m_CallbackLastSearch = null;
795 
796  // Total number of active servers
797  m_iTotalNumberOfRooms = m_Lobby.TotalRoomCount();
798 
799  SearchRoomsFiltered();
800  }
801 
802  // Searches to get the filtered servers to display
803  //------------------------------------------------------------------------------------------------
804  protected void SearchRoomsFiltered()
805  {
806  if (m_ScrollableList)
807  m_Lobby.SetViewSize(m_ScrollableList.GetPageEntriesCount() * 2);
808  else
809  m_Lobby.SetViewSize(SERVER_LIST_VIEW_SIZE);
810 
811  // Callback
812  ref ServerBrowserCallback searchCallback = new ServerBrowserCallback;
813 
814  // Invoker actions
815  searchCallback.m_OnSuccess.Insert(OnSearchRoomsSuccess);
816  searchCallback.m_OnFail.Insert(OnSearchRoomsFail);
817  searchCallback.m_OnTimeOut.Insert(OnSearchRoomsTimeOut);
818 
819  m_CallbackLastSearch = searchCallback;
820 
821  m_Lobby.SearchRooms(m_ParamsFilter, searchCallback);
822  }
823 
824  //------------------------------------------------------------------------------------------------
825  protected void OnSearchRoomsSuccess(ServerBrowserCallback callback)
826  {
827  PrintDebug(string.Format("Success - servers found: %1", m_Lobby.TotalRoomCount()), "OnSearchRoomsSuccess");
828 
829  // Display rooms
830  OnRoomsFound();
831  m_CallbackLastSearch = null;
832 
833  PrintDebug("AFTER - m_RejoinRoom: " + m_RejoinRoom, "OnSearchRoomsSuccess");
834  }
835 
836  //------------------------------------------------------------------------------------------------
837  protected void OnSearchRoomsFail(ServerBrowserCallback callback, int code, int restCode, int apiCode)
838  {
839  PrintDebug(string.Format("Room search fail - code: %1 | restCode: %2 | apiCode: %3", code, restCode, apiCode), "OnSearchRoomsFail");
840  m_CallbackLastSearch = null;
841 
842  // Run again if failed ping
843  if (m_bFirstRoomLoad && m_ParamsFilter.GetSortOrder() == m_ParamsFilter.SORT_PING)
844  {
845  Refresh();
846  return;
847  }
848 
849  Messages_ShowMessage("BACKEND_SERVICE_FAIL");
850  }
851 
852  //------------------------------------------------------------------------------------------------
853  protected void OnSearchRoomsTimeOut()
854  {
855  ShowTimeoutDialog();
856  PrintDebug("time out!", "OnSearchRoomsTimeOut");
857  }
858 
859  //------------------------------------------------------------------------------------------------
861  protected void SetupParams(ClientLobbyApi lobby)
862  {
863  FilteredServerParams params = FilteredServerParams.Cast(lobby.GetParameters());
864  if (!params)
865  {
866  // Default filter setup
867  string strParams = lobby.GetStrParams();
868  if (!strParams.IsEmpty())
869  {
870  m_ParamsFilter.ExpandFromRAW(strParams);
871  lobby.ClearParams();
872  }
873  }
874  else
875  {
876  // Restore previous filter setup
877  m_ParamsFilter = params;
878  }
879 
880  // Reset search
881  m_ParamsFilter.SetSearch(string.Empty);
882 
883  SetupFilteringUI(m_ParamsFilter);
884  }
885 
886  //------------------------------------------------------------------------------------------------
888  protected void SetupFilteringUI(FilteredServerParams filterParams)
889  {
890  // Tabview
891  if (m_TabView)
892  {
893  if (m_ParamsFilter)
894  m_TabView.ShowTab(m_ParamsFilter.GetSelectedTab());
895  }
896 
897  if (m_FilterPanel)
898  {
899  bool show = m_FilterPanel.AnyFilterButtonsVisible();
900  m_FilterPanel.ShowFilterListBox(show, show);
901  }
902  }
903 
904  //------------------------------------------------------------------------------------------------
906  protected void SetupCallbacks()
907  {
908  // Loading
909  SCR_MenuLoadingComponent.m_OnMenuOpening.Insert(OnOpeningByLoadComponent);
910 
911  // Server list
912  m_ScrollableList.GetOnSetPage().Insert(CallOnServerListSetPage);
913  }
914 
915 
916  //------------------------------------------------------------------------------------------------
917  // ENTRIES
918  //------------------------------------------------------------------------------------------------
919  //------------------------------------------------------------------------------------------------
920  protected void OnServerEntryFocusEnter(SCR_ScriptedWidgetComponent entry)
921  {
923 
924  if (!serverEntry || !m_ModsManager)
925  return;
926 
927  Room room = serverEntry.GetRoomInfo();
928  if (!room)
929  {
930  m_ServerEntry = null;
931  return;
932  }
933 
934  DisplayFavoriteAction(room.IsFavorite());
935  UpdateNavigationButtons();
936  serverEntry.m_OnClick.Insert(OnEntryMouseClick);
937 
938  if (m_ServerEntry == serverEntry)
939  return;
940 
941  m_ServerEntry = serverEntry;
942  m_RoomToJoin = room;
943 
944  m_ModsManager.Clear();
945  m_ServerEntry.SetModsManager(m_ModsManager);
946 
947  ReceiveRoomContent(m_RoomToJoin, true);
948  }
949 
950  //------------------------------------------------------------------------------------------------
951  protected void OnServerEntryFocusLeave(SCR_ScriptedWidgetComponent entry)
952  {
954 
955  serverEntry.m_OnClick.Remove(OnEntryMouseClick);
956  }
957 
958  //------------------------------------------------------------------------------------------------
959  protected void OnEntryMouseClick(SCR_ScriptedWidgetComponent button)
960  {
961  m_ClickedEntry = SCR_ServerBrowserEntryComponent.Cast(button);
962  }
963 
964  //------------------------------------------------------------------------------------------------
965  protected void ReceiveRoomContent(notnull Room room, bool receiveMods)
966  {
967  GetGame().GetCallqueue().Remove(ReceiveRoomContent_Mods);
968 
969  if (m_ServerScenarioDetails)
970  m_ServerScenarioDetails.DisplayRoomData(room, receiveMods);
971 
972  // Allow check only if client is authorized to join server
973  if (!room.IsAuthorized())
974  {
975  return;
976  }
977 
978  // Check room mods count
979  array<Dependency> roomMod = {};
980  room.GetItems(roomMod);
981 
982  // Show mod count immidiatelly
983  if (!roomMod.IsEmpty() && m_ServerScenarioDetails)
984  m_ServerScenarioDetails.DisplayModsCount(roomMod.Count());
985 
986  // Receive mod data only if currently view is focused
987  if (room.IsDownloadListLoaded())
988  {
989  ReceiveRoomContent_Mods(room);
990  return;
991  }
992  else
993  {
994  // Load mods after short delay - to prevent spamming mods receive requiest with fast server selecting
995  GetGame().GetCallqueue().CallLater(ReceiveRoomContent_Mods, ROOM_CONTENT_LOAD_DELAY, false, room);
996  }
997  }
998 
999  //------------------------------------------------------------------------------------------------
1002  protected void ReceiveRoomContent_Scenario()
1003  {
1004  // Load scenario
1005  m_ModsManager.GetOnGetScenario().Insert(OnLoadingScenario);
1006  m_ModsManager.ReceiveRoomScenario(m_RoomToJoin);
1007  }
1008 
1009  //------------------------------------------------------------------------------------------------
1012  protected void ReceiveRoomContent_Mods(Room room)
1013  {
1014  if (!m_ModsManager || !room || m_RoomToJoin != room)
1015  return;
1016 
1017  m_ModsManager.GetOnGetAllDependencies().Insert(OnLoadingDependencyList);
1018  m_ModsManager.ReceiveRoomMods(room);
1019  }
1020 
1021  //------------------------------------------------------------------------------------------------
1022  // SETUP
1023  //------------------------------------------------------------------------------------------------
1025  protected void SetupHandlers()
1026  {
1027  // Tab view
1028  m_TabView = SCR_TabViewComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_TAB_VIEW, SCR_TabViewComponent));
1029  if (m_TabView)
1030  {
1031  m_TabView.GetOnChanged().Insert(OnTabViewSwitch);
1032  OnTabViewSwitch(null, null, m_TabView.GetShownTab());
1033 
1034  if (!GetGame().IsPlatformGameConsole())
1035  m_TabView.AddTab("", "#AR-Workshop_ButtonHost");
1036  }
1037 
1038  // Filter panel
1039  m_FilterPanel = SCR_FilterPanelComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_FILTER, SCR_FilterPanelComponent));
1040  if (m_FilterPanel)
1041  {
1042  // Invoker
1043  m_FilterPanel.GetOnFilterPanelToggled().Insert(OnFilterPanelToggle);
1044  m_FilterPanel.GetOnFilterChanged().Insert(OnChangeFilter);
1045 
1046  // Attempt load previous filter setup
1047  m_FilterPanel.TryLoad();
1048  m_ParamsFilter.SetFilters(m_FilterPanel.GetFilter());
1049 
1050  FilterCrossplayCheck();
1051  }
1052 
1053  // Sorting header
1054  m_SortBar = SCR_SortHeaderComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_SERVER_HEADER, SCR_SortHeaderComponent));
1055 
1056  if (m_SortBar)
1057  {
1058  m_SortBar.m_OnChanged.Insert(OnChangeSort);
1059 
1060  // Initial sort
1061  // todo move default sorting values out of here, it can be set in layout file now
1062  m_SortBar.SetCurrentSortElement(3, ESortOrder.DESCENDING);
1063  }
1064 
1065  // Search edit box
1066  m_SearchEditBox = SCR_EditBoxSearchComponent.Cast(
1067  m_Widgets.FindHandlerReference(m_Widgets.m_wSearchEditBox, m_Widgets.WIDGET_SEARCH, SCR_EditBoxSearchComponent)
1068  );
1069 
1070  if (m_SearchEditBox)
1071  m_SearchEditBox.m_OnConfirm.Insert(OnSearchEditBoxConfirm);
1072 
1073  // Server list and scroll --------------------
1074  m_ScrollableList = SCR_PooledServerListComponent.Cast(m_Widgets.FindHandlerReference(
1075  null, m_Widgets.WIDGET_SCROLLABLE_LIST, SCR_PooledServerListComponent
1076  ));
1077 
1078  // Add callbacks
1079  array<SCR_ServerBrowserEntryComponent> entries = m_ScrollableList.GetRoomEntries();
1080 
1081  foreach (SCR_ServerBrowserEntryComponent entry : entries)
1082  {
1083  // Set invoker actions
1084  entry.GetOnFocus().Insert(OnServerEntryFocusEnter);
1085  entry.GetOnFocusLost().Insert(OnServerEntryFocusLeave);
1086  entry.GetOnFavorite().Insert(OnRoomEntrySetFavorite);
1087  entry.GetOnMouseInteractionButtonClicked().Insert(OnEntryMouseButton);
1088  }
1089 
1090  // Detail screen
1091  m_ServerScenarioDetails = SCR_ServerScenarioDetailsPanelComponent.Cast(m_Widgets.FindHandlerReference(
1092  null, m_Widgets.WIDGET_SERVER_SCENARIO_DETAILS_PANEL, SCR_ServerScenarioDetailsPanelComponent
1093  ));
1094 
1095  // Bacis setup and hide
1096  if (m_ServerScenarioDetails)
1097  m_ServerScenarioDetails.SetModsManager(m_ModsManager);
1098 
1099  // Messages
1100  m_SimpleMessageWrap = SCR_SimpleMessageComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_MESSAGE_WRAP, SCR_SimpleMessageComponent));
1101  m_SimpleMessageList = SCR_SimpleMessageComponent.Cast(m_Widgets.FindHandlerReference(null, m_Widgets.WIDGET_MESSAGE_LIST, SCR_SimpleMessageComponent));
1102  if (m_SimpleMessageList)
1103  m_SimpleMessageList.SetVisible(false);
1104 
1105 
1106  // Navigation buttons
1107  m_Widgets.m_JoinButton.m_OnActivated.Insert(OnJoinButton);
1108  m_Widgets.m_DetailsButton.m_OnActivated.Insert(OnActionDetails);
1109  m_Widgets.m_FavoritesButton.m_OnActivated.Insert(OnActionFavorite);
1110 
1111  // Header
1112  m_MenuHeader = SCR_CoreMenuHeaderComponent.FindComponentInHierarchy(GetRootWidget());
1113  }
1114 
1115  //------------------------------------------------------------------------------------------------
1117  protected void FilterCrossplayCheck()
1118  {
1119  if (!m_FilterPanel)
1120  return;
1121 
1122  bool hasCrossplay = GetGame().GetPlatformService().GetPrivilege(UserPrivilege.CROSS_PLAY);
1123  //hasCrossplay = false;
1124 
1125  // Cross play privilege missing
1126  if (!hasCrossplay)
1127  {
1128  SCR_FilterSet filterSet = m_FilterPanel.GetFilter();
1129  if (filterSet)
1130  {
1131  SCR_FilterCategory crossPlay = filterSet.FindFilterCategory("Crossplay");
1132 
1133  if (crossPlay)
1134  {
1135  SCR_FilterEntry enabled = crossPlay.FindFilter("CrossplayEnabled");
1136  if (enabled)
1137  {
1138  enabled.SetSelected(false);
1139  m_FilterPanel.SelectFilter(enabled, false, false);
1140  }
1141 
1142  SCR_FilterEntry disabled = crossPlay.FindFilter("CrossPlayDisabled");
1143  if (disabled)
1144  {
1145  disabled.SetSelected(true);
1146  m_FilterPanel.SelectFilter(disabled, true, false);
1147  }
1148  }
1149  }
1150  }
1151  }
1152 
1153  //------------------------------------------------------------------------------------------------
1155  protected void SwitchFocus(SCR_EListMenuWidgetFocus focus, bool force = false)
1156  {
1157  if (m_iFocusedWidgetState == focus && !force)
1158  return;
1159 
1160  Widget focusTarget;
1161 
1162  switch(focus)
1163  {
1164  case SCR_EListMenuWidgetFocus.LIST:
1165  {
1166  if (m_ServerEntry && m_ServerEntry.IsVisible())
1167  focusTarget = m_ServerEntry.GetRootWidget();
1168  else if (m_ScrollableList)
1169  focusTarget = m_ScrollableList.FirstAvailableEntry();
1170 
1171  break;
1172  }
1173 
1174  case SCR_EListMenuWidgetFocus.FILTERING:
1175  {
1176  focusTarget = m_FilterPanel.GetWidgets().m_FilterButton;
1177  break;
1178  }
1179 
1180  case SCR_EListMenuWidgetFocus.SORTING:
1181  {
1182  focusTarget = m_Widgets.m_wSortSessionFavorite;
1183  break;
1184  }
1185  }
1186 
1187  m_iFocusedWidgetState = focus;
1188 
1189  if (!focusTarget || !focusTarget.IsVisible())
1190  {
1191  // Fallback
1192  focusTarget = m_Widgets.m_wSortSessionFavorite;
1193  m_iFocusedWidgetState = SCR_EListMenuWidgetFocus.SORTING;
1194  }
1195 
1196  GetGame().GetWorkspace().SetFocusedWidget(focusTarget);
1197  }
1198 
1199  //------------------------------------------------------------------------------------------------
1202  void ActivateFilter(string filterName, bool enabled, bool processFilters = true)
1203  {
1204  // Setup filter
1205  SCR_FilterEntry filter = new SCR_FilterEntry;
1206  filter.m_sInternalName = filterName;
1207  filter.SetSelected(true);
1208 
1209  // Register filter
1210  m_aFiltersToSelect.Insert(filter);
1211 
1212  // Activate filter if possible
1213  if (processFilters)
1214  ActivateFiltersFromList();
1215  }
1216 
1217  //------------------------------------------------------------------------------------------------
1218  protected void ActivateFiltersFromList()
1219  {
1220  // Filters array check
1221  if (!m_aFiltersToSelect || m_aFiltersToSelect.IsEmpty())
1222  return;
1223 
1224  // Filter panel check
1225  if (!m_FilterPanel || !m_ParamsFilter)
1226  return;
1227 
1228  // Get filter set
1229  ref SCR_FilterSet filterSet = m_FilterPanel.GetFilter();
1230  if (!filterSet)
1231  return;
1232 
1233  // Check and enable each filter
1234  foreach (SCR_FilterEntry filter : m_aFiltersToSelect)
1235  {
1236  if (!filter)
1237  continue;
1238 
1239  // Find filter to select
1240  SCR_FilterEntry targetFilter = filterSet.FindFilter(filter.m_sInternalName);
1241 
1242  // Set select if is found
1243  if (targetFilter && targetFilter.GetSelected() != filter.GetSelected())
1244  {
1245  targetFilter.SetSelected(filter.GetSelected());
1246  m_FilterPanel.SelectFilter(targetFilter, filter.GetSelected());
1247  }
1248  }
1249 
1250  // Clear filters
1251  m_aFiltersToSelect.Clear();
1252 
1253  // Filter
1254  m_ParamsFilter.SetFilters(filterSet);
1255  Refresh();
1256  }
1257 
1258  //------------------------------------------------------------------------------------------------
1260  protected void FocusWidget(Widget w)
1261  {
1262  GetGame().GetWorkspace().SetFocusedWidget(w);
1263  }
1264 
1265  //------------------------------------------------------------------------------------------------
1266  protected void CallOnServerListSetPage(int page)
1267  {
1268  GetGame().GetCallqueue().Remove(OnServerListSetPage);
1269  GetGame().GetCallqueue().CallLater(OnServerListSetPage, ROOM_CONTENT_LOAD_DELAY, false, page);
1270  }
1271 
1272  //------------------------------------------------------------------------------------------------
1275  protected void Messages_ShowMessage(string messageTag, bool showWrap = false)
1276  {
1277  // Check message component references
1278  if (!m_Widgets.m_wPanelEmpty || !m_SimpleMessageWrap || !m_SimpleMessageList)
1279  {
1280  string msg = string.Format("Missing ref - WrapLayout: %1 Wrap: %2, List: %3", m_Widgets.m_wPanelEmpty, m_SimpleMessageWrap, m_SimpleMessageList);
1281  PrintDebug(msg, "Messages_ShowMessage");
1282  return;
1283  }
1284 
1285  // Show menu content
1286  if (m_Widgets.m_wContent)
1287  m_Widgets.m_wContent.SetVisible(!showWrap);
1288 
1289  m_Widgets.m_wPanelEmpty.SetVisible(showWrap);
1290 
1291  // Display messages
1292  m_SimpleMessageWrap.SetVisible(showWrap);
1293  m_SimpleMessageList.SetVisible(!showWrap);
1294 
1295  // List
1296  m_SimpleMessageWrap.SetContentFromPreset(messageTag);
1297  m_SimpleMessageList.SetContentFromPreset(messageTag);
1298 
1299  // Hide footer buttons during full layout mode
1300  if (m_Widgets.m_RefreshButton)
1301  m_Widgets.m_RefreshButton.SetVisible(!showWrap, false);
1302 
1303  if (m_Widgets.m_DirectJoinButton)
1304  m_Widgets.m_DirectJoinButton.SetVisible(!showWrap, false);
1305 
1306  if (m_Widgets.m_FilterButton)
1307  m_Widgets.m_FilterButton.SetVisible(!showWrap, false);
1308  }
1309 
1310  //------------------------------------------------------------------------------------------------
1312  protected void Messages_Hide()
1313  {
1314  Widget wrapLayout = m_Widgets.m_wPanelEmpty;
1315 
1316  // Check message component references
1317  if (!wrapLayout || !m_SimpleMessageWrap || !m_SimpleMessageList)
1318  {
1319  string msg = string.Format("Missing ref - WrapLayout: %1 Wrap: %2, List: %3", wrapLayout, m_SimpleMessageWrap, m_SimpleMessageList);
1320  PrintDebug(msg, "Messages_Hide");
1321  return;
1322  }
1323 
1324  // Hide
1325  m_SimpleMessageWrap.SetVisible(false);
1326  m_SimpleMessageList.SetVisible(false);
1327 
1328  wrapLayout.SetVisible(false);
1329 
1330  if (m_Widgets.m_wContent)
1331  m_Widgets.m_wContent.SetVisible(true);
1332  }
1333 
1334  //------------------------------------------------------------------------------------------------
1336  protected void DisplayFavoriteAction(bool favorited)
1337  {
1338  string label = GetFavoriteLabel(favorited);
1339 
1340  if (m_Widgets && m_Widgets.m_FavoritesButton && m_ServerEntry)
1341  m_Widgets.m_FavoritesButton.SetLabel(label);
1342  }
1343 
1344  //------------------------------------------------------------------------------------------------
1345  // CALLBACKS
1346  //------------------------------------------------------------------------------------------------
1349  protected void OnOpeningByLoadComponent(int menuPreset)
1350  {
1351  // Check menu opening
1352  if (menuPreset == ChimeraMenuPreset.ServerBrowserMenu)
1353  return;
1354  }
1355 
1356  //------------------------------------------------------------------------------------------------
1358  protected void OnChangeSort(SCR_SortHeaderComponent sortHeader)
1359  {
1360  if (!m_ParamsFilter)
1361  return;
1362 
1363  // Reload data
1364  bool sortAscending = sortHeader.GetSortOrderAscending();
1365  string sortElementName = sortHeader.GetSortElementName();
1366  m_ParamsFilter.SetSorting(sortElementName, sortAscending);
1367 
1368  if (!m_bFirstRoomLoad)
1369  Refresh();
1370  }
1371 
1372  //------------------------------------------------------------------------------------------------
1374  void OnTabViewSwitch(SCR_TabViewComponent tabView, Widget w, int id)
1375  {
1376  // Default setup
1377  m_ParamsFilter.SetFavoriteFilter(false);
1378  m_ParamsFilter.SetRecentlyPlayedFilter(false);
1379  m_ParamsFilter.SetOwnedOnly(false);
1380  m_bHostedServers = false;
1381 
1382  m_Widgets.m_wHostNewServerButton.SetVisible(false);
1383 
1384  switch (id)
1385  {
1386  // All
1387  case 0:
1388  {
1389  m_ParamsFilter.SetOfficialFilter(false, false);
1390  break;
1391  }
1392 
1393  // Community
1394  case 1:
1395  {
1396  m_ParamsFilter.SetOfficialFilter(true, false);
1397  break;
1398  }
1399 
1400  // Official
1401  case 2:
1402  {
1403  m_ParamsFilter.SetOfficialFilter(true, true);
1404  break;
1405  }
1406 
1407  // Favorite servers
1408  case 3:
1409  {
1410  m_ParamsFilter.SetFavoriteFilter(true);
1411  m_ParamsFilter.SetOfficialFilter(false, false);
1412  break;
1413  }
1414 
1415  // Recently played
1416  case 4:
1417  {
1418  m_ParamsFilter.SetRecentlyPlayedFilter(true);
1419  m_ParamsFilter.SetOfficialFilter(false, false);
1420  break;
1421  }
1422 
1423  // Hostest
1424  case 5:
1425  {
1426  // Call focus later to prevent override from auto widget focus
1427  GetGame().GetCallqueue().CallLater(FocusWidget, 0, false, m_Widgets.m_wHostNewServerButton);
1428 
1429  // Filters
1430  m_ParamsFilter.SetOfficialFilter(false, false);
1431  m_ParamsFilter.SetOwnedOnly(true);
1432  m_bHostedServers = true;
1433 
1434  break;
1435  }
1436  }
1437 
1438  // Hosting widgets
1439  m_Widgets.m_wHostNewServerButton.SetVisible(m_bHostedServers);
1440  m_Widgets.m_wHostNewServerButton.SetEnabled(m_bHostedServers);
1441 
1442  // Set tab filter json
1443  if (m_ParamsFilter)
1444  m_ParamsFilter.SetSelectedTab(id);
1445 
1446  if (!m_bFirstRoomLoad)
1447  Refresh();
1448 
1449  Widget focus = GetGame().GetWorkspace().GetFocusedWidget();
1450  if (!m_FilterPanel || !m_FilterPanel.GetFilterListBoxShown() || !focus || !focus.IsVisible())
1451  SwitchFocus(SCR_EListMenuWidgetFocus.LIST, true);
1452  }
1453 
1454  //------------------------------------------------------------------------------------------------
1455  protected void OnFilterPanelToggle(bool show)
1456  {
1457  if (!m_FilterPanel)
1458  return;
1459 
1460  // Focus back to server list
1461  if (show || m_Lobby.TotalRoomCount() == 0)
1462  {
1463  SwitchFocus(SCR_EListMenuWidgetFocus.FILTERING);
1464  return;
1465  }
1466 
1467  // Focus back to last entry
1468  SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
1469  }
1470 
1471  //------------------------------------------------------------------------------------------------
1474  protected void OnChangeFilter(SCR_FilterEntry filter)
1475  {
1476  // Set filter and refresh
1477  m_ParamsFilter.SetFilters(m_FilterPanel.GetFilter());
1478  Refresh();
1479 
1480  // Prevent using cross play filter
1481  bool hasCrossplay = GetGame().GetPlatformService().GetPrivilege(UserPrivilege.CROSS_PLAY);
1482  //hasCrossplay = false;
1483 
1484  if (!hasCrossplay)
1485  {
1486  // Is crossplay filter
1487  if (filter.GetCategory().m_sInternalName == "Crossplay")
1488 
1489  if (!m_CallbackGetPrivilege)
1490  m_CallbackGetPrivilege = new SCR_ScriptPlatformRequestCallback();
1491 
1492  m_CallbackGetPrivilege.m_OnResult.Insert(OnCrossPlayPrivilegeResultFilter);
1493  NegotiatePrivilegeAsync(UserPrivilege.CROSS_PLAY);
1494  }
1495  }
1496 
1497  //------------------------------------------------------------------------------------------------
1498  protected void OnCrossPlayPrivilegeResultFilter(UserPrivilege privilege, UserPrivilegeResult result)
1499  {
1500  if (privilege == UserPrivilege.CROSS_PLAY)
1501  {
1502  if (result != UserPrivilegeResult.ALLOWED)
1503  {
1504  FilterCrossplayCheck();
1505  Refresh();
1506  }
1507  }
1508 
1509  m_CallbackGetPrivilege.m_OnResult.Remove(OnCrossPlayPrivilegeResultFilter);
1510  }
1511 
1512  //------------------------------------------------------------------------------------------------
1514  protected void OnServerListSetPage(int page)
1515  {
1516  // Check list
1517  if (!m_ScrollableList)
1518  return;
1519 
1520  // Get entries count
1521  int entriesC = m_ScrollableList.GetPageEntriesCount();
1522  int pos = entriesC * page;
1523 
1524  // Setup scroll callback
1525  //m_CallbackScroll.m_OnSuccess.Insert(OnScrollSuccess);
1526  m_CallbackScroll.GetEventOnResponse().Insert(OnScrollResponse);
1527 
1528  array<Room> rooms = {};
1529  m_Lobby.Rooms(rooms);
1530  m_Lobby.Scroll(pos, m_CallbackScroll);
1531  }
1532 
1533  //------------------------------------------------------------------------------------------------
1535  protected void OnScrollResponse(SCR_BackendCallback callback)
1536  {
1537  switch (callback.GetResponseType())
1538  {
1539  case EBackendCallbackResponse.SUCCESS:
1540  {
1541  OnScrollSuccess(callback);
1542  break;
1543  }
1544 
1545  case EBackendCallbackResponse.ERROR:
1546  {
1547  PrintDebug("Scroll error!", "OnScrollResponse");
1548  break;
1549  }
1550 
1551  case EBackendCallbackResponse.TIMEOUT:
1552  {
1553  PrintDebug("Scroll timeout!", "OnScrollResponse");
1554  break;
1555  }
1556  }
1557  }
1558 
1559  //------------------------------------------------------------------------------------------------
1560  protected void OnScrollSuccess(SCR_BackendCallback callback)
1561  {
1562  // Check if loaded room should display details
1563  bool loadedRoomFocused = false;
1564  if (m_ServerEntry && !m_ScrollableList.IsRoomLoaded(m_ServerEntry))
1565  loadedRoomFocused = true;
1566 
1567  // Update rooms
1568  m_Lobby.Rooms(m_aRooms);
1569 
1570  if (m_aRooms.IsEmpty())
1571  {
1572  PrintDebug("No room found", "OnScrollSuccess");
1573 
1574  if (m_Lobby.TotalRoomCount() > 0)
1575  {
1576  if (m_ScrollableList)
1577  CallOnServerListSetPage(m_ScrollableList.GetCurrentPage());
1578  else
1579  Refresh();
1580  }
1581  }
1582 
1583  m_ScrollableList.UpdateLoadedPage();
1584 
1585  DisplayRooms(m_aRooms);
1586 
1587  // Focus on new room
1588  if (loadedRoomFocused)
1589  ReceiveRoomContent(m_ServerEntry.GetRoomInfo(), true);
1590  }
1591 
1592  //------------------------------------------------------------------------------------------------
1594  protected void OnSearchEditBoxConfirm(SCR_EditBoxComponent editBox, string sInput)
1595  {
1596  m_ParamsFilter.SetSearch(sInput);
1597  Refresh();
1598  }
1599 
1600  //------------------------------------------------------------------------------------------------
1602  protected void OnRoomEntrySetFavorite(SCR_ListMenuEntryComponent entry, bool favorite)
1603  {
1605  if(!serverEntry)
1606  return;
1607 
1608  Room roomClicked = serverEntry.GetRoomInfo();
1609  if (!roomClicked)
1610  return;
1611 
1612  int roomId = m_aRooms.Find(roomClicked);
1613  if (roomId == -1)
1614  return;
1615 
1616  // Setup callback
1617  m_CallbackFavorite.SetRoom(roomClicked);
1618  m_CallbackFavorite.GetEventOnResponse().Insert(OnRoomSetFavoriteResponse);
1619 
1620  m_aRooms[roomId].SetFavorite(favorite, m_CallbackFavorite);
1621  }
1622 
1623  //------------------------------------------------------------------------------------------------
1624  protected void OnRoomSetFavoriteResponse(SCR_RoomCallback callback)
1625  {
1626  switch (callback.GetResponseType())
1627  {
1628  case EBackendCallbackResponse.SUCCESS:
1629  {
1630  if (callback.GetRoom())
1631  {
1632  DisplayFavoriteAction(callback.GetRoom().IsFavorite());
1633  m_OnFavoritesResponse.Invoke();
1634  }
1635  break;
1636  }
1637 
1638  case EBackendCallbackResponse.ERROR: PrintDebug("Error!", "OnRoomSetFavoriteResponse"); break;
1639  case EBackendCallbackResponse.TIMEOUT: PrintDebug("Timeout!", "OnRoomSetFavoriteResponse"); break;
1640  }
1641 
1642  // Clear
1643  m_CallbackFavorite.SetRoom(null);
1644  m_CallbackFavorite.GetEventOnResponse().Remove(OnRoomSetFavoriteResponse);
1645  }
1646 
1647 
1648  //------------------------------------------------------------------------------------------------
1650  protected void OnLoadingDependencyList()
1651  {
1652  // Remove data receiving actions
1653  m_ModsManager.GetOnGetAllDependencies().Remove(OnLoadingDependencyList);
1654 
1655  array<ref SCR_WorkshopItem> updated = m_ModsManager.GetRoomItemsUpdated();
1656  array<ref SCR_WorkshopItem> outdated = m_ModsManager.GetRoomItemsToUpdate();
1657 
1658  // setup of server detail
1659  bool modsUpdated = outdated.IsEmpty();
1660 
1661  if (m_ServerScenarioDetails)
1662  m_ServerScenarioDetails.DisplayMods();
1663 
1664  ReceiveRoomContent_Scenario();
1665  }
1666 
1667  //------------------------------------------------------------------------------------------------
1670  protected void OnModListFail(Room room)
1671  {
1672  if (m_ModListFailDialog)
1673  return;
1674 
1675  m_ModListFailDialog = SCR_CommonDialogs.CreateRequestErrorDialog();
1676  m_ModListFailDialog.m_OnClose.Insert(OnModListFailDialogClose);
1677  }
1678 
1679  //------------------------------------------------------------------------------------------------\
1680  protected void OnModListFailDialogClose(SCR_ConfigurableDialogUi dialog)
1681  {
1682  m_ModListFailDialog = null;
1683  }
1684 
1685  //------------------------------------------------------------------------------------------------
1688  protected void OnLoadingScenario(Dependency scenario)
1689  {
1690  // Remove action
1691  m_ModsManager.GetOnGetScenario().Remove(OnLoadingScenario);
1692 
1693  // Set server details
1694  Room roomInfo = null;
1695 
1696  if (m_ServerEntry)
1697  roomInfo = m_ServerEntry.GetRoomInfo();
1698 
1699  if (!roomInfo)
1700  return;
1701  // Get scenario item
1702  MissionWorkshopItem scenarioItem = roomInfo.HostScenario();
1703  SCR_AddonManager mgr = SCR_AddonManager.GetInstance();
1704 
1705  // Hide scneario img if scenario if modded client can't see UGC
1706  Dependency scenarioMod = roomInfo.HostScenarioMod();
1707  bool hideScenario = scenarioMod && !mgr.GetUgcPrivilege();
1708 
1709  // Display room and scenario data
1710  if (m_ServerScenarioDetails)
1711  {
1712  // Hide scenario image
1713  m_ServerScenarioDetails.SetHideScenarioImg(hideScenario);
1714 
1715  if (scenarioItem)
1716  {
1717  m_ServerScenarioDetails.SetScenario(scenarioItem);
1718  }
1719  else
1720  m_ServerScenarioDetails.DisplayDefaultScenarioImage();
1721  }
1722 
1724  if (m_Dialogs)
1725  m_Dialogs.UpdateRoomDetailsScenarioImage(scenarioItem);
1726 
1727  m_RoomScenario = scenarioItem;
1728 
1729  m_OnScenarioLoad.Invoke(m_RoomScenario);
1730  }
1731 
1732  //------------------------------------------------------------------------------------------------
1734  protected void OnRejoinCancel()
1735  {
1736  SCR_KickDialogs.GetOnReconnect().Remove(OnLastRoomReconnectConfirm);
1737  SCR_KickDialogs.GetOnCancel().Remove(OnRejoinCancel);
1738  }
1739 
1740  //------------------------------------------------------------------------------------------------
1742  protected void OnDirectJoinCancel()
1743  {
1744  // TODO@wernerjak - restore old search
1745  }
1746 
1747  //------------------------------------------------------------------------------------------------
1748  // HELPERS
1749  //------------------------------------------------------------------------------------------------
1750  protected MissionWorkshopItem MissionFromMod(Dependency scenario)
1751  {
1752  if (!scenario)
1753  return null;
1754 
1755  WorkshopItem item = scenario.GetCachedItem();
1756  if (!item)
1757  return null;
1758 
1759  Revision rev = item.GetActiveRevision();
1760  if (!rev)
1761  return null;
1762 
1763  array<MissionWorkshopItem> scenarios = {};
1764  rev.GetScenarios(scenarios);
1765  if (scenarios.IsEmpty())
1766  return null;
1767 
1768  for (int i = 0, count = scenarios.Count(); i < count; i++)
1769  {
1770  if (scenarios[i].GetOwner() == item)
1771  return scenarios[i];
1772  }
1773 
1774  return null;
1775  }
1776 
1777  //------------------------------------------------------------------------------------------------
1780  protected bool CanJoinRoom(Room room)
1781  {
1782  if (!room)
1783  {
1784  PrintDebug("No room found for can join room check", "CanJoinRoom");
1785  return false;
1786  }
1787 
1788  // Room to client version check
1789  bool versionMatch = ClientRoomVersionMatch(room);
1790 
1791  //TODO: check platform restriction
1792 
1793  return versionMatch && !m_ModsManager.HasBlockedMods() && room.Joinable();
1794  }
1795 
1796  //------------------------------------------------------------------------------------------------
1797  protected bool ClientRoomVersionMatch(Room room)
1798  {
1799  if (!room)
1800  return false;
1801 
1802  string clientV = GetGame().GetBuildVersion();
1803  string roomV = room.GameVersion();
1804 
1805 
1806  return (clientV == roomV);
1807  }
1808 
1809  //------------------------------------------------------------------------------------------------
1810  protected string GetFavoriteLabel(bool isFavorite)
1811  {
1812  if (isFavorite)
1813  return UIConstants.FAVORITE_LABEL_REMOVE;
1814  else
1815  return UIConstants.FAVORITE_LABEL_ADD;
1816  }
1817 
1818  //------------------------------------------------------------------------------------------------
1819  protected SCR_ServerBrowserEntryComponent GetEntryUnderCursor()
1820  {
1821  Widget w = WidgetManager.GetWidgetUnderCursor();
1822 
1823  if (!w)
1824  return null;
1825 
1827  }
1828 
1829  //------------------------------------------------------------------------------------------------
1830  protected SCR_ServerBrowserEntryComponent GetSelectedEntry()
1831  {
1832  // We are not over a line, use currently focused line
1833  Widget wfocused = GetGame().GetWorkspace().GetFocusedWidget();
1835  if (wfocused)
1836  comp = SCR_ServerBrowserEntryComponent.Cast(wfocused.FindHandler(SCR_ServerBrowserEntryComponent));
1837 
1838  EInputDeviceType inputDevice = GetGame().GetInputManager().GetLastUsedInputDevice();
1839  bool isCursorOnInnerButton = m_ServerEntry && m_ServerEntry.IsInnerButtonInteraction();
1840 
1841  if (inputDevice == EInputDeviceType.MOUSE && (GetEntryUnderCursor() || isCursorOnInnerButton))
1842  return m_ServerEntry;
1843 
1844  return comp;
1845  }
1846 
1847  //------------------------------------------------------------------------------------------------
1848  protected void ClearScenarioFilters()
1849  {
1850  if (!m_ParamsFilter)
1851  return;
1852 
1853  m_ParamsFilter.SetScenarioId("");
1854  m_ParamsFilter.SetHostedScenarioModId("");
1855  }
1856 
1857  //------------------------------------------------------------------------------------------------
1858  protected void SetMenuHeader(string header)
1859  {
1860  if (m_MenuHeader)
1861  m_MenuHeader.SetTitle(header);
1862  }
1863 
1864  //------------------------------------------------------------------------------------------------
1865  // API
1866  //------------------------------------------------------------------------------------------------
1867  //------------------------------------------------------------------------------------------------
1868  void FilterScenarioId(string scenarioId)
1869  {
1870  if (m_ParamsFilter)
1871  m_ParamsFilter.SetScenarioId(scenarioId);
1872  }
1873 
1874  //------------------------------------------------------------------------------------------------
1875  void FilterHostedScenarioModId(string scenarioModId)
1876  {
1877  if (m_ParamsFilter)
1878  m_ParamsFilter.SetHostedScenarioModId(scenarioModId);
1879  }
1880 
1881  //------------------------------------------------------------------------------------------------
1882  void SetFilteredScenario(MissionWorkshopItem scenario)
1883  {
1884  if (m_Widgets && m_Widgets.m_HostButton)
1885  m_Widgets.m_HostButton.SetScenario(scenario);
1886  }
1887 
1888  //------------------------------------------------------------------------------------------------
1890  static void OpenWithScenarioFilter(MissionWorkshopItem mission)
1891  {
1892  ServerBrowserMenuUI sb = ServerBrowserMenuUI.Cast(GetGame().GetMenuManager().OpenMenu(ChimeraMenuPreset.ServerBrowserMenu));
1893  if (!sb)
1894  return;
1895 
1896  // Scenario id
1897  string scenarioId = mission.Id();
1898  sb.FilterScenarioId(scenarioId);
1899 
1900  // Modded
1901  string modId = "";
1902  WorkshopItem owner = mission.GetOwner();
1903  if (owner)
1904  modId = owner.Id();
1905 
1906  if (modId != string.Empty)
1907  sb.FilterHostedScenarioModId(modId);
1908 
1909  sb.SetMenuHeader(mission.Name());
1910  sb.SetFilteredScenario(mission);
1911  SCR_MenuLoadingComponent.SaveLastMenu(ChimeraMenuPreset.ServerBrowserMenu);
1912  }
1913 
1914  //------------------------------------------------------------------------------------------------
1915  static bool IsServerPingAboveThreshold(Room room)
1916  {
1917  //TODO: unify this check with the value in the filters
1918  return room && room.GetPing() >= HIGH_PING_SERVER_THRESHOLD;
1919  }
1920 
1921  //------------------------------------------------------------------------------------------------
1922  // ROOM JOINING PROCESS
1923  //------------------------------------------------------------------------------------------------
1924  //------------------------------------------------------------------------------------------------
1926  protected void JoinActions_Join()
1927  {
1928  // Prevent join if no entry selected
1929  if (!m_ServerEntry)
1930  {
1931  PrintDebug("Quick join is not possible because there is no selected server", "JoinActions_Join");
1932  return;
1933  }
1934 
1935  // Join
1936  Room roomToJoin = m_ServerEntry.GetRoomInfo();
1937  if (roomToJoin)
1938  JoinProcess_Init(roomToJoin);
1939 
1940  GameSessionStorage.s_Data["m_iRejoinAttempt"] = "0";
1941  }
1942 
1943  //------------------------------------------------------------------------------------------------
1944  // Action for finding server on direct join
1945  protected void JoinActions_DirectJoin(string params, EDirectJoinFormats format, bool publicNetwork)
1946  {
1947  JoinProcess_FindRoom(params, format, publicNetwork);
1948  GameSessionStorage.s_Data["m_iRejoinAttempt"] = "0";
1949  }
1950 
1951  //------------------------------------------------------------------------------------------------
1953  protected void OnLastRoomReconnectConfirm()
1954  {
1955  SCR_KickDialogs.GetOnReconnect().Remove(OnLastRoomReconnectConfirm);
1956  SCR_KickDialogs.GetOnCancel().Remove(OnRejoinCancel);
1957 
1958  // Find
1959  string lastId = m_Lobby.GetPreviousRoomId();
1960  JoinProcess_FindRoomById(lastId, m_CallbackSearchPreviousRoom);
1961  }
1962 
1963  //------------------------------------------------------------------------------------------------
1965  void JoinProcess_FindRoom(string params, EDirectJoinFormats format, bool publicNetwork)
1966  {
1967  m_DirectJoinParams = new FilteredServerParams();
1968 
1969  // Format
1970  switch (format)
1971  {
1972  // IP:PORT
1973  case EDirectJoinFormats.IP_PORT:
1974  {
1975  m_DirectJoinParams.SetHostAddress(params);
1976  break;
1977  }
1978 
1979  // Direct join code
1980  case EDirectJoinFormats.JOIN_CODE:
1981  {
1982  m_DirectJoinParams.SetJoinCode(params);
1983  break;
1984  }
1985 
1986  // Invalid format
1987  case EDirectJoinFormats.INVALID:
1988  {
1989  PrintDebug("Invalid format of direct join", "JoinProcess_FindRoom");
1990  return;
1991  }
1992  }
1993 
1994  // Set room search
1995  m_DirectJoinParams.SetUsePlayerLimit(false);
1996  m_Lobby.SearchTarget(m_DirectJoinParams, m_CallbackSearchTarget);
1997 
1998  // Setup join dialog
1999  SetupJoinDialogs();
2000  if (m_Dialogs)
2001  m_Dialogs.DisplayDialog(EJoinDialogState.SEARCHING_SERVER);
2002 
2003  // Set invokers
2004  m_CallbackSearchTarget.m_OnSuccess.Insert(JoinProcess_OnFindRoomSuccess);
2005  m_CallbackSearchTarget.m_OnFail.Insert(JoinProcess_OnFindRoomFail);
2006  m_CallbackSearchTarget.m_OnTimeOut.Insert(JoinProcess_OnFindRoomTimeout);
2007  }
2008 
2009  //------------------------------------------------------------------------------------------------
2011  protected void JoinProcess_OnFindRoomSuccess(ServerBrowserCallback callback)
2012  {
2013  m_aDirectFoundRooms = m_CallbackSearchTarget.GetFoundRooms();
2014  if (m_aDirectFoundRooms.IsEmpty())
2015  {
2016  PrintDebug("No room found through direct join!", "JoinProcess_OnFindRoomSuccess");
2017  return;
2018  }
2019 
2020  // Check if room was found
2021  if (!m_aDirectFoundRooms || m_aDirectFoundRooms.Count() < 1)
2022  {
2023  if (m_Dialogs)
2024  m_Dialogs.DisplayDialog(EJoinDialogState.SERVER_NOT_FOUND);
2025 
2026  return;
2027  }
2028 
2029  if (m_aDirectFoundRooms.Count() == 1)
2030  {
2031  // Check content of specific server
2032  m_ModsManager.Clear();
2033 
2034  m_RoomToJoin = m_aDirectFoundRooms[0];
2035  JoinProcess_Init(m_RoomToJoin);
2036  }
2037  else
2038  {
2039  // Show multiple rooms in list - fallback logic, shouldn't happend in relased game
2040  OnRoomsFound(m_aDirectFoundRooms);
2041  }
2042 
2043  // Clear direct join callback
2044  JoinProcess_CleanFindCallback();
2045  }
2046 
2047  //------------------------------------------------------------------------------------------------
2049  protected void JoinProcess_OnFindRoomFail(ServerBrowserCallback callback, int code, int restCode, int apiCode)
2050  {
2051  if (m_Dialogs)
2052  m_Dialogs.DisplayDialog(EJoinDialogState.SERVER_NOT_FOUND);
2053 
2054  JoinProcess_CleanFindCallback();
2055  }
2056 
2057  //------------------------------------------------------------------------------------------------
2059  protected void JoinProcess_OnFindRoomTimeout(ServerBrowserCallback callback)
2060  {
2061  if (m_Dialogs)
2062  m_Dialogs.DisplayDialog(EJoinDialogState.SERVER_NOT_FOUND);
2063 
2064  JoinProcess_CleanFindCallback();
2065  }
2066 
2067  //------------------------------------------------------------------------------------------------
2068  protected void JoinProcess_CleanFindCallback()
2069  {
2070  m_CallbackSearchTarget.m_OnSuccess.Remove(JoinProcess_OnFindRoomSuccess);
2071  m_CallbackSearchTarget.m_OnFail.Remove(JoinProcess_OnFindRoomFail);
2072  m_CallbackSearchTarget.m_OnTimeOut.Remove(JoinProcess_OnFindRoomTimeout);
2073  }
2074 
2075  //------------------------------------------------------------------------------------------------
2077  protected void JoinProcess_FindRoomById(string id, ServerBrowserCallback callback)
2078  {
2079  // Setup ID
2080  m_SearchIds.ClearIds();
2081  m_SearchIds.RegisterId(id);
2082 
2083  // Search
2084  m_Lobby.GetRoomsByIds(m_SearchIds, callback);
2085  callback.event_OnResponse.Insert(JoinProcess_OnFindRoomByIdResponse);
2086 
2087  // Setup join dialog
2088  SetupJoinDialogs();
2089  if (m_Dialogs)
2090  m_Dialogs.DisplayDialog(EJoinDialogState.SEARCHING_SERVER);
2091  }
2092 
2093  //------------------------------------------------------------------------------------------------
2095  protected void JoinProcess_OnFindRoomByIdResponse(ServerBrowserCallback callback)
2096  {
2097  switch (callback.GetResultType())
2098  {
2099  // Success
2100  case EServerBrowserRequestResult.SUCCESS:
2101  {
2102  m_Lobby.Rooms(m_aDirectFoundRooms);
2103 
2104  // No rooms received
2105  if (m_aDirectFoundRooms.IsEmpty())
2106  {
2107  JoinProcess_OnFindRoomFail(null, -1, -1, -1);
2108  break;
2109  }
2110 
2111  // Get first room
2112  m_RoomToJoin = m_aDirectFoundRooms[0];
2113  m_RejoinRoom = m_RoomToJoin;
2114  JoinProcess_Init(m_RoomToJoin);
2115  break;
2116  }
2117 
2118  // Error
2119  case EServerBrowserRequestResult.ERROR:
2120  {
2121  JoinProcess_OnFindRoomFail(null, -1, -1, -1);
2122  break;
2123  }
2124 
2125  // Timeout
2126  case EServerBrowserRequestResult.TIMEOUT:
2127  {
2128  JoinProcess_OnFindRoomFail(null, -1, -1, -1);
2129  break;
2130  }
2131  }
2132 
2133  // Clear
2134  callback.event_OnResponse.Remove(JoinProcess_OnFindRoomByIdResponse);
2135  }
2136 
2137  //------------------------------------------------------------------------------------------------
2139  void JoinProcess_Init(Room roomToJoin)
2140  {
2141  if (!m_DownloadManager)
2142  m_DownloadManager = SCR_DownloadManager.GetInstance();
2143 
2144  // Set immidiate refresh to receive player count
2145  //m_Lobby.SetRefreshRate(1);
2146  m_bWaitForRefresh = true;
2147 
2148  // Setup join dialog
2149  SetupJoinDialogs();
2150 
2151  // Setup room
2152  m_RoomToJoin = roomToJoin;
2153 
2154  // Check cross play
2155  bool hasPrivilege = GetGame().GetPlatformService().GetPrivilege(UserPrivilege.CROSS_PLAY);
2156 
2157  if (roomToJoin.IsCrossPlatform() && !hasPrivilege)
2158  {
2159  //m_Dialogs.DisplayDialog(EJoinDialogState.MOD_UGC_PRIVILEGE_MISSING);
2160 
2161  // Negotatiate cross play privilege
2162  if (!m_CallbackGetPrivilege)
2163  m_CallbackGetPrivilege = new SCR_ScriptPlatformRequestCallback();
2164 
2165  m_CallbackGetPrivilege.m_OnResult.Insert(OnCrossPlayPrivilegeResultJoin);
2166  NegotiatePrivilegeAsync(UserPrivilege.CROSS_PLAY);
2167  return;
2168  }
2169 
2170  //Quick Join: Next step check version
2171  if (m_bQuickJoin)
2172  JoinProcess_CheckVersion(m_RoomToJoin);
2173  //Single click Join: Next step check password
2174  else
2175  JoinProcess_CheckRoomPasswordProtected(m_RoomToJoin);
2176  }
2177 
2178  //------------------------------------------------------------------------------------------------
2179  protected void OnCrossPlayPrivilegeResultJoin(UserPrivilege privilege, UserPrivilegeResult result)
2180  {
2181  if (privilege == UserPrivilege.CROSS_PLAY)
2182  {
2183  if (result == UserPrivilegeResult.ALLOWED)
2184  JoinProcess_CheckVersion(m_RoomToJoin);
2185  }
2186 
2187  m_CallbackGetPrivilege.m_OnResult.Remove(OnCrossPlayPrivilegeResultJoin);
2188  }
2189 
2190  //------------------------------------------------------------------------------------------------
2193  protected void JoinProcess_CheckVersion(Room roomToJoin)
2194  {
2195  // Chekc match
2196  bool versionsMatch = ClientRoomVersionMatch(roomToJoin);
2197 
2198 #ifdef SB_DEBUG
2199 #else
2200  // Stop join process with error dialog with wrong version
2201  if (!versionsMatch)
2202  {
2203  m_Dialogs.SetJoinRoom(roomToJoin);
2204  m_Dialogs.DisplayDialog(EJoinDialogState.VERSION_MISMATCH);
2205  return;
2206  }
2207 #endif
2208 
2209  // Check room password protection
2210  JoinProcess_CheckHighPing(roomToJoin);
2211  }
2212 
2213  //------------------------------------------------------------------------------------------------
2215  protected void JoinProcess_CheckHighPing(Room roomToJoin)
2216  {
2217  if (IsServerPingAboveThreshold(roomToJoin))
2218  {
2219  m_Dialogs.SetJoinRoom(roomToJoin);
2220  m_Dialogs.DisplayDialog(EJoinDialogState.HIGH_PING_SERVER);
2221  m_Dialogs.GetOnConfirm().Insert(OnHighPingServerWarningDialogConfirm);
2222 
2223  return;
2224  }
2225 
2226  JoinProcess_CheckRoomPasswordProtected(roomToJoin);
2227  }
2228 
2229  //------------------------------------------------------------------------------------------------
2230  protected void OnHighPingServerWarningDialogConfirm()
2231  {
2232  m_Dialogs.GetOnConfirm().Remove(OnHighPingServerWarningDialogConfirm);
2233  JoinProcess_CheckRoomPasswordProtected(m_Dialogs.GetJoinRoom());
2234  }
2235 
2236  //------------------------------------------------------------------------------------------------
2238  protected void JoinProcess_CheckRoomPasswordProtected(Room roomToJoin)
2239  {
2240  // Skip password if using direct join code or is invited
2241  bool skipPassword;
2242 
2243  if (m_Lobby.GetInviteRoom() == m_RoomToJoin || m_RejoinRoom)
2244  skipPassword = m_RoomToJoin.IsAuthorized();
2245 
2246  // Next step if no password protection
2247  if (!m_RoomToJoin.PasswordProtected() || skipPassword)
2248  {
2249  JoinProcess_ShowJoinDetailsDialog(roomToJoin);
2250  return;
2251  }
2252 
2253  m_PasswordVerification.GetOnVerified().Insert(OnPasswordVerified);
2254  m_PasswordVerification.GetOnFailVerification().Clear();
2255  m_PasswordVerification.GetOnFailVerification().Insert(OnRejoinAuthorizationFailed);
2256  m_PasswordVerification.CheckRejoinAuthorization(roomToJoin);
2257  }
2258 
2259  //------------------------------------------------------------------------------------------------
2260  protected void OnRejoinAuthorizationFailed(string message)
2261  {
2262  m_PasswordVerification.GetOnFailVerification().Remove(OnRejoinAuthorizationFailed);
2263 
2264  m_Dialogs.CloseCurrentDialog();
2265  JoinProcess_PasswordClearInvokers();
2266  GetGame().GetCallqueue().CallLater(JoinProcess_PasswordDialogOpen);
2267  }
2268 
2269  //------------------------------------------------------------------------------------------------
2270  protected void JoinProcess_PasswordDialogOpen()
2271  {
2272  m_Dialogs.DisplayDialog(EJoinDialogState.PASSWORD_REQUIRED);
2273  m_Dialogs.GetOnCancel().Insert(JoinProcess_PasswordClearInvokers);
2274 
2275  m_PasswordVerification.SetupDialog(m_Dialogs.GetCurrentDialog(), m_RoomToJoin);
2276  m_PasswordVerification.GetOnVerified().Insert(OnPasswordVerified);
2277  m_PasswordVerification.GetOnFailVerification().Insert(OnPasswordFailVerification);
2278  }
2279 
2280  //------------------------------------------------------------------------------------------------
2282  protected void OnPasswordVerified(Room room)
2283  {
2284  JoinProcess_PasswordClearInvokers();
2285 
2286  if (!room)
2287  {
2288  #ifdef WORKBENCH
2289  Print("ServerBrowserMenuUI - OnPasswordVerified() - NULL ROOM");
2290  #endif
2291 
2292  return;
2293  }
2294 
2295  m_RoomToJoin = room;
2296  JoinProcess_ShowJoinDetailsDialog(m_RoomToJoin);
2297 
2298  ReceiveRoomContent(m_RoomToJoin, true);
2299  }
2300 
2301  //------------------------------------------------------------------------------------------------
2303  protected void OnPasswordFailVerification(string message)
2304  {
2305  m_Dialogs.DisplayDialog(EJoinDialogState.PASSWORD_REQUIRED);
2306  m_PasswordVerification.SetupDialog(m_Dialogs.GetCurrentDialog(), m_RoomToJoin, message);
2307  }
2308 
2309  //------------------------------------------------------------------------------------------------
2310  protected void JoinProcess_PasswordClearInvokers()
2311  {
2312  m_PasswordVerification.GetOnVerified().Remove(OnPasswordVerified);
2313  m_PasswordVerification.GetOnFailVerification().Remove(OnPasswordFailVerification);
2314  m_Dialogs.GetOnCancel().Remove(JoinProcess_PasswordClearInvokers);
2315  }
2316 
2317  //------------------------------------------------------------------------------------------------
2318  protected void JoinProcess_ShowJoinDetailsDialog(Room roomToJoin)
2319  {
2320  // Skip the dialog on double click
2321  if (m_bQuickJoin)
2322  {
2323  JoinProcess_LoadModContent();
2324  return;
2325  }
2326 
2327  CreateServerDetailsDialog(roomToJoin);
2328  }
2329 
2330  //------------------------------------------------------------------------------------------------
2331  protected void CreateServerDetailsDialog(Room roomToJoin)
2332  {
2333  if (!roomToJoin)
2334  return;
2335 
2336  // Create details dialog
2337  array<ref SCR_WorkshopItem> items = {};
2338  array<Dependency> dependencies = {};
2339  roomToJoin.GetItems(dependencies);
2340 
2341  if (m_ModsManager.GetRoomItemsScripted().Count() == dependencies.Count())
2342  items = m_ModsManager.GetRoomItemsScripted();
2343 
2344  SCR_ServerDetailsDialog serverDetails = m_Dialogs.CreateServerDetailsDialog(roomToJoin, items, m_OnFavoritesResponse);
2345  serverDetails.SetCanJoin(CanJoinRoom(roomToJoin));
2346  serverDetails.m_OnFavorites.Insert(OnActionFavorite);
2347 
2348  bool loaded = roomToJoin.IsDownloadListLoaded();
2349 
2350  if (!dependencies.IsEmpty())
2351  {
2352  //Fill with last loaded mod list
2353  if (!roomToJoin.IsDownloadListLoaded())
2354  m_ModsManager.GetOnGetAllDependencies().Insert(OnServerDetailModsLoaded);
2355  else
2356  OnServerDetailModsLoaded();
2357  }
2358  else
2359  {
2360  // Fill with emtpy data
2361  m_Dialogs.FillRoomDetailsMods({});
2362  }
2363 
2364  m_Dialogs.GetCurrentDialog().m_OnConfirm.Insert(JoinProcess_LoadModContent);
2365  m_Dialogs.GetCurrentDialog().m_OnClose.Insert(OnServerDetailsClosed);
2366  }
2367 
2368  //------------------------------------------------------------------------------------------------
2370  protected void OnServerDetailModsLoaded()
2371  {
2372  m_Dialogs.FillRoomDetailsMods(m_ModsManager.GetRoomItemsScripted(), m_ModsManager);
2373  m_ModsManager.GetOnGetAllDependencies().Remove(OnServerDetailModsLoaded);
2374  }
2375 
2376  //------------------------------------------------------------------------------------------------
2377  protected void OnServerDetailsClosed(SCR_ConfigurableDialogUi dialog)
2378  {
2379  m_ModsManager.GetOnGetAllDependencies().Remove(OnServerDetailModsLoaded);
2380  }
2381 
2382  //------------------------------------------------------------------------------------------------
2385  protected void JoinProcess_LoadModContent()
2386  {
2387  // Check references
2388  if (!m_Dialogs || !m_ModsManager)
2389  return;
2390 
2391  // Check mods use privilege - UGC privilege
2392  SCR_AddonManager mgr = SCR_AddonManager.GetInstance();
2393  array<Dependency> deps = {};
2394 
2395  m_RoomToJoin.GetItems(deps);
2396 
2397  if (!mgr.GetUgcPrivilege() && !deps.IsEmpty())
2398  {
2399  m_Dialogs.DisplayDialog(EJoinDialogState.MOD_UGC_PRIVILEGE_MISSING);
2400 
2401  // Negotatiate UGC privilege
2402  mgr.m_OnUgcPrivilegeResult.Insert(Platform_OnUgcPrivilegeResult);
2403  mgr.NegotiateUgcPrivilegeAsync();
2404  return;
2405  }
2406 
2407  // Show state of mods if all loaded
2408  JoinProcess_LoadModContentVisualize();
2409  }
2410 
2411  //------------------------------------------------------------------------------------------------
2412  protected void Platform_OnUgcPrivilegeResult(bool result)
2413  {
2414  SCR_AddonManager mgr = SCR_AddonManager.GetInstance();
2415  mgr.m_OnUgcPrivilegeResult.Remove(Platform_OnUgcPrivilegeResult);
2416  if (result)
2417  JoinProcess_LoadModContentVisualize();
2418  }
2419 
2420  //------------------------------------------------------------------------------------------------
2421  protected void JoinProcess_LoadModContentVisualize()
2422  {
2423  // Show state of mods if all loaded
2424  if (m_RoomToJoin.IsDownloadListLoaded())
2425  {
2426  //SolveJoiningCases(); //TODO@wernerjak - solve joining cases function clearing
2427  JoinProcess_CheckModContent();
2428  return;
2429  }
2430 
2431  // Show mods loading dialog
2432  if (m_Dialogs)
2433  m_Dialogs.DisplayDialog(EJoinDialogState.CHECKING_CONTENT);
2434 
2435  // Set wait for loading
2436  m_ModsManager.GetOnGetAllDependencies().Insert(JoinProcess_CheckModContent);
2437  m_ModsManager.GetOnModsFail().Insert(JoinProcess_OnModCheckFailed);
2438  m_ModsManager.GetOnDependenciesLoadingPrevented().Insert(OnDependenciesLoadingPrevented);
2439 
2440  m_ModsManager.ReceiveRoomMods(m_RoomToJoin);
2441  }
2442 
2443  //------------------------------------------------------------------------------------------------
2444  protected void JoinProcess_OnModCheckFailed(Room room)
2445  {
2446  m_Dialogs.CloseCurrentDialog();
2447  OnModListFail(room);
2448 
2449  m_ModsManager.GetOnGetAllDependencies().Remove(JoinProcess_CheckModContent);
2450  m_ModsManager.GetOnModsFail().Remove(JoinProcess_OnModCheckFailed);
2451  m_ModsManager.GetOnDependenciesLoadingPrevented().Remove(OnDependenciesLoadingPrevented);
2452  }
2453 
2454  //------------------------------------------------------------------------------------------------
2455  protected void OnDependenciesLoadingPrevented(Room room, array<ref SCR_WorkshopItem> dependencies)
2456  {
2457  m_Dialogs.CloseCurrentDialog();
2458 
2459  if (room != m_RoomToJoin)
2460  return;
2461 
2462  JoinProcess_CheckModContent();
2463  }
2464 
2465  //------------------------------------------------------------------------------------------------
2469  protected void JoinProcess_CheckModContent()
2470  {
2471  m_Dialogs.CloseCurrentDialog();
2472  m_Dialogs.SetJoinRoom(m_RoomToJoin);
2473 
2474  // Remove mods check actions
2475  m_ModsManager.GetOnGetAllDependencies().Remove(JoinProcess_CheckModContent);
2476  m_ModsManager.GetOnModsFail().Remove(JoinProcess_OnModCheckFailed);
2477  m_ModsManager.GetOnDependenciesLoadingPrevented().Remove(OnDependenciesLoadingPrevented);
2478 
2479  // Restricted content check
2480  array<ref SCR_WorkshopItem> items = m_ModsManager.GetRoomItemsScripted();
2481 
2482  array<ref SCR_WorkshopItem> restricedMods = SCR_AddonManager.SelectItemsOr(items, EWorkshopItemQuery.RESTRICTED);
2483  bool restricted = restricedMods.Count() > 0;
2484 
2485  // Stop join if there are restricted mods
2486  if (restricted)
2487  {
2488  SCR_ReportedAddonsDialog dialog = m_ModsManager.DisplayRestrictedAddonsList();
2489  dialog.GetOnAllReportsCanceled().Insert(JoinProcess_LoadModContentVisualize);
2490  return;
2491  }
2492 
2493  // Get necessary downloads
2494  m_aRequiredMods = SCR_AddonManager.SelectItemsBasic(items, EWorkshopItemQuery.NOT_LOCAL_VERSION_MATCH_DEPENDENCY);
2495 
2496  // If no downloads are required proceed with the joining process, otherwise stop unrelated downloads and get the required addons to join
2497  if (!m_aRequiredMods.IsEmpty())
2498  {
2499  m_aUnrelatedDownloads = m_DownloadManager.GetUnrelatedDownloads(items);
2500 
2501  if (!m_aUnrelatedDownloads.IsEmpty())
2502  JoinProcess_DisplayUnrelatedDownloadsWarning();
2503  else
2504  JoinProcess_DownloadRequiredMods();
2505 
2506  return;
2507  }
2508 
2509  JoinProcess_CheckRunningDownloads();
2510  }
2511 
2512  //------------------------------------------------------------------------------------------------
2513  // Display a dialog asking for unrelated download stop confirmation (this includes wrong versions of required mods)
2514  protected void JoinProcess_DisplayUnrelatedDownloadsWarning()
2515  {
2516  m_Dialogs.DisplayJoinDownloadsWarning(m_aUnrelatedDownloads, SCR_EJoinDownloadsConfirmationDialogType.UNRELATED);
2517  m_Dialogs.GetOnConfirm().Insert(JoinProcess_StopDownloadingUnrelatedMods);
2518  }
2519 
2520  //------------------------------------------------------------------------------------------------
2521  // Pause existing downloads that are unrelated to the specific server we want to join
2522  protected void JoinProcess_StopDownloadingUnrelatedMods()
2523  {
2524  m_Dialogs.GetOnConfirm().Remove(JoinProcess_StopDownloadingUnrelatedMods);
2525 
2526  if (!m_DownloadManager || m_DownloadManager.GetDownloadQueue().IsEmpty())
2527  {
2528  OnAllUnrelatedDownloadsStopped();
2529  return;
2530  }
2531 
2532  // Stop downloads
2533  m_DownloadManager.GetOnAllDownloadsStopped().Insert(OnAllUnrelatedDownloadsStopped);
2534 
2535  foreach (SCR_WorkshopItemActionDownload download : m_aUnrelatedDownloads)
2536  {
2537  download.Cancel();
2538  }
2539 
2540  // Display filler dialog
2541  m_Dialogs.DisplayDialog(EJoinDialogState.UNRELATED_DOWNLOADS_CANCELING);
2542 
2543  //TODO: pause downloads instead of clearing them, and allow the player to resume them once out of multiplayer games
2544  //TODO: give the option to keep downloading while playing multiplayer?
2545  }
2546 
2547  //------------------------------------------------------------------------------------------------
2548  protected void OnAllUnrelatedDownloadsStopped()
2549  {
2550  if (m_DownloadManager)
2551  m_DownloadManager.GetOnAllDownloadsStopped().Remove(OnAllUnrelatedDownloadsStopped);
2552 
2553  // Must call the next frame or the download will instantly fail
2554  GetGame().GetCallqueue().CallLater(JoinProcess_CloseUnrelatedDownloadsCancelingDialog);
2555  }
2556 
2557  //------------------------------------------------------------------------------------------------
2558  protected void JoinProcess_CloseUnrelatedDownloadsCancelingDialog()
2559  {
2560  m_Dialogs.GetCurrentDialog().Close();
2561  JoinProcess_DownloadRequiredMods();
2562  }
2563 
2564  //------------------------------------------------------------------------------------------------
2565  // Start downloading necessary mods for the server
2566  protected void JoinProcess_DownloadRequiredMods()
2567  {
2568  if (m_DownloadManager)
2569  m_DownloadManager.DownloadItems(m_aRequiredMods);
2570 
2571  m_Dialogs.DisplayJoinDownloadsWarning(m_DownloadManager.GetDownloadQueue(), SCR_EJoinDownloadsConfirmationDialogType.REQUIRED);
2572 
2573  // Display Download Manager dialog
2574  m_Dialogs.GetOnDownloadComplete().Insert(JoinProcess_OnJoinRoomDemand);
2575  m_Dialogs.GetOnCancel().Insert(OnDownloadRequiredModsCancel);
2576  }
2577 
2578  //------------------------------------------------------------------------------------------------
2579  protected void OnDownloadRequiredModsCancel()
2580  {
2581  m_Dialogs.GetOnCancel().Remove(OnDownloadRequiredModsCancel);
2582 
2583  if (m_DownloadManager)
2584  {
2585  m_DownloadManager.EndAllDownloads();
2586  m_DownloadManager.ClearFailedDownloads();
2587  }
2588  }
2589 
2590  //------------------------------------------------------------------------------------------------
2591  protected void JoinProcess_OnJoinRoomDemand(Room roomToJoin)
2592  {
2593  m_Dialogs.GetOnDownloadComplete().Remove(JoinProcess_OnJoinRoomDemand);
2594 
2595  m_RoomToJoin = roomToJoin;
2596  JoinProcess_CheckRunningDownloads();
2597  }
2598 
2599  //------------------------------------------------------------------------------------------------
2601  protected void JoinProcess_CheckRunningDownloads()
2602  {
2603  int nCompleted, nTotal;
2604  SCR_DownloadManager mgr = SCR_DownloadManager.GetInstance();
2605 
2606  if (m_DownloadManager)
2607  m_DownloadManager.GetDownloadQueueState(nCompleted, nTotal);
2608 
2609  if (nTotal <= 0)
2610  {
2611  JoinProcess_Join();
2612  return;
2613  }
2614 
2615  m_Dialogs.DisplayJoinDownloadsWarning(m_DownloadManager.GetDownloadQueue(), SCR_EJoinDownloadsConfirmationDialogType.REQUIRED);
2616  m_Dialogs.GetOnConfirm().Insert(OnInterruptDownloadConfirm);
2617 
2618  }
2619 
2620  //------------------------------------------------------------------------------------------------
2621  protected void OnInterruptDownloadConfirm()
2622  {
2623  if (!m_RoomToJoin)
2624  {
2625  PrintDebug("Missing m_RoomToJoin!", "OnInteruptDownloadConfirm");
2626  return;
2627  }
2628 
2629  // TODO: pause and cache instead of canceling
2630  // Cancel downloading
2631  SCR_DownloadManager mgr = SCR_DownloadManager.GetInstance();
2632  if (mgr)
2633  mgr.EndAllDownloads();
2634 
2635  JoinProcess_Join();
2636  }
2637 
2638  //------------------------------------------------------------------------------------------------
2639  // Join ...Finally!
2640  protected void JoinProcess_Join()
2641  {
2642  // Add join callbacks
2643  if (!m_CallbackJoin)
2644  m_CallbackJoin = new ServerBrowserCallback;
2645  m_CallbackJoin.m_OnSuccess.Insert(JoinProcess_OnJoinSuccess);
2646  m_CallbackJoin.m_OnFail.Insert(JoinProcess_OnJoinFail);
2647  m_CallbackJoin.m_OnTimeOut.Insert(JoinProcess_OnJoinTimeout);
2648 
2649  // Join server
2650  m_RoomToJoin.Join(m_CallbackJoin, m_JoinData);
2651 
2652  if (m_Dialogs)
2653  m_Dialogs.DisplayDialog(EJoinDialogState.JOIN);
2654  }
2655 
2656  //------------------------------------------------------------------------------------------------
2659  protected void JoinProcess_OnJoinSuccess(ServerBrowserCallback callback)
2660  {
2661  // Connect - gathers mods needed and calls for a reload
2662  if (!GameStateTransitions.RequestConnectViaRoom(m_RoomToJoin))
2663  return; // Transition is not guaranteed
2664 
2665  // Save menu to reopen
2666  SCR_MenuLoadingComponent.SaveLastMenu(ChimeraMenuPreset.ServerBrowserMenu);
2667 
2668  // Cleanups - TODO@wernerjak - remove this cleaning to on function with other cleaning?
2669  m_RoomToJoin = null;
2670  GetGame().GetMenuManager().CloseAllMenus();
2671  GetGame().GetBackendApi().GetWorkshop().Cleanup();
2672 
2673  JoinProcess_Clear();
2674  }
2675 
2676  //------------------------------------------------------------------------------------------------
2677  protected void JoinProcess_OnJoinFail(ServerBrowserCallback callback, int code, int restCode, int apiCode)
2678  {
2679  JoinProcess_Clear();
2680 
2681  if (!m_Dialogs)
2682  return;
2683 
2684  // Server is full
2685  if (apiCode == EApiCode.EACODE_ERROR_MP_ROOM_IS_FULL)
2686  {
2687  m_Dialogs.SetJoinRoom(m_RoomToJoin);
2688  m_Dialogs.GetOnJoinRoomDemand().Insert(JoinProcess_OnJoinRoomDemand);
2689 
2690  m_Dialogs.DisplayDialog(EJoinDialogState.QUEUE_WAITING);
2691  GetGame().GetBackendApi().GetClientLobby().SetRefreshCallback(m_CallbackAutoRefresh);
2692 
2693  return;
2694  }
2695 
2696  // Banned
2697  if (!m_JoinData.scope.IsEmpty())
2698  m_Dialogs.DisplayJoinBan(m_JoinData);
2699  // Generic
2700  else
2701  m_Dialogs.DisplayJoinFail(apiCode);
2702  }
2703 
2704  //------------------------------------------------------------------------------------------------
2706  protected void JoinProcess_OnJoinTimeout(ServerBrowserCallback callback)
2707  {
2708  JoinProcess_Clear();
2709  m_Dialogs.CloseCurrentDialog();
2710  SCR_CommonDialogs.CreateTimeoutOkDialog();
2711  }
2712 
2713  //------------------------------------------------------------------------------------------------
2715  protected void JoinProcess_Clear()
2716  {
2717  m_CallbackJoin = null;
2718 
2719  ClientLobbyApi lobby = GetGame().GetBackendApi().GetClientLobby();
2720  lobby.ClearInviteRoom();
2721 
2722  // Clear mods manager callbacks
2723  m_ModsManager.GetOnGetAllDependencies().Clear();
2724  m_ModsManager.GetOnModsFail().Clear();
2725  m_ModsManager.GetOnDependenciesLoadingPrevented().Clear();
2726  m_ModsManager.GetOnGetScenario().Clear();
2727 
2728  // Clear dialog
2729  m_Dialogs.GetOnConfirm().Clear();
2730  m_Dialogs.GetOnCancel().Clear();
2731  m_Dialogs.GetOnDialogClose().Clear();
2732  m_Dialogs.GetOnDownloadComplete().Clear();
2733  m_Dialogs.GetOnDownloadCancelDialogClose().Clear();
2734  m_Dialogs.GetOnJoinRoomDemand().Clear();
2735 
2736  // TODO: remove specific subscriptions instead of clearing!
2737  }
2738 
2739  //------------------------------------------------------------------------------------------------
2741  protected void SetupJoinDialogs()
2742  {
2743  // Check dialog
2744  if (!m_Dialogs)
2745  return;
2746 
2747  // Setup basics
2748  m_Dialogs.SetServerBrowser(this);
2749  m_Dialogs.SetModManager(m_ModsManager);
2750 
2751  // Invokers
2752  m_Dialogs.GetOnDownloadComplete().Clear();
2753  m_Dialogs.GetOnCancel().Insert(JoinProcess_Clear);
2754 
2755  m_CallbackLastSearch = null;
2756  }
2757 
2758  //------------------------------------------------------------------------------------------------
2760  //------------------------------------------------------------------------------------------------
2761  //------------------------------------------------------------------------------------------------
2763  protected void NegotiateMPPrivilegeAsync()
2764  {
2765  if (!m_CallbackGetPrivilege)
2766  {
2767  m_CallbackGetPrivilege = new SCR_ScriptPlatformRequestCallback();
2768  m_CallbackGetPrivilege.m_OnResult.Insert(OnMPPrivilegeResult);
2769  }
2770 
2771  GetGame().GetPlatformService().GetPrivilegeAsync(UserPrivilege.MULTIPLAYER_GAMEPLAY, m_CallbackGetPrivilege);
2772  }
2773 
2774  //------------------------------------------------------------------------------------------------
2776  protected void NegotiatePrivilegeAsync(UserPrivilege privilege)
2777  {
2778  if (!m_CallbackGetPrivilege)
2779  m_CallbackGetPrivilege = new SCR_ScriptPlatformRequestCallback();
2780 
2781  switch (privilege)
2782  {
2783  case UserPrivilege.MULTIPLAYER_GAMEPLAY:
2784  {
2785  m_CallbackGetPrivilege.m_OnResult.Insert(OnMPPrivilegeResult);
2786  break;
2787  }
2788 
2789  case UserPrivilege.CROSS_PLAY:
2790  {
2791  m_CallbackGetPrivilege.m_OnResult.Insert(OnCrossPlayPrivilegeResult);
2792  break;
2793  }
2794  }
2795 
2796  GetGame().GetPlatformService().GetPrivilegeAsync(privilege, m_CallbackGetPrivilege);
2797  }
2798 
2799  //------------------------------------------------------------------------------------------------
2800  protected void OnMPPrivilegeResult(UserPrivilege privilege, UserPrivilegeResult result)
2801  {
2802  // Sucessful
2803  if (privilege == UserPrivilege.MULTIPLAYER_GAMEPLAY && result == UserPrivilegeResult.ALLOWED)
2804  Refresh();
2805 
2806  m_CallbackGetPrivilege.m_OnResult.Remove(OnMPPrivilegeResult);
2807  }
2808 
2809  //------------------------------------------------------------------------------------------------
2810  protected void OnCrossPlayPrivilegeResult(UserPrivilege privilege, UserPrivilegeResult result)
2811  {
2812  // Sucessful
2813  if (privilege == UserPrivilege.CROSS_PLAY && result == UserPrivilegeResult.ALLOWED)
2814  Refresh();
2815 
2816  m_CallbackGetPrivilege.m_OnResult.Remove(OnCrossPlayPrivilegeResult);
2817  }
2818 
2819  //------------------------------------------------------------------------------------------------
2820  // DEBUG
2821  //------------------------------------------------------------------------------------------------
2822  //------------------------------------------------------------------------------------------------
2824  protected void PrintDebug(string msg, string functionName = string.Empty)
2825  {
2826  #ifdef SB_DEBUG
2827  //Setup function format
2828  string fncStr = string.Empty;
2829  if (functionName != string.Empty)
2830  fncStr = string.Format(" Fnc: %1()", functionName);
2831 
2832  // Display message
2833  PrintFormat("[ServerBrowserMenuUI]%1 -- Msg: %2", fncStr, msg);
2834  #endif
2835  }
2836 }
2837 
2838 //------------------------------------------------------------------------------------------------
2840 class SCR_GetRoomsIds extends GetRoomsIds
2841 {
2842  protected ref array<string> roomIds = {};
2843 
2844  //------------------------------------------------------------------------------------------------
2845  void RegisterId(string id)
2846  {
2847  roomIds.Insert(id);
2848  RegV("roomIds");
2849  }
2850 
2851  //------------------------------------------------------------------------------------------------
2852  void ClearIds()
2853  {
2854  roomIds.Clear();
2855  }
2856 }
ServerBrowserMenuWidgets
Definition: ServerBrowserMenuWidgets.c:5
SCR_FilterEntry
Definition: SCR_FilterSet.c:9
m_WorkshopApi
protected WorkshopApi m_WorkshopApi
Definition: SCR_ContentBrowser_AddonsSubMenu.c:48
SCR_KickDialogs
Definition: SCR_KickDialogs.c:1
UIConstants
Definition: Constants.c:130
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
SCR_ScriptPlatformRequestCallback
Definition: SCR_OnlineServiceWorkshop.c:2
RegisterId
void RegisterId(string id)
Definition: ServerBrowserMenuUI.c:2845
EDirectJoinFormats
EDirectJoinFormats
Definition: MultiplayerDialogUI.c:259
SCR_FilterCategory
Definition: SCR_FilterSet.c:65
SCR_CommonDialogs
Definition: CommonDialogs.c:5
SCR_WorkshopItemActionDownload
Definition: SCR_WorkshopItemActionDownload.c:9
IsPlatformGameConsole
bool IsPlatformGameConsole()
Definition: game.c:1393
SCR_FilterSet
Definition: SCR_FilterSet.c:183
SCR_ServerBrowserEntryComponent
This component handles server entry and visiualization of server data.
Definition: SCR_ServerBrowserEntryComponent.c:2
m_TabView
protected SCR_TabViewComponent m_TabView
Definition: SCR_EntitiesToolbarEditorUIComponent.c:39
ClearIds
void ClearIds()
Definition: ServerBrowserMenuUI.c:2852
func
func
Definition: SCR_AIThreatSystem.c:5
ServerBrowserCallback
Callback for searching servers dirrecly.
Definition: ServerBrowserMenuCallbacks.c:112
m_Widgets
ref SCR_VoNOverlay_ElementWidgets m_Widgets
Definition: SCR_VonDisplay.c:3
SCR_TabViewComponent
Definition: SCR_TabViewComponent.c:13
SCR_ServerBrowserDialogManager
Definition: SCR_ServerBrowserDialogManager.c:7
GetRootWidget
Widget GetRootWidget()
Definition: SCR_UITaskManagerComponent.c:160
EJoinDialogState
EJoinDialogState
Enum for tracking current state of joining process.
Definition: SCR_ServerBrowserDialogManager.c:626
SCR_BackendCallback
Scripted backend callback class unifying backend response.
Definition: SCR_BackendCallback.c:21
SCR_FilterPanelComponent
Definition: SCR_FilterPanelComponent.c:11
SCR_ServerScenarioDetailsPanelComponent
Definition: SCR_ServerScenarioDetailsPanelComponent.c:6
GameStateTransitions
Definition: GameStateTransitions.c:12
MenuRootBase
Definition: MenuRootBase.c:6
m_ModsManager
protected SCR_RoomModsManager m_ModsManager
Definition: SCR_ServerBrowserEntryComponent.c:52
MultiplayerDialogUI
Definition: MultiplayerDialogUI.c:2
GetOwner
IEntity GetOwner()
Owner entity of the fuel tank.
Definition: SCR_FuelNode.c:128
SCR_RoomPasswordVerification
Definition: SCR_RoomPasswordVerification.c:6
SCR_ServerDetailsDialog
Definition: SCR_ServerDetailsDialog.c:7
SCR_RoomCallback
Scripted room callback specific for single room.
Definition: ServerBrowserMenuCallbacks.c:151
SCR_PooledServerListComponent
Pooled scrollable list with server entries handling.
Definition: SCR_PooledListServerComponent.c:2
SCR_ReportedAddonsDialog
Show list of reported mods and provide option to cancel reports.
Definition: SCR_ReportedAddonsDialog.c:3
SCR_ServicesStatusHelper
Definition: SCR_ServicesStatusHelper.c:15
SCR_ListMenuEntryComponent
Definition: SCR_ListMenuEntryComponent.c:9
ScriptInvokerVoid
ScriptInvokerBase< ScriptInvokerVoidMethod > ScriptInvokerVoid
Definition: SCR_ScriptInvokerHelper.c:9
SCR_RoomModsManager
Definition: SCR_RoomModsManager.c:27
GetInputManager
protected InputManager GetInputManager()
Definition: SCR_BaseManualCameraComponent.c:65
ChimeraMenuPreset
ChimeraMenuPreset
Menu presets.
Definition: ChimeraMenuBase.c:3
SCR_SimpleMessageComponent
Definition: SCR_SimpleMessageComponent.c:1
SCR_ConfigurableDialogUi
Definition: SCR_ConfigurableDialogUI.c:13
SCR_AddonManager
Definition: SCR_AddonManager.c:72
EBackendCallbackResponse
EBackendCallbackResponse
Basic callback responses.
Definition: SCR_BackendCallback.c:12
SCR_EditBoxComponent
Definition: SCR_EditBoxComponent.c:8
SCR_MenuActionsComponent
Definition: SCR_MenuActionsComponent.c:9
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
FilteredServerParams
Server search filtering.
Definition: ServerBrowserFiltering.c:7
EServerBrowserRequestResult
EServerBrowserRequestResult
Definition: ServerBrowserMenuCallbacks.c:6
SCR_ScriptedWidgetComponent
Definition: SCR_ScriptedWidgetComponent.c:7
SCR_EJoinDownloadsConfirmationDialogType
SCR_EJoinDownloadsConfirmationDialogType
Enum for confirmation dialogs that guide the player through the download processes required to join t...
Definition: SCR_ServerBrowserDialogManager.c:663
callback
DownloadConfigCallback callback
SCR_DownloadManager
Definition: SCR_DownloadManager.c:20
SCR_SortHeaderComponent
Definition: SCR_SortHeaderComponent.c:7
roomIds
ServerBrowserMenuUI roomIds
Overrided GetRoomsIds class to manipulation in script.
SCR_EditBoxSearchComponent
Definition: SCR_EditBoxSearchComponent.c:2
ServerBrowserMenuUI
Definition: ServerBrowserMenuUI.c:10
SCR_CoreMenuHeaderComponent
Definition: SCR_CoreMenuHeaderComponent.c:6
EWorkshopItemQuery
EWorkshopItemQuery
Definition: SCR_AddonManager.c:34
ScriptInvokerRoom
ScriptInvokerBase< ScriptInvokerRoomMethod > ScriptInvokerRoom
Definition: ServerBrowserMenuUI.c:8
ESortOrder
ESortOrder
Definition: SCR_SortElementComponent.c:1
ScriptInvokerRoomMethod
func ScriptInvokerRoomMethod
Definition: ServerBrowserMenuUI.c:7