diff --git a/IPA.Injector/GameVersionEarly.cs b/IPA.Injector/GameVersionEarly.cs
index e6e0280c..5ed1ace7 100644
--- a/IPA.Injector/GameVersionEarly.cs
+++ b/IPA.Injector/GameVersionEarly.cs
@@ -1,4 +1,5 @@
-using IPA.Utilities;
+#nullable enable
+using IPA.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
@@ -48,7 +49,7 @@ namespace IPA.Injector
}
var rewind = -sizeof(int) - sizeof(byte);
- stream.Seek(rewind, SeekOrigin.Current); // rewind to the string length
+ _ = stream.Seek(rewind, SeekOrigin.Current); // rewind to the string length
var strlen = reader.ReadInt32();
var strbytes = reader.ReadBytes(strlen);
@@ -57,7 +58,7 @@ namespace IPA.Injector
}
}
- internal static AlmostVersion SafeParseVersion() => new AlmostVersion(GetGameVersion());
+ internal static AlmostVersion SafeParseVersion() => new(GetGameVersion());
private static void _Load()
{
diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs
index acfbe4a2..7d338af7 100644
--- a/IPA.Injector/Injector.cs
+++ b/IPA.Injector/Injector.cs
@@ -80,11 +80,13 @@ namespace IPA.Injector
Logging.Logger.Injector.Debug("Prepping bootstrapper");
+ // make sure to load the game version and check boundaries before installing the bootstrap, because that uses the game assemblies property
+ GameVersionEarly.Load();
+ SelfConfig.Instance.CheckVersionBoundary();
+
// updates backup
InstallBootstrapPatch();
- GameVersionEarly.Load();
-
AntiMalwareEngine.Initialize();
Updates.InstallPendingUpdates();
diff --git a/IPA.Loader/Config/Data/Value.cs b/IPA.Loader/Config/Data/Value.cs
index 0d61cebd..966f844c 100644
--- a/IPA.Loader/Config/Data/Value.cs
+++ b/IPA.Loader/Config/Data/Value.cs
@@ -1,151 +1,146 @@
-#nullable enable
-using System;
-using System.Collections;
-using System.Collections.Generic;
+#nullable enable
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace IPA.Config.Data
-{
- ///
- /// A base value type for config data abstract representations, to be serialized with an
- /// . If a is , then
- /// that represents just that: a null in whatever serialization is being used.
- /// Also contains factory functions for all derived types.
- ///
- public abstract class Value
- {
- ///
- /// Converts this into a human-readable format.
- ///
- /// a human-readable string containing the value provided
- public abstract override string ToString();
-
- ///
- /// Creates a Null .
- ///
- ///
- public static Value? Null() => null;
-
- ///
- /// Creates an empty .
- ///
- /// an empty
- ///
- public static List List() => new();
- ///
- /// Creates an empty .
- ///
- /// an empty
- ///
- ///
- public static Map Map() => new();
-
- ///
- /// Creates a new representing a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- [return: NotNullIfNotNull("val")]
- public static Text? From(string? val) => Text(val);
- ///
- /// Creates a new object wrapping a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- [return: NotNullIfNotNull("val")]
- public static Text? Text(string? val) => val == null ? null : new(val);
-
- ///
- /// Creates a new wrapping a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- public static Integer From(long val) => Integer(val);
- ///
- /// Creates a new wrapping a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- public static Integer Integer(long val) => new(val);
-
- ///
- /// Creates a new wrapping a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- public static FloatingPoint From(decimal val) => Float(val);
- ///
- /// Creates a new wrapping a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- public static FloatingPoint Float(decimal val) => new(val);
-
- ///
- /// Creates a new wrapping a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- public static Boolean From(bool val) => Bool(val);
- ///
- /// Creates a new wrapping a .
- ///
- /// the value to wrap
- /// a wrapping
- ///
- public static Boolean Bool(bool val) => new(val);
-
- ///
- /// Creates a new holding the content of an
- /// of .
- ///
- /// the s to initialize the with
- /// a containing the content of
- ///
- [return: NotNullIfNotNull("vals")]
- public static List? From(IEnumerable? vals)
- {
- if (vals is null) return null;
- var l = List();
- l.AddRange(vals);
- return l;
- }
-
- ///
- /// Creates a new holding the content of an
- /// of to .
- ///
- /// the dictionary of s to initialize the wtih
- /// a containing the content of
- ///
- ///
- public static Map From(IDictionary vals) => From(vals as IEnumerable>);
-
- ///
- /// Creates a new holding the content of an
- /// of of to .
- ///
- /// the enumerable of of name to
- /// a containing the content of
- ///
- ///
- [return: NotNullIfNotNull("vals")]
- public static Map? From(IEnumerable>? vals)
- {
- if (vals is null) return null;
- var m = Map();
- foreach (var v in vals) m.Add(v.Key, v.Value);
- return m;
- }
- }
-}
+
+namespace IPA.Config.Data
+{
+ ///
+ /// A base value type for config data abstract representations, to be serialized with an
+ /// . If a is , then
+ /// that represents just that: a null in whatever serialization is being used.
+ /// Also contains factory functions for all derived types.
+ ///
+ public abstract class Value
+ {
+ ///
+ /// Converts this into a human-readable format.
+ ///
+ /// a human-readable string containing the value provided
+ public abstract override string ToString();
+
+ ///
+ /// Creates a Null .
+ ///
+ ///
+ public static Value? Null() => null;
+
+ ///
+ /// Creates an empty .
+ ///
+ /// an empty
+ ///
+ public static List List() => new();
+ ///
+ /// Creates an empty .
+ ///
+ /// an empty
+ ///
+ ///
+ public static Map Map() => new();
+
+ ///
+ /// Creates a new representing a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ [return: NotNullIfNotNull("val")]
+ public static Text? From(string? val) => Text(val);
+ ///
+ /// Creates a new object wrapping a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ [return: NotNullIfNotNull("val")]
+ public static Text? Text(string? val) => val == null ? null : new(val);
+
+ ///
+ /// Creates a new wrapping a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ public static Integer From(long val) => Integer(val);
+ ///
+ /// Creates a new wrapping a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ public static Integer Integer(long val) => new(val);
+
+ ///
+ /// Creates a new wrapping a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ public static FloatingPoint From(decimal val) => Float(val);
+ ///
+ /// Creates a new wrapping a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ public static FloatingPoint Float(decimal val) => new(val);
+
+ ///
+ /// Creates a new wrapping a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ public static Boolean From(bool val) => Bool(val);
+ ///
+ /// Creates a new wrapping a .
+ ///
+ /// the value to wrap
+ /// a wrapping
+ ///
+ public static Boolean Bool(bool val) => new(val);
+
+ ///
+ /// Creates a new holding the content of an
+ /// of .
+ ///
+ /// the s to initialize the with
+ /// a containing the content of
+ ///
+ [return: NotNullIfNotNull("vals")]
+ public static List? From(IEnumerable? vals)
+ {
+ if (vals is null) return null;
+ var l = List();
+ l.AddRange(vals);
+ return l;
+ }
+
+ ///
+ /// Creates a new holding the content of an
+ /// of to .
+ ///
+ /// the dictionary of s to initialize the wtih
+ /// a containing the content of
+ ///
+ ///
+ public static Map From(IDictionary vals) => From(vals as IEnumerable>);
+
+ ///
+ /// Creates a new holding the content of an
+ /// of of to .
+ ///
+ /// the enumerable of of name to
+ /// a containing the content of
+ ///
+ ///
+ [return: NotNullIfNotNull("vals")]
+ public static Map? From(IEnumerable>? vals)
+ {
+ if (vals is null) return null;
+ var m = Map();
+ foreach (var v in vals) m.Add(v.Key, v.Value);
+ return m;
+ }
+ }
+}
diff --git a/IPA.Loader/Config/SelfConfig.cs b/IPA.Loader/Config/SelfConfig.cs
index 433ac088..0bfefb92 100644
--- a/IPA.Loader/Config/SelfConfig.cs
+++ b/IPA.Loader/Config/SelfConfig.cs
@@ -54,7 +54,7 @@ namespace IPA.Config
CommandLineValues.YeetMods = false;
break;
case "--no-logs":
- CommandLineValues.WriteLogs = true;
+ CommandLineValues.WriteLogs = false;
break;
case "--condense-logs":
CommandLineValues.Debug.CondenseModLogs = true;
@@ -75,6 +75,14 @@ namespace IPA.Config
}
}
+ public void CheckVersionBoundary()
+ {
+ if (ResetGameAssebliesOnVersionChange && Utilities.UnityGame.IsGameVersionBoundary)
+ {
+ GameAssemblies = GetDefaultGameAssemblies();
+ }
+ }
+
internal const string IPAName = "Beat Saber IPA";
internal const string IPAVersion = "4.2.2.0";
@@ -180,19 +188,30 @@ namespace IPA.Config
[JsonIgnore]
public bool WriteLogs { get; set; } = true;
+ public virtual bool ResetGameAssebliesOnVersionChange { get; set; } = true;
+
// LINE: ignore
[NonNullable, UseConverter(typeof(CollectionConverter>))]
- public virtual HashSet GameAssemblies { get; set; } = new HashSet
+ public virtual HashSet GameAssemblies { get; set; } = GetDefaultGameAssemblies();
+
+ // BEGIN: section ignore
+ public static HashSet GetDefaultGameAssemblies()
+ => new()
{
- // LINE: ignore 5
#if BeatSaber // provide these defaults only for Beat Saber builds
- "Main.dll", "Core.dll", "HMLib.dll", "HMUI.dll", "HMRendering.dll", "VRUI.dll",
+ "Main.dll", "Core.dll", "HMLib.dll", "HMUI.dll", "HMRendering.dll", "VRUI.dll",
"BeatmapCore.dll", "GameplayCore.dll","HMLibAttributes.dll",
#else // otherwise specify Assembly-CSharp.dll
"Assembly-CSharp.dll"
- // LINE: ignore
#endif
};
+ // END: section ignore
+
+ // LINE: ignore
+#if false // used to make schema gen happy
+ private static HashSet GetDefaultGameAssemblies() => null;
+ // LINE: ignore
+#endif
// LINE: ignore
public static HashSet GameAssemblies_ => Instance?.GameAssemblies ?? new HashSet { "Assembly-CSharp.dll" };
diff --git a/IPA.Loader/Utilities/CriticalSection.cs b/IPA.Loader/Utilities/CriticalSection.cs
index 4630f572..61d3d85d 100644
--- a/IPA.Loader/Utilities/CriticalSection.cs
+++ b/IPA.Loader/Utilities/CriticalSection.cs
@@ -1,9 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
+#nullable enable
+using System;
using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
using IPA.Logging;
namespace IPA.Utilities
@@ -21,9 +18,9 @@ namespace IPA.Utilities
ResetExitHandlers();
}
- private static void Reset(object sender, EventArgs e)
+ private static void Reset(object? sender, EventArgs? e)
{
- Win32.SetConsoleCtrlHandler(registeredHandler, false);
+ _ = Win32.SetConsoleCtrlHandler(registeredHandler, false);
WinHttp.SetPeekMessageHook(null);
}
@@ -32,8 +29,8 @@ namespace IPA.Utilities
private static readonly Win32.ConsoleCtrlDelegate registeredHandler = HandleExit;
internal static void ResetExitHandlers()
{
- Win32.SetConsoleCtrlHandler(registeredHandler, false);
- Win32.SetConsoleCtrlHandler(registeredHandler, true);
+ _ = Win32.SetConsoleCtrlHandler(registeredHandler, false);
+ _ = Win32.SetConsoleCtrlHandler(registeredHandler, true);
WinHttp.SetPeekMessageHook(PeekMessageHook);
AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
@@ -60,14 +57,14 @@ namespace IPA.Utilities
[DllImport("bsipa-doorstop")]
public static extern void SetPeekMessageHook(
[MarshalAs(UnmanagedType.FunctionPtr)]
- PeekMessageHook hook);
+ PeekMessageHook? hook);
[DllImport("bsipa-doorstop")]
public static extern void SetIgnoreUnhandledExceptions(
[MarshalAs(UnmanagedType.Bool)] bool ignore);
}
- private static Win32.ConsoleCtrlDelegate _handler = null;
+ private static Win32.ConsoleCtrlDelegate? _handler = null;
private static volatile bool isInExecuteSection = false;
// returns true to continue looping and calling PeekMessage