Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ServicesStatusHelper.c
Go to the documentation of this file.
4 NOT_EXECUTED = 0, // No backend
5 RUNNING, // Still pinging
6 FINISHED, // Success
7 FAILED // Lost connection
8}
9
10void ScriptInvokerCommStatusMethod(SCR_ECommStatus status, float responseTime, float lastSuccessTime, float lastFailTime);
12typedef ScriptInvokerBase<ScriptInvokerCommStatusMethod> ScriptInvokerCommStatus;
13
14//------------------------------------------------------------------------------------------------
16{
17 protected static int s_iLastPingUpdate = -1;
18 protected static int s_iLastStatusUpdate = -1;
20 protected static const ref array<ServiceStatusItem> SERVICE_STATUSES = {};
21
22 // Timers
23 protected static const int COMM_STATUS_CHECK_FREQUENCY_MS = 500; // frequency of checking for comm test response
24 protected static const int FIRST_REFRESH_DELAY = 1000; // wait a bit for the very first refresh
25
26 static const int REFRESH_COOLDOWN = 10000; // minimum ping age to allow for refreshing
27 static const int CONNECTION_CHECK_EXPIRE_TIME = 15000; // fallback in case pinging hangs, considered failed after this time has passed
28 static const int AUTOMATIC_REFRESH_RATE = 60000; // time after which a refresh request is automatically triggered
29
30 // Statuses
31 static const string STATUS_OK = "ok";
32 static const string STATUS_ERROR = "error";
33
34 // Services
35 static const string SERVICE_ACCOUNT_PROFILE = "game-identity";
36 static const string SERVICE_XBOX = "game-identity";
37 static const string SERVICE_BI_BACKEND_MULTIPLAYER = "game-api";
38 static const string SERVICE_WORKSHOP = "reforger-workshop-api";
39
40 // Ping thresholds
41 static const int PING_MAX = 999;
42 static const int PING_THRESHOLD_GOOD = 100;
43 static const int PING_THRESHOLD_BAD = 300;
44 static const int PING_THRESHOLD_AWFUL = 600;
45
47 protected static bool s_bIsCheckingCommStatus;
48 protected static float s_fLastReceivedCommResponseTime;
49
50 protected static float s_fPingStartTime;
51
52 protected static bool s_bFirstRefresh = true;
53
54 // Invokers
57
58 //------------------------------------------------------------------------------------------------
60 static bool IsBackendEnabled()
61 {
62 return GetGame().GetBackendApi() && GetGame().GetBackendApi().IsRunning();
63 }
64
65 //------------------------------------------------------------------------------------------------
67 static bool IsBackendReady()
68 {
69 return GetGame().GetBackendApi() && GetGame().GetBackendApi().IsActive();
70 }
71
72 //------------------------------------------------------------------------------------------------
74 static bool IsAuthenticated()
75 {
76 return IsBackendReady() && BackendAuthenticatorApi.IsAuthenticated();
77 }
78
79 //------------------------------------------------------------------------------------------------
80 // PING
81 //------------------------------------------------------------------------------------------------
82
83 //------------------------------------------------------------------------------------------------
85 protected static bool IsPinging()
86 {
87 return GetGame().GetBackendApi() && GetGame().GetBackendApi().GetCommTestStatus() == 1;
88 }
89
90 //------------------------------------------------------------------------------------------------
93 // TODO: add a force refresh for when certain important menus are opened? eg we want to disable buttons to open multiplayer or workshop
94 static void RefreshPing()
95 {
96 if (!GetGame() || !GetGame().InPlayMode())
97 return;
98
99 if (!s_bFirstRefresh && !CanRefresh())
100 {
101 // If we receive a refresh request while in cooldown (for example when a new menu is opened), refresh automatically to update the UI asap
103 {
105 GetGame().GetCallqueue().CallLater(RefreshPing, (REFRESH_COOLDOWN - GetPingAge()) + 100);
106 }
107
108 return;
109 }
110
112
113 if (s_bFirstRefresh)
114 {
115 s_bFirstRefresh = false;
117
118 // TODO: when testing without workbench, immediatly refreshing will cause GetCommTestStatus() to return 0 even if backend is initialized?!
119 GetGame().GetCallqueue().CallLater(RefreshPing_Internal, FIRST_REFRESH_DELAY);
120 return;
121 }
122
124 }
125
126 //------------------------------------------------------------------------------------------------
127 protected static void RefreshPing_Internal()
128 {
129 // Start pinging to get the current status
130 if (IsBackendReady())
131 GetGame().GetBackendApi().RefreshCommStatus();
132 else
134
135 s_fPingStartTime = System.GetTickCount();
136
138 }
139
140 //------------------------------------------------------------------------------------------------
141 protected static void StartStatusCheck()
142 {
144
147
148 // This will perform regular checks for backend initialization or communication status, untill a result is obtained or a set amount of time has passed
149 GetGame().GetCallqueue().CallLater(CheckStatus, COMM_STATUS_CHECK_FREQUENCY_MS);
150 }
151
152 //------------------------------------------------------------------------------------------------
153 protected static void CheckStatus()
154 {
156
157 if (IsBackendReady())
159 else
161 }
162
163 //------------------------------------------------------------------------------------------------
164 // Try to give a definitive result
165 // Once a result is out, this is also where the refresh cooldown starts, as it's based on s_iLastPingUpdate
166 protected static void CheckCommStatus()
167 {
168 BackendApi backend = GetGame().GetBackendApi();
169
170 // Still pinging, need to wait some more to get definitive results
171 if (IsPinging() && !IsPingingStuck())
172 {
174
176 return;
177 }
178
179 // At this point, the comm test result should be either 0, 2 or 3
180 if (!backend || IsPingingStuck() || !IsBackendReady())
182 else
183 s_eLastReceivedCommStatus = backend.GetCommTestStatus();
184
185 // If the comm test went well, update statuses
188
189 s_iLastPingUpdate = System.GetTickCount();
190 s_fLastReceivedCommResponseTime = backend.GetCommResponseTime();
191
192 // Notify that results are out
194 s_OnCommStatusCheckFinished.Invoke(s_eLastReceivedCommStatus, s_fLastReceivedCommResponseTime, backend.GetCommTimeLastSuccess(), backend.GetCommTimeLastFail());
195 }
196
197 //------------------------------------------------------------------------------------------------
198 // Wait for backend to be ready and then try again
199 protected static void CheckBackendStatus()
200 {
201 // After some time stop checking and move on to giving a result
202 if (!GetGame().GetBackendApi() || IsPingingStuck())
203 {
205 return;
206 }
207
208 if (IsBackendReady())
210 else
212 }
213
214 //------------------------------------------------------------------------------------------------
216 static void ClearRefreshQueue()
217 {
218 GetGame().GetCallqueue().Remove(RefreshPing);
219 }
220
221 //------------------------------------------------------------------------------------------------
227
228 //------------------------------------------------------------------------------------------------
231 static int GetPingValue()
232 {
234 return -1;
235
237 }
238
239 //------------------------------------------------------------------------------------------------
241 static int GetPingAge()
242 {
243 return System.GetTickCount() - s_iLastPingUpdate;
244 }
245
246 //------------------------------------------------------------------------------------------------
249 // We want to still allow attempting a refresh if backend is not initialized
250 static bool CanRefresh()
251 {
253 }
254
255 //------------------------------------------------------------------------------------------------
258 {
259 return GetPingAge() < REFRESH_COOLDOWN;
260 }
261
262 //------------------------------------------------------------------------------------------------
264 static bool IsPingingStuck()
265 {
266 return System.GetTickCount() - s_fPingStartTime >= CONNECTION_CHECK_EXPIRE_TIME;
267 }
268
269 //------------------------------------------------------------------------------------------------
270 // STATUSES
271 //------------------------------------------------------------------------------------------------
272 //------------------------------------------------------------------------------------------------
274 static void RefreshStatuses()
275 {
276 if (!IsBackendReady())
277 return;
278
279 s_MainStatus = GetGame().GetBackendApi().GetMainStatus();
280
281 SERVICE_STATUSES.Clear();
283 for (int i, cnt = GetGame().GetBackendApi().GetStatusCount(); i < cnt; i++)
284 {
285 item = GetGame().GetBackendApi().GetStatusItem(i);
286 if (item)
287 SERVICE_STATUSES.Insert(item);
288 }
289
290 s_iLastStatusUpdate = System.GetTickCount();
291
292 #ifdef SERVICES_DEBUG
293 DEBUG();
294 #endif
295 }
296
297 //------------------------------------------------------------------------------------------------
300 {
301 return s_MainStatus;
302 }
303
304 //------------------------------------------------------------------------------------------------
307 static ServiceStatusItem GetStatusByName(string statusName)
308 {
309 ServiceStatusItem result;
310
311 statusName.ToLower();
312 string serviceNameLC;
313
314 foreach (ServiceStatusItem statusItem : SERVICE_STATUSES)
315 {
316 serviceNameLC = statusItem.Name();
317 serviceNameLC.ToLower();
318
319 if (serviceNameLC == statusName)
320 return statusItem;
321 }
322
323 return result;
324 }
325
326 //------------------------------------------------------------------------------------------------
328 static void GetStatuses(notnull array<ServiceStatusItem> statuses)
329 {
330 statuses.Copy(SERVICE_STATUSES);
331 }
332
333 //------------------------------------------------------------------------------------------------
336 static bool AreServicesReady()
337 {
338 return s_MainStatus && !SERVICE_STATUSES.IsEmpty();
339 }
340
341 //------------------------------------------------------------------------------------------------
343 static int GetStatusesAge()
344 {
345 if (!IsBackendReady())
346 return -1;
347
348 return Math.Round((System.GetTickCount() - s_iLastStatusUpdate) * 0.001);
349 }
350
351 //------------------------------------------------------------------------------------------------
356 {
357 switch (System.GetPlatform())
358 {
359 case EPlatform.UNKNOWN:
360 {
361 return false;
362 }
363 case EPlatform.WINDOWS:
364 case EPlatform.LINUX:
365 {
366 return SCR_Enum.HasFlag(service.m_ePlatforms, SCR_EBackendServicePlatforms.PC);
367 }
368 case EPlatform.XBOX_ONE:
369 case EPlatform.XBOX_ONE_S:
370 case EPlatform.XBOX_ONE_X:
371 case EPlatform.XBOX_SERIES_S:
372 case EPlatform.XBOX_SERIES_X:
373 {
374 return SCR_Enum.HasFlag(service.m_ePlatforms, SCR_EBackendServicePlatforms.XBOX);
375 }
376 case EPlatform.PS4:
377 case EPlatform.PS5:
378 case EPlatform.PS5_PRO:
379 {
380 return SCR_Enum.HasFlag(service.m_ePlatforms, SCR_EBackendServicePlatforms.PS);
381 }
382 }
383
384 return false;
385 }
386
387 //------------------------------------------------------------------------------------------------
390 static bool IsServiceActive(string serviceName)
391 {
393 return false;
394
395 ServiceStatusItem serviceStatus = GetStatusByName(serviceName);
396 if (!serviceStatus)
397 return false;
398
399 return serviceStatus.Status() == STATUS_OK;
400 }
401
402 //------------------------------------------------------------------------------------------------
405 // Check if all conditions for multiplayer are fine in here
410
411 //------------------------------------------------------------------------------------------------
417
418 //------------------------------------------------------------------------------------------------
419 // INVOKERS
420 //------------------------------------------------------------------------------------------------
429
430 //------------------------------------------------------------------------------------------------
439
440 //------------------------------------------------------------------------------------------------
442 static void DEBUG()
443 {
444 Print("--------------------------------------------------");
445 Print("SERVICE STATUS DEBUG");
446 Print("--------------------------------------------------");
447 if (!GetGame().GetBackendApi())
448 {
449 Print("no backend API found.");
450 return;
451 }
452
453 Print("is main service found: " + (GetGame().GetBackendApi().GetMainStatus() != null));
454 Print("number of services found: " + GetGame().GetBackendApi().GetStatusCount());
455
456 if (s_MainStatus)
457 PrintFormat("Service %1: %2 (Name/Status/Message: %3/%4/%5)", -1, s_MainStatus, s_MainStatus.Name(), s_MainStatus.Status(), s_MainStatus.Message());
458 else
459 Print("Main Status not found");
460
461 foreach (int index, ServiceStatusItem statusItem : SERVICE_STATUSES)
462 {
463 if (statusItem)
464 PrintFormat("Service %1: %2 (Name/Status/Message: %3/%4/%5)", index, statusItem, statusItem.Name(), statusItem.Status(), statusItem.Message());
465 }
466
467 Print("--------------------------------------------------");
468 }
469}
470
471//------------------------------------------------------------------------------------------------
473[BaseContainerProps(configRoot : true)]
474class SCR_BackendServiceDisplayPresets
475{
476 [Attribute()]
477 protected ref array<ref SCR_BackendServiceDisplay> m_aServices;
478
479 //------------------------------------------------------------------------------------------------
481 array<ref SCR_BackendServiceDisplay> GetServices()
482 {
483 array<ref SCR_BackendServiceDisplay> services = {};
484 if (m_aServices)
485 services = m_aServices;
486
487 return services;
488 }
489}
490
491//------------------------------------------------------------------------------------------------
494{
495 [Attribute(desc: "internal tag")]
496 string m_sId;
497
498 [Attribute(desc: "the id used to query backend")]
499 string m_sServiceId;
500
501 [Attribute(desc: "displayed name")]
502 string m_sTitle;
503
504 [Attribute(typename.EnumToString(SCR_EBackendServicePlatforms, SCR_EBackendServicePlatforms.PC), UIWidgets.Flags, "", "Platforms this service should be displayed on", ParamEnumArray.FromEnum(SCR_EBackendServicePlatforms))]
505 SCR_EBackendServicePlatforms m_ePlatforms;
506}
507
508//------------------------------------------------------------------------------------------------
509enum SCR_EBackendServicePlatforms
510{
511 PC = 1 << 0,
512 XBOX = 1 << 1,
513 PS = 1 << 2
514}
ArmaReforgerScripted GetGame()
Definition game.c:1398
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
@ FAILED
Job failed during its processing and can be retried.
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
SCR_Faction ScriptedFaction SCR_BaseContainerCustomTitleField("m_sCallsign")
int GetServices(out array< SCR_ServicePointComponent > services=null)
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
ScriptInvokerBase< ScriptInvokerVoidMethod > ScriptInvokerVoid
ScriptInvokerBase< ScriptInvokerCommStatusMethod > ScriptInvokerCommStatus
class SCR_BackendServiceDisplay PC
func ScriptInvokerCommStatusMethod
SCR_ECommStatus
This class may become obsolete on BackendAPI update.
class SCR_BackendServiceDisplay XBOX
Backend Api instance.
Definition BackendApi.c:14
Definition Math.c:13
static bool IsServiceActive(string serviceName)
static const int COMM_STATUS_CHECK_FREQUENCY_MS
static const string SERVICE_ACCOUNT_PROFILE
static ServiceStatusItem GetMainStatus()
static ServiceStatusItem s_MainStatus
static ScriptInvokerCommStatus GetOnCommStatusCheckFinished()
static const ref array< ServiceStatusItem > SERVICE_STATUSES
static const int CONNECTION_CHECK_EXPIRE_TIME
static ref ScriptInvokerCommStatus s_OnCommStatusCheckFinished
static ScriptInvokerVoid GetOnCommStatusCheckStart()
static bool DisplayServiceOnCurrentPlatform(SCR_BackendServiceDisplay service)
static void GetStatuses(notnull array< ServiceStatusItem > statuses)
static int GetStatusesAge()
Return statuses age IN SECONDS.
static SCR_ECommStatus s_eLastReceivedCommStatus
static SCR_ECommStatus GetLastReceivedCommStatus()
static const string SERVICE_BI_BACKEND_MULTIPLAYER
static ServiceStatusItem GetStatusByName(string statusName)
static int GetPingAge()
Return the last ping's age in milliseconds.
static ref ScriptInvokerVoid s_OnCommStatusCheckStart
Service status item.
@ RUNNING
@ FINISHED
Job was successfully finished.
Definition ENodeResult.c:19
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
SCR_FieldOfViewSettings Attribute
EPlatform
Definition EPlatform.c:13