diff --git a/IPA.Loader/Config/SelfConfig.cs b/IPA.Loader/Config/SelfConfig.cs index 57856357..83f1e8d3 100644 --- a/IPA.Loader/Config/SelfConfig.cs +++ b/IPA.Loader/Config/SelfConfig.cs @@ -68,7 +68,7 @@ namespace IPA.Config } internal const string IPAName = "Beat Saber IPA"; - internal const string IPAVersion = "3.99.99.10"; + internal const string IPAVersion = "3.99.99.11"; // uses Updates.AutoUpdate, Updates.AutoCheckUpdates, YeetMods, Debug.ShowCallSource, Debug.ShowDebug, // Debug.CondenseModLogs diff --git a/IPA.Loader/Loader/manifest.json b/IPA.Loader/Loader/manifest.json index c5487c0d..5357df61 100644 --- a/IPA.Loader/Loader/manifest.json +++ b/IPA.Loader/Loader/manifest.json @@ -5,10 +5,10 @@ "#![IPA.Loader.description.md]", "A mod loader specifically for Beat Saber." ], - "gameVersion": "1.8.0b1", + "gameVersion": "1.8.0b2", "id": "BSIPA", "name": "Beat Saber IPA", - "version": "4.0.0-beta.10", + "version": "4.0.0-beta.11", "icon": "IPA.icon_white.png", "features": [ "define-feature(print, IPA.Loader.Features.PrintFeature)", diff --git a/IPA.Loader/Utilities/Utils.cs b/IPA.Loader/Utilities/Utils.cs index e3931e28..028848b8 100644 --- a/IPA.Loader/Utilities/Utils.cs +++ b/IPA.Loader/Utilities/Utils.cs @@ -1,246 +1,246 @@ -using System; -using System.IO; -using System.Text; -using System.Linq; -using System.Collections.Generic; -using Mono.Cecil; -using System.Runtime.CompilerServices; +using System; +using System.IO; +using System.Text; +using System.Linq; +using System.Collections.Generic; +using Mono.Cecil; +using System.Runtime.CompilerServices; using System.Threading; -#if NET3 -using File = Net3_Proxy.File; -#endif +#if NET3 +using File = Net3_Proxy.File; +#endif -namespace IPA.Utilities -{ - /// - /// A class providing static utility functions that in any other language would just *exist*. - /// - public static class Utils - { - /// - /// Converts a hex string to a byte array. - /// - /// the hex stream - /// the corresponding byte array - public static byte[] StringToByteArray(string hex) - { - int numberChars = hex.Length; - byte[] bytes = new byte[numberChars / 2]; - for (int i = 0; i < numberChars; i += 2) - bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); - return bytes; - } - - /// - /// Converts a byte array to a hex string. - /// - /// the byte array - /// the hex form of the array - public static string ByteArrayToString(byte[] ba) - { - StringBuilder hex = new StringBuilder(ba.Length * 2); - foreach (byte b in ba) - hex.AppendFormat("{0:x2}", b); - return hex.ToString(); - } - - // Copyright (c) 2008-2013 Hafthor Stefansson - // Distributed under the MIT/X11 software license - // Ref: http://www.opensource.org/licenses/mit-license.php. - // From: https://stackoverflow.com/a/8808245/3117125 - /// - /// Uses unsafe code to compare 2 byte arrays quickly. - /// - /// array 1 - /// array 2 - /// whether or not they are byte-for-byte equal - public static unsafe bool UnsafeCompare(byte[] a1, byte[] a2) - { - if (a1 == a2) return true; - if (a1 == null || a2 == null || a1.Length != a2.Length) - return false; - fixed (byte* p1 = a1, p2 = a2) - { - byte* x1 = p1, x2 = p2; - int l = a1.Length; - for (int i = 0; i < l / 8; i++, x1 += 8, x2 += 8) - if (*((long*)x1) != *((long*)x2)) return false; - if ((l & 4) != 0) { if (*((int*)x1) != *((int*)x2)) return false; x1 += 4; x2 += 4; } - if ((l & 2) != 0) { if (*((short*)x1) != *((short*)x2)) return false; x1 += 2; x2 += 2; } - if ((l & 1) != 0) if (*x1 != *x2) return false; - return true; - } - } - - /// - /// Gets a path relative to the provided folder. - /// - /// the file to relativize - /// the source folder - /// a path to get from to - public static string GetRelativePath(string file, string folder) - { - Uri pathUri = new Uri(file); - // 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)); - } - - /// - /// Copies all files from to . - /// - /// the source directory - /// the destination directory - /// the filename of the file to append together - /// a delegate called when there is an error copying. Return true to keep going. - public static void CopyAll(DirectoryInfo source, DirectoryInfo target, string appendFileName = "", - Func onCopyException = null) - { - if (source.FullName.ToLower() == target.FullName.ToLower()) - { - return; - } - - // Check if the target directory exists, if not, create it. - if (Directory.Exists(target.FullName) == false) - { - Directory.CreateDirectory(target.FullName); - } - - // Copy each file into it's new directory. - foreach (FileInfo fi in source.GetFiles()) - { - try - { - if (fi.Name == appendFileName) - File.AppendAllLines(Path.Combine(target.ToString(), fi.Name), File.ReadAllLines(fi.FullName)); - else - fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true); - } - catch (Exception e) - { - var keepOn = onCopyException?.Invoke(e, fi); - if (!keepOn.Unwrap()) - throw; - } - } - - // Copy each subdirectory using recursion. - foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) - { - DirectoryInfo nextTargetSubDir = - target.CreateSubdirectory(diSourceSubDir.Name); - CopyAll(diSourceSubDir, nextTargetSubDir, appendFileName, onCopyException); - } - } - - /// - /// Whether you can safely use without Mono throwing a fit. - /// - /// if you can use safely, otherwise - public static bool CanUseDateTimeNowSafely { get; private set; } = true; - private static bool DateTimeSafetyUnknown = true; - private static long UnsafeAdvanceTicks = 1; - - /// - /// Gets the current if supported, otherwise, if Mono would throw a fit, - /// returns plus some value, such that each time it is called - /// the value will be greater than the previous result. Not suitable for timing. - /// - /// the current if supported, otherwise some indeterminant increasing value. - public static DateTime CurrentTime() - { - if (DateTimeSafetyUnknown) - { - DateTime time = DateTime.MinValue; - try - { - time = DateTime.Now; - } - catch (TimeZoneNotFoundException) - { // Mono did a fucky wucky and we need to avoid this call - CanUseDateTimeNowSafely = false; - } - DateTimeSafetyUnknown = false; - return time; - } - else - { - if (CanUseDateTimeNowSafely) return DateTime.Now; - else return DateTime.MinValue.AddTicks(Interlocked.Increment(ref UnsafeAdvanceTicks)); // return MinValue as a fallback - } - } - - /// - /// Compares a pair of s ignoring both the prerelease and build fields. - /// - /// the left value - /// the right value - /// < 0 if l is less than r, 0 if they are equal in the numeric portion, or > 0 if l is greater than r - public static int VersionCompareNoPrerelease(SemVer.Version l, SemVer.Version r) - { - var cmpVal = l.Major - r.Major; - if (cmpVal != 0) return cmpVal; - cmpVal = l.Minor - r.Minor; - if (cmpVal != 0) return cmpVal; - cmpVal = l.Patch - r.Patch; - return cmpVal; - } - - /// - /// An object used to manage scope guards. - /// - /// - /// - /// using var _ = new Utils.ScopeGuardObject(() => RunOnScopeExit(value)); - /// - /// - /// - public struct ScopeGuardObject : IDisposable - { - private readonly Action action; - /// - /// Creates a new scope guard that will invoke when disposed. - /// - /// the action to run on dispose - public ScopeGuardObject(Action action) - => this.action = action; - void IDisposable.Dispose() - => action?.Invoke(); - } - - /// - /// Creates a scope guard for a given . - /// - /// the to run on dispose - /// a that will run on disposal - /// - /// - /// using var _ = Utils.ScopeGuard(() => RunOnScopeExit(value)); - /// - /// - public static ScopeGuardObject ScopeGuard(Action action) - => new ScopeGuardObject(action); - - internal static bool HasInterface(this TypeDefinition type, string interfaceFullName) - { - return (type?.Interfaces?.Any(i => i.InterfaceType.FullName == interfaceFullName) ?? false) - || (type?.Interfaces?.Any(t => HasInterface(t?.InterfaceType?.Resolve(), interfaceFullName)) ?? false); - } - -#if NET4 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static IEnumerable StrJP(this IEnumerable a) => a; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static IEnumerable StrJP(this IEnumerable a) => a.Select(o => $"{o}" /* safer than .ToString() */); -#endif -#if NET3 - internal static string[] StrJP(this IEnumerable a) => a.ToArray(); - internal static string[] StrJP(this IEnumerable a) => a.Select(o => $"{o}" /* safer than .ToString() */).ToArray(); -#endif - } -} +namespace IPA.Utilities +{ + /// + /// A class providing static utility functions that in any other language would just *exist*. + /// + public static class Utils + { + /// + /// Converts a hex string to a byte array. + /// + /// the hex stream + /// the corresponding byte array + public static byte[] StringToByteArray(string hex) + { + int numberChars = hex.Length; + byte[] bytes = new byte[numberChars / 2]; + for (int i = 0; i < numberChars; i += 2) + bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); + return bytes; + } + + /// + /// Converts a byte array to a hex string. + /// + /// the byte array + /// the hex form of the array + public static string ByteArrayToString(byte[] ba) + { + StringBuilder hex = new StringBuilder(ba.Length * 2); + foreach (byte b in ba) + hex.AppendFormat("{0:x2}", b); + return hex.ToString(); + } + + // Copyright (c) 2008-2013 Hafthor Stefansson + // Distributed under the MIT/X11 software license + // Ref: http://www.opensource.org/licenses/mit-license.php. + // From: https://stackoverflow.com/a/8808245/3117125 + /// + /// Uses unsafe code to compare 2 byte arrays quickly. + /// + /// array 1 + /// array 2 + /// whether or not they are byte-for-byte equal + public static unsafe bool UnsafeCompare(byte[] a1, byte[] a2) + { + if (a1 == a2) return true; + if (a1 == null || a2 == null || a1.Length != a2.Length) + return false; + fixed (byte* p1 = a1, p2 = a2) + { + byte* x1 = p1, x2 = p2; + int l = a1.Length; + for (int i = 0; i < l / 8; i++, x1 += 8, x2 += 8) + if (*((long*)x1) != *((long*)x2)) return false; + if ((l & 4) != 0) { if (*((int*)x1) != *((int*)x2)) return false; x1 += 4; x2 += 4; } + if ((l & 2) != 0) { if (*((short*)x1) != *((short*)x2)) return false; x1 += 2; x2 += 2; } + if ((l & 1) != 0) if (*x1 != *x2) return false; + return true; + } + } + + /// + /// Gets a path relative to the provided folder. + /// + /// the file to relativize + /// the source folder + /// a path to get from to + public static string GetRelativePath(string file, string folder) + { + Uri pathUri = new Uri(file); + // 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)); + } + + /// + /// Copies all files from to . + /// + /// the source directory + /// the destination directory + /// the filename of the file to append together + /// a delegate called when there is an error copying. Return true to keep going. + public static void CopyAll(DirectoryInfo source, DirectoryInfo target, string appendFileName = "", + Func onCopyException = null) + { + if (source.FullName.ToLower() == target.FullName.ToLower()) + { + return; + } + + // Check if the target directory exists, if not, create it. + if (Directory.Exists(target.FullName) == false) + { + Directory.CreateDirectory(target.FullName); + } + + // Copy each file into it's new directory. + foreach (FileInfo fi in source.GetFiles()) + { + try + { + if (fi.Name == appendFileName) + File.AppendAllLines(Path.Combine(target.ToString(), fi.Name), File.ReadAllLines(fi.FullName)); + else + fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true); + } + catch (Exception e) + { + var keepOn = onCopyException?.Invoke(e, fi); + if (!keepOn.Unwrap()) + throw; + } + } + + // Copy each subdirectory using recursion. + foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) + { + DirectoryInfo nextTargetSubDir = + target.CreateSubdirectory(diSourceSubDir.Name); + CopyAll(diSourceSubDir, nextTargetSubDir, appendFileName, onCopyException); + } + } + + /// + /// Whether you can safely use without Mono throwing a fit. + /// + /// if you can use safely, otherwise + public static bool CanUseDateTimeNowSafely { get; private set; } = true; + private static bool DateTimeSafetyUnknown = true; + private static long UnsafeAdvanceTicks = 1; + + /// + /// Gets the current if supported, otherwise, if Mono would throw a fit, + /// returns plus some value, such that each time it is called + /// the value will be greater than the previous result. Not suitable for timing. + /// + /// the current if supported, otherwise some indeterminant increasing value. + public static DateTime CurrentTime() + { + if (DateTimeSafetyUnknown) + { + DateTime time = DateTime.MinValue; + try + { + time = DateTime.Now; + } + catch (TimeZoneNotFoundException) + { // Mono did a fucky wucky and we need to avoid this call + CanUseDateTimeNowSafely = false; + } + DateTimeSafetyUnknown = false; + return time; + } + else + { + if (CanUseDateTimeNowSafely) return DateTime.Now; + else return DateTime.MinValue.AddTicks(Interlocked.Increment(ref UnsafeAdvanceTicks)); // return MinValue as a fallback + } + } + + /// + /// Compares a pair of s ignoring both the prerelease and build fields. + /// + /// the left value + /// the right value + /// < 0 if l is less than r, 0 if they are equal in the numeric portion, or > 0 if l is greater than r + public static int VersionCompareNoPrerelease(SemVer.Version l, SemVer.Version r) + { + var cmpVal = l.Major - r.Major; + if (cmpVal != 0) return cmpVal; + cmpVal = l.Minor - r.Minor; + if (cmpVal != 0) return cmpVal; + cmpVal = l.Patch - r.Patch; + return cmpVal; + } + + /// + /// An object used to manage scope guards. + /// + /// + /// + /// using var _ = new Utils.ScopeGuardObject(() => RunOnScopeExit(value)); + /// + /// + /// + public struct ScopeGuardObject : IDisposable + { + private readonly Action action; + /// + /// Creates a new scope guard that will invoke when disposed. + /// + /// the action to run on dispose + public ScopeGuardObject(Action action) + => this.action = action; + void IDisposable.Dispose() + => action?.Invoke(); + } + + /// + /// Creates a scope guard for a given . + /// + /// the to run on dispose + /// a that will run on disposal + /// + /// + /// using var _ = Utils.ScopeGuard(() => RunOnScopeExit(value)); + /// + /// + public static ScopeGuardObject ScopeGuard(Action action) + => new ScopeGuardObject(action); + + internal static bool HasInterface(this TypeDefinition type, string interfaceFullName) + { + return (type?.Interfaces?.Any(i => i.InterfaceType.FullName == interfaceFullName) ?? false) + || (type?.Interfaces?.Any(t => HasInterface(t?.InterfaceType?.Resolve(), interfaceFullName)) ?? false); + } + +#if NET4 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static IEnumerable StrJP(this IEnumerable a) => a; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static IEnumerable StrJP(this IEnumerable a) => a.Select(o => $"{o}" /* safer than .ToString() */); +#endif +#if NET3 + internal static string[] StrJP(this IEnumerable a) => a.ToArray(); + internal static string[] StrJP(this IEnumerable a) => a.Select(o => $"{o}" /* safer than .ToString() */).ToArray(); +#endif + } +} diff --git a/IPA/Program.cs b/IPA/Program.cs index 1bc0231f..0243b9f1 100644 --- a/IPA/Program.cs +++ b/IPA/Program.cs @@ -23,7 +23,7 @@ namespace IPA Unknown } - public const string FileVersion = "3.99.99.10"; + public const string FileVersion = "3.99.99.11"; public static Version Version => Assembly.GetEntryAssembly().GetName().Version; diff --git a/Refs/Main.dll b/Refs/Main.dll new file mode 100644 index 00000000..509f50f8 Binary files /dev/null and b/Refs/Main.dll differ diff --git a/Refs/Unity.TextMeshPro.dll b/Refs/Unity.TextMeshPro.dll index 957aba6e..397fc3af 100644 Binary files a/Refs/Unity.TextMeshPro.dll and b/Refs/Unity.TextMeshPro.dll differ diff --git a/Refs/UnityEngine.CoreModule.Net4.dll b/Refs/UnityEngine.CoreModule.Net4.dll index 872881e5..45c11737 100644 Binary files a/Refs/UnityEngine.CoreModule.Net4.dll and b/Refs/UnityEngine.CoreModule.Net4.dll differ diff --git a/Refs/UnityEngine.UI.dll b/Refs/UnityEngine.UI.dll index 57ac8e0b..bb1d0707 100644 Binary files a/Refs/UnityEngine.UI.dll and b/Refs/UnityEngine.UI.dll differ diff --git a/appveyor.yml b/appveyor.yml index a053ce08..7da3e5d7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ version: 'BSIPA-{branch}-{build}' environment: - bsipa_version: '4.0.0-beta.10' + bsipa_version: '4.0.0-beta.11' gh_token: secure: E42gl/yepETuoLSwbJZ1GmEIPK6cCJu6zkd59NA21XiICtEV6COOLW7aehi1tcVU