9 [
EntityEditorProps(
category:
"", description:
"Entity of the download manager. Most likely only needed in the main menu world.")]
22 protected const int DOWNLOAD_STUCK_DELAY = 60;
27 protected ref array<ref SCR_DownloadManager_Entry> m_aDownloadActions =
new array<ref SCR_DownloadManager_Entry>();
32 protected ref array<ref SCR_WorkshopItemActionDownload> m_aDownloadQueue =
new array<ref SCR_WorkshopItemActionDownload>;
33 protected int m_iQueueDownloadsCompleted;
35 protected float m_fNoDownloadProgressTimer = 0;
36 protected float m_fDownloadQueueSize;
37 protected float m_fDownloadedSize;
40 protected bool m_bDownloadsPaused;
42 protected const int FAIL_TIME = 500;
43 protected ref array<ref SCR_WorkshopItemActionDownload> m_aFailedDownloads = {};
47 ref ScriptInvoker m_OnNewDownload =
new ScriptInvoker;
49 protected ref ScriptInvoker<> Event_OnDownloadFail;
50 ref ScriptInvokerBase<ScriptInvoker_DownloadManagerAction> m_OnDownloadComplete =
new ScriptInvokerBase<ScriptInvoker_DownloadManagerAction>();
51 ref ScriptInvokerBase<ScriptInvoker_DownloadManagerActionError> m_OnDownloadFailed =
new ScriptInvokerBase<ScriptInvoker_DownloadManagerActionError>();
52 protected ref ScriptInvokerBase<ScriptInvoker_ActionDownloadFullStorage> m_OnFullStorageError;
53 ref ScriptInvokerBase<ScriptInvoker_DownloadManagerAction> m_OnDownloadCanceled =
new ScriptInvokerBase<ScriptInvoker_DownloadManagerAction>();
58 void InvokeEventOnDownloadFail()
60 if (Event_OnDownloadFail)
61 Event_OnDownloadFail.Invoke();
65 ScriptInvoker GetEventOnDownloadFail()
67 if (!Event_OnDownloadFail)
68 Event_OnDownloadFail =
new ScriptInvoker();
70 return Event_OnDownloadFail;
74 ScriptInvokerBase<ScriptInvoker_ActionDownloadFullStorage> GetOnFullStorageError()
76 if (!m_OnFullStorageError)
77 m_OnFullStorageError =
new ScriptInvokerBase<ScriptInvoker_ActionDownloadFullStorage>();
79 return m_OnFullStorageError;
85 if (!m_OnDownloadQueueCompleted)
88 return m_OnDownloadQueueCompleted;
94 if (!m_OnAllDownloadsStopped)
97 return m_OnAllDownloadsStopped;
113 void GetAllDownloads(array<ref SCR_DownloadManager_Entry> downloads)
117 foreach (
auto dl : m_aDownloadActions)
118 downloads.Insert(dl);
124 void GetDownloadQueueState(out
int nCompleted, out
int nTotal)
126 nTotal = m_aDownloadQueue.Count();
127 nCompleted = m_iQueueDownloadsCompleted;
131 bool HasRunningDownloads()
133 return !m_aDownloadQueue.IsEmpty();
142 if (download.m_Wrapper.GetId() !=
id)
145 if (runningOnly && download.IsActive() && !download.IsCompleted() && !download.IsFailed() && !download.IsCanceled())
153 array<ref SCR_WorkshopItemActionDownload> GetDownloadQueue()
155 array<ref SCR_WorkshopItemActionDownload> downloads = {};
157 if (!m_aDownloadQueue)
160 foreach (
auto i : m_aDownloadQueue)
172 if (entry.m_Item == item)
173 return entry.m_Action;
183 void SetDownloadsPaused(
bool pause,
int count = -1)
185 if (pause == m_bDownloadsPaused)
188 m_bDownloadsPaused = pause;
192 count = m_aDownloadQueue.Count() - 1;
195 PauseAction(m_aDownloadQueue[count], pause);
199 GetGame().GetCallqueue().CallLater(SetDownloadsPaused, 0,
false, pause, count - 1);
208 if (action.IsActive())
215 if (action.IsPaused())
217 else if (action.IsInactive())
222 bool GetDownloadsPaused()
224 return m_bDownloadsPaused;
232 void EndAllDownloads()
242 array<ref SCR_WorkshopItemActionDownload> GetUnrelatedDownloads(array<ref SCR_WorkshopItem> requiredItems)
244 array<ref SCR_WorkshopItemActionDownload> unrelatedDownloads = {};
248 if (!IsDownloadingActionRequired(action, requiredItems))
249 unrelatedDownloads.Insert(action);
252 return unrelatedDownloads;
269 sameId = requiredItem.GetId() == item.GetId();
270 sameVersion = requiredItem.GetDependency().GetVersion() == action.GetTargetRevision().GetVersion();
271 required = sameId && sameVersion;
288 if (!item.GetOffline())
291 Revision latestRevision = item.GetLatestRevision();
292 Revision targetRevision;
293 bool downloading, paused;
295 item.GetDownloadState(downloading, paused, progress, targetRevision);
299 return !Revision.AreEqual(item.GetCurrentLocalRevision(), latestRevision);
304 if (Revision.AreEqual(item.GetLatestRevision(), targetRevision))
313 static void SelectAddonsForLatestDownload(array<ref SCR_WorkshopItem> arrayIn, array<ref SCR_WorkshopItem> arrayOut)
317 if (IsLatestDownloadRequired(addon))
318 arrayOut.Insert(addon);
326 array<ref SCR_WorkshopItemAction> DownloadLatestWithDependencies(notnull
SCR_WorkshopItem mainItem,
bool downloadMainItem, array<ref SCR_WorkshopItem> dependencies)
328 array<ref SCR_WorkshopItemAction> actions = {};
330 if (IsLatestDownloadRequired(mainItem) && downloadMainItem)
332 auto actionMain = mainItem.DownloadLatestVersion();
335 actions.Insert(actionMain);
336 if (!m_bDownloadsPaused)
337 actionMain.Activate();
343 if (dependencies.Count() > 0)
345 auto actionDependencies = mainItem.DownloadDependenciesLatest(dependencies);
346 if (actionDependencies)
348 if (!m_bDownloadsPaused)
349 actionDependencies.Activate();
351 actions.Insert(actionDependencies);
364 array<ref SCR_WorkshopItemActionDownload> DownloadItems(array<ref SCR_WorkshopItem> items)
366 array<ref SCR_WorkshopItemActionDownload> actions = {};
368 for (
int i = 0, count = items.Count(); i < count; i++)
370 Revision target = items[i].GetItemTargetRevision();
373 target = items[i].GetDependency().GetRevision();
382 actions.Insert(action);
392 void DownloadDependecies(array<Dependency> dependencies)
394 for (
int i = 0, count = dependencies.Count(); i < count; i++)
405 static float GetTotalSizeBytes(array<ref SCR_WorkshopItem> arrayIn,
SCR_WorkshopItem extraItem =
null)
411 float s = addon.GetTargetRevisionPatchSize();
417 float s = extraItem.GetTargetRevisionPatchSize();
425 protected float DownloadQueueSize()
427 array<ref SCR_WorkshopItem> downloading = {};
428 for (
int i = 0, count = m_aDownloadQueue.Count(); i < count; i++)
430 downloading.Insert(m_aDownloadQueue[i].m_Wrapper);
433 return GetTotalSizeBytes(downloading);
438 static float GetDownloadActionsProgress(array<ref SCR_WorkshopItemActionDownload> actions)
440 float totalSizeBytes = 0;
441 float totalBytesDownloaded = 0;
445 float dlsize = dl.GetSizeBytes();
446 totalSizeBytes += dlsize;
447 totalBytesDownloaded += dl.GetProgress() * dlsize;
450 if (totalSizeBytes == 0)
453 float progress = totalBytesDownloaded / totalSizeBytes;
464 auto actionThisItem = item.GetDownloadAction();
465 auto actionDependencies = item.GetDependencyCompositeAction();
467 array<ref SCR_WorkshopItemAction> allActions;
468 if (actionDependencies)
469 allActions = actionDependencies.GetActions();
471 allActions =
new array<ref SCR_WorkshopItemAction>;
474 allActions.Insert(actionThisItem);
477 auto allDownloadActions =
new array<ref SCR_WorkshopItemActionDownload>;
478 foreach (
auto a : allActions)
482 allDownloadActions.Insert(downloadAction);
491 array<ref SCR_WorkshopItemActionDownload> GetFailedDownloads()
493 array<ref SCR_WorkshopItemActionDownload> actions = {};
494 for (
int i = 0, count = m_aFailedDownloads.Count(); i < count; i++)
496 actions.Insert(m_aFailedDownloads[i]);
503 void ClearFailedDownloads()
505 m_aFailedDownloads.Clear();
511 RemoveSameAddonFromDownloads(item);
514 m_aDownloadActions.Insert(entry);
523 for (
int i = 0, count = m_aDownloadActions.Count(); i < count; i++)
526 if (m_aDownloadActions[i].
m_Item.GetId() == item.GetId())
528 m_aDownloadActions.Remove(i);
534 for (
int i = 0, count = m_aDownloadQueue.Count(); i < count; i++)
537 if (m_aDownloadQueue[i].m_Wrapper.GetId() == item.GetId())
539 m_aDownloadQueue.Remove(i);
546 float GetDownloadQueueSize()
548 return m_fDownloadQueueSize;
552 float GetDownloadedSize()
554 return m_fDownloadedSize;
575 override void EOnFrame(IEntity owner,
float timeSlice)
580 for (
int i = m_aDownloadQueue.Count() - 1; i >= 0; i--)
584 if (action.IsCanceled() || action.IsFailed())
585 ClearUnfinishedAction(action);
586 else if (action.IsPaused())
591 if (pausedCount == m_aDownloadQueue.Count())
593 m_fNoDownloadProgressTimer = 0;
598 if (!m_aDownloadQueue.IsEmpty() && m_iQueueDownloadsCompleted == m_aDownloadQueue.Count())
600 m_aDownloadQueue.Clear();
601 m_iQueueDownloadsCompleted = 0;
602 m_fDownloadedSize = 0;
603 m_bDownloadsPaused =
false;
605 if (m_OnDownloadQueueCompleted)
606 m_OnDownloadQueueCompleted.Invoke();
608 m_fNoDownloadProgressTimer = 0;
627 override void EOnInit(IEntity owner)
633 Print(
"SCR_DownloadManager_Entity: SCR_AddonManager was not found. It must be placed in the world for download manager to work.", LogLevel.ERROR);
637 addonManager.m_OnNewDownload.Insert(Callback_OnNewDownload);
646 #ifdef WORKSHOP_DEBUG
647 Revision rev = action.GetTargetRevision();
649 _print(
string.Format(
"Callback_OnNewDownloadStarted: %1, %2", item.GetName(), action.GetTargetRevision().GetVersion()));
651 _print(
string.Format(
"Callback_OnNewDownloadStarted: %1", item.GetName()));
654 RemoveSameAddonFromDownloads(item);
658 m_aDownloadActions.Insert(entry);
661 m_aDownloadQueue.Insert(action);
662 m_fDownloadQueueSize = DownloadQueueSize();
664 m_OnNewDownload.Invoke(item, action);
666 action.GetOnDownloadProgress().Insert(OnDownloadProgress);
667 action.m_OnCompleted.Insert(Callback_OnDownloadCompleted);
668 action.m_OnFailed.Insert(Callback_OnFailed);
669 action.GetOnFullStorageError().Insert(Callback_OnFullStorageError);
670 action.m_OnCanceled.Insert(Callback_OnCanceled);
672 m_fNoDownloadProgressTimer = 0;
678 m_fDownloadedSize += progressSize;
681 m_fNoDownloadProgressTimer = 0;
691 if (settings.m_bAutoEnableDownloadedAddons && !action.GetUpdate())
698 item.SetEnabled(
true);
702 m_iQueueDownloadsCompleted++;
703 m_OnDownloadComplete.Invoke(action);
706 protected const int ERROR_FULL_STORAGE = 19;
712 m_aFailedDownloads.Insert(action);
718 if (reason == ERROR_FULL_STORAGE)
722 m_OnDownloadFailed.Invoke(action, reason);
729 if (m_OnFullStorageError)
730 m_OnFullStorageError.Invoke(action, size);
736 m_aFailedDownloads.Insert(action);
737 m_OnDownloadCanceled.Invoke(action);
742 protected void ForceFailRunningDownloads()
744 for (
int i = 0, count = m_aDownloadQueue.Count(); i < count; i++)
746 m_aDownloadQueue[i].ForceFail();
752 void DownloadAddons(array<ref SCR_WorkshopItem> items)
755 sequence.GetOnReady().Insert(OnDownloadAddonsReady);
783 sequence.GetOnReady().Remove(OnDownloadAddonsReady);
790 m_aDownloadQueue.RemoveItem(action);
793 m_fDownloadQueueSize = Math.Clamp(m_fDownloadQueueSize - action.GetDownloadSize(), 0,
float.MAX);
794 m_fDownloadedSize = Math.Clamp(m_fDownloadedSize - action.GetDownloadSize(), 0,
float.MAX);
796 if (m_OnAllDownloadsStopped && m_aDownloadQueue.IsEmpty())
797 m_OnAllDownloadsStopped.Invoke();
803 SetEventMask( EntityEvent.FRAME | EntityEvent.INIT);
804 SetFlags(EntityFlags.NO_TREE | EntityFlags.NO_LINK);
822 void _print(
string str, LogLevel logLevel = LogLevel.DEBUG)
824 Print(
string.Format(
"[SCR_DownloadManager] %1 %2",
this, str), logLevel);