Decompiled source of JotunnCompatibilityPatch v0.5.0

BepInEx/patchers/JotunnCompatibilityPatch/JG224.JotunnCompatibilityPatch.Preloader.dll

Decompiled 13 hours ago
using 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 ago
using 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;
		}
	}
}