From c3a3712e7515af6c5eb87495bf015947d96e9319 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Sat, 11 Dec 2021 05:31:31 -0600 Subject: [PATCH] Make GameVersion field optional --- IPA.Loader/Loader/PluginLoader.cs | 4 +- IPA.Loader/Loader/PluginManifest.cs | 4 +- IPA.Loader/Loader/manifest.json | 1 - IPA.Loader/Utilities/AlmostVersion.cs | 540 +++++++++++++------------- 4 files changed, 274 insertions(+), 275 deletions(-) diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index d04ecf59..e217ab43 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -888,8 +888,8 @@ namespace IPA.Loader internal static PluginExecutor? InitPlugin(PluginMetadata meta, IEnumerable alreadyLoaded) { - if (meta.Manifest.GameVersion != UnityGame.GameVersion) - Logger.loader.Warn($"Mod {meta.Name} developed for game version {meta.Manifest.GameVersion}, so it may not work properly."); + if (meta.Manifest.GameVersion is { } gv && gv != UnityGame.GameVersion) + Logger.loader.Warn($"Mod {meta.Name} developed for game version {gv}, so it may not work properly."); if (meta.IsSelf) return new PluginExecutor(meta, PluginExecutor.Special.Self); diff --git a/IPA.Loader/Loader/PluginManifest.cs b/IPA.Loader/Loader/PluginManifest.cs index a8da82f4..96b6933d 100644 --- a/IPA.Loader/Loader/PluginManifest.cs +++ b/IPA.Loader/Loader/PluginManifest.cs @@ -30,8 +30,8 @@ namespace IPA.Loader [JsonProperty("version", Required = Required.Always), JsonConverter(typeof(SemverVersionConverter))] public Version Version = null!; - [JsonProperty("gameVersion", Required = Required.Always), JsonConverter(typeof(AlmostVersionConverter))] - public AlmostVersion GameVersion = null!; + [JsonProperty("gameVersion", Required = Required.DisallowNull), JsonConverter(typeof(AlmostVersionConverter))] + public AlmostVersion? GameVersion; [JsonProperty("author", Required = Required.Always)] public string Author = null!; diff --git a/IPA.Loader/Loader/manifest.json b/IPA.Loader/Loader/manifest.json index e437e64c..2ad8a6cc 100644 --- a/IPA.Loader/Loader/manifest.json +++ b/IPA.Loader/Loader/manifest.json @@ -5,7 +5,6 @@ "#![IPA.Loader.description.md]", "A mod loader specifically for Beat Saber." ], - "gameVersion": "1.16.1", "id": "BSIPA", "name": "Beat Saber IPA", "version": "4.2.1-pre.2", diff --git a/IPA.Loader/Utilities/AlmostVersion.cs b/IPA.Loader/Utilities/AlmostVersion.cs index 22ec7c19..03ff5736 100644 --- a/IPA.Loader/Utilities/AlmostVersion.cs +++ b/IPA.Loader/Utilities/AlmostVersion.cs @@ -1,283 +1,283 @@ -#nullable enable -using IPA.Config.Data; -using IPA.Config.Stores; -using IPA.Config.Stores.Converters; -using System; -using System.Collections.Generic; -using SVersion = SemVer.Version; -using Version = Hive.Versioning.Version; - -namespace IPA.Utilities -{ - /// - /// A type that wraps so that the string of the version is stored when the string is - /// not a valid . - /// +#nullable enable +using IPA.Config.Data; +using IPA.Config.Stores; +using IPA.Config.Stores.Converters; +using System; +using System.Collections.Generic; +using SVersion = SemVer.Version; +using Version = Hive.Versioning.Version; + +namespace IPA.Utilities +{ + /// + /// A type that wraps so that the string of the version is stored when the string is + /// not a valid . + /// public class AlmostVersion : IComparable, IComparable, #pragma warning disable CS0618 // Type or member is obsolete IComparable #pragma warning restore CS0618 // Type or member is obsolete - { - /// - /// Represents a storage type of either parsed object or raw . - /// - public enum StoredAs - { - /// - /// The version was stored as a . - /// - SemVer, - /// - /// The version was stored as a . - /// - String - } - - /// - /// Creates a new with the version string provided in . - /// - /// the version string to store - public AlmostVersion(string vertext) - { - if (!TryParseFrom(vertext, StoredAs.SemVer)) - _ = TryParseFrom(vertext, StoredAs.String); - } - - /// - /// Creates an from the provided in . - /// - /// the to store - public AlmostVersion(Version ver) - { - SemverValue = ver; - StorageMode = StoredAs.SemVer; + { + /// + /// Represents a storage type of either parsed object or raw . + /// + public enum StoredAs + { + /// + /// The version was stored as a . + /// + SemVer, + /// + /// The version was stored as a . + /// + String + } + + /// + /// Creates a new with the version string provided in . + /// + /// the version string to store + public AlmostVersion(string vertext) + { + if (!TryParseFrom(vertext, StoredAs.SemVer)) + _ = TryParseFrom(vertext, StoredAs.String); + } + + /// + /// Creates an from the provided in . + /// + /// the to store + public AlmostVersion(Version ver) + { + SemverValue = ver; + StorageMode = StoredAs.SemVer; + } + + /// + /// Creates an from the provided in . + /// + /// the to store + [Obsolete("Use Hive.Versioning.Version constructor instead.")] + public AlmostVersion(SVersion ver) : this(ver?.UnderlyingVersion ?? throw new ArgumentNullException(nameof(ver))) { } + + /// + /// Creates an from the version string in stored using + /// the storage mode specified in . + /// + /// the text to parse as an + /// the storage mode to store the version in + public AlmostVersion(string vertext, StoredAs mode) + { + if (!TryParseFrom(vertext, mode)) + throw new ArgumentException($"{nameof(vertext)} could not be stored as {mode}!"); } - /// - /// Creates an from the provided in . - /// - /// the to store - [Obsolete("Use Hive.Versioning.Version constructor instead.")] - public AlmostVersion(SVersion ver) : this(ver?.UnderlyingVersion ?? throw new ArgumentNullException(nameof(ver))) { } - - /// - /// Creates an from the version string in stored using - /// the storage mode specified in . - /// - /// the text to parse as an - /// the storage mode to store the version in - public AlmostVersion(string vertext, StoredAs mode) - { - if (!TryParseFrom(vertext, mode)) - throw new ArgumentException($"{nameof(vertext)} could not be stored as {mode}!"); - } - - /// - /// Creates a new from the version string in stored the - /// same way as the passed in . - /// - /// the text to parse as an - /// an to copy the storage mode of - public AlmostVersion(string vertext, AlmostVersion copyMode) - { - if (copyMode is null) - throw new ArgumentNullException(nameof(copyMode)); - - if (!TryParseFrom(vertext, copyMode.StorageMode)) - _ = TryParseFrom(vertext, StoredAs.String); // silently parse differently - } - - private bool TryParseFrom(string str, StoredAs mode) - { + /// + /// Creates a new from the version string in stored the + /// same way as the passed in . + /// + /// the text to parse as an + /// an to copy the storage mode of + public AlmostVersion(string vertext, AlmostVersion copyMode) + { + if (copyMode is null) + throw new ArgumentNullException(nameof(copyMode)); + + if (!TryParseFrom(vertext, copyMode.StorageMode)) + _ = TryParseFrom(vertext, StoredAs.String); // silently parse differently + } + + private bool TryParseFrom(string str, StoredAs mode) + { if (mode == StoredAs.SemVer) { StorageMode = StoredAs.SemVer; var result = Version.TryParse(str, out var version); SemverValue = version; return result; - } - else - { - StringValue = str; - StorageMode = StoredAs.String; - return true; - } - } - - /// - /// The value of the if it was stored as a . - /// - /// the stored value as a , or if not stored as a string. - public string? StringValue { get; private set; } - - /// - /// The value of the if it was stored as a . - /// - /// the stored value as a , or if not stored as a version. - public Version? SemverValue { get; private set; } - - /// - /// The way the value is stored, whether it be as a or a . - /// - /// the storage mode used to store this value - public StoredAs StorageMode { get; private set; } - - /// - /// Gets a string representation of the current version. If the value is stored as a string, this returns it. If it is - /// stored as a , it is equivalent to calling . - /// - /// a string representation of the current version - /// - public override string ToString() => - StorageMode == StoredAs.SemVer ? SemverValue!.ToString() : StringValue!; - - /// - /// Compares to the in using - /// or , depending on the current store. - /// - /// - /// The storage methods of the two objects must be the same, or this will throw an . - /// - /// the to compare to - /// less than 0 if is considered bigger than , 0 if equal, and greater than zero if smaller - /// - public int CompareTo(AlmostVersion other) - { - if (other is null) return 1; - + } + else + { + StringValue = str; + StorageMode = StoredAs.String; + return true; + } + } + + /// + /// The value of the if it was stored as a . + /// + /// the stored value as a , or if not stored as a string. + public string? StringValue { get; private set; } + + /// + /// The value of the if it was stored as a . + /// + /// the stored value as a , or if not stored as a version. + public Version? SemverValue { get; private set; } + + /// + /// The way the value is stored, whether it be as a or a . + /// + /// the storage mode used to store this value + public StoredAs StorageMode { get; private set; } + + /// + /// Gets a string representation of the current version. If the value is stored as a string, this returns it. If it is + /// stored as a , it is equivalent to calling . + /// + /// a string representation of the current version + /// + public override string ToString() => + StorageMode == StoredAs.SemVer ? SemverValue!.ToString() : StringValue!; + + /// + /// Compares to the in using + /// or , depending on the current store. + /// + /// + /// The storage methods of the two objects must be the same, or this will throw an . + /// + /// the to compare to + /// less than 0 if is considered bigger than , 0 if equal, and greater than zero if smaller + /// + public int CompareTo(AlmostVersion other) + { + if (other is null) return 1; + return StorageMode == StoredAs.SemVer && other.StorageMode == StoredAs.SemVer ? SemverValue!.CompareTo(other.SemverValue!) - : string.Compare(ToString(), other.ToString(), StringComparison.Ordinal); - } - - /// - /// Compares to the in using . - /// - /// - /// The storage method of must be , else an will - /// be thrown. - /// - /// the to compare to - /// less than 0 if is considered bigger than , 0 if equal, and greater than zero if smaller - /// - public int CompareTo(Version other) - { - if (StorageMode != StoredAs.SemVer) - throw new InvalidOperationException("Cannot compare a SemVer version with an AlmostVersion stored as a string!"); - - return SemverValue!.CompareTo(other); + : string.Compare(ToString(), other.ToString(), StringComparison.Ordinal); } - /// - /// Compares to the in using . - /// - /// - /// The storage method of must be , else an will - /// be thrown. - /// - /// the to compare to - /// less than 0 if is considered bigger than , 0 if equal, and greater than zero if smaller - /// - [Obsolete("Use the Hive.Versioning.Version overload instead.")] - public int CompareTo(SVersion other) => CompareTo(other.UnderlyingVersion); - - /// - /// Performs a strict equality check between and . - /// - /// - /// This may return where returns - /// - /// the object to compare to - /// if they are equal, otherwise - /// - public override bool Equals(object obj) - { - return obj is AlmostVersion version && - SemverValue == version.SemverValue && - StringValue == version.StringValue && - StorageMode == version.StorageMode; - } - - /// - /// Default generated hash code function generated by VS. - /// - /// a value unique to each object, except those that are considered equal by - /// - public override int GetHashCode() - { - var hashCode = -126402897; - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(SemverValue); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(StringValue); - hashCode = (hashCode * -1521134295) + StorageMode.GetHashCode(); - return hashCode; + /// + /// Compares to the in using . + /// + /// + /// The storage method of must be , else an will + /// be thrown. + /// + /// the to compare to + /// less than 0 if is considered bigger than , 0 if equal, and greater than zero if smaller + /// + public int CompareTo(Version other) + { + if (StorageMode != StoredAs.SemVer) + throw new InvalidOperationException("Cannot compare a SemVer version with an AlmostVersion stored as a string!"); + + return SemverValue!.CompareTo(other); + } + + /// + /// Compares to the in using . + /// + /// + /// The storage method of must be , else an will + /// be thrown. + /// + /// the to compare to + /// less than 0 if is considered bigger than , 0 if equal, and greater than zero if smaller + /// + [Obsolete("Use the Hive.Versioning.Version overload instead.")] + public int CompareTo(SVersion other) => CompareTo(other.UnderlyingVersion); + + /// + /// Performs a strict equality check between and . + /// + /// + /// This may return where returns + /// + /// the object to compare to + /// if they are equal, otherwise + /// + public override bool Equals(object obj) + { + return obj is AlmostVersion version && + SemverValue == version.SemverValue && + StringValue == version.StringValue && + StorageMode == version.StorageMode; } - /// - /// Compares two versions, only taking into account the numeric part of the version if they are stored as s, - /// or strict equality if they are stored as s. - /// - /// - /// This is a looser equality than , meaning that this may return where - /// does not. - /// - /// the first value to compare - /// the second value to compare - /// if they are mostly equal, otherwise - /// - public static bool operator==(AlmostVersion l, AlmostVersion r) - { - if (l is null && r is null) return true; - if (l is null || r is null) return false; - if (l.StorageMode != r.StorageMode) return false; + /// + /// Default generated hash code function generated by VS. + /// + /// a value unique to each object, except those that are considered equal by + /// + public override int GetHashCode() + { + var hashCode = -126402897; + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(SemverValue); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(StringValue); + hashCode = (hashCode * -1521134295) + StorageMode.GetHashCode(); + return hashCode; + } + + /// + /// Compares two versions, only taking into account the numeric part of the version if they are stored as s, + /// or strict equality if they are stored as s. + /// + /// + /// This is a looser equality than , meaning that this may return where + /// does not. + /// + /// the first value to compare + /// the second value to compare + /// if they are mostly equal, otherwise + /// + public static bool operator==(AlmostVersion l, AlmostVersion r) + { + if (l is null && r is null) return true; + if (l is null || r is null) return false; + if (l.StorageMode != r.StorageMode) return false; return l.StorageMode == StoredAs.SemVer ? Utils.VersionCompareNoPrerelease(l.SemverValue!, r.SemverValue!) == 0 - : l.StringValue == r.StringValue; - } - - /// - /// The opposite of . Equivalent to !(l == r). - /// - /// the first value to compare - /// the second value to compare - /// if they are not mostly equal, otherwise - /// + : l.StringValue == r.StringValue; + } + + /// + /// The opposite of . Equivalent to !(l == r). + /// + /// the first value to compare + /// the second value to compare + /// if they are not mostly equal, otherwise + /// public static bool operator!=(AlmostVersion l, AlmostVersion r) => !(l == r); // implicitly convertible from Version #pragma warning disable CS0618 // Type or member is obsolete #pragma warning disable CA2225 // Operator overloads have named alternates - /// - /// Implicitly converts a to using . - /// - /// the to convert - /// + /// + /// Implicitly converts a to using . + /// + /// the to convert + /// [Obsolete("Use Hive.Versioning.Version instead of SemVer.Version")] public static implicit operator AlmostVersion?(SVersion? ver) => ver is null ? null : new(ver); // implicitly convertible to Version - /// - /// Implicitly converts an to , if applicable, using . - /// If not applicable, returns - /// - /// the to convert to a - /// - [Obsolete("Use Hive.Versioning.Version instead of SemVer.Version")] + /// + /// Implicitly converts an to , if applicable, using . + /// If not applicable, returns + /// + /// the to convert to a + /// + [Obsolete("Use Hive.Versioning.Version instead of SemVer.Version")] public static implicit operator SVersion?(AlmostVersion? av) => av?.SemverValue is not null ? SVersion.ForHiveVersion(av.SemverValue) : null; #pragma warning restore CS0618 // Type or member is obsolete - /// - /// Implicitly converts a to using . - /// - /// the to convert + /// + /// Implicitly converts a to using . + /// + /// the to convert /// public static implicit operator AlmostVersion?(Version? ver) => ver is null ? null : new(ver); // implicitly convertible to Version - /// - /// Implicitly converts an to , if applicable, using . - /// If not applicable, returns - /// - /// the to convert to a - /// + /// + /// Implicitly converts an to , if applicable, using . + /// If not applicable, returns + /// + /// the to convert to a + /// public static implicit operator Version?(AlmostVersion av) => av?.SemverValue; #pragma warning restore CA2225 // Operator overloads have named alternates @@ -292,28 +292,28 @@ namespace IPA.Utilities public static bool operator >=(AlmostVersion left, AlmostVersion right) => left is null ? right is null : left.CompareTo(right) >= 0; - } - - /// - /// A for s. - /// - public sealed class AlmostVersionConverter : ValueConverter - { - /// - /// Converts a node into an . - /// - /// the node to convert - /// the owner of the new object - /// - public override AlmostVersion FromValue(Value value, object parent) - => new(Converter.Default.FromValue(value, parent)); - /// - /// Converts an to a node. - /// - /// the to convert - /// the parent of - /// a node representing - public override Value ToValue(AlmostVersion obj, object parent) - => Value.From(obj.ToString()); - } -} + } + + /// + /// A for s. + /// + public sealed class AlmostVersionConverter : ValueConverter + { + /// + /// Converts a node into an . + /// + /// the node to convert + /// the owner of the new object + /// + public override AlmostVersion FromValue(Value value, object parent) + => new(Converter.Default.FromValue(value, parent)); + /// + /// Converts an to a node. + /// + /// the to convert + /// the parent of + /// a node representing + public override Value ToValue(AlmostVersion obj, object parent) + => Value.From(obj.ToString()); + } +}