Browse Source

Updater now checks Modsaber.ML to try and find updates

refactor
Anairkoen Schno 6 years ago
parent
commit
0fe771c648
12 changed files with 250 additions and 28 deletions
  1. +5
    -6
      IllusionInjector/BeatSaber/CompositeBSPlugin.cs
  2. +1
    -0
      IllusionInjector/IllusionInjector.csproj
  3. +2
    -2
      IllusionInjector/PluginComponent.cs
  4. +28
    -8
      IllusionInjector/PluginManager.cs
  5. +18
    -8
      IllusionInjector/Updating/ModsaberML/ApiEndpoint.cs
  6. +167
    -0
      IllusionInjector/Updating/ModsaberML/Updater.cs
  7. +2
    -0
      IllusionInjector/Updating/Old/ModUpdater.cs
  8. +1
    -1
      IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache
  9. +10
    -2
      IllusionPlugin/BeatSaber/IBeatSaberPlugin.cs
  10. +14
    -0
      IllusionPlugin/BeatSaber/ModsaberModInfo.cs
  11. +1
    -0
      IllusionPlugin/IllusionPlugin.csproj
  12. +1
    -1
      IllusionPlugin/obj/Debug/IllusionPlugin.csproj.CoreCompileInputs.cache

+ 5
- 6
IllusionInjector/BeatSaber/CompositeBSPlugin.cs View File

@ -1,4 +1,5 @@
using IllusionPlugin; using IllusionPlugin;
using IllusionPlugin.BeatSaber;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -78,16 +79,14 @@ namespace IllusionInjector {
Invoke(plugin => plugin.OnFixedUpdate()); Invoke(plugin => plugin.OnFixedUpdate());
} }
public string Name {
get { throw new NotImplementedException(); }
}
public string Name => throw new NotImplementedException();
public Version Version {
get { throw new NotImplementedException(); }
}
public string Version => throw new NotImplementedException();
public Uri UpdateUri => throw new NotImplementedException(); public Uri UpdateUri => throw new NotImplementedException();
public ModsaberModInfo ModInfo => throw new NotImplementedException();
public void OnLateUpdate() { public void OnLateUpdate() {
Invoke(plugin => { Invoke(plugin => {
if (plugin is IEnhancedBeatSaberPlugin) if (plugin is IEnhancedBeatSaberPlugin)


+ 1
- 0
IllusionInjector/IllusionInjector.csproj View File

@ -69,6 +69,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PluginComponent.cs" /> <Compile Include="PluginComponent.cs" />
<Compile Include="Updating\ModsaberML\ApiEndpoint.cs" /> <Compile Include="Updating\ModsaberML\ApiEndpoint.cs" />
<Compile Include="Updating\ModsaberML\Updater.cs" />
<Compile Include="Updating\Old\ModUpdater.cs" /> <Compile Include="Updating\Old\ModUpdater.cs" />
<Compile Include="Updating\Old\UpdateScript.cs" /> <Compile Include="Updating\Old\UpdateScript.cs" />
<Compile Include="Utilities\SimpleJson.cs" /> <Compile Include="Utilities\SimpleJson.cs" />


+ 2
- 2
IllusionInjector/PluginComponent.cs View File

@ -1,5 +1,4 @@
using IllusionInjector.Updating;
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
@ -27,6 +26,7 @@ namespace IllusionInjector
// this has no relevance since there is a new mod updater system // this has no relevance since there is a new mod updater system
//gameObject.AddComponent<ModUpdater>(); // AFTER plugins are loaded, but before most things //gameObject.AddComponent<ModUpdater>(); // AFTER plugins are loaded, but before most things
gameObject.AddComponent<Updating.ModsaberML.Updater>();
bsPlugins.OnApplicationStart(); bsPlugins.OnApplicationStart();
ipaPlugins.OnApplicationStart(); ipaPlugins.OnApplicationStart();


+ 28
- 8
IllusionInjector/PluginManager.cs View File

@ -1,5 +1,6 @@
using IllusionInjector.Logging; using IllusionInjector.Logging;
using IllusionPlugin; using IllusionPlugin;
using IllusionPlugin.BeatSaber;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -15,11 +16,12 @@ namespace IllusionInjector
public static class PluginManager public static class PluginManager
{ {
#pragma warning disable CS0618 // Type or member is obsolete (IPlugin) #pragma warning disable CS0618 // Type or member is obsolete (IPlugin)
public class BSPluginMeta public class BSPluginMeta
{ {
public IBeatSaberPlugin Plugin { get; internal set; } public IBeatSaberPlugin Plugin { get; internal set; }
public string Filename { get; internal set; } public string Filename { get; internal set; }
public ModsaberModInfo ModsaberInfo { get; internal set; }
} }
public static IEnumerable<IBeatSaberPlugin> BSPlugins public static IEnumerable<IBeatSaberPlugin> BSPlugins
@ -100,15 +102,16 @@ namespace IllusionInjector
foreach (string s in copiedPlugins) foreach (string s in copiedPlugins)
{ {
var result = LoadPluginsFromFile(s, exeName); var result = LoadPluginsFromFile(s, exeName);
_bsPlugins.AddRange(result.Item1.Select(p => new BSPluginMeta { Plugin = p, Filename = s }));
_bsPlugins.AddRange(result.Item1);
_ipaPlugins.AddRange(result.Item2); _ipaPlugins.AddRange(result.Item2);
} }
// DEBUG // DEBUG
Logger.log.Info($"Running on Unity {UnityEngine.Application.unityVersion}"); Logger.log.Info($"Running on Unity {UnityEngine.Application.unityVersion}");
Logger.log.Info($"Game version {UnityEngine.Application.version}");
Logger.log.Info("-----------------------------"); Logger.log.Info("-----------------------------");
Logger.log.Info($"Loading plugins from {pluginDirectory} and found {_bsPlugins.Count}");
Logger.log.Info($"Loading plugins from {GetRelativePath(pluginDirectory, Environment.CurrentDirectory)} and found {_bsPlugins.Count + _ipaPlugins.Count}");
Logger.log.Info("-----------------------------"); Logger.log.Info("-----------------------------");
foreach (var plugin in _bsPlugins) foreach (var plugin in _bsPlugins)
{ {
@ -122,13 +125,25 @@ namespace IllusionInjector
Logger.log.Info("-----------------------------"); Logger.log.Info("-----------------------------");
} }
private static Tuple<IEnumerable<IBeatSaberPlugin>, IEnumerable<IPlugin>> LoadPluginsFromFile(string file, string exeName)
private static string GetRelativePath(string filespec, string folder)
{
Uri pathUri = new Uri(filespec);
// Folders must end in a slash
if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
folder += Path.DirectorySeparatorChar;
}
Uri folderUri = new Uri(folder);
return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString().Replace('/', Path.DirectorySeparatorChar));
}
private static Tuple<IEnumerable<BSPluginMeta>, IEnumerable<IPlugin>> LoadPluginsFromFile(string file, string exeName)
{ {
List<IBeatSaberPlugin> bsPlugins = new List<IBeatSaberPlugin>();
List<BSPluginMeta> bsPlugins = new List<BSPluginMeta>();
List<IPlugin> ipaPlugins = new List<IPlugin>(); List<IPlugin> ipaPlugins = new List<IPlugin>();
if (!File.Exists(file) || !file.EndsWith(".dll", true, null)) if (!File.Exists(file) || !file.EndsWith(".dll", true, null))
return new Tuple<IEnumerable<IBeatSaberPlugin>, IEnumerable<IPlugin>>(bsPlugins, ipaPlugins);
return new Tuple<IEnumerable<BSPluginMeta>, IEnumerable<IPlugin>>(bsPlugins, ipaPlugins);
T OptionalGetPlugin<T>(Type t) where T : class T OptionalGetPlugin<T>(Type t) where T : class
{ {
@ -166,7 +181,12 @@ namespace IllusionInjector
IBeatSaberPlugin bsPlugin = OptionalGetPlugin<IBeatSaberPlugin>(t); IBeatSaberPlugin bsPlugin = OptionalGetPlugin<IBeatSaberPlugin>(t);
if (bsPlugin != null) if (bsPlugin != null)
{ {
bsPlugins.Add(bsPlugin);
bsPlugins.Add(new BSPluginMeta
{
Plugin = bsPlugin,
Filename = file,
ModsaberInfo = bsPlugin.ModInfo
});
} }
else else
{ {
@ -184,7 +204,7 @@ namespace IllusionInjector
Logger.log.Error($"Could not load {Path.GetFileName(file)}! {e}"); Logger.log.Error($"Could not load {Path.GetFileName(file)}! {e}");
} }
return new Tuple<IEnumerable<IBeatSaberPlugin>, IEnumerable<IPlugin>>(bsPlugins, ipaPlugins);
return new Tuple<IEnumerable<BSPluginMeta>, IEnumerable<IPlugin>>(bsPlugins, ipaPlugins);
} }
public class AppInfo public class AppInfo


+ 18
- 8
IllusionInjector/Updating/ModsaberML/ApiEndpoint.cs View File

@ -9,8 +9,13 @@ namespace IllusionInjector.Updating.ModsaberML
{ {
class ApiEndpoint class ApiEndpoint
{ {
const string ApiBase = "https://www.modsaber.ml/api/";
const string GetApprovedEndpoint = "public/temp/approved";
#if DEBUG
public const string ApiBase = "https://www.modsaber.ml/api/";
public const string GetApprovedEndpoint = "public/temp/approved";
#else
public const string ApiBase = "https://www.modsaber.ml/api/";
public const string GetApprovedEndpoint = "public/temp/approved";
#endif
public class Mod public class Mod
{ {
@ -35,17 +40,22 @@ namespace IllusionInjector.Updating.ModsaberML
Author = obj["author"] Author = obj["author"]
}; };
foreach (var item in obj["files"].Keys)
foreach (var item in obj["files"])
{ {
var key = item as JSONString;
if (key.Value == "steam")
outp.SteamFile = obj[key.Value]["url"];
if (key.Value == "oculus")
outp.OculusFile = obj[key.Value]["url"];
var key = item.Key;
if (key == "steam")
outp.SteamFile = item.Value["url"];
if (key == "oculus")
outp.OculusFile = item.Value["url"];
} }
return outp; return outp;
} }
public override string ToString()
{
return $"{{\"{Title} ({Name})\"v{Version} for {GameVersion} by {Author} with \"{SteamFile}\" and \"{OculusFile}\"}}";
}
} }
} }


+ 167
- 0
IllusionInjector/Updating/ModsaberML/Updater.cs View File

@ -0,0 +1,167 @@
using SimpleJSON;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using Logger = IllusionInjector.Logging.Logger;
namespace IllusionInjector.Updating.ModsaberML
{
class Updater : MonoBehaviour
{
public Updater instance;
public void Awake()
{
instance = this;
CheckForUpdates();
}
public void CheckForUpdates()
{
StartCoroutine(CheckForUpdatesCoroutine());
}
private Regex commentRegex = new Regex(@"(?: \/\/.+)?$", RegexOptions.Compiled | RegexOptions.Multiline);
private Dictionary<Uri, UpdateScript> cachedRequests = new Dictionary<Uri, UpdateScript>();
IEnumerator CheckForUpdatesCoroutine()
{
Logger.log.Info("Checking for mod updates...");
var toUpdate = new List<PluginManager.BSPluginMeta>();
var modList = new List<ApiEndpoint.Mod>();
using (var request = UnityWebRequest.Get(ApiEndpoint.ApiBase+ApiEndpoint.GetApprovedEndpoint))
{
yield return request.SendWebRequest();
if (request.isNetworkError)
{
Logger.log.Error("Network error while trying to update mods");
Logger.log.Error(request.error);
yield break;
}
if (request.isHttpError)
{
Logger.log.Error($"Server returned an error code while trying to update mods");
Logger.log.Error(request.error);
}
var json = request.downloadHandler.text;
JSONObject obj = null;
try
{
obj = JSON.Parse(json).AsObject;
}
catch (InvalidCastException)
{
Logger.log.Error($"Parse error while trying to update mods");
Logger.log.Error($"Response doesn't seem to be a JSON object");
yield break;
}
catch (Exception e)
{
Logger.log.Error($"Parse error while trying to update mods");
Logger.log.Error(e);
yield break;
}
foreach (var modObj in obj["mods"].AsArray.Children)
{
try
{
modList.Add(ApiEndpoint.Mod.DecodeJSON(modObj.AsObject));
}
catch (Exception e)
{
Logger.log.Error($"Parse error while trying to update mods");
Logger.log.Error($"Response doesn't seem to be correctly formatted");
Logger.log.Error(e);
break;
}
}
}
var GameVersion = new Version(Application.version);
foreach (var plugin in PluginManager.BSMetas)
{
var info = plugin.ModsaberInfo;
var modRegistry = modList.FirstOrDefault(o => o.Name == info.InternalName);
if (modRegistry != null)
{ // a.k.a we found it
Logger.log.Debug($"Found Modsaber.ML registration for {plugin.Plugin.Name} ({info.InternalName})");
Logger.log.Debug($"Installed version: {info.CurrentVersion}; Latest version: {modRegistry.Version}");
if (modRegistry.Version > info.CurrentVersion)
{
Logger.log.Debug($"{plugin.Plugin.Name} needs an update!");
if (modRegistry.GameVersion == GameVersion)
{
Logger.log.Debug($"Queueing update...");
toUpdate.Add(plugin);
}
else
{
Logger.log.Warn($"Update avaliable for {plugin.Plugin.Name}, but for a different Beat Saber version!");
}
}
}
}
Logger.log.Info($"{toUpdate.Count} mods need updating");
if (toUpdate.Count == 0) yield break;
string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
Logger.log.Debug($"Created temp download dirtectory {tempDirectory}");
foreach (var item in toUpdate)
{
StartCoroutine(DownloadPluginCoroutine(tempDirectory, item));
}
}
IEnumerator DownloadPluginCoroutine(string tempdir, PluginManager.BSPluginMeta item)
{
yield return null;
/*var file = Path.Combine(tempdir, item. + ".dll");
using (var req = UnityWebRequest.Get(item.DownloadUri))
{
req.downloadHandler = new DownloadHandlerFile(file);
yield return req.SendWebRequest();
if (req.isNetworkError)
{
Logger.log.Error($"Network error while trying to download update for {item.Plugin.Plugin.Name}");
Logger.log.Error(req.error);
yield break;
}
if (req.isHttpError)
{
Logger.log.Error($"Server returned an error code while trying to download update for {item.Plugin.Plugin.Name}");
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);
Logger.log.Info($"{item.Plugin.Plugin.Name} updated to {item.NewVersion}");*/
}
}
}

+ 2
- 0
IllusionInjector/Updating/Old/ModUpdater.cs View File

@ -17,6 +17,7 @@ using Logger = IllusionInjector.Logging.Logger;
namespace IllusionInjector.Updating namespace IllusionInjector.Updating
{ {
#if OLD_UPDATER
class ModUpdater : MonoBehaviour class ModUpdater : MonoBehaviour
{ {
public ModUpdater instance; public ModUpdater instance;
@ -202,4 +203,5 @@ namespace IllusionInjector.Updating
Logger.log.Info($"{item.Plugin.Plugin.Name} updated to {item.NewVersion}"); Logger.log.Info($"{item.Plugin.Plugin.Name} updated to {item.NewVersion}");
} }
} }
#endif
} }

+ 1
- 1
IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache View File

@ -1 +1 @@
1b7ab3d058c6a212976e4869e8586d3cc95bb707
4b98b2d3f93866107d7a8621254570f2cc16296c

+ 10
- 2
IllusionPlugin/BeatSaber/IBeatSaberPlugin.cs View File

@ -1,4 +1,5 @@
using System;
using IllusionPlugin.BeatSaber;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
@ -20,13 +21,20 @@ namespace IllusionPlugin
/// <summary> /// <summary>
/// Gets the version of the plugin. /// Gets the version of the plugin.
/// </summary> /// </summary>
Version Version { get; }
string Version { get; }
#if OLD_UPDATER
/// <summary> /// <summary>
/// The URI to the update script for the plugin. May be <see langword="null"/>. /// The URI to the update script for the plugin. May be <see langword="null"/>.
/// Actually tho this does nothing I just don't want to try to remove it completely /// Actually tho this does nothing I just don't want to try to remove it completely
/// </summary> /// </summary>
Uri UpdateUri { get; } Uri UpdateUri { get; }
#endif
/// <summary>
/// Gets the info for the Modsaber release of this plugin.
/// </summary>
ModsaberModInfo ModInfo { get; }
/// <summary> /// <summary>
/// Gets invoked when the application is started. /// Gets invoked when the application is started.


+ 14
- 0
IllusionPlugin/BeatSaber/ModsaberModInfo.cs View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IllusionPlugin.BeatSaber
{
public class ModsaberModInfo
{
public string InternalName { get; set; }
public Version CurrentVersion { get; set; }
}
}

+ 1
- 0
IllusionPlugin/IllusionPlugin.csproj View File

@ -44,6 +44,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BeatSaber\IEnhancedBeatSaberPlugin.cs" /> <Compile Include="BeatSaber\IEnhancedBeatSaberPlugin.cs" />
<Compile Include="BeatSaber\ModsaberModInfo.cs" />
<Compile Include="IniFile.cs" /> <Compile Include="IniFile.cs" />
<Compile Include="BeatSaber\IBeatSaberPlugin.cs" /> <Compile Include="BeatSaber\IBeatSaberPlugin.cs" />
<Compile Include="IPA\IEnhancedPlugin.cs" /> <Compile Include="IPA\IEnhancedPlugin.cs" />


+ 1
- 1
IllusionPlugin/obj/Debug/IllusionPlugin.csproj.CoreCompileInputs.cache View File

@ -1 +1 @@
1bbd9ba53463d8e0c57caf8203d0145bfc70fa26
9c8aaadb0a1830ce0d658b39574b7acf02507f4a

Loading…
Cancel
Save