diff --git a/Doorstop b/Doorstop index 02647aa4..bcab2ee0 160000 --- a/Doorstop +++ b/Doorstop @@ -1 +1 @@ -Subproject commit 02647aa40bdde4e5027eb596082a6787497b92e9 +Subproject commit bcab2ee05684ad679aa926b4414600f3892657f0 diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index f0316662..22ff4fab 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -16,6 +16,7 @@ using MethodAttributes = Mono.Cecil.MethodAttributes; #if NET3 using Net3_Proxy; using Path = Net3_Proxy.Path; +using File = Net3_Proxy.File; using Directory = Net3_Proxy.Directory; #endif @@ -29,6 +30,7 @@ namespace IPA.Injector { private static Task pluginAsyncLoadTask; private static Task permissionFixTask; + private static string otherNewtonsoftJson = null; // ReSharper disable once UnusedParameter.Global internal static void Main(string[] args) @@ -45,6 +47,16 @@ namespace IPA.Injector SetupLibraryLoading(); + var otherNewtonsoft = Path.Combine( + Directory.EnumerateDirectories(Environment.CurrentDirectory, "*_Data").First(), + "Managed", + "Newtonsoft.Json.dll"); + if (File.Exists(otherNewtonsoft)) + { // this game ships its own Newtonsoft; force load ours and flag loading theirs + LibLoader.LoadLibrary(new AssemblyName("Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed")); + otherNewtonsoftJson = otherNewtonsoft; + } + EnsureDirectories(); // this is weird, but it prevents Mono from having issues loading the type. @@ -259,6 +271,9 @@ namespace IPA.Injector if (bootstrapped) return; bootstrapped = true; + if (otherNewtonsoftJson != null) + Assembly.LoadFrom(otherNewtonsoftJson); + Application.logMessageReceived += delegate (string condition, string stackTrace, LogType type) { var level = UnityLogRedirector.LogTypeToLevel(type); diff --git a/IPA.Loader/Config/SelfConfig.cs b/IPA.Loader/Config/SelfConfig.cs index ce588cf0..98dbe8aa 100644 --- a/IPA.Loader/Config/SelfConfig.cs +++ b/IPA.Loader/Config/SelfConfig.cs @@ -51,7 +51,6 @@ namespace IPA.Config public bool AutoCheckUpdates = true; } - [JsonProperty(Required = Required.Always)] public UpdateObject Updates = new UpdateObject(); public class DebugObject @@ -63,7 +62,6 @@ namespace IPA.Config public int HideLogThreshold = 512; } - [JsonProperty(Required = Required.Always)] public DebugObject Debug = new DebugObject(); [JsonProperty(Required = Required.Default)] diff --git a/IPA.Loader/Loader/LibLoader.cs b/IPA.Loader/Loader/LibLoader.cs index 5ab7588e..dab45cff 100644 --- a/IPA.Loader/Loader/LibLoader.cs +++ b/IPA.Loader/Loader/LibLoader.cs @@ -49,6 +49,11 @@ namespace IPA.Loader public static Assembly AssemblyLibLoader(object source, ResolveEventArgs e) { var asmName = new AssemblyName(e.Name); + return LoadLibrary(asmName); + } + + internal static Assembly LoadLibrary(AssemblyName asmName) + { Log(Logger.Level.Debug, $"Resolving library {asmName}"); SetupAssemblyFilenames(); diff --git a/IPA.Loader/Logging/ConsoleWindow.cs b/IPA.Loader/Logging/ConsoleWindow.cs index a9cf9469..0d8c9a7e 100644 --- a/IPA.Loader/Logging/ConsoleWindow.cs +++ b/IPA.Loader/Logging/ConsoleWindow.cs @@ -91,7 +91,14 @@ namespace IPA.Logging if (!file.IsInvalid) { handle = file; +#if NET4 var fs = new FileStream(file, dotNetFileAccess); +#elif NET3 +#pragma warning disable CS0618 + // this is marked obsolete, and shouldn't need to be used, but the constructor used in .NET 4 doesn't exist in Unity's mscorlib.dll + var fs = new FileStream(file.DangerousGetHandle(), dotNetFileAccess); +#pragma warning restore +#endif return fs; } @@ -99,7 +106,7 @@ namespace IPA.Logging return null; } - #region Win API Functions and Constants +#region Win API Functions and Constants [DllImport("kernel32.dll", EntryPoint = "AllocConsole", SetLastError = true, @@ -150,6 +157,6 @@ namespace IPA.Logging private const uint AttachParent = 0xFFFFFFFF; - #endregion +#endregion } } \ No newline at end of file diff --git a/IPA.Loader/Logging/Printers/ColoredConsolePrinter.cs b/IPA.Loader/Logging/Printers/ColoredConsolePrinter.cs index 338940eb..7d4d5b3b 100644 --- a/IPA.Loader/Logging/Printers/ColoredConsolePrinter.cs +++ b/IPA.Loader/Logging/Printers/ColoredConsolePrinter.cs @@ -19,7 +19,9 @@ namespace IPA.Logging.Printers /// The color to print messages as. /// /// the color to print this message as - public ConsoleColor Color { get; set; } = Console.ForegroundColor; + // Initializer calls this function because Unity's .NET 3.5 doesn't have the color properties on Console + // TODO: move this garbo out to Net3_Proxy + public ConsoleColor Color { get; set; } = GetConsoleColor(WinConsole.OutHandle); /// /// Prints an entry to the console window. @@ -71,6 +73,12 @@ namespace IPA.Logging.Printers return (short)(attr | (int)color); } + private static ConsoleColor GetConsoleColor(IntPtr handle) + { + GetConsoleScreenBufferInfo(handle, out var info); + return (ConsoleColor)(info.Attribute & 15); + } + // ReSharper disable NotAccessedField.Local #pragma warning disable 649 diff --git a/IPA.Loader/Logging/Printers/GZFilePrinter.cs b/IPA.Loader/Logging/Printers/GZFilePrinter.cs index 64968295..58d50053 100644 --- a/IPA.Loader/Logging/Printers/GZFilePrinter.cs +++ b/IPA.Loader/Logging/Printers/GZFilePrinter.cs @@ -23,7 +23,13 @@ namespace IPA.Logging.Printers IntPtr lpSecurityAttributes ); - internal static Regex removeControlCodes = new Regex("\x1b\\[\\d+m", RegexOptions.Compiled); +#if NET4 + private const RegexOptions reOptions = RegexOptions.Compiled; +#elif NET3 // Needed because Compiled doesn't exist in Unity's .NET 3 runtime + private const RegexOptions reOptions = RegexOptions.None; +#endif + + internal static Regex removeControlCodes = new Regex("\x1b\\[\\d+m", reOptions); private FileInfo fileInfo; diff --git a/IPA.Loader/Logging/StdoutInterceptor.cs b/IPA.Loader/Logging/StdoutInterceptor.cs index 5ef6aa71..495815b8 100644 --- a/IPA.Loader/Logging/StdoutInterceptor.cs +++ b/IPA.Loader/Logging/StdoutInterceptor.cs @@ -121,12 +121,16 @@ namespace IPA.Logging var console = typeof(Console); var resetColor = console.GetMethod("ResetColor"); var foregroundProperty = console.GetProperty("ForegroundColor"); - var setFg = foregroundProperty.GetSetMethod(); - var getFg = foregroundProperty.GetGetMethod(); + var setFg = foregroundProperty?.GetSetMethod(); + var getFg = foregroundProperty?.GetGetMethod(); - harmony.Patch(resetColor, transpiler: new HarmonyMethod(typeof(ConsoleHarmonyPatches), "PatchResetColor")); - harmony.Patch(setFg, transpiler: new HarmonyMethod(typeof(ConsoleHarmonyPatches), "PatchSetForegroundColor")); - harmony.Patch(getFg, transpiler: new HarmonyMethod(typeof(ConsoleHarmonyPatches), "PatchGetForegroundColor")); + if (resetColor != null) + harmony.Patch(resetColor, transpiler: new HarmonyMethod(typeof(ConsoleHarmonyPatches), "PatchResetColor")); + if (foregroundProperty != null) + { + harmony.Patch(setFg, transpiler: new HarmonyMethod(typeof(ConsoleHarmonyPatches), "PatchSetForegroundColor")); + harmony.Patch(getFg, transpiler: new HarmonyMethod(typeof(ConsoleHarmonyPatches), "PatchGetForegroundColor")); + } } public static ConsoleColor GetColor() => stdoutInterceptor.currentColor; diff --git a/docs/build.ps1 b/docs/build.ps1 index 389ab67e..5a87c729 100644 --- a/docs/build.ps1 +++ b/docs/build.ps1 @@ -55,6 +55,7 @@ if ((Test-Path $newtonsoftLoc -PathType Leaf) -and (Test-Path $selfConfigLoc -Pa # Generate schema $schemagen = New-Object -TypeName Newtonsoft.Json.Schema.Generation.JSchemaGenerator + $schemagen.DefaultRequired = [Newtonsoft.Json.Required]::Always $schema = $schemagen.Generate([IPA.Config.SelfConfig]) $schema.ToString() | Out-File "other_api/config/_schema.json"