From 02941b0636069abf53b341ff5a69c7fba5ebd6da Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Wed, 5 Sep 2018 21:50:10 -0500 Subject: [PATCH] Started work on supporting modsaber dependencies Plugins are now fixed as they get moved to the cache As I work, I realize that this changes enough to warrent a new version --- IPA.Injector/Properties/AssemblyInfo.cs | 4 +- IPA.Loader/IPA.Loader.csproj | 6 ++ IPA.Loader/Loader/PluginManager.cs | 83 +++++++++---------- .../BeatSaber/ModsaberModInfo.cs | 4 +- .../Converters/ModsaberDependencyConverter.cs | 29 +++++++ .../Converters/SemverRangeConverter.cs | 17 ++++ .../Converters/SemverVersionConverter.cs | 18 ++++ IPA.Loader/Updating/ModsaberML/ApiEndpoint.cs | 24 +++++- IPA.Loader/Updating/ModsaberML/Updater.cs | 31 ++++++- IPA.Loader/Updating/SelfPlugin.cs | 4 +- IPA/Properties/AssemblyInfo.cs | 4 +- 11 files changed, 167 insertions(+), 57 deletions(-) create mode 100644 IPA.Loader/Updating/Converters/ModsaberDependencyConverter.cs create mode 100644 IPA.Loader/Updating/Converters/SemverRangeConverter.cs create mode 100644 IPA.Loader/Updating/Converters/SemverVersionConverter.cs diff --git a/IPA.Injector/Properties/AssemblyInfo.cs b/IPA.Injector/Properties/AssemblyInfo.cs index d88c5e7b..4519cca1 100644 --- a/IPA.Injector/Properties/AssemblyInfo.cs +++ b/IPA.Injector/Properties/AssemblyInfo.cs @@ -33,5 +33,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.9.2")] -[assembly: AssemblyFileVersion("3.9.2")] +[assembly: AssemblyVersion("3.10.0")] +[assembly: AssemblyFileVersion("3.10.0")] diff --git a/IPA.Loader/IPA.Loader.csproj b/IPA.Loader/IPA.Loader.csproj index 07306013..46a172a7 100644 --- a/IPA.Loader/IPA.Loader.csproj +++ b/IPA.Loader/IPA.Loader.csproj @@ -69,6 +69,9 @@ + + + @@ -98,6 +101,9 @@ 11.0.2 + + 1.2.0 + diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs index 2e28a2b2..1f25869c 100644 --- a/IPA.Loader/Loader/PluginManager.cs +++ b/IPA.Loader/Loader/PluginManager.cs @@ -111,6 +111,46 @@ namespace IPA.Loader { string pluginCopy = Path.Combine(cacheDir, Path.GetFileName(s)); File.Copy(Path.Combine(pluginDirectory, s), pluginCopy); + + #region Fix assemblies for refactor + + var module = ModuleDefinition.ReadModule(Path.Combine(pluginDirectory, s)); + foreach (var @ref in module.AssemblyReferences) + { // fix assembly references + if (@ref.Name == "IllusionPlugin" || @ref.Name == "IllusionInjector") + { + @ref.Name = "IPA.Loader"; + } + } + + foreach (var @ref in module.GetTypeReferences()) + { // fix type references + if (@ref.FullName == "IllusionPlugin.IPlugin") @ref.Namespace = "IPA.Old"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.IEnhancedPlugin") @ref.Namespace = "IPA.Old"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.IBeatSaberPlugin") @ref.Namespace = "IPA"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.IEnhancedBeatSaberPlugin") @ref.Namespace = "IPA"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.BeatSaber.ModsaberModInfo") @ref.Namespace = "IPA"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.IniFile") @ref.Namespace = "IPA.Config"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.IModPrefs") @ref.Namespace = "IPA.Config"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.ModPrefs") @ref.Namespace = "IPA.Config"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.Utils.ReflectionUtil") @ref.Namespace = "IPA.Utilities"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.Logging.Logger") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; + if (@ref.FullName == "IllusionPlugin.Logging.LogPrinter") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.PluginManager") @ref.Namespace = "IPA.Loader"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.PluginComponent") @ref.Namespace = "IPA.Loader"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.CompositeBSPlugin") @ref.Namespace = "IPA.Loader.Composite"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.CompositeIPAPlugin") @ref.Namespace = "IPA.Loader.Composite"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.Logging.UnityLogInterceptor") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.Logging.StandardLogger") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.Updating.SelfPlugin") @ref.Namespace = "IPA.Updating"; //@ref.Name = ""; + if (@ref.FullName == "IllusionInjector.Updating.Backup.BackupUnit") @ref.Namespace = "IPA.Updating.Backup"; //@ref.Name = ""; + if (@ref.Namespace == "IllusionInjector.Utilities") @ref.Namespace = "IPA.Utilities"; //@ref.Name = ""; + if (@ref.Namespace == "IllusionInjector.Logging.Printers") @ref.Namespace = "IPA.Logging.Printers"; //@ref.Name = ""; + if (@ref.Namespace == "IllusionInjector.Updating.ModsaberML") @ref.Namespace = "IPA.Updating.ModsaberML"; //@ref.Name = ""; + } + module.Write(pluginCopy); + + #endregion } var selfPlugin = new BSPluginMeta @@ -186,49 +226,6 @@ namespace IPA.Loader try { - #region Fix assemblies for refactor - - var module = ModuleDefinition.ReadModule(file); - bool modifiedModule = false; - foreach (var @ref in module.AssemblyReferences) - { // fix assembly references - if (@ref.Name == "IllusionPlugin" || @ref.Name == "IllusionInjector") - { - @ref.Name = "IPA.Loader"; - modifiedModule = true; - } - } - if (modifiedModule) - { // types don't need to be fixed if it's already referencing the new version - foreach (var @ref in module.GetTypeReferences()) - { // fix type references - if (@ref.FullName == "IllusionPlugin.IPlugin") @ref.Namespace = "IPA.Old"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.IEnhancedPlugin") @ref.Namespace = "IPA.Old"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.IBeatSaberPlugin") @ref.Namespace = "IPA"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.IEnhancedBeatSaberPlugin") @ref.Namespace = "IPA"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.BeatSaber.ModsaberModInfo") @ref.Namespace = "IPA"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.IniFile") @ref.Namespace = "IPA.Config"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.IModPrefs") @ref.Namespace = "IPA.Config"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.ModPrefs") @ref.Namespace = "IPA.Config"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.Utils.ReflectionUtil") @ref.Namespace = "IPA.Utilities"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.Logging.Logger") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; - if (@ref.FullName == "IllusionPlugin.Logging.LogPrinter") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.PluginManager") @ref.Namespace = "IPA.Loader"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.PluginComponent") @ref.Namespace = "IPA.Loader"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.CompositeBSPlugin") @ref.Namespace = "IPA.Loader.Composite"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.CompositeIPAPlugin") @ref.Namespace = "IPA.Loader.Composite"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.Logging.UnityLogInterceptor") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.Logging.StandardLogger") @ref.Namespace = "IPA.Logging"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.Updating.SelfPlugin") @ref.Namespace = "IPA.Updating"; //@ref.Name = ""; - if (@ref.FullName == "IllusionInjector.Updating.Backup.BackupUnit") @ref.Namespace = "IPA.Updating.Backup"; //@ref.Name = ""; - if (@ref.Namespace == "IllusionInjector.Utilities") @ref.Namespace = "IPA.Utilities"; //@ref.Name = ""; - if (@ref.Namespace == "IllusionInjector.Logging.Printers") @ref.Namespace = "IPA.Logging.Printers"; //@ref.Name = ""; - if (@ref.Namespace == "IllusionInjector.Updating.ModsaberML") @ref.Namespace = "IPA.Updating.ModsaberML"; //@ref.Name = ""; - } - module.Write(file); - } - - #endregion Assembly assembly = Assembly.LoadFrom(file); diff --git a/IPA.Loader/PluginInterfaces/BeatSaber/ModsaberModInfo.cs b/IPA.Loader/PluginInterfaces/BeatSaber/ModsaberModInfo.cs index ba5fb374..33671149 100644 --- a/IPA.Loader/PluginInterfaces/BeatSaber/ModsaberModInfo.cs +++ b/IPA.Loader/PluginInterfaces/BeatSaber/ModsaberModInfo.cs @@ -17,8 +17,8 @@ namespace IPA public string InternalName { get; set; } /// - /// The version of the currently installed mod. Used to compare to the version on ModSaber. + /// The version of the currently installed mod. Used to compare to the version on ModSaber. Should be a valid SemVer version. /// - public Version CurrentVersion { get; set; } + public string CurrentVersion { get; set; } } } diff --git a/IPA.Loader/Updating/Converters/ModsaberDependencyConverter.cs b/IPA.Loader/Updating/Converters/ModsaberDependencyConverter.cs new file mode 100644 index 00000000..43da9f89 --- /dev/null +++ b/IPA.Loader/Updating/Converters/ModsaberDependencyConverter.cs @@ -0,0 +1,29 @@ +using IPA.Updating.ModsaberML; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static IPA.Updating.ModsaberML.ApiEndpoint.Mod; + +namespace IPA.Updating.Converters +{ + internal class ModsaberDependencyConverter : JsonConverter + { + public override Dependency ReadJson(JsonReader reader, Type objectType, Dependency existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var parts = (reader.Value as string).Split('@'); + return new Dependency() + { + Name = parts[0], + VersionRange = new SemVer.Range(parts[1]) + }; + } + + public override void WriteJson(JsonWriter writer, Dependency value, JsonSerializer serializer) + { + writer.WriteValue($"{value.Name}@{value.VersionRange.ToString()}"); + } + } +} diff --git a/IPA.Loader/Updating/Converters/SemverRangeConverter.cs b/IPA.Loader/Updating/Converters/SemverRangeConverter.cs new file mode 100644 index 00000000..46d2a8c2 --- /dev/null +++ b/IPA.Loader/Updating/Converters/SemverRangeConverter.cs @@ -0,0 +1,17 @@ +using Newtonsoft.Json; +using SemVer; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IPA.Updating.Converters +{ + internal class SemverRangeConverter : JsonConverter + { + public override Range ReadJson(JsonReader reader, Type objectType, Range existingValue, bool hasExistingValue, JsonSerializer serializer) => new Range(reader.Value as string); + + public override void WriteJson(JsonWriter writer, Range value, JsonSerializer serializer) => writer.WriteValue(value.ToString()); + } +} diff --git a/IPA.Loader/Updating/Converters/SemverVersionConverter.cs b/IPA.Loader/Updating/Converters/SemverVersionConverter.cs new file mode 100644 index 00000000..57804965 --- /dev/null +++ b/IPA.Loader/Updating/Converters/SemverVersionConverter.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using SemVer; +using Version = SemVer.Version; + +namespace IPA.Updating.Converters +{ + internal class SemverVersionConverter : JsonConverter + { + public override Version ReadJson(JsonReader reader, Type objectType, Version existingValue, bool hasExistingValue, JsonSerializer serializer) => new Version(reader.Value as string); + + public override void WriteJson(JsonWriter writer, Version value, JsonSerializer serializer) => writer.WriteValue(value.ToString()); + } +} diff --git a/IPA.Loader/Updating/ModsaberML/ApiEndpoint.cs b/IPA.Loader/Updating/ModsaberML/ApiEndpoint.cs index 38776d50..7c1934b7 100644 --- a/IPA.Loader/Updating/ModsaberML/ApiEndpoint.cs +++ b/IPA.Loader/Updating/ModsaberML/ApiEndpoint.cs @@ -1,13 +1,16 @@ using IPA.Logging; +using IPA.Updating.Converters; using IPA.Utilities; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using SemVer; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Version = SemVer.Version; namespace IPA.Updating.ModsaberML { @@ -71,18 +74,24 @@ namespace IPA.Updating.ModsaberML #pragma warning disable CS0649 [JsonProperty("name")] public string Name; + [JsonProperty("version"), - JsonConverter(typeof(VersionConverter))] + JsonConverter(typeof(SemverVersionConverter))] public Version Version; + [JsonProperty("approved")] public bool Approved; + [JsonProperty("title")] public string Title; + [JsonProperty("gameVersion"), - JsonConverter(typeof(VersionConverter))] + JsonConverter(typeof(SemverVersionConverter))] public Version GameVersion; + [JsonProperty("author")] public string Author; + #pragma warning restore CS0649 [Serializable] public class PlatformFile @@ -90,8 +99,10 @@ namespace IPA.Updating.ModsaberML [JsonProperty("hash"), JsonConverter(typeof(HexArrayConverter))] public byte[] Hash = new byte[20]; + [JsonProperty("files", ItemConverterType = typeof(HexArrayConverter))] public Dictionary FileHashes = new Dictionary(); + [JsonProperty("url")] public string DownloadPath = null; @@ -113,6 +124,15 @@ namespace IPA.Updating.ModsaberML [JsonProperty("files")] public FilesObject Files = null; + public class Dependency + { + public string Name = null; + public Range VersionRange = null; + } + + [JsonProperty("dependsOn", ItemConverterType = typeof(ModsaberDependencyConverter))] + public Dependency[] Dependencies = new Dependency[0]; + public override string ToString() { return $"{{\"{Title} ({Name})\"v{Version} for {GameVersion} by {Author} with \"{Files.Steam}\" and \"{Files.Oculus}\"}}"; diff --git a/IPA.Loader/Updating/ModsaberML/Updater.cs b/IPA.Loader/Updating/ModsaberML/Updater.cs index a7251911..4b171813 100644 --- a/IPA.Loader/Updating/ModsaberML/Updater.cs +++ b/IPA.Loader/Updating/ModsaberML/Updater.cs @@ -16,6 +16,7 @@ using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; using Logger = IPA.Logging.Logger; +using Version = SemVer.Version; using IPA.Updating.Backup; namespace IPA.Updating.ModsaberML @@ -47,9 +48,30 @@ namespace IPA.Updating.ModsaberML StartCoroutine(CheckForUpdatesCoroutine()); } + private class ParsedPluginMeta : PluginManager.BSPluginMeta + { + private Version _verCache = null; + public Version ModVersion + { + get + { + if (_verCache == null) + _verCache = new Version(ModsaberInfo.CurrentVersion); + return _verCache; + } + } + + public ParsedPluginMeta(PluginManager.BSPluginMeta meta) + { + this.Plugin = meta.Plugin; + this.ModsaberInfo = meta.ModsaberInfo; + this.Filename = meta.Filename; + } + } + private struct UpdateStruct { - public PluginManager.BSPluginMeta plugin; + public ParsedPluginMeta plugin; public ApiEndpoint.Mod externInfo; } @@ -60,8 +82,9 @@ namespace IPA.Updating.ModsaberML var toUpdate = new List(); var GameVersion = new Version(Application.version); - foreach (var plugin in PluginManager.BSMetas) + foreach (var _plugin in PluginManager.BSMetas) { + var plugin = new ParsedPluginMeta(_plugin); var info = plugin.ModsaberInfo; if (info == null) continue; @@ -104,8 +127,8 @@ namespace IPA.Updating.ModsaberML } Logger.updater.Debug($"Found Modsaber.ML registration for {plugin.Plugin.Name} ({info.InternalName})"); - Logger.updater.Debug($"Installed version: {info.CurrentVersion}; Latest version: {modRegistry.Version}"); - if (modRegistry.Version > info.CurrentVersion) + Logger.updater.Debug($"Installed version: {plugin.ModVersion}; Latest version: {modRegistry.Version}"); + if (modRegistry.Version > plugin.ModVersion) { Logger.updater.Debug($"{plugin.Plugin.Name} needs an update!"); if (modRegistry.GameVersion == GameVersion) diff --git a/IPA.Loader/Updating/SelfPlugin.cs b/IPA.Loader/Updating/SelfPlugin.cs index 2fde0921..57fe3bf1 100644 --- a/IPA.Loader/Updating/SelfPlugin.cs +++ b/IPA.Loader/Updating/SelfPlugin.cs @@ -11,7 +11,7 @@ namespace IPA.Updating internal class SelfPlugin : IBeatSaberPlugin { internal const string IPA_Name = "Beat Saber IPA"; - internal const string IPA_Version = "3.9.2"; + internal const string IPA_Version = "3.10.0"; public string Name => IPA_Name; @@ -19,7 +19,7 @@ namespace IPA.Updating public ModsaberModInfo ModInfo => new ModsaberModInfo { - CurrentVersion = new Version(IPA_Version), + CurrentVersion = IPA_Version, InternalName = "beatsaber-ipa-reloaded" }; diff --git a/IPA/Properties/AssemblyInfo.cs b/IPA/Properties/AssemblyInfo.cs index 63939eed..17291691 100644 --- a/IPA/Properties/AssemblyInfo.cs +++ b/IPA/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.9.2")] -[assembly: AssemblyFileVersion("3.9.2")] +[assembly: AssemblyVersion("3.10.0")] +[assembly: AssemblyFileVersion("3.10.0")]