|
@ -1,4 +1,6 @@ |
|
|
using SimpleJSON; |
|
|
|
|
|
|
|
|
using IllusionInjector.Utilities; |
|
|
|
|
|
using Ionic.Zip; |
|
|
|
|
|
using SimpleJSON; |
|
|
using System; |
|
|
using System; |
|
|
using System.Collections; |
|
|
using System.Collections; |
|
|
using System.Collections.Generic; |
|
|
using System.Collections.Generic; |
|
@ -6,6 +8,7 @@ using System.IO; |
|
|
using System.Linq; |
|
|
using System.Linq; |
|
|
using System.Text; |
|
|
using System.Text; |
|
|
using System.Text.RegularExpressions; |
|
|
using System.Text.RegularExpressions; |
|
|
|
|
|
using System.Threading; |
|
|
using System.Threading.Tasks; |
|
|
using System.Threading.Tasks; |
|
|
using UnityEngine; |
|
|
using UnityEngine; |
|
|
using UnityEngine.Networking; |
|
|
using UnityEngine.Networking; |
|
@ -15,12 +18,24 @@ namespace IllusionInjector.Updating.ModsaberML |
|
|
{ |
|
|
{ |
|
|
class Updater : MonoBehaviour |
|
|
class Updater : MonoBehaviour |
|
|
{ |
|
|
{ |
|
|
public Updater instance; |
|
|
|
|
|
|
|
|
public static Updater instance; |
|
|
|
|
|
|
|
|
public void Awake() |
|
|
public void Awake() |
|
|
{ |
|
|
{ |
|
|
instance = this; |
|
|
|
|
|
CheckForUpdates(); |
|
|
|
|
|
|
|
|
try |
|
|
|
|
|
{ |
|
|
|
|
|
if (instance != null) |
|
|
|
|
|
Destroy(this); |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
instance = this; |
|
|
|
|
|
CheckForUpdates(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception e) |
|
|
|
|
|
{ |
|
|
|
|
|
Logger.log.Error(e); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void CheckForUpdates() |
|
|
public void CheckForUpdates() |
|
@ -28,13 +43,17 @@ namespace IllusionInjector.Updating.ModsaberML |
|
|
StartCoroutine(CheckForUpdatesCoroutine()); |
|
|
StartCoroutine(CheckForUpdatesCoroutine()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private Regex commentRegex = new Regex(@"(?: \/\/.+)?$", RegexOptions.Compiled | RegexOptions.Multiline); |
|
|
|
|
|
private Dictionary<Uri, UpdateScript> cachedRequests = new Dictionary<Uri, UpdateScript>(); |
|
|
|
|
|
|
|
|
private struct UpdateStruct |
|
|
|
|
|
{ |
|
|
|
|
|
public PluginManager.BSPluginMeta plugin; |
|
|
|
|
|
public ApiEndpoint.Mod externInfo; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
IEnumerator CheckForUpdatesCoroutine() |
|
|
IEnumerator CheckForUpdatesCoroutine() |
|
|
{ |
|
|
{ |
|
|
Logger.log.Info("Checking for mod updates..."); |
|
|
Logger.log.Info("Checking for mod updates..."); |
|
|
|
|
|
|
|
|
var toUpdate = new List<PluginManager.BSPluginMeta>(); |
|
|
|
|
|
|
|
|
var toUpdate = new List<UpdateStruct>(); |
|
|
|
|
|
|
|
|
var modList = new List<ApiEndpoint.Mod>(); |
|
|
var modList = new List<ApiEndpoint.Mod>(); |
|
|
using (var request = UnityWebRequest.Get(ApiEndpoint.ApiBase+ApiEndpoint.GetApprovedEndpoint)) |
|
|
using (var request = UnityWebRequest.Get(ApiEndpoint.ApiBase+ApiEndpoint.GetApprovedEndpoint)) |
|
@ -105,7 +124,11 @@ namespace IllusionInjector.Updating.ModsaberML |
|
|
if (modRegistry.GameVersion == GameVersion) |
|
|
if (modRegistry.GameVersion == GameVersion) |
|
|
{ |
|
|
{ |
|
|
Logger.log.Debug($"Queueing update..."); |
|
|
Logger.log.Debug($"Queueing update..."); |
|
|
toUpdate.Add(plugin); |
|
|
|
|
|
|
|
|
toUpdate.Add(new UpdateStruct |
|
|
|
|
|
{ |
|
|
|
|
|
plugin = plugin, |
|
|
|
|
|
externInfo = modRegistry |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
@ -124,44 +147,93 @@ namespace IllusionInjector.Updating.ModsaberML |
|
|
Logger.log.Debug($"Created temp download dirtectory {tempDirectory}"); |
|
|
Logger.log.Debug($"Created temp download dirtectory {tempDirectory}"); |
|
|
foreach (var item in toUpdate) |
|
|
foreach (var item in toUpdate) |
|
|
{ |
|
|
{ |
|
|
StartCoroutine(DownloadPluginCoroutine(tempDirectory, item)); |
|
|
|
|
|
|
|
|
StartCoroutine(UpdateModCoroutine(tempDirectory, item)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class StreamDownloadHandler : DownloadHandlerScript |
|
|
|
|
|
{ |
|
|
|
|
|
public MemoryStream Stream { get; set; } |
|
|
|
|
|
|
|
|
|
|
|
protected void ReceiveContentLength(long contentLength) |
|
|
|
|
|
{ |
|
|
|
|
|
Stream.Capacity = (int)contentLength; |
|
|
|
|
|
Logger.log.Debug($"Got content length: {contentLength}"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected void OnContentComplete() |
|
|
|
|
|
{ |
|
|
|
|
|
Logger.log.Debug("Download complete"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected bool ReceiveData(byte[] data, long dataLength) |
|
|
|
|
|
{ |
|
|
|
|
|
Stream.Write(data, 0, (int)dataLength); |
|
|
|
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
IEnumerator DownloadPluginCoroutine(string tempdir, PluginManager.BSPluginMeta item) |
|
|
|
|
|
|
|
|
IEnumerator UpdateModCoroutine(string tempdir, UpdateStruct item) |
|
|
{ |
|
|
{ |
|
|
|
|
|
async Task DownloadPluginAsync(MemoryStream stream) |
|
|
|
|
|
{ // embedded because i don't think unity likes it in the top level
|
|
|
|
|
|
|
|
|
yield return null; |
|
|
|
|
|
/*var file = Path.Combine(tempdir, item. + ".dll"); |
|
|
|
|
|
|
|
|
Logger.log.Debug($"Getting ZIP file for {item.plugin.Plugin.Name}"); |
|
|
|
|
|
//var stream = await httpClient.GetStreamAsync(url);
|
|
|
|
|
|
|
|
|
|
|
|
using (var zipFile = new ZipInputStream(new BlockingStream(stream))) |
|
|
|
|
|
{ |
|
|
|
|
|
Logger.log.Debug("Streams opened"); |
|
|
|
|
|
ZipEntry entry; |
|
|
|
|
|
while ((entry = zipFile.GetNextEntry()) != null) |
|
|
|
|
|
{ |
|
|
|
|
|
Logger.log.Debug(entry?.FileName); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Logger.log.Debug("Downloader exited"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
string url; |
|
|
|
|
|
if (SteamCheck.IsAvailable || item.externInfo.OculusFile == null) |
|
|
|
|
|
url = item.externInfo.SteamFile; |
|
|
|
|
|
else |
|
|
|
|
|
url = item.externInfo.OculusFile; |
|
|
|
|
|
|
|
|
using (var req = UnityWebRequest.Get(item.DownloadUri)) |
|
|
|
|
|
|
|
|
Logger.log.Debug($"URL = {url}"); |
|
|
|
|
|
|
|
|
|
|
|
using (var req = UnityWebRequest.Get(url)) |
|
|
|
|
|
using (var memStream = new MemoryStream()) |
|
|
{ |
|
|
{ |
|
|
req.downloadHandler = new DownloadHandlerFile(file); |
|
|
|
|
|
|
|
|
req.downloadHandler = new StreamDownloadHandler |
|
|
|
|
|
{ |
|
|
|
|
|
Stream = memStream |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var downloadTask = Task.Run(async () => |
|
|
|
|
|
{ // use slightly more multithreaded approach than coroutines
|
|
|
|
|
|
await DownloadPluginAsync(memStream); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
Logger.log.Debug("Sending request"); |
|
|
yield return req.SendWebRequest(); |
|
|
yield return req.SendWebRequest(); |
|
|
|
|
|
|
|
|
if (req.isNetworkError) |
|
|
if (req.isNetworkError) |
|
|
{ |
|
|
{ |
|
|
Logger.log.Error($"Network error while trying to download update for {item.Plugin.Plugin.Name}"); |
|
|
|
|
|
|
|
|
Logger.log.Error("Network error while trying to update mod"); |
|
|
Logger.log.Error(req.error); |
|
|
Logger.log.Error(req.error); |
|
|
yield break; |
|
|
yield break; |
|
|
} |
|
|
} |
|
|
if (req.isHttpError) |
|
|
if (req.isHttpError) |
|
|
{ |
|
|
{ |
|
|
Logger.log.Error($"Server returned an error code while trying to download update for {item.Plugin.Plugin.Name}"); |
|
|
|
|
|
|
|
|
Logger.log.Error($"Server returned an error code while trying to update mod"); |
|
|
Logger.log.Error(req.error); |
|
|
Logger.log.Error(req.error); |
|
|
yield break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var pluginDir = Path.GetDirectoryName(item.Plugin.Filename); |
|
|
|
|
|
var newFile = Path.Combine(pluginDir, item.Name + ".dll"); |
|
|
|
|
|
|
|
|
|
|
|
File.Delete(item.Plugin.Filename); |
|
|
|
|
|
if (File.Exists(newFile)) |
|
|
|
|
|
File.Delete(newFile); |
|
|
|
|
|
File.Move(file, newFile); |
|
|
|
|
|
|
|
|
downloadTask.Wait(); // wait for the damn thing to finish
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Logger.log.Info($"{item.Plugin.Plugin.Name} updated to {item.NewVersion}");*/ |
|
|
|
|
|
|
|
|
yield return null; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |