Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of JotunnCompatibilityPatch v0.5.0
BepInEx/patchers/JotunnCompatibilityPatch/JG224.JotunnCompatibilityPatch.Preloader.dll
Decompiled 13 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using BepInEx.Preloader.Patching; using HarmonyLib; using JG224.JotunnCompatibilityPatch.Rewriting; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("JG224.JotunnCompatibilityPatch.Preloader")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.5.0.0")] [assembly: AssemblyInformationalVersion("0.5.0")] [assembly: AssemblyProduct("JG224.JotunnCompatibilityPatch.Preloader")] [assembly: AssemblyTitle("JG224.JotunnCompatibilityPatch.Preloader")] [assembly: AssemblyVersion("0.5.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace JG224.JotunnCompatibilityPatch.Rewriting { public static class CompatibilityRewriter { public const string OriginalHash = "F65751BC15E7AE7466B0F7D3B38C758397741C99A50890DEB19ACF738376BFB1"; private static IEnumerable<TypeDefinition> Types(ModuleDefinition module) { return ((IEnumerable<TypeDefinition>)module.Types).SelectMany(Types); } private static IEnumerable<TypeDefinition> Types(TypeDefinition type) { return ((IEnumerable<TypeDefinition>)(object)new TypeDefinition[1] { type }).Concat(((IEnumerable<TypeDefinition>)type.NestedTypes).SelectMany(Types)); } private static void Require(bool condition, string reason) { if (!condition) { throw new InvalidOperationException(reason); } } public static byte[] Rewrite(byte[] input, string managed) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0803: Unknown result type (might be due to invalid IL or missing references) //IL_0808: Unknown result type (might be due to invalid IL or missing references) //IL_0817: Unknown result type (might be due to invalid IL or missing references) //IL_081c: Unknown result type (might be due to invalid IL or missing references) //IL_0820: Unknown result type (might be due to invalid IL or missing references) //IL_0825: Unknown result type (might be due to invalid IL or missing references) //IL_0827: Unknown result type (might be due to invalid IL or missing references) //IL_082a: Unknown result type (might be due to invalid IL or missing references) //IL_083c: Expected I4, but got Unknown //IL_0840: Unknown result type (might be due to invalid IL or missing references) //IL_084e: Unknown result type (might be due to invalid IL or missing references) //IL_085c: Unknown result type (might be due to invalid IL or missing references) //IL_06e8: Unknown result type (might be due to invalid IL or missing references) //IL_072c: Unknown result type (might be due to invalid IL or missing references) //IL_074c: Unknown result type (might be due to invalid IL or missing references) //IL_0a2f: Unknown result type (might be due to invalid IL or missing references) //IL_0a34: Unknown result type (might be due to invalid IL or missing references) //IL_0a45: Expected O, but got Unknown using SHA256 sHA = SHA256.Create(); Require(BitConverter.ToString(sHA.ComputeHash(input)).Replace("-", "") == "F65751BC15E7AE7466B0F7D3B38C758397741C99A50890DEB19ACF738376BFB1", "Unsupported Jotunn input. Requires the exact original 2.29.2 release; original file was not changed."); DefaultAssemblyResolver val = new DefaultAssemblyResolver(); try { ((BaseAssemblyResolver)val).AddSearchDirectory(managed); AssemblyDefinition game = AssemblyDefinition.ReadAssembly(Path.Combine(managed, "assembly_valheim.dll"), new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)val }); ModuleDefinition module; try { AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly((Stream)new MemoryStream(input, writable: false), new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)val }); try { module = val2.MainModule; FieldDefinition val3 = ((IEnumerable<FieldDefinition>)Native("PieceTable").Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == "m_availablePiecesByCategory"); Require(((MemberReference)((FieldReference)val3).FieldType).FullName == "System.Collections.Generic.List`1<System.Collections.Generic.List`1<Piece>>", "Unexpected piece category storage."); MethodDefinition val4 = NativeMethod("Character", "Message", new string[5] { "MessageHud/MessageType", "System.String", "System.Int32", "UnityEngine.Sprite", "System.Boolean" }); MethodDefinition val5 = NativeMethod("TerrainComp", "Save", new string[1] { "System.Boolean" }); MethodDefinition val6 = NativeMethod("Heightmap", "Poke", new string[2] { "System.Int32", "System.Boolean" }); Require(object.Equals(((IEnumerable<ParameterDefinition>)((MethodReference)val4).Parameters).Last().Constant, false) && object.Equals(((MethodReference)val5).Parameters[0].Constant, false) && object.Equals(((MethodReference)val6).Parameters[0].Constant, 0) && object.Equals(((MethodReference)val6).Parameters[1].Constant, false), "Native defaults changed."); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; foreach (MethodDefinition item in from m in Types(module).SelectMany((TypeDefinition t) => (IEnumerable<MethodDefinition>)t.Methods) where m.HasBody select m) { Instruction[] array = item.Body.Instructions.ToArray(); foreach (Instruction val7 in array) { object operand = val7.Operand; FieldReference val8 = (FieldReference)((operand is FieldReference) ? operand : null); if (val8 != null && ((MemberReference)((MemberReference)val8).DeclaringType).FullName == "PieceTable" && ((MemberReference)val8).Name == "m_availablePieces") { Require(((MemberReference)val8.FieldType).FullName == ((MemberReference)((FieldReference)val3).FieldType).FullName, "Unexpected original piece field signature."); val7.Operand = module.ImportReference((FieldReference)(object)val3); num++; } object operand2 = val7.Operand; MethodReference val9 = (MethodReference)((operand2 is MethodReference) ? operand2 : null); if (val9 != null) { if (((MemberReference)((MemberReference)val9).DeclaringType).FullName == "Character" && ((MemberReference)val9).Name == "Message" && val9.Parameters.Count == 4) { AppendFalseArgument(item, val7, module.ImportReference((MethodReference)(object)val4)); num2++; } if (((MemberReference)((MemberReference)val9).DeclaringType).FullName == "TerrainComp" && ((MemberReference)val9).Name == "Save" && val9.Parameters.Count == 0) { AppendFalseArgument(item, val7, module.ImportReference((MethodReference)(object)val5)); num3++; } if (((MemberReference)((MemberReference)val9).DeclaringType).FullName == "Heightmap" && ((MemberReference)val9).Name == "Poke" && val9.Parameters.Count == 1) { Require(Integer(val7.Previous) == 0, "Only immediate full terrain Poke is supported."); AppendFalseArgument(item, val7, module.ImportReference((MethodReference)(object)val6)); num4++; } } } } Require(num == 7 && num2 == 3 && num3 == 1 && num4 == 1, $"Unexpected original call counts: pieces={num}, messages={num2}, saves={num3}, pokes={num4}."); TypeDefinition val10 = Owner("Jotunn.Utils.ExtEquipment"); string[] array2 = new string[3] { "RightItem", "RightBackItem", "ChestItem" }; foreach (string slot in array2) { MethodDefinition val11 = ((IEnumerable<MethodDefinition>)val10.Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "VisEquipment_Set" + slot); Require(((ParameterReference)((MethodReference)((slot == "ChestItem") ? NativeMethod("VisEquipment", "Set" + slot, new string[1] { "System.Int32" }) : NativeMethod("VisEquipment", "Set" + slot, new string[2] { "System.Int32", "System.Int32" }))).Parameters[0]).Name == "itemHash", "Unexpected native equipment argument."); Require(((MethodReference)val11).Parameters.Count == 2 && ((MemberReference)((ParameterReference)((MethodReference)val11).Parameters[1]).ParameterType).FullName == "System.String", "Unexpected equipment prefix."); ((ParameterReference)((MethodReference)val11).Parameters[1]).Name = "itemHash"; ((ParameterReference)((MethodReference)val11).Parameters[1]).ParameterType = module.TypeSystem.Int32; Instruction oldField = ((IEnumerable<Instruction>)val11.Body.Instructions).Single(delegate(Instruction i) { object operand3 = i.Operand; FieldReference val15 = (FieldReference)((operand3 is FieldReference) ? operand3 : null); return val15 != null && ((MemberReference)((MemberReference)val15).DeclaringType).FullName == "VisEquipment" && ((MemberReference)val15.FieldType).FullName == "System.String"; }); FieldDefinition val12 = ((IEnumerable<FieldDefinition>)Native("VisEquipment").Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == ((MemberReference)(FieldReference)oldField.Operand).Name && ((MemberReference)((FieldReference)f).FieldType).FullName == "System.Int32"); oldField.Operand = module.ImportReference((FieldReference)(object)val12); Instruction obj = ((IEnumerable<Instruction>)val11.Body.Instructions).Single(delegate(Instruction i) { object operand3 = i.Operand; MethodReference val15 = (MethodReference)((operand3 is MethodReference) ? operand3 : null); return val15 != null && ((MemberReference)((MemberReference)val15).DeclaringType).FullName == "System.String" && ((MemberReference)val15).Name == "op_Equality"; }); obj.OpCode = OpCodes.Ceq; obj.Operand = null; Instruction val13 = ((IEnumerable<Instruction>)val11.Body.Instructions).Single(delegate(Instruction i) { object operand3 = i.Operand; MethodReference val15 = (MethodReference)((operand3 is MethodReference) ? operand3 : null); return val15 != null && ((MemberReference)((MemberReference)val15).DeclaringType).FullName == "System.String" && ((MemberReference)val15).Name == "IsNullOrEmpty"; }); val13.OpCode = OpCodes.Ldc_I4_0; val13.Operand = null; val11.Body.GetILProcessor().InsertAfter(val13, Instruction.Create(OpCodes.Ceq)); } MethodDefinition val14 = ((IEnumerable<MethodDefinition>)Owner("Jotunn.Managers.SkillManager/Patches").Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "Skills_IsSkillValid"); Require(NativeMethod("Skills", "IsSkillValid", new string[1] { "Skills/SkillType" }).IsStatic, "Skills.IsSkillValid must now be static."); Require(((ParameterReference)((MethodReference)val14).Parameters[0]).Name == "__instance", "Unexpected skills injection."); Enumerator<Instruction> enumerator2 = val14.Body.Instructions.GetEnumerator(); try { while (enumerator2.MoveNext()) { Instruction current2 = enumerator2.Current; OpCode opCode = current2.OpCode; Code code = ((OpCode)(ref opCode)).Code; switch (code - 2) { case 0: current2.OpCode = OpCodes.Ldnull; break; case 1: current2.OpCode = OpCodes.Ldarg_0; break; case 2: current2.OpCode = OpCodes.Ldarg_1; break; } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } ((MethodReference)val14).Parameters.RemoveAt(0); MethodDefinition method = ((IEnumerable<MethodDefinition>)Owner("Jotunn.Managers.CommandManager").Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "CreateVanillaCommand"); NativeMethod("Terminal/ConsoleCommand", ".ctor", new string[13] { "System.String", "System.String", "Terminal/ConsoleEvent", "System.Boolean", "System.Boolean", "System.Boolean", "System.Boolean", "System.Boolean", "System.Boolean", "Terminal/ConsoleOptionsFetcher", "System.Boolean", "System.Boolean", "System.Boolean" }); ExpandConstructorArray(method, "System.Type", module); ExpandConstructorArray(method, "System.Object", module); PreservePieceAvailability(((IEnumerable<MethodDefinition>)Owner("Jotunn.Managers.PieceManager").Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "ReorderAllCategoryPieces")); foreach (MethodDefinition item2 in from m in Types(module).SelectMany((TypeDefinition t) => (IEnumerable<MethodDefinition>)t.Methods) where m.HasBody select m) { ExpandBranches(item2); } using MemoryStream memoryStream = new MemoryStream(); val2.Write((Stream)memoryStream, new WriterParameters { Timestamp = 0u }); return memoryStream.ToArray(); } finally { ((IDisposable)val2)?.Dispose(); } } finally { if (game != null) { ((IDisposable)game).Dispose(); } } TypeDefinition Native(string name) { return Types(game.MainModule).Single((TypeDefinition t) => ((MemberReference)t).FullName == name); } MethodDefinition NativeMethod(string type, string name, string[] parameters) { return ((IEnumerable<MethodDefinition>)Native(type).Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == name && ((IEnumerable<ParameterDefinition>)((MethodReference)m).Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName).SequenceEqual(parameters)); } TypeDefinition Owner(string name) { return Types(module).Single((TypeDefinition t) => ((MemberReference)t).FullName == name); } } finally { ((IDisposable)val)?.Dispose(); } } private static void AppendFalseArgument(MethodDefinition method, Instruction instruction, MethodReference replacement) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) OpCode opCode = instruction.OpCode; Require(opCode == OpCodes.Call || opCode == OpCodes.Callvirt, "Expected a call instruction."); instruction.OpCode = OpCodes.Ldc_I4_0; instruction.Operand = null; method.Body.GetILProcessor().InsertAfter(instruction, Instruction.Create(opCode, replacement)); } private static int? Integer(Instruction instruction) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected I4, but got Unknown OpCode opCode = instruction.OpCode; Code code = ((OpCode)(ref opCode)).Code; switch (code - 21) { case 0: return -1; case 1: return 0; case 2: return 1; case 3: return 2; case 4: return 3; case 5: return 4; case 6: return 5; case 7: return 6; case 8: return 7; case 9: return 8; case 10: case 11: return Convert.ToInt32(instruction.Operand); default: return null; } } private static void SetInteger(Instruction instruction, int value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = value; } private static void ExpandConstructorArray(MethodDefinition method, string arrayType, ModuleDefinition module) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) Instruction obj = ((IEnumerable<Instruction>)method.Body.Instructions).Single((Instruction i) => i.OpCode == OpCodes.Newarr && ((MemberReference)(TypeReference)i.Operand).FullName == arrayType); Require(Integer(obj.Previous) == 12, "Unexpected original constructor array length."); SetInteger(obj.Previous, 13); Instruction next = obj.Next; Instruction val = null; for (int num = 0; num < 12; num++) { Require(next.OpCode == OpCodes.Dup && Integer(next.Next) == num, "Unexpected constructor array initializer."); if (num >= 8) { SetInteger(next.Next, num + 1); } while (next.OpCode != OpCodes.Stelem_Ref) { next = next.Next; } if (num == 7) { val = next; } next = next.Next; } List<Instruction> list = new List<Instruction> { Instruction.Create(OpCodes.Dup), Instruction.Create(OpCodes.Ldc_I4, 8) }; if (arrayType == "System.Type") { MethodReference val2 = (MethodReference)((IEnumerable<Instruction>)method.Body.Instructions).First(delegate(Instruction i) { object operand = i.Operand; MethodReference val3 = (MethodReference)((operand is MethodReference) ? operand : null); return val3 != null && ((MemberReference)val3).Name == "GetTypeFromHandle"; }).Operand; list.Add(Instruction.Create(OpCodes.Ldtoken, module.TypeSystem.Boolean)); list.Add(Instruction.Create(OpCodes.Call, val2)); } else { list.Add(Instruction.Create(OpCodes.Ldc_I4_0)); list.Add(Instruction.Create(OpCodes.Box, module.TypeSystem.Boolean)); } list.Add(Instruction.Create(OpCodes.Stelem_Ref)); ILProcessor iLProcessor = method.Body.GetILProcessor(); foreach (Instruction item in list) { iLProcessor.InsertAfter(val, item); val = item; } } private static void PreservePieceAvailability(MethodDefinition method) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) Instruction remove = ((IEnumerable<Instruction>)method.Body.Instructions).Single(delegate(Instruction i) { object operand2 = i.Operand; MethodReference val2 = (MethodReference)((operand2 is MethodReference) ? operand2 : null); return val2 != null && ((MemberReference)val2).Name == "Remove"; }); Require(remove.Next.OpCode == OpCodes.Pop, "Expected discarded removal result."); Instruction previous = ((IEnumerable<Instruction>)method.Body.Instructions).First(delegate(Instruction i) { if (i.Offset > remove.Offset) { object operand2 = i.Operand; MethodReference val2 = (MethodReference)((operand2 is MethodReference) ? operand2 : null); if (val2 != null) { return ((MemberReference)val2).Name == "MoveNext"; } } return false; }).Previous; remove.Next.OpCode = OpCodes.Brfalse; remove.Next.Operand = previous; Instruction previous2 = ((IEnumerable<Instruction>)method.Body.Instructions).Single(delegate(Instruction i) { object operand2 = i.Operand; MethodReference val2 = (MethodReference)((operand2 is MethodReference) ? operand2 : null); return val2 != null && ((MemberReference)val2).Name == "Min"; }).Previous; object operand = previous2.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); Require(val != null && ((MemberReference)val).Name == "get_Count" && previous2.Previous.OpCode == OpCodes.Ldfld, "Unexpected reorder index expression."); previous2.Previous.Previous.OpCode = OpCodes.Ldloc_3; previous2.Previous.Previous.Operand = null; previous2.Previous.OpCode = OpCodes.Nop; previous2.Previous.Operand = null; TypeReference declaringType = ((MemberReference)(MethodReference)remove.Operand).DeclaringType; previous2.Operand = (object)new MethodReference("get_Count", ((MemberReference)method).Module.TypeSystem.Int32, declaringType) { HasThis = true }; } private static void ExpandBranches(MethodDefinition method) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Invalid comparison between Unknown and I4 //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, OpCode> dictionary = (from f in typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public) where f.FieldType == typeof(OpCode) select f).Select((Func<FieldInfo, OpCode>)((FieldInfo f) => (OpCode)f.GetValue(null))).ToDictionary((OpCode c) => ((OpCode)(ref c)).Name); Enumerator<Instruction> enumerator = method.Body.Instructions.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; OpCode opCode = current.OpCode; if ((int)((OpCode)(ref opCode)).OperandType == 15) { opCode = current.OpCode; string name = ((OpCode)(ref opCode)).Name; opCode = current.OpCode; current.OpCode = dictionary[name.Substring(0, ((OpCode)(ref opCode)).Name.Length - 2)]; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } } } namespace JG224.JotunnCompatibilityPatch.Preloader { public static class Loader { private static readonly object Gate = new object(); private static string _originalPath; public static bool Applied { get; private set; } public static string InputHash { get; private set; } public static Assembly LoadedJotunn { get; private set; } public static string FailureReason { get; private set; } internal static void Refuse(Exception exception) { FailureReason = exception.Message; } internal static void ValidateStartup() { RequireJotunnNotLoaded(); GetLocationMap(); } public static Assembly LoadPlugin(string path) { string fullPath = Path.GetFullPath(path); AssemblyName assemblyName = AssemblyName.GetAssemblyName(fullPath); if (!string.Equals(assemblyName.Name, "Jotunn", StringComparison.Ordinal)) { return Assembly.LoadFile(path); } lock (Gate) { try { if (FailureReason != null) { throw new InvalidOperationException(FailureReason); } if (LoadedJotunn != null) { if (!string.Equals(fullPath, _originalPath, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("A second Jotunn DLL was requested. Keep exactly one pristine baseline Jotunn installation."); } return LoadedJotunn; } RequireJotunnNotLoaded(); RequireSinglePluginCopy(fullPath); IDictionary<string, string> locationMap = GetLocationMap(); byte[] rawAssembly = CompatibilityRewriter.Rewrite(File.ReadAllBytes(fullPath), Paths.ManagedPath); if (locationMap.TryGetValue(assemblyName.FullName, out var value) && !string.Equals(Path.GetFullPath(value), fullPath, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("BepInEx already mapped Jotunn to a different location: " + value); } locationMap[assemblyName.FullName] = fullPath; Assembly assembly = Assembly.Load(rawAssembly); if (!string.Equals(assembly.FullName, assemblyName.FullName, StringComparison.Ordinal) || !string.Equals(assembly.Location, fullPath, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("BepInEx did not preserve Jotunn's identity and original assembly location."); } _originalPath = fullPath; LoadedJotunn = assembly; InputHash = "F65751BC15E7AE7466B0F7D3B38C758397741C99A50890DEB19ACF738376BFB1"; Applied = true; Patcher.Log.LogInfo((object)("Applied validated Jotunn 2.29.2 compatibility changes in memory. Original DLL unchanged: " + fullPath)); return assembly; } catch (Exception ex) { Refuse(ex); throw new InvalidOperationException("Jotunn Compatibility Patch refused to load Jotunn: " + ex.Message + " Restore pristine Jotunn 2.29.2, BepInExPack 5.4.2333 with runtime patches enabled, and the supported Valheim 1.0.7 API. See the add-on README.", ex); } } } private static void RequireJotunnNotLoaded() { if (AppDomain.CurrentDomain.GetAssemblies().Any((Assembly assembly) => string.Equals(assembly.GetName().Name, "Jotunn", StringComparison.Ordinal))) { throw new InvalidOperationException("Jotunn was loaded before the compatibility bridge. Remove conflicting preloaders or duplicate DLLs and restart."); } } private static void RequireSinglePluginCopy(string target) { string text = Path.GetFullPath(Paths.PluginPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); char directorySeparatorChar = Path.DirectorySeparatorChar; string text2 = text + directorySeparatorChar; if (!target.StartsWith(text2, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("Jotunn must be loaded from the active BepInEx plugins directory."); } List<string> list = new List<string>(); foreach (string item in Directory.EnumerateFiles(text2, "*.dll", SearchOption.AllDirectories)) { AssemblyName assemblyName; try { assemblyName = AssemblyName.GetAssemblyName(item); } catch (BadImageFormatException) { continue; } if (string.Equals(assemblyName.Name, "Jotunn", StringComparison.Ordinal)) { list.Add(Path.GetFullPath(item)); } } if (list.Count != 1 || !string.Equals(list[0], target, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("Expected exactly one baseline Jotunn assembly in the active plugin tree; found " + list.Count + ". Remove the old replacement package and retain upstream Jotunn."); } } private static IDictionary<string, string> GetLocationMap() { Type patches = typeof(AssemblyPatcher).Assembly.GetType("BepInEx.Preloader.RuntimeFixes.UnityPatches", throwOnError: true); if (!(patches.GetProperty("AssemblyLocations", BindingFlags.Static | BindingFlags.Public)?.GetValue(null, null) is IDictionary<string, string> result)) { throw new InvalidOperationException("Supported BepInEx assembly-location mapping is unavailable."); } string[] array = new string[2] { "Location", "CodeBase" }; foreach (string propertyName in array) { MethodInfo methodInfo = AccessTools.DeclaredPropertyGetter(typeof(Loader).Assembly.GetType(), propertyName) ?? AccessTools.DeclaredPropertyGetter(typeof(Assembly), propertyName); Patches val = ((methodInfo == null) ? null : Harmony.GetPatchInfo((MethodBase)methodInfo)); if (val == null || !val.Postfixes.Any((Patch patch) => patch.PatchMethod.DeclaringType?.FullName == patches.FullName + "+Get" + propertyName)) { throw new InvalidOperationException("BepInEx runtime assembly " + propertyName + " mapping is inactive. Enable Preloader.ApplyRuntimePatches and restart."); } } return result; } } public static class Patcher { internal const string HarmonyId = "com.jg224.jotunncompatibilitypatch.preloader"; internal static readonly ManualLogSource Log = Logger.CreateLogSource("Jotunn Compatibility Preloader"); private static Harmony _harmony; private static bool _bridgeInstalled; public static IEnumerable<string> TargetDLLs => new string[0]; public static void Patch(AssemblyDefinition assembly) { } public static void Finish() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown if (_harmony != null) { return; } try { _harmony = new Harmony("com.jg224.jotunncompatibilitypatch.preloader"); MethodInfo methodInfo = AccessTools.Method(typeof(Chainloader), "Start", Type.EmptyTypes, (Type[])null); _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Patcher), "RequireBridgeInstalled", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patcher), "RoutePluginLoads", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); _bridgeInstalled = true; Loader.ValidateStartup(); AppDomain.CurrentDomain.ProcessExit += OnExit; AppDomain.CurrentDomain.DomainUnload += OnExit; Log.LogInfo((object)"Add-on 3.0.1 armed for pristine Jotunn 2.29.2; the installed DLL stays unchanged."); } catch (Exception ex) { Loader.Refuse(ex); Log.LogError((object)("Compatibility bridge could not initialize: " + ex)); throw; } } public static void RequireBridgeInstalled() { if (!_bridgeInstalled) { throw new InvalidOperationException("Jotunn compatibility plugin-loading bridge failed. Startup stopped to prevent loading an incompatible baseline. " + Loader.FailureReason); } } public static IEnumerable<CodeInstruction> RoutePluginLoads(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); MethodInfo original = typeof(Assembly).GetMethod("LoadFile", new Type[1] { typeof(string) }); MethodInfo method = typeof(Loader).GetMethod("LoadPlugin"); List<CodeInstruction> list2 = list.Where((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, original)).ToList(); if (list2.Count != 1) { throw new InvalidOperationException("Unsupported BepInEx Chainloader: expected exactly one Assembly.LoadFile plugin call, found " + list2.Count + "."); } list2[0].operand = method; return list; } private static void OnExit(object sender, EventArgs args) { try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex) { Log.LogWarning((object)("Bridge shutdown: " + ex.Message)); } } } }
BepInEx/plugins/JotunnCompatibilityPatch/JG224.JotunnCompatibilityPatch.dll
Decompiled 13 hours agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using JG224.JotunnCompatibilityPatch.Preloader; using JG224.ModCore.API; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("JG224.JotunnCompatibilityPatch")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.5.0.0")] [assembly: AssemblyInformationalVersion("0.5.0")] [assembly: AssemblyProduct("JG224.JotunnCompatibilityPatch")] [assembly: AssemblyTitle("JG224.JotunnCompatibilityPatch")] [assembly: AssemblyVersion("0.5.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace JG224.JotunnCompatibilityPatch { [BepInPlugin("com.jg224.jotunncompatibilitypatch", "Jotunn Compatibility Patch", "0.5.0")] [BepInDependency("com.jg224.modcore", "0.5.0")] [BepInDependency("com.jotunn.jotunn", "2.29.2")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.jg224.jotunncompatibilitypatch"; public const string PluginName = "Jotunn Compatibility Patch"; public const string PluginVersion = "0.5.0"; public const int ProtocolVersion = 1; public static readonly ModuleId ModuleId = new ModuleId("jotunncompatibilitypatch"); private ICoreServices _core; private IDisposable _registration; private void Awake() { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) try { if (!ModCoreApi.IsAvailable) { throw new InvalidOperationException("ModCore did not initialize before the compatibility reporter."); } _core = ModCoreApi.Services; SemanticVersion val = default(SemanticVersion); if (!SemanticVersion.TryParse("0.5.0", ref val)) { throw new InvalidOperationException("Invalid add-on version."); } _registration = _core.Modules.Register(new ModuleDescriptor(ModuleId, "com.jg224.jotunncompatibilitypatch", "Jotunn Compatibility Patch", val, 1, (ModuleSide)3, (ModuleRequirement)4, 0uL, 1, 1)); if (!Loader.Applied || Loader.InputHash != "F65751BC15E7AE7466B0F7D3B38C758397741C99A50890DEB19ACF738376BFB1" || Loader.FailureReason != null || !Chainloader.PluginInfos.TryGetValue("com.jotunn.jotunn", out var value) || (Object)(object)value.Instance == (Object)null || (object)((object)value.Instance).GetType().Assembly != Loader.LoadedJotunn) { throw new InvalidOperationException("Validated preloader changes are not active on the loaded Jotunn instance. " + Loader.FailureReason); } _core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Jotunn 2.29.2 compatibility changes active in memory; original DLL preserved."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Jotunn Compatibility Patch 0.5.0 loaded; matching add-on required on server and clients."); } catch (Exception ex) { if (_registration != null) { _core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message); } ((BaseUnityPlugin)this).Logger.LogError((object)("Jotunn compatibility initialization failed safely: " + ex)); ((Behaviour)this).enabled = false; } } private void OnDestroy() { _registration?.Dispose(); _registration = null; _core = null; } } }