3 using System.Collections.Generic;
5 using System.Threading.Tasks;
8 using Microsoft.Xna.Framework;
12 public static class BulkDownloader
14 private static void CloseAllMessageBoxes()
16 GUIMessageBox.MessageBoxes.ForEachMod(b =>
18 if (b is GUIMessageBox m) { m.Close(); }
19 else { GUIMessageBox.MessageBoxes.Remove(b); }
23 public static void PrepareUpdates()
25 CloseAllMessageBoxes();
26 GUIMessageBox msgBox =
new GUIMessageBox(headerText:
"", text: TextManager.Get(
"DeterminingRequiredModUpdates"),
27 buttons: Array.Empty<LocalizedString>());
29 "BulkDownloader.PrepareUpdates > GetItemsThatNeedUpdating",
30 GetItemsThatNeedUpdating(),
34 if (!t.TryGetResult(out IReadOnlyList<Steamworks.Ugc.Item>? items)) { return; }
36 InitiateDownloads(items);
40 internal static void SubscribeToServerMods(IEnumerable<UInt64> missingIds, ConnectCommand rejoinCommand)
42 CloseAllMessageBoxes();
43 GUIMessageBox msgBox =
new GUIMessageBox(headerText:
"", text: TextManager.Get(
"PreparingWorkshopDownloads"),
44 buttons: Array.Empty<LocalizedString>());
46 "BulkDownloader.SubscribeToServerMods > GetItems",
47 Task.WhenAll(missingIds.Select(SteamManager.Workshop.GetItem)),
51 if (!t.TryGetResult(out Option<Steamworks.Ugc.Item>[]? itemOptions)) { return; }
53 List<Steamworks.Ugc.Item> itemsToDownload =
new List<Steamworks.Ugc.Item>();
54 foreach (Option<Steamworks.Ugc.Item> itemOption in itemOptions)
56 if (itemOption.TryUnwrap(out var item))
58 itemsToDownload.Add(item);
62 itemsToDownload.ForEach(it => it.Subscribe());
63 InitiateDownloads(itemsToDownload, onComplete: () =>
65 ContentPackageManager.UpdateContentPackageList();
66 GameMain.Instance.ConnectCommand = Option<ConnectCommand>.Some(rejoinCommand);
71 public static async Task<IReadOnlyList<Steamworks.Ugc.Item>> GetItemsThatNeedUpdating()
73 var determiningTasks = ContentPackageManager.WorkshopPackages.Select(async p => (p, await p.IsUpToDate()));
74 (ContentPackage Package,
bool IsUpToDate)[] outOfDatePackages = await Task.WhenAll(determiningTasks);
76 return (await Task.WhenAll(outOfDatePackages.Where(p => !p.IsUpToDate)
77 .Select(p => p.Package.UgcId)
79 .OfType<SteamWorkshopId>()
80 .Select(async
id => await SteamManager.Workshop.GetItem(
id.Value))))
84 public static void InitiateDownloads(IReadOnlyList<Steamworks.Ugc.Item> itemsToDownload, Action? onComplete =
null)
86 var msgBox =
new GUIMessageBox(TextManager.Get(
"WorkshopItemDownloading"),
"", relativeSize: (0.5f, 0.6f),
87 buttons:
new LocalizedString[] { TextManager.Get(
"Cancel") });
88 msgBox.Buttons[0].OnClicked = msgBox.Close;
89 var modsList =
new GUIListBox(
new RectTransform((1.0f, 0.8f), msgBox.Content.RectTransform))
93 foreach (var item
in itemsToDownload)
95 var itemFrame =
new GUIFrame(
new RectTransform((1.0f, 0.08f), modsList.Content.RectTransform),
100 var itemTitle =
new GUITextBlock(
new RectTransform(Vector2.One, itemFrame.RectTransform),
101 text: item.Title ??
"");
102 var itemDownloadProgress
103 =
new GUIProgressBar(
new RectTransform((0.5f, 0.75f),
104 itemFrame.RectTransform,
Anchor.CenterRight), 0.0f)
106 Color = GUIStyle.Green
108 var textShadow =
new GUITextBlock(
new RectTransform(Vector2.One, itemDownloadProgress.RectTransform) { AbsoluteOffset = new Point(GUI.IntScale(3)) },
"",
109 textColor: Color.Black, textAlignment: Alignment.Center);
110 var text =
new GUITextBlock(
new RectTransform(Vector2.One, itemDownloadProgress.RectTransform),
"",
111 textAlignment: Alignment.Center);
112 var itemDownloadProgressUpdater =
new GUICustomComponent(
113 new RectTransform(Vector2.Zero, msgBox.Content.RectTransform),
114 onUpdate: (f, component) =>
116 float progress = 0.0f;
117 if (item.IsDownloading)
119 progress = item.DownloadAmount;
120 text.Text = textShadow.Text = TextManager.GetWithVariable(
121 "PublishPopupDownload",
123 ((int)MathF.Round(item.DownloadAmount * 100)).ToString());
125 else if (itemDownloadProgress.BarSize > 0.0f)
127 if (!item.IsInstalled && !SteamManager.Workshop.CanBeInstalled(item.Id))
129 itemDownloadProgress.Color = GUIStyle.Red;
130 text.Text = textShadow.Text = TextManager.Get(
"workshopiteminstallfailed");
134 text.Text = textShadow.Text = TextManager.Get(item.IsInstalled ?
"workshopiteminstalled" :
"PublishPopupInstall");
139 itemDownloadProgress.BarSize = Math.Max(itemDownloadProgress.BarSize,
140 MathHelper.Lerp(itemDownloadProgress.BarSize, progress, 0.1f));
143 TaskPool.Add(
"DownloadItems", DownloadItems(itemsToDownload, msgBox), _ =>
145 if (GUIMessageBox.MessageBoxes.Contains(msgBox))
147 onComplete?.Invoke();
150 ContentPackageManager.WorkshopPackages.Refresh();
151 ContentPackageManager.EnabledPackages.RefreshUpdatedMods();
152 if (SettingsMenu.Instance?.WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu)
154 mutableWorkshopMenu.PopulateInstalledModLists(forceRefreshEnabled: true);
156 GameMain.MainMenuScreen.ResetModUpdateButton();
160 private static async Task DownloadItems(IReadOnlyList<Steamworks.Ugc.Item> itemsToDownload, GUIMessageBox msgBox)
162 foreach (var item
in itemsToDownload)
164 DebugConsole.Log($
"Reinstalling {item.Title}...");
165 await SteamManager.Workshop.Reinstall(item);
166 DebugConsole.Log($
"Finished installing {item.Title}...");
167 if (!GUIMessageBox.MessageBoxes.Contains(msgBox))
169 DebugConsole.Log($
"Download prompt closed, interrupting {nameof(DownloadItems)}.");
173 DebugConsole.Log($
"{nameof(DownloadItems)} finished.");