DayZ 1.30
DayZ Explorer by KGB
 
Загрузка...
Поиск...
Не найдено
BunkerBroadcastHandler.c
См. документацию.
1//#ifdef DIAG_DEVELOPER
2//#define BUNKER_BROADCAST_CHEAT_CODE
3//#endif
4
10
11class BunkerBroadcastHandlerPersistenceData
12{
14}
15
17{
18 private const string STORAGE_PATH = "$mission:BunkerBroadcastPersistenceStorage.bin";
19
21 ref BunkerBroadcastHandlerPersistenceData m_HandlerData;
22
24
25 private bool m_Loaded;
26
27 // --------------------------------------------------------------------------------
28
30 {
31 m_HandlerData = new BunkerBroadcastHandlerPersistenceData();
33
34 m_Loaded = Load();
35 }
36
37 // --------------------------------------------------------------------------------
38
46
47 // --------------------------------------------------------------------------------
48
49 bool IsLoaded()
50 {
51 return m_Loaded;
52 }
53
54 // --------------------------------------------------------------------------------
55
56 bool Load()
57 {
58 FileSerializer file = new FileSerializer();
59 if (file.Open(STORAGE_PATH, FileMode.READ))
60 {
61 file.Read(m_HandlerData);
63 file.Close();
64
65 return true;
66 }
67
68 return false;
69 }
70
71 // --------------------------------------------------------------------------------
72
73 void Save()
74 {
75 FileSerializer file = new FileSerializer();
76 if (file.Open(STORAGE_PATH, FileMode.WRITE))
77 {
78 file.Write(m_HandlerData);
80 file.Close();
81 }
82 }
83}
84
85class BunkerBroadcastLockCodeMode
86{
87 const int DIGITSONLY = 0;
88 const int ALPHANUMERIC = 1;
89}
90
92
94{
95 protected const int LOCK_CODE_HISTORY_LENGTH = 5;
96
97 protected const int UPDATE_BATCH_SIZE = 10;
98 protected const float UPDATE_TIME = 10.0;
99
104
105 protected bool m_ConfigLoaded;
106 protected bool m_CanUpdate;
107 protected bool m_ProcessComponents;
108 protected bool m_ProcessingFinished;
109 protected int m_NextToProcessIdx;
110 protected float m_UpdateTimer;
111
114 protected ref BunkerBroadcastConfigInstance m_Config;
115
116 protected ref SimpleCircularBuffer<string> m_LockCodeHistory;
117 protected ref SimpleCircularBuffer<int> m_ActiveBunkersHistory;
118
120
122
125
126 #ifdef DIAG_DEVELOPER
127 static ref BunkerComponentsArray m_RegisteredBunkersStorage;
128 static ref TIntArray m_BunkersHistoryStorage;
129 static bool m_LoggingEnabled;
130 #endif
131
132 // --------------------------------------------------------------------------------
133
135 {
136 if (!m_Instance)
138
139 return m_Instance;
140 }
141
142 // --------------------------------------------------------------------------------
143
145 {
147 if (!m_ConfigLoaded)
148 return;
149
151
153
154 m_LockCodeHistory = new SimpleCircularBuffer<string>(LOCK_CODE_HISTORY_LENGTH, "0000");
155 m_ActiveBunkersHistory = new SimpleCircularBuffer<int>(2, -1);
156
163 m_UpdateTimer = 0;
164
165 #ifdef DIAG_DEVELOPER
166 m_RegisteredBunkersStorage = new BunkerComponentsArray();
167 m_BunkersHistoryStorage = new TIntArray();
168 #endif
169
171 m_LastActiveBunkersCount = m_PersitenceStorage.m_HandlerData.m_LastActiveBunkers.Count();
172
173 // temporarily keeps number of bunkers added from storage
175
178 {
179 m_BroadcastScheduler.GetOnAskForNewBunkers().Insert(SelectNew);
180 m_BroadcastScheduler.CheckActivePeriod();
181 }
182 }
183
185 {
187 m_BroadcastScheduler.GetOnAskForNewBunkers().Remove(SelectNew);
188 }
189
190 // --------------------------------------------------------------------------------
191
193 {
194 if (!m_ConfigLoaded)
195 return;
196
198 int componentId = component.GetId();
199 string lockCode;
200 if (m_PersitenceStorage.m_HandlerData.m_LastActiveBunkers.Find(componentId, lockCode))
201 {
202 // necessary to postpone while loaded and activated from storage
203 Param2<string, bool> params = new Param2<string, bool>(lockCode, true);
204 g_Game.GetCallQueue(CALL_CATEGORY_GAMEPLAY).CallLaterByName(component, "OnActivate", 1000, false, params);
205
206 m_RegisteredBunkers.Set(componentId, component);
208
209 #ifdef ENABLE_LOGGING
210 Log(string.Format("Directly registering (store load) - object=%1, id=%2, pos=%3, code=%4", component, componentId, component.GetPosition(), lockCode));
211 #endif
212
214
215 return;
216 }
217
218 if (m_RegisterQueue.Contains(componentId))
219 {
220 #ifdef ENABLE_LOGGING
221 Log(string.Format("Already in register queue - object=%1, id=%2, pos=%3", component, componentId, component.GetPosition()));
222 #endif
223 return;
224 }
225
226 m_RegisterQueue.Set(componentId, component);
227
228 m_CanUpdate = true;
229 }
230
231 // --------------------------------------------------------------------------------
232
234 {
235 if (!m_ConfigLoaded)
236 return;
237
238 int componentId = component.GetId();
239 if (m_UnregisterQueue.Contains(componentId))
240 {
241 #ifdef ENABLE_LOGGING
242 Log(string.Format("Already in un-register queue - object=%1, id=%2, pos=%3", component, componentId, component.GetPosition()));
243 #endif
244 return;
245 }
246
247 m_UnregisterQueue.Set(componentId, component);
248 }
249
250 // --------------------------------------------------------------------------------
251
256
257 // --------------------------------------------------------------------------------
258
260 {
263 {
265 bunkers.Insert(component);
266 }
267
268 return bunkers;
269 }
270
271 // --------------------------------------------------------------------------------
272
274 {
275 TIntArray history = new TIntArray();
276
278 history = m_ActiveBunkersHistory.GetValues();
279
280 return history;
281 }
282
283 // --------------------------------------------------------------------------------
284
289
290 // --------------------------------------------------------------------------------
291
292 void Update(float timeslice)
293 {
294 if (!m_ConfigLoaded)
295 return;
296
298 {
299 m_ActiveBunkersFromStorageCount = -1; // resets the count; no more processing
301 m_CanUpdate = true;
302 return;
303 }
304
305 if (!m_CanUpdate)
306 return;
307
309 m_BroadcastScheduler.OnUpdate(timeslice);
310
312 {
314
316 {
317 int registeredCountRound = Math.Max(Math.Round(m_RegisteredBunkers.Count() / 2), m_Config.bunkerSettings.numberOfActive);
318 if (registeredCountRound > 2)
319 m_ActiveBunkersHistory.Resize(registeredCountRound, -1);
320
321 Reset();
322 }
323 }
324 else
325 {
326 m_UpdateTimer += timeslice;
328 {
329 #ifdef ENABLE_LOGGING
330 Log(string.Format("General update (%1s)", UPDATE_TIME));
331 #endif
332
335
336 if (!m_BroadcastScheduler.IsActivePeriod())
337 {
338 #ifdef ENABLE_LOGGING
339 //Log("We are outside of active period, deactivating bunkers");
340 #endif
341
343 if (m_ActiveBunkers.Count() > 0 && m_ActiveBunkersFromStorageCount == 0)
344 Deactivate();
345 }
346
347 #ifdef DIAG_DEVELOPER
349 TIntArray bunkersHistory = GetActiveBunkersHistory();
350 SyncBunkersInfo(bunkerList, bunkersHistory);
351 #endif
352
354 m_BroadcastScheduler.CheckActivePeriod();
355
357
358 if (!m_CanUpdate)
359 Reset();
360 }
361 }
362 }
363
364 // --------------------------------------------------------------------------------
365
366 protected void SelectNew()
367 {
368 Deactivate();
369 int numOfActivatedBunkers = Activate();
370
371 if (numOfActivatedBunkers > 0)
373 #ifdef DIAG_DEVELOPER
374 else
375 #ifdef ENABLE_LOGGING
376 Log("No active bunker selected");
377 #endif
378 #endif
379 }
380
381 // --------------------------------------------------------------------------------
382
383 private int Activate()
384 {
385 BunkerComponentsArray selectedBunkers = SelectRandomBunkers(GetRegisteredBunkers(), m_Config.bunkerSettings.numberOfActive);
386
387 foreach (BunkerBroadcastComponentBase bunker : selectedBunkers)
388 {
389 string lockCode = GenerateLockCode();
390 bunker.OnActivate(lockCode);
391 m_ActiveBunkers.Insert(bunker);
392 }
393
394 return m_ActiveBunkers.Count();
395 }
396
397 // --------------------------------------------------------------------------------
398
399 private void Deactivate()
400 {
403 {
404 int componentId = bunker.GetId();
405 #ifdef ENABLE_LOGGING
406 Log(string.Format("Deactivating bunker:%1", componentId));
407 #endif
408 bunker.OnDeactivate();
409 toRemove.Insert(bunker);
410
411 if (m_RegisteredBunkers.Count() >= (m_Config.bunkerSettings.numberOfActive / 2))
412 m_ActiveBunkersHistory.Add(bunker.GetId());
413 }
414
415 foreach (BunkerBroadcastComponentBase bunkerToRemove : toRemove)
416 m_ActiveBunkers.RemoveItem(bunkerToRemove);
417 }
418
419 // --------------------------------------------------------------------------------
420
421 protected string GenerateLockCode()
422 {
423 TStringArray lockCodeArray = new TStringArray();
424 string lockCode;
425
426 #ifdef DIAG_DEVELOPER
427 #ifdef BUNKER_BROADCAST_CHEAT_CODE
428 return "1234";
429 #endif
430 #endif
431
432 bool needGenerate = true;
433 //int iterationNumber = 0;
434 while (needGenerate /*&& iterationNumber > <= max number of iterations?*/ )
435 {
436 //iterationNumber++;
437 for (int i = 0; i < m_Config.bunkerSettings.lockCodeLength; ++i)
438 {
439 int charCode = GetRandomChar();
440 lockCodeArray.Insert(charCode.AsciiToString());
441 }
442
443 lockCode = string.Join("", lockCodeArray);
444 if (m_LockCodeHistory.GetValues().Find(lockCode) > INDEX_NOT_FOUND)
445 {
446 needGenerate = true;
447 continue;
448 }
449
450 needGenerate = false;
451 //iterationNumber = 0;
452 break;
453 }
454
455 //if (iterationNumber > 0)
456 // lockCode = GetFallbackCodeFromStaticArray();
457
458 return lockCode;
459 }
460
461 // --------------------------------------------------------------------------------
462
464 protected bool ProcessBatch()
465 {
466 int count = m_RegisteredBunkers.Count();
467 int target = (int)Math.Clamp(m_NextToProcessIdx + UPDATE_BATCH_SIZE, 0, count);
468
469 TIntArray indices = m_RegisteredBunkers.GetKeyArray();
470
472 {
473 if (m_RegisteredBunkers.Contains(indices[m_NextToProcessIdx]))
474 {
477 component.OnUpdate(m_UpdateTimer);
478 }
479 }
480
481 bool returnValue = target == count;
482 if (returnValue)
484
485 return returnValue;
486 }
487
488 // --------------------------------------------------------------------------------
489
490 protected void Reset()
491 {
492 m_ProcessComponents = false;
494
495 m_UpdateTimer = 0;
496 }
497
498 // --------------------------------------------------------------------------------
499
500 protected void HandleChangedComponents()
501 {
502 foreach (int uid, BunkerBroadcastComponentBase componentToUnregister : m_UnregisterQueue)
503 {
504 if (!componentToUnregister)
505 {
506 #ifdef ENABLE_LOGGING
507 Log(string.Format("Invalid bunker to unregister (%1).", componentToUnregister));
508 #endif
509 continue;
510 }
511
512 if (!m_RegisteredBunkers.Contains(uid))
513 {
514 #ifdef ENABLE_LOGGING
515 Log(string.Format("Bunker (id=%1) is not registered, cannot unregister.", uid));
516 #endif
517 continue;
518 }
519
520 m_RegisteredBunkers.Remove(uid);
521 m_UnregisterQueue.Remove(uid);
522 }
523
524 foreach (int rid, BunkerBroadcastComponentBase componentToRegister : m_RegisterQueue)
525 {
526 if (!componentToRegister)
527 {
528 #ifdef ENABLE_LOGGING
529 Log(string.Format("Invalid bunker to register (%1)", componentToRegister));
530 #endif
531 continue;
532 }
533
534 if (m_RegisteredBunkers.Contains(rid))
535 {
536 #ifdef ENABLE_LOGGING
537 Log(string.Format("Bunker (id=%1) is already registered", rid));
538 #endif
539 continue;
540 }
541
542 m_RegisteredBunkers.Set(rid, componentToRegister);
543 m_RegisterQueue.Remove(rid);
544 }
545 }
546
547 // --------------------------------------------------------------------------------
548
549 #ifdef DIAG_DEVELOPER
550 static void OnRPC(PlayerIdentity sender, Object target, int rpc_type, ParamsReadContext ctx)
551 {
552 switch (rpc_type)
553 {
554 case ERPCs.DIAG_MISC_RADIOGAMEPLAY_BUNKERS_LIST:
555 if (!m_RegisteredBunkersStorage)
556 m_RegisteredBunkersStorage = new BunkerComponentsArray();
557
558 if (!m_BunkersHistoryStorage)
559 m_BunkersHistoryStorage = new TIntArray();
560
561 m_RegisteredBunkersStorage.Clear();
562 m_BunkersHistoryStorage.Clear();
563 ctx.Read(m_RegisteredBunkersStorage);
564 ctx.Read(m_BunkersHistoryStorage);
565 break;
566 }
567 }
568
569 // --------------------------------------------------------------------------------
570
571 private void SyncBunkersInfo(BunkerComponentsArray bunkers, TIntArray bunkersHistory)
572 {
573 if (bunkers && bunkers.Count() > 0 )
574 {
575 ScriptRPC rpc = new ScriptRPC();
576 rpc.Write(bunkers);
577 rpc.Write(bunkersHistory);
578 rpc.Send(null, ERPCs.DIAG_MISC_RADIOGAMEPLAY_BUNKERS_LIST, true, null);
579 }
580 }
581 #endif
582
583 #ifdef ENABLE_LOGGING
584 private static void Log(string message, bool indented = false)
585 {
586 #ifdef DIAG_DEVELOPER
587 if (m_LoggingEnabled || LogManager.IsRadioGameplayLogEnabled())
588 #else
589 if (LogManager.IsRadioGameplayLogEnabled())
590 #endif
591 {
592 string indentation = "";
593 if (indented)
594 indentation = " \\__";
595
596 Debug.RadioGameplayLog(string.Format("%1 %2", indentation, message), m_Instance.ClassName(), "n/a", "n/a", "n/a");
597 }
598 }
599 #endif
600
601 // --------------------------------------------------------------------------------
602
603 protected void CheckUpdating()
604 {
605 m_CanUpdate = m_RegisteredBunkers.Count() != 0;
606 }
607
608 // --------------------------------------------------------------------------------
609
610 private int GetRandomChar()
611 {
612 int charSet = 0;
613 if (m_Config.bunkerSettings.lockCodeMode == BunkerBroadcastLockCodeMode.ALPHANUMERIC)
614 charSet = Math.RandomIntInclusive(0, 1);
615
616 int charCode;
617
618 if (charSet == 0)
619 charCode = Math.RandomInt(48, 58); // Digit: '0' (48) to '9' (57)
620 else
621 charCode = Math.RandomInt(97, 123); // Lowercase: 'a' (97) to 'z' (122)
622
623 return charCode;
624 }
625
626 // --------------------------------------------------------------------------------
627
629 {
631
632 // Build list of available elements
633 bunkers.ShuffleArray();
634 #ifdef ENABLE_LOGGING
635 Log("Random bunker selection:");
636 #endif
637 foreach (BunkerBroadcastComponentBase bunker : bunkers)
638 {
639 if (!bunker)
640 continue;
641 if (m_ActiveBunkersHistory.GetValues().Find(bunker.GetId()) == INDEX_NOT_FOUND)
642 available.Insert(bunker);
643 #ifdef ENABLE_LOGGING
644 else
645 Log(string.Format("Bunker was already used (%1)", bunker.GetId()), true);
646 #endif
647 }
648
649 int n = available.Count();
650 if (amount > n)
651 amount = n; // Or handle error/return empty
652
654 TIntArray used = new TIntArray();
655
656 while (selected.Count() < amount)
657 {
658 int randomIndex = Math.RandomInt(0, n);
659 // Ensure unique selection
660 bool alreadyUsed = false;
661 foreach (int u : used)
662 {
663 if (u == randomIndex)
664 {
665 alreadyUsed = true;
666 break;
667 }
668 }
669
670 if (!alreadyUsed)
671 {
672 selected.Insert(available[randomIndex]);
673 #ifdef ENABLE_LOGGING
674 Log(string.Format("Selecting bunker (%1)", available[randomIndex].GetId()), true);
675 #endif
676 used.Insert(randomIndex);
677 }
678 }
679
680 return selected;
681 }
682
683 // --------------------------------------------------------------------------------
684}
ActionOverrideData int
array< ref BunkerBroadcastComponentBase > BunkerComponentsArray
Определения BunkerBroadcastHandler.c:91
const int ALPHANUMERIC
Определения BunkerBroadcastHandler.c:88
BunkerBroadcastPersistenceStorage DIGITSONLY
class BunkerBroadcastSchedulerPersistenceData m_LastActiveBunkers
string Debug()
Определения CachedEquipmentStorageBase.c:26
int GetId()
Определения ConstructionPart.c:725
DayZGame g_Game
Определения DayZGame.c:4074
ERPCs
Определения ERPCs.c:2
class BoxCollidingParams component
ComponentInfo for BoxCollidingResult.
class LogTemplates Log(string message, LogTemplateID template_id=0)
Creates debug log (optional) from LogTemplate which are registred.
Определения LogTemplates.c:75
ref BunkerBroadcastConfigInstance m_Config
Определения BunkerBroadcastHandler.c:114
BunkerComponentsArray SelectRandomBunkers(BunkerComponentsArray bunkers, int amount)
Определения BunkerBroadcastHandler.c:628
TIntArray GetActiveBunkersHistory()
Определения BunkerBroadcastHandler.c:273
ref map< int, ref BunkerBroadcastComponentBase > m_UnregisterQueue
Определения BunkerBroadcastHandler.c:103
void Update(float timeslice)
Определения BunkerBroadcastHandler.c:292
static ref BunkerBroadcastHandler m_Instance
Определения BunkerBroadcastHandler.c:121
ref SimpleCircularBuffer< int > m_ActiveBunkersHistory
Определения BunkerBroadcastHandler.c:117
void ~BunkerBroadcastHandler()
Определения BunkerBroadcastHandler.c:184
bool ProcessBatch()
returns 'true' when all the batches are finished
Определения BunkerBroadcastHandler.c:464
void BunkerBroadcastHandler()
Определения BunkerBroadcastHandler.c:144
BunkerComponentsArray GetRegisteredBunkers()
Определения BunkerBroadcastHandler.c:259
ref map< int, ref BunkerBroadcastComponentBase > m_RegisterQueue
Определения BunkerBroadcastHandler.c:102
ref map< int, ref BunkerBroadcastComponentBase > m_RegisteredBunkers
how often is update called [seconds]
Определения BunkerBroadcastHandler.c:100
const float UPDATE_TIME
max batch size
Определения BunkerBroadcastHandler.c:98
static BunkerBroadcastHandler GetInstance()
Определения BunkerBroadcastHandler.c:134
int m_LastActiveBunkersCount
Определения BunkerBroadcastHandler.c:123
bool m_ProcessingFinished
Определения BunkerBroadcastHandler.c:108
string GenerateLockCode()
Определения BunkerBroadcastHandler.c:421
ref ScriptInvoker m_OnActiveBunkersSelected
Определения BunkerBroadcastHandler.c:119
BunkerBroadcastScheduler m_BroadcastScheduler
Определения BunkerBroadcastHandler.c:113
void Unregister(BunkerBroadcastComponentBase component)
Определения BunkerBroadcastHandler.c:233
ref BunkerComponentsArray m_ActiveBunkers
Определения BunkerBroadcastHandler.c:101
int m_ActiveBunkersFromStorageCount
Определения BunkerBroadcastHandler.c:124
void Register(BunkerBroadcastComponentBase component)
Определения BunkerBroadcastHandler.c:192
ScriptInvoker GetOnActiveBunkersSelected()
Определения BunkerBroadcastHandler.c:252
BunkerBroadcastPersistenceStorage m_PersitenceStorage
Определения BunkerBroadcastHandler.c:112
const int UPDATE_BATCH_SIZE
how many of previously generated codes are stored (prevents the reuse)
Определения BunkerBroadcastHandler.c:97
void HandleChangedComponents()
Определения BunkerBroadcastHandler.c:500
const int LOCK_CODE_HISTORY_LENGTH
Определения BunkerBroadcastHandler.c:95
BunkerComponentsArray GetActiveBunkers()
Определения BunkerBroadcastHandler.c:285
ref SimpleCircularBuffer< string > m_LockCodeHistory
Определения BunkerBroadcastHandler.c:116
static BunkerBroadcastPersistenceStorage GetInstance()
Определения BunkerBroadcastHandler.c:39
ref BunkerBroadcastSchedulerPersistenceData m_SchedulerData
Определения BunkerBroadcastHandler.c:20
static ref BunkerBroadcastPersistenceStorage m_Instance
Определения BunkerBroadcastHandler.c:23
ref BunkerBroadcastHandlerPersistenceData m_HandlerData
Определения BunkerBroadcastHandler.c:21
static BunkerBroadcastScheduler GetInstance(notnull BunkerBroadcastHandler handler)
Определения BunkerBroadcastScheduler.c:27
static BunkerBroadcastConfigInstance GetData()
Определения CfgBunkerBroadcastHandler.c:46
static bool IsInitialized()
Определения CfgBunkerBroadcastHandler.c:41
proto native bool Open(string path, FileMode mode=FileMode.READ)
proto native void Close()
Serializer API implementation for File IO. See Serializer for more info. usage:
Определения Serializer.c:104
void OnRPC(ParamsReadContext ctx)
Определения TransferValues.c:165
TODO doc.
Определения EnScript.c:118
Определения EnMath.c:7
Определения ObjectTyped.c:2
Определения PPEConstants.c:68
The class that will be instanced (moddable)
Определения gameplay.c:389
ScriptInvoker Class provide list of callbacks usage:
Определения 2_GameLib/DayZ/tools.c:116
proto native void Send(Object target, int rpc_type, bool guaranteed, PlayerIdentity recipient=NULL)
Initiate remote procedure call. When called on client, RPC is evaluated on server; When called on ser...
proto bool Write(void value_out)
proto bool Read(void value_in)
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
Определения Transport.c:70
const int INDEX_NOT_FOUND
Определения gameplay.c:13
Serializer ParamsReadContext
Определения gameplay.c:15
map< int, string > TIntStringMap
Определения EnScript.c:995
array< int > TIntArray
Определения EnScript.c:733
class array< Class T > TStringArray
FileMode
Определения EnSystem.c:383
static proto float Max(float x, float y)
Returns bigger of two given values.
static proto float Round(float f)
Returns mathematical round of value.
static proto float Clamp(float value, float min, float max)
Clamps 'value' to 'min' if it is lower than 'min', or to 'max' if it is higher than 'max'.
static proto int RandomInt(int min, int max)
Returns a random int number between and min [inclusive] and max [exclusive].
static int RandomIntInclusive(int min, int max)
Returns a random int number between and min [inclusive] and max [inclusive].
Определения EnMath.c:54
static string Join(string separator, notnull TStringArray tokens)
Определения EnString.c:424
const int CALL_CATEGORY_GAMEPLAY
Определения 3_Game/DayZ/tools/tools.c:10