using System.Reflection; using System.Text; using HarmonyLib; using Sandbox.Engine.Networking; using Steamworks; using VRage.Game; using VRage.GameServices; using VRage.Utils; using Parallel = ParallelTasks.Parallel; namespace PluginLoader; public static class SteamAPI { private static MethodInfo? _downloadModsBlocking; public static bool IsSubscribed(ulong id) { var state = (EItemState)SteamUGC.GetItemState(new(id)); return (state & EItemState.k_EItemStateSubscribed) == EItemState.k_EItemStateSubscribed; } public static void SubscribeToItem(ulong id) { SteamUGC.SubscribeItem(new(id)); } public static void Update(IEnumerable ids) { var enumerable = ids as ulong[] ?? ids.ToArray(); if (!enumerable.Any()) return; var modItems = new List( enumerable.Select(x => new MyObjectBuilder_Checkpoint.ModItem(x, "Steam"))); LogFile.WriteLine($"Updating {modItems.Count} workshop items"); // Source: MyWorkshop.DownloadWorldModsBlocking var result = new MyWorkshop.ResultData(); var task = Parallel.Start(delegate { result = UpdateInternal(modItems); }); while (!task.IsComplete) { MyGameService.Update(); Thread.Sleep(10); } if (result.Result is not MyGameServiceCallResult.OK) { var exceptions = task.Exceptions; if (exceptions is { Length: > 0 }) { var sb = new StringBuilder(); sb.AppendLine("An error occurred while updating workshop items:"); foreach (var e in exceptions) sb.Append(e); LogFile.WriteLine(sb.ToString()); } else { LogFile.WriteLine("Unable to update workshop items"); } } } public static MyWorkshop.ResultData UpdateInternal(List mods) { // Source: MyWorkshop.DownloadWorldModsBlockingInternal MyLog.Default.IncreaseIndent(); var list = new List(mods.Select(x => new WorkshopId(x.PublishedFileId, x.PublishedServiceName))); if (_downloadModsBlocking == null) _downloadModsBlocking = AccessTools.Method(typeof(MyWorkshop), "DownloadModsBlocking"); var resultData = (MyWorkshop.ResultData)_downloadModsBlocking.Invoke(mods, new object[] { mods, new MyWorkshop.ResultData { Result = MyGameServiceCallResult.OK }, list, new MyWorkshop.CancelToken() })!; MyLog.Default.DecreaseIndent(); return resultData; } }