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 AdvancedTerrainCompatibility v1.0.1
patchers/L4zerShark_Team-AdvancedTerrainCompatibility/AdvancedTerrainCompatibility.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security.Cryptography; using BepInEx; using BepInEx.Logging; using HarmonyLib; 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: AssemblyTitle("Advanced Terrain Compatibility")] [assembly: AssemblyDescription("Valheim 1.0.12 compatibility for AdvancedTerrainModifiers")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.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 ValheimThreeCompatibility { public static class CompatibilityLog { private static readonly object Gate = new object(); private static ManualLogSource _source; public static ManualLogSource Source { get { lock (Gate) { if (_source == null) { _source = Logger.CreateLogSource("AdvancedTerrainCompatibility"); } return _source; } } } public static void Info(string message) { Source.LogInfo((object)message); } public static void Warning(string message) { Source.LogWarning((object)message); } public static void Error(string message) { Source.LogError((object)message); } } public static class Loader { private sealed class PreparedEntry { public string CachePath; public string SimpleName; } public const string PatcherName = "AdvancedTerrainCompatibility"; public const string PatcherVersion = "1.0.0"; public const string HarmonyId = "ValheimThreeCompatibility.AdvancedTerrainCompatibility"; private const string CombinedPatcherName = "ThreeModCompatibility"; private const string CombinedHarmonyId = "ValheimThreeCompatibility.ThreeModCompatibility"; private const string CombinedReplacementMethodName = "LoadCompatible"; private const string LoaderTypeFullName = "ValheimThreeCompatibility.Loader"; private const string PrepareMethodName = "PrepareCompatiblePath"; private const string CacheFolderName = "ValheimThreeCompatibility"; private const string GameAssemblyFileName = "assembly_valheim.dll"; private static readonly string[] SupportedFileNames = new string[1] { "TerrainTools.dll" }; private static readonly object SyncRoot = new object(); private static readonly Dictionary<string, PreparedEntry> PreparedByOriginalPath = new Dictionary<string, PreparedEntry>(StringComparer.OrdinalIgnoreCase); private static bool _finishRan; private static int _transpilerRuns; private static bool _lastTranspileInserted; private static string _lastTranspileFailure; private static readonly MethodInfo LoadFileMethod = typeof(Assembly).GetMethod("LoadFile", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); private static readonly MethodInfo PrepareCompatiblePathMethod = typeof(Loader).GetMethod("PrepareCompatiblePath", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); public static IEnumerable<string> TargetDLLs => new string[0]; public static void Patch(AssemblyDefinition assembly) { } public static void Finish() { //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Expected O, but got Unknown //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Expected O, but got Unknown lock (SyncRoot) { if (_finishRan) { CompatibilityLog.Warning("Finish invoked more than once; ignoring duplicate call."); return; } _finishRan = true; } try { ValidateBuildTarget(); if (LoadFileMethod == null) { throw new MissingMethodException("System.Reflection.Assembly", "LoadFile(string)"); } if (PrepareCompatiblePathMethod == null) { throw new MissingMethodException(typeof(Loader).FullName, "PrepareCompatiblePath(string)"); } string text = FindCombinedAddon(); if (text != null) { CompatibilityLog.Error("AdvancedTerrainCompatibility 1.0.0: the archived combined ThreeModCompatibility patcher is installed (" + text + "). It cannot coexist with the split compatibility addons. Remove the combined patcher from BepInEx/patchers. TerrainTools.dll will NOT be repaired by AdvancedTerrainCompatibility this session."); return; } Type type = Type.GetType("BepInEx.Bootstrap.Chainloader, BepInEx", throwOnError: false); if (type == null) { throw new TypeLoadException("BepInEx.Bootstrap.Chainloader was not found in assembly BepInEx."); } MethodInfo methodInfo = AccessTools.Method(type, "Start", Type.EmptyTypes, (Type[])null); if (methodInfo == null || !methodInfo.IsStatic || methodInfo.ReturnType != typeof(void)) { throw new MissingMethodException(type.FullName, "static void Start()"); } FieldInfo fieldInfo = AccessTools.Field(type, "_loaded"); if (fieldInfo != null && fieldInfo.IsStatic && fieldInfo.FieldType == typeof(bool) && (bool)fieldInfo.GetValue(null)) { throw new InvalidOperationException("Chainloader has already started; the load hook can no longer be installed."); } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo != null) { foreach (Patch item in AllPatches(patchInfo)) { if (string.Equals(item.owner, "ValheimThreeCompatibility.ThreeModCompatibility", StringComparison.Ordinal)) { CompatibilityLog.Error("AdvancedTerrainCompatibility 1.0.0: Chainloader.Start is already patched by the archived combined ThreeModCompatibility patcher (Harmony owner ValheimThreeCompatibility.ThreeModCompatibility). Remove the combined patcher. TerrainTools.dll will NOT be repaired by AdvancedTerrainCompatibility this session."); return; } } foreach (Patch transpiler in patchInfo.Transpilers) { if (string.Equals(transpiler.owner, "ValheimThreeCompatibility.AdvancedTerrainCompatibility", StringComparison.Ordinal)) { MethodInfo patchMethod = transpiler.PatchMethod; if (patchMethod != null && patchMethod.DeclaringType == typeof(Loader)) { CompatibilityLog.Warning("Chainloader.Start transpiler is already installed; skipping duplicate application."); } else { CompatibilityLog.Error("AdvancedTerrainCompatibility 1.0.0: another copy of AdvancedTerrainCompatibility (" + ((patchMethod != null && patchMethod.DeclaringType != null) ? DescribeAssembly(patchMethod.DeclaringType.Assembly) : "unknown assembly") + ") already installed Harmony owner ValheimThreeCompatibility.AdvancedTerrainCompatibility. Remove the duplicate package; this copy will not install."); } return; } } } MethodInfo methodInfo2 = AccessTools.Method(typeof(Loader), "ChainloaderStartTranspiler", (Type[])null, (Type[])null); if (methodInfo2 == null) { throw new MissingMethodException(typeof(Loader).FullName, "ChainloaderStartTranspiler"); } int transpilerRuns = _transpilerRuns; _lastTranspileInserted = false; _lastTranspileFailure = null; Harmony val = new Harmony("ValheimThreeCompatibility.AdvancedTerrainCompatibility"); val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null); if (_transpilerRuns == transpilerRuns) { throw new InvalidOperationException("Harmony did not invoke the Chainloader.Start transpiler."); } if (!_lastTranspileInserted) { try { val.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)3, "ValheimThreeCompatibility.AdvancedTerrainCompatibility"); } catch (Exception ex) { CompatibilityLog.Warning("AdvancedTerrainCompatibility: could not remove inactive transpiler: " + ex.Message); } CompatibilityLog.Error("AdvancedTerrainCompatibility 1.0.0: FAILED to install plugin load hook: " + (_lastTranspileFailure ?? "unknown transpiler failure") + " TerrainTools.dll will NOT be repaired this session."); } else { CompatibilityLog.Info("AdvancedTerrainCompatibility 1.0.0: installed plugin load hook for " + string.Join(", ", SupportedFileNames) + "."); } } catch (Exception ex2) { CompatibilityLog.Error("AdvancedTerrainCompatibility 1.0.0: FAILED to install plugin load hook. Supported target (" + string.Join(", ", SupportedFileNames) + ") will NOT be repaired this session." + Environment.NewLine + ex2); } } private static void ValidateBuildTarget() { string text = "TerrainTools.dll"; if (string.IsNullOrEmpty("AdvancedTerrainCompatibility")) { throw new InvalidOperationException("BuildTarget.Name is empty."); } if (string.Equals("AdvancedTerrainCompatibility", "ThreeModCompatibility", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("BuildTarget.Name must not be the archived combined name 'ThreeModCompatibility'."); } if (string.IsNullOrEmpty(text)) { throw new InvalidOperationException("BuildTarget.TargetFile is empty."); } if (!string.Equals(Path.GetFileName(text), text, StringComparison.Ordinal)) { throw new InvalidOperationException("BuildTarget.TargetFile must be a bare file name: '" + text + "'."); } if (!text.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("BuildTarget.TargetFile must be a .dll: '" + text + "'."); } } private static IEnumerable<Patch> AllPatches(Patches patches) { foreach (Patch prefix in patches.Prefixes) { yield return prefix; } foreach (Patch postfix in patches.Postfixes) { yield return postfix; } foreach (Patch transpiler in patches.Transpilers) { yield return transpiler; } foreach (Patch finalizer in patches.Finalizers) { yield return finalizer; } } private static string FindCombinedAddon() { Assembly assembly = typeof(Loader).Assembly; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies) { if (!(assembly2 == assembly)) { string name; try { name = assembly2.GetName().Name; } catch (Exception) { continue; } if (string.Equals(name, "ThreeModCompatibility", StringComparison.OrdinalIgnoreCase)) { return DescribeAssembly(assembly2); } Type type; try { type = assembly2.GetType("ValheimThreeCompatibility.Loader", throwOnError: false); } catch (Exception) { continue; } if (!(type == null) && string.Equals(ReadPatcherName(type), "ThreeModCompatibility", StringComparison.Ordinal)) { return DescribeAssembly(assembly2); } } } return null; } private static string ReadPatcherName(Type loaderType) { try { FieldInfo field = loaderType.GetField("PatcherName", BindingFlags.Static | BindingFlags.Public); if (field == null) { return null; } return (field.IsLiteral ? field.GetRawConstantValue() : field.GetValue(null)) as string; } catch (Exception) { return null; } } private static string DescribeAssembly(Assembly a) { string text; try { text = a.GetName().Name; } catch (Exception) { text = "<unnamed>"; } return "assembly '" + text + "' at '" + (SafeLocation(a) ?? "<no location>") + "'"; } private static IEnumerable<CodeInstruction> ChainloaderStartTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Invalid comparison between Unknown and I4 _transpilerRuns++; _lastTranspileInserted = false; _lastTranspileFailure = null; if (instructions == null) { RecordTranspileFailure("Harmony supplied no instructions for Chainloader.Start."); return instructions; } List<CodeInstruction> list = new List<CodeInstruction>(instructions); string text; int matchIndex; try { text = FindInsertionPoint(list, out matchIndex); } catch (Exception ex) { matchIndex = -1; text = "unexpected error while inspecting Chainloader.Start: " + ex.Message; } if (text != null) { RecordTranspileFailure(text); return list; } List<CodeInstruction> list2 = new List<CodeInstruction>(list.Count + 1); for (int i = 0; i < list.Count; i++) { if (i != matchIndex) { list2.Add(list[i]); continue; } CodeInstruction val = list[i]; CodeInstruction val2 = new CodeInstruction(OpCodes.Call, (object)PrepareCompatiblePathMethod); val2.labels.AddRange(val.labels); CodeInstruction val3 = new CodeInstruction(val.opcode, val.operand); foreach (ExceptionBlock block in val.blocks) { if ((int)block.blockType == 5) { val3.blocks.Add(block); } else { val2.blocks.Add(block); } } list2.Add(val2); list2.Add(val3); } _lastTranspileInserted = true; return list2; } private static void RecordTranspileFailure(string failure) { _lastTranspileFailure = failure; CompatibilityLog.Error("AdvancedTerrainCompatibility 1.0.0: " + failure + " Chainloader.Start left unchanged by this addon; TerrainTools.dll will NOT be repaired."); } private static string FindInsertionPoint(List<CodeInstruction> list, out int matchIndex) { matchIndex = -1; int num = 0; int num2 = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val == null) { return "Chainloader.Start contains a null IL instruction at index " + i + "; refusing to patch."; } MethodInfo methodInfo = val.operand as MethodInfo; if (methodInfo == null) { continue; } Type declaringType = methodInfo.DeclaringType; if (declaringType == typeof(Assembly) && methodInfo.Name == "LoadFile") { if (!IsExactLoadFileString(methodInfo)) { return "Chainloader.Start calls an unexpected Assembly.LoadFile overload at index " + i + "; refusing to patch."; } if (val.opcode != OpCodes.Call) { return "Assembly.LoadFile(string) at index " + i + " uses unexpected opcode " + val.opcode.ToString() + "; refusing to patch."; } num++; num2 = i; } else { if (declaringType == null || !string.Equals(declaringType.FullName, "ValheimThreeCompatibility.Loader", StringComparison.Ordinal)) { continue; } if (methodInfo.Name == "LoadCompatible") { return "Chainloader.Start already contains the archived combined ThreeModCompatibility replacement (LoadCompatible from " + DescribeAssembly(declaringType.Assembly) + ") at index " + i + ". Remove the combined patcher; it cannot coexist with split addons."; } if (methodInfo.Name == "PrepareCompatiblePath") { if (declaringType == typeof(Loader)) { return "this addon's PrepareCompatiblePath call is already present at index " + i + "; refusing duplicate insertion."; } string text = ReadPatcherName(declaringType); if (text == null) { return "unrecognised PrepareCompatiblePath call from " + DescribeAssembly(declaringType.Assembly) + " at index " + i + "; refusing to patch."; } if (string.Equals(text, "ThreeModCompatibility", StringComparison.Ordinal)) { return "Chainloader.Start contains a call from the archived combined ThreeModCompatibility patcher at index " + i + ". Remove the combined patcher."; } if (string.Equals(text, "AdvancedTerrainCompatibility", StringComparison.Ordinal)) { return "another copy of AdvancedTerrainCompatibility (" + DescribeAssembly(declaringType.Assembly) + ") already inserted its hook at index " + i + ". Remove the duplicate package."; } } } } if (num != 1) { return "Expected exactly one Assembly.LoadFile(string) call in Chainloader.Start but found " + num + "; refusing to patch."; } matchIndex = num2; return null; } private static bool IsExactLoadFileString(MethodInfo method) { if (!method.IsStatic || method.ReturnType != typeof(Assembly)) { return false; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 1) { return parameters[0].ParameterType == typeof(string); } return false; } public static string PrepareCompatiblePath(string path) { string text = TryGetSupportedFileName(path); if (text == null) { return path; } lock (SyncRoot) { return PrepareSupportedTarget(path, text); } } private static string TryGetSupportedFileName(string path) { if (string.IsNullOrEmpty(path)) { return null; } string fileName; try { fileName = Path.GetFileName(path); } catch (ArgumentException) { return null; } string[] supportedFileNames = SupportedFileNames; foreach (string text in supportedFileNames) { if (string.Equals(text, fileName, StringComparison.OrdinalIgnoreCase)) { return text; } } return null; } private static string PrepareSupportedTarget(string path, string supported) { string text = "resolving original path"; string text2 = path; string text3 = null; try { text2 = Path.GetFullPath(path); if (PreparedByOriginalPath.TryGetValue(text2, out var value)) { text = "checking already-loaded assemblies"; EnsureNoConflictingLoadedAssembly(value.CachePath, value.SimpleName); return value.CachePath; } text = "reading original file"; byte[] array = File.ReadAllBytes(text2); text = "hashing original file"; text3 = Sha256Hex(array); text = "querying RepairCatalog"; if (!RepairCatalog.TryGet(supported, text3, out var repair)) { CompatibilityLog.Warning(supported + " at '" + text2 + "' has unrecognised SHA256 " + text3 + "; no repair is known for this build. Chainloader will load the original file UNMODIFIED."); return path; } if (repair == null) { throw new InvalidOperationException("RepairCatalog reported a match but returned a null repair delegate."); } text = "building repaired image"; string simpleName; byte[] array2 = BuildRepairedImage(text2, array, repair, out simpleName); text = "writing/verifying cache file"; string cachePath = GetCachePath(text3, supported); EnsureCacheFile(cachePath, array2); text = "checking already-loaded assemblies"; EnsureNoConflictingLoadedAssembly(cachePath, simpleName); PreparedByOriginalPath[text2] = new PreparedEntry { CachePath = cachePath, SimpleName = simpleName }; CompatibilityLog.Info("Prepared repaired " + supported + " (source sha256 " + text3 + ", repaired sha256 " + Sha256Hex(array2) + ") at '" + cachePath + "'."); return cachePath; } catch (Exception ex) { string text4 = "AdvancedTerrainCompatibility: refusing to load unpatched supported target " + supported + " ('" + text2 + "', sha256 " + (text3 ?? "unknown") + ") - failed while " + text + ": " + ex.Message; CompatibilityLog.Error(text4 + Environment.NewLine + ex); throw new InvalidOperationException(text4, ex); } } private static byte[] BuildRepairedImage(string originalPath, byte[] originalBytes, Action<AssemblyDefinition, AssemblyDefinition> repair, out string simpleName) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Expected O, but got Unknown string text = Path.Combine(Paths.ManagedPath, "assembly_valheim.dll"); if (!File.Exists(text)) { throw new FileNotFoundException("Game assembly not found.", text); } DefaultAssemblyResolver val = CreateResolver(Path.GetDirectoryName(originalPath)); byte[] array; try { ReaderParameters val2 = new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)val, ReadingMode = (ReadingMode)1, InMemory = true, ReadSymbols = false, ReadWrite = false }; ReaderParameters val3 = new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)val, ReadingMode = (ReadingMode)1, ReadSymbols = false, ReadWrite = false }; AssemblyDefinition val4 = AssemblyDefinition.ReadAssembly(text, val2); try { using MemoryStream memoryStream = new MemoryStream(originalBytes, writable: false); AssemblyDefinition val5 = AssemblyDefinition.ReadAssembly((Stream)memoryStream, val3); try { if (val5.Name == null || string.IsNullOrEmpty(((AssemblyNameReference)val5.Name).Name)) { throw new BadImageFormatException("Target assembly has no name."); } simpleName = ((AssemblyNameReference)val5.Name).Name; repair(val5, val4); if (val5.Name == null || !string.Equals(((AssemblyNameReference)val5.Name).Name, simpleName, StringComparison.Ordinal)) { throw new InvalidOperationException("Repair changed the assembly simple name; refusing."); } using MemoryStream memoryStream2 = new MemoryStream(); val5.Write((Stream)memoryStream2); array = memoryStream2.ToArray(); } finally { ((IDisposable)val5)?.Dispose(); } } finally { ((IDisposable)val4)?.Dispose(); } } finally { ((IDisposable)val)?.Dispose(); } if (array == null || array.Length == 0) { throw new InvalidOperationException("Repair produced an empty image."); } using MemoryStream memoryStream3 = new MemoryStream(array, writable: false); AssemblyDefinition val6 = AssemblyDefinition.ReadAssembly((Stream)memoryStream3, new ReaderParameters { ReadingMode = (ReadingMode)2, ReadSymbols = false }); try { if (val6.Name == null || !string.Equals(((AssemblyNameReference)val6.Name).Name, simpleName, StringComparison.Ordinal)) { throw new BadImageFormatException("Repaired image failed metadata re-read verification."); } return array; } finally { ((IDisposable)val6)?.Dispose(); } } private static DefaultAssemblyResolver CreateResolver(string sourceDir) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown DefaultAssemblyResolver val = new DefaultAssemblyResolver(); HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase); AddSearchDir(val, seen, sourceDir); AddSearchDir(val, seen, Paths.ManagedPath); try { AddSearchDir(val, seen, Path.GetDirectoryName(typeof(Paths).Assembly.Location)); } catch (Exception) { } try { AddSearchDir(val, seen, Path.GetDirectoryName(typeof(Harmony).Assembly.Location)); } catch (Exception) { } AddSearchDir(val, seen, Paths.PluginPath); try { if (!string.IsNullOrEmpty(Paths.PluginPath) && Directory.Exists(Paths.PluginPath)) { string[] directories = Directory.GetDirectories(Paths.PluginPath, "*", SearchOption.AllDirectories); foreach (string dir in directories) { AddSearchDir(val, seen, dir); } } } catch (IOException) { } catch (UnauthorizedAccessException) { } return val; } private static void AddSearchDir(DefaultAssemblyResolver resolver, HashSet<string> seen, string dir) { if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir) && seen.Add(dir)) { ((BaseAssemblyResolver)resolver).AddSearchDirectory(dir); } } private static string GetCachePath(string sourceHash, string fileName) { return Path.GetFullPath(Path.Combine(Path.Combine(Path.Combine(Path.Combine(Paths.CachePath, "ValheimThreeCompatibility"), "1.0.0"), sourceHash.Substring(0, 16)), fileName)); } private static void EnsureCacheFile(string cachePath, byte[] expected) { Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); if (FileMatches(cachePath, expected)) { return; } string text = Path.Combine(Path.GetDirectoryName(cachePath), "t" + Guid.NewGuid().ToString("N").Substring(0, 12) + ".tmp"); try { using (FileStream fileStream = new FileStream(text, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { fileStream.Write(expected, 0, expected.Length); fileStream.Flush(flushToDisk: true); } if (!FileMatches(text, expected)) { throw new IOException("Temporary cache file failed verification: " + text); } try { if (File.Exists(cachePath)) { File.Replace(text, cachePath, null); } else { File.Move(text, cachePath); } } catch (Exception ex) { if (FileMatches(cachePath, expected)) { return; } try { if (File.Exists(cachePath)) { File.Delete(cachePath); } File.Move(text, cachePath); } catch (Exception ex2) { throw new IOException("Could not install cache file '" + cachePath + "': " + ex.Message + " / fallback: " + ex2.Message, ex2); } } } finally { TryDelete(text); } if (FileMatches(cachePath, expected)) { return; } throw new IOException("Cache file failed post-write verification: " + cachePath); } private static void EnsureNoConflictingLoadedAssembly(string cachePath, string simpleName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { string name; try { name = assembly.GetName().Name; } catch (Exception) { continue; } if (string.Equals(name, simpleName, StringComparison.OrdinalIgnoreCase)) { string text = SafeLocation(assembly); if (text == null || !PathsEqual(text, cachePath)) { throw new InvalidOperationException("An assembly named '" + simpleName + "' is already loaded from '" + (text ?? "<no location>") + "'; refusing to load a mixed or unpatched copy."); } } } } private static bool FileMatches(string path, byte[] expected) { try { if (!File.Exists(path)) { return false; } byte[] array = File.ReadAllBytes(path); if (array.Length != expected.Length) { return false; } for (int i = 0; i < array.Length; i++) { if (array[i] != expected[i]) { return false; } } return true; } catch (IOException) { return false; } catch (UnauthorizedAccessException) { return false; } } private static void TryDelete(string path) { try { if (File.Exists(path)) { File.Delete(path); } } catch (Exception) { } } private static string SafeLocation(Assembly assembly) { try { string location = assembly.Location; return string.IsNullOrEmpty(location) ? null : location; } catch (Exception) { return null; } } private static bool PathsEqual(string a, string b) { try { return string.Equals(Path.GetFullPath(a), Path.GetFullPath(b), StringComparison.OrdinalIgnoreCase); } catch (Exception) { return false; } } private static string Sha256Hex(byte[] data) { using SHA256 sHA = SHA256.Create(); return BitConverter.ToString(sHA.ComputeHash(data)).Replace("-", string.Empty).ToLowerInvariant(); } } public static class RepairCatalog { public static bool TryGet(string fileName, string hash, out Action<AssemblyDefinition, AssemblyDefinition> repair) { repair = null; if (!fileName.Equals("TerrainTools.dll", StringComparison.OrdinalIgnoreCase)) { return false; } if (fileName.Equals("CreatureLevelControl.dll", StringComparison.OrdinalIgnoreCase) && hash.Equals("601739B998F956BC49A871A4B0C7761E1F6389E5F8604D3234868F9E92D2761E", StringComparison.OrdinalIgnoreCase)) { repair = delegate(AssemblyDefinition a, AssemblyDefinition g) { new Repairs(a, g).Creature(); }; } if (fileName.Equals("TerrainTools.dll", StringComparison.OrdinalIgnoreCase) && hash.Equals("BE8F51E45BAFA1C6B9BC2587360A22B4D33D69516EDF191A46383DE18E608D15", StringComparison.OrdinalIgnoreCase)) { repair = delegate(AssemblyDefinition a, AssemblyDefinition g) { new Repairs(a, g).Terrain(); }; } if (fileName.Equals("QuickTeleport.dll", StringComparison.OrdinalIgnoreCase) && hash.Equals("25283FA2010A0EE8AD9A1B921FF7F447AE5C63406F46FFAB9F5949E782A318D2", StringComparison.OrdinalIgnoreCase)) { repair = delegate(AssemblyDefinition a, AssemblyDefinition g) { new Repairs(a, g).Teleport(); }; } return repair != null; } } internal sealed class Repairs { private readonly ModuleDefinition mod; private readonly ModuleDefinition game; private readonly TypeDefinition bridges; private readonly Dictionary<string, MethodDefinition> forwards = new Dictionary<string, MethodDefinition>(); public Repairs(AssemblyDefinition target, AssemblyDefinition currentGame) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown mod = target.MainModule; game = currentGame.MainModule; bridges = new TypeDefinition("ValheimThreeCompatibility.Generated", "GameApi", (TypeAttributes)384, mod.TypeSystem.Object); mod.Types.Add(bridges); } private static IEnumerable<TypeDefinition> AllTypes(IEnumerable<TypeDefinition> types) { foreach (TypeDefinition t in types) { yield return t; foreach (TypeDefinition item in AllTypes((IEnumerable<TypeDefinition>)t.NestedTypes)) { yield return item; } } } private IEnumerable<MethodDefinition> Methods() { return (from m in (from t in AllTypes((IEnumerable<TypeDefinition>)mod.Types) where t != bridges select t).SelectMany((TypeDefinition t) => (IEnumerable<MethodDefinition>)t.Methods) where m.HasBody select m).ToArray(); } private TypeDefinition Type(string name) { return AllTypes((IEnumerable<TypeDefinition>)mod.Types).Single((TypeDefinition t) => ((MemberReference)t).FullName == name); } private TypeDefinition GameType(string name) { return game.GetType(name) ?? throw new InvalidOperationException("Missing game type " + name); } private MethodDefinition GameMethod(string type, string name, int count) { return ((IEnumerable<MethodDefinition>)GameType(type).Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == name && ((MethodReference)m).Parameters.Count == count); } private static void Require(bool condition, string message) { if (!condition) { throw new InvalidOperationException(message); } } private MethodReference Import(MethodReference method) { return mod.ImportReference(method); } private FieldReference Import(FieldReference field) { return mod.ImportReference(field); } private MethodDefinition Forward(MethodReference old, MethodDefinition current) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_066b: Unknown result type (might be due to invalid IL or missing references) //IL_0664: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_05ce: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Expected O, but got Unknown //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_0613: Unknown result type (might be due to invalid IL or missing references) //IL_058c: 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_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_06f1: Unknown result type (might be due to invalid IL or missing references) //IL_06f8: Expected O, but got Unknown //IL_0724: Unknown result type (might be due to invalid IL or missing references) //IL_0731: Unknown result type (might be due to invalid IL or missing references) //IL_073e: Unknown result type (might be due to invalid IL or missing references) //IL_077a: Unknown result type (might be due to invalid IL or missing references) //IL_0787: Unknown result type (might be due to invalid IL or missing references) //IL_07c3: Unknown result type (might be due to invalid IL or missing references) Require(old.HasThis == ((MethodReference)current).HasThis, "Changed instance/static contract: " + ((MemberReference)old).FullName); if (forwards.TryGetValue(((MemberReference)old).FullName, out var value)) { return value; } value = new MethodDefinition("Forward" + forwards.Count, (MethodAttributes)22, mod.ImportReference(old.ReturnType)); bridges.Methods.Add(value); forwards.Add(((MemberReference)old).FullName, value); if (old.HasThis) { ((MethodReference)value).Parameters.Add(new ParameterDefinition("instance", (ParameterAttributes)0, mod.ImportReference(((MemberReference)old).DeclaringType))); } Enumerator<ParameterDefinition> enumerator = old.Parameters.GetEnumerator(); try { while (enumerator.MoveNext()) { ParameterDefinition current2 = enumerator.Current; ((MethodReference)value).Parameters.Add(new ParameterDefinition(((ParameterReference)current2).Name, (ParameterAttributes)0, mod.ImportReference(((ParameterReference)current2).ParameterType))); } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } ILProcessor iLProcessor = value.Body.GetILProcessor(); int num = (old.HasThis ? 1 : 0); if (((MemberReference)((MemberReference)old).DeclaringType).FullName == "ZDOMan" && ((MemberReference)old).Name == "FindSectorObjects") { Require(old.HasThis && old.Parameters.Count == 5 && ((MethodReference)current).Parameters.Count == 4, "Unexpected sector query contract"); Require(((MemberReference)((ParameterReference)((MethodReference)current).Parameters[0]).ParameterType).FullName == "Vector2s" && ((MemberReference)((ParameterReference)((MethodReference)current).Parameters[1]).ParameterType).FullName == "SimulationDistance" && ((MemberReference)((ParameterReference)((MethodReference)current).Parameters[2]).ParameterType).FullName == ((MemberReference)((ParameterReference)old.Parameters[3]).ParameterType).FullName && ((MemberReference)((ParameterReference)((MethodReference)current).Parameters[3]).ParameterType).FullName == ((MemberReference)((ParameterReference)old.Parameters[4]).ParameterType).FullName, "Changed sector query parameter types"); iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[0]); iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[1]); TypeDefinition val = ((ParameterReference)((MethodReference)current).Parameters[0]).ParameterType.Resolve(); iLProcessor.Emit(OpCodes.Newobj, Import((MethodReference)(object)((IEnumerable<MethodDefinition>)val.Methods).Single((MethodDefinition m) => m.IsConstructor && ((MethodReference)m).Parameters.Count == 1 && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).FullName == "Vector2i"))); iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[2]); iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[3]); iLProcessor.Emit(OpCodes.Ldc_I4_0); MethodDefinition val2 = ((IEnumerable<MethodDefinition>)((ParameterReference)((MethodReference)current).Parameters[1]).ParameterType.Resolve().Methods).Single((MethodDefinition m) => m.IsConstructor && ((MethodReference)m).Parameters.Count == 3); Require(((MethodReference)val2).Parameters[2].HasConstant && object.Equals(((MethodReference)val2).Parameters[2].Constant, false), "Unexpected SimulationDistance default"); iLProcessor.Emit(OpCodes.Newobj, Import((MethodReference)(object)val2)); iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[4]); iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[5]); iLProcessor.Emit(OpCodes.Callvirt, Import((MethodReference)(object)current)); iLProcessor.Emit(OpCodes.Ret); return value; } Require(((MethodReference)current).Parameters.Count >= old.Parameters.Count, "Removed API parameters: " + ((MemberReference)old).FullName); if (old.HasThis) { iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[0]); } for (int num2 = 0; num2 < old.Parameters.Count; num2++) { iLProcessor.Emit(OpCodes.Ldarg, ((MethodReference)value).Parameters[num2 + num]); string fullName = ((MemberReference)((ParameterReference)old.Parameters[num2]).ParameterType).FullName; string fullName2 = ((MemberReference)((ParameterReference)((MethodReference)current).Parameters[num2]).ParameterType).FullName; if (!(fullName == fullName2)) { Require(fullName == "Vector2i" && fullName2 == "Vector2s", "Unsupported parameter conversion " + ((MemberReference)old).FullName); TypeDefinition val3 = ((ParameterReference)((MethodReference)current).Parameters[num2]).ParameterType.Resolve(); iLProcessor.Emit(OpCodes.Newobj, Import((MethodReference)(object)((IEnumerable<MethodDefinition>)val3.Methods).Single((MethodDefinition m) => m.IsConstructor && ((MethodReference)m).Parameters.Count == 1 && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).FullName == "Vector2i"))); } } for (int num3 = old.Parameters.Count; num3 < ((MethodReference)current).Parameters.Count; num3++) { ParameterDefinition val4 = ((MethodReference)current).Parameters[num3]; if (((MemberReference)((ParameterReference)val4).ParameterType).FullName == "System.Boolean" && val4.HasConstant && object.Equals(val4.Constant, false)) { iLProcessor.Emit(OpCodes.Ldc_I4_0); continue; } if (((MemberReference)((ParameterReference)val4).ParameterType).FullName == "ZDOID" && val4.IsOptional) { VariableDefinition val5 = new VariableDefinition(mod.ImportReference(((ParameterReference)val4).ParameterType)); value.Body.Variables.Add(val5); value.Body.InitLocals = true; iLProcessor.Emit(OpCodes.Ldloca, val5); iLProcessor.Emit(OpCodes.Initobj, ((VariableReference)val5).VariableType); iLProcessor.Emit(OpCodes.Ldloc, val5); continue; } throw new InvalidOperationException("No reviewed default for " + ((MemberReference)current).FullName + " parameter " + ((ParameterReference)val4).Name); } iLProcessor.Emit(((MethodReference)current).HasThis ? OpCodes.Callvirt : OpCodes.Call, Import((MethodReference)(object)current)); if (((MemberReference)old.ReturnType).FullName != ((MemberReference)((MethodReference)current).ReturnType).FullName) { Require(((MemberReference)old.ReturnType).FullName == "Vector2i" && ((MemberReference)((MethodReference)current).ReturnType).FullName == "Vector2s", "Unsupported result conversion " + ((MemberReference)old).FullName); VariableDefinition val6 = new VariableDefinition(mod.ImportReference(((MethodReference)current).ReturnType)); value.Body.Variables.Add(val6); value.Body.InitLocals = true; TypeDefinition val7 = ((MethodReference)current).ReturnType.Resolve(); iLProcessor.Emit(OpCodes.Stloc, val6); iLProcessor.Emit(OpCodes.Ldloca, val6); iLProcessor.Emit(OpCodes.Ldfld, Import((FieldReference)(object)((IEnumerable<FieldDefinition>)val7.Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == "x"))); iLProcessor.Emit(OpCodes.Ldloca, val6); iLProcessor.Emit(OpCodes.Ldfld, Import((FieldReference)(object)((IEnumerable<FieldDefinition>)val7.Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == "y"))); iLProcessor.Emit(OpCodes.Newobj, Import((MethodReference)(object)((IEnumerable<MethodDefinition>)old.ReturnType.Resolve().Methods).Single((MethodDefinition m) => m.IsConstructor && ((MethodReference)m).Parameters.Count == 2 && ((IEnumerable<ParameterDefinition>)((MethodReference)m).Parameters).All((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName == "System.Int32")))); } iLProcessor.Emit(OpCodes.Ret); return value; } private int RewriteCalls(Func<MethodReference, MethodDefinition> choose) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (MethodDefinition item in Methods()) { Enumerator<Instruction> enumerator2 = item.Body.Instructions.GetEnumerator(); try { while (enumerator2.MoveNext()) { Instruction current = enumerator2.Current; object operand = current.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val != null && (!(current.OpCode != OpCodes.Call) || !(current.OpCode != OpCodes.Callvirt))) { MethodDefinition val2 = choose(val); if (val2 != null) { current.OpCode = OpCodes.Call; current.Operand = Forward(val, val2); num++; } } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } return num; } private int MessageCalls() { return RewriteCalls((MethodReference r) => (!(((MemberReference)((MemberReference)r).DeclaringType).FullName == "Character") || !(((MemberReference)r).Name == "Message") || r.Parameters.Count != 4) ? null : GameMethod("Character", "Message", 5)); } public void Teleport() { int num = RewriteCalls(delegate(MethodReference r) { if (((MemberReference)((MemberReference)r).DeclaringType).FullName == "ZoneSystem" && ((MemberReference)r).Name == "GetZone" && ((MemberReference)r.ReturnType).FullName == "Vector2i") { return GameMethod("ZoneSystem", "GetZone", 1); } if (((MemberReference)((MemberReference)r).DeclaringType).FullName == "ZoneSystem" && ((MemberReference)r).Name == "IsZoneLoaded" && ((MemberReference)((ParameterReference)r.Parameters[0]).ParameterType).FullName == "Vector2i") { return ((IEnumerable<MethodDefinition>)GameType("ZoneSystem").Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "IsZoneLoaded" && ((MethodReference)m).Parameters.Count == 1 && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).FullName == "Vector2s"); } return (((MemberReference)((MemberReference)r).DeclaringType).FullName == "ZDOMan" && ((MemberReference)r).Name == "FindSectorObjects" && ((MemberReference)((ParameterReference)r.Parameters[0]).ParameterType).FullName == "Vector2i") ? GameMethod("ZDOMan", "FindSectorObjects", 4) : null; }); Require(num == 3, "QuickTeleport expected three sector API calls, found " + num); } public void Terrain() { //IL_0157: 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_0173: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) TypeDefinition val = Type("TerrainTools.Helpers.PreciseTerrainModifier"); MethodDefinition val2 = ((IEnumerable<MethodDefinition>)val.Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "PaintClearedPrefix"); Require(((MethodReference)val2).Parameters.Count == 5 && ((MemberReference)((ParameterReference)((MethodReference)val2).Parameters[2]).ParameterType).FullName == "System.Single", "Unexpected terrain prefix signature"); MethodDefinition val3 = GameMethod("TerrainComp", "PaintCleared", 3); TypeDefinition val4 = ((ParameterReference)((MethodReference)val3).Parameters[2]).ParameterType.Resolve(); Require(((MemberReference)((ParameterReference)((MethodReference)val3).Parameters[0]).ParameterType).FullName == ((MemberReference)((ParameterReference)((MethodReference)val2).Parameters[1]).ParameterType).FullName && ((MemberReference)val4).FullName == "TerrainOp/Settings", "Changed terrain paint contract"); Require(!((IEnumerable<CustomAttribute>)val2.CustomAttributes).Where((CustomAttribute a) => ((MemberReference)a.AttributeType).FullName == "HarmonyLib.HarmonyPatch").Any((CustomAttribute a) => ((IEnumerable<CustomAttributeArgument>)a.ConstructorArguments).Any((CustomAttributeArgument v) => ((CustomAttributeArgument)(ref v)).Type.IsArray)), "Unexpected explicit terrain patch argument list"); ((MemberReference)val2).Name = "PaintClearedLegacy141"; MethodDefinition val5 = new MethodDefinition("PaintClearedPrefix", val2.Attributes, mod.TypeSystem.Boolean); CustomAttribute[] array = val2.CustomAttributes.ToArray(); foreach (CustomAttribute val6 in array) { val5.CustomAttributes.Add(val6); val2.CustomAttributes.Remove(val6); } ((MethodReference)val5).Parameters.Add(new ParameterDefinition("__instance", (ParameterAttributes)0, ((ParameterReference)((MethodReference)val2).Parameters[0]).ParameterType)); ((MethodReference)val5).Parameters.Add(new ParameterDefinition(((ParameterReference)((MethodReference)val3).Parameters[0]).Name, (ParameterAttributes)0, ((ParameterReference)((MethodReference)val2).Parameters[1]).ParameterType)); ((MethodReference)val5).Parameters.Add(new ParameterDefinition(((ParameterReference)((MethodReference)val3).Parameters[2]).Name, (ParameterAttributes)0, mod.ImportReference((TypeReference)(object)val4))); val.Methods.Add(val5); ILProcessor iLProcessor = val5.Body.GetILProcessor(); iLProcessor.Emit(OpCodes.Ldarg_0); iLProcessor.Emit(OpCodes.Ldarg_1); int num2 = 2; string[] array2 = new string[3] { "m_paintRadius", "m_paintType", "m_paintHeightCheck" }; foreach (string name in array2) { FieldDefinition val7 = ((IEnumerable<FieldDefinition>)val4.Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == name); Require(((MemberReference)((FieldReference)val7).FieldType).FullName == ((MemberReference)((ParameterReference)((MethodReference)val2).Parameters[num2++]).ParameterType).FullName, "Changed terrain settings field " + name); iLProcessor.Emit(OpCodes.Ldarg_2); iLProcessor.Emit(OpCodes.Ldfld, Import((FieldReference)(object)val7)); } iLProcessor.Emit(OpCodes.Call, (MethodReference)(object)val2); iLProcessor.Emit(OpCodes.Ret); Require(MessageCalls() == 1, "Expected one terrain message API call"); } public void Creature() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) int num = 0; FieldDefinition val = ((IEnumerable<FieldDefinition>)GameType("ZRoutedRpc").Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == "Everybody"); Require(val.IsLiteral && val.Constant is long, "Unexpected RPC broadcast constant"); foreach (MethodDefinition item in Methods()) { Enumerator<Instruction> enumerator2 = item.Body.Instructions.GetEnumerator(); try { while (enumerator2.MoveNext()) { Instruction current = enumerator2.Current; if (current.OpCode == OpCodes.Ldsfld && current.Operand is FieldReference && ((MemberReference)(FieldReference)current.Operand).FullName == "System.Int64 ZRoutedRpc::Everybody") { current.OpCode = OpCodes.Ldc_I8; current.Operand = (long)val.Constant; num++; } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } Require(num == 5, "Expected five embedded broadcast constant loads"); Require(MessageCalls() == 4, "Expected four creature message calls"); int num2 = RewriteCalls(delegate(MethodReference r) { if (((MemberReference)((MemberReference)r).DeclaringType).FullName == "ZDO" && ((MemberReference)r).Name == "GetSector" && ((MemberReference)r.ReturnType).FullName == "Vector2i") { return GameMethod("ZDO", "GetSector", 0); } if (((MemberReference)((MemberReference)r).DeclaringType).FullName == "ZoneSystem" && ((MemberReference)r).Name == "GetZonePos" && ((MemberReference)((ParameterReference)r.Parameters[0]).ParameterType).FullName == "Vector2i") { return GameMethod("ZoneSystem", "GetZonePos", 1); } if (((MemberReference)((MemberReference)r).DeclaringType).FullName == "EffectList" && ((MemberReference)r).Name == "Create" && r.Parameters.Count == 5) { return GameMethod("EffectList", "Create", 6); } return (((MemberReference)((MemberReference)r).DeclaringType).FullName == "Inventory" && ((MemberReference)r).Name == "Changed" && r.Parameters.Count == 0) ? GameMethod("Inventory", "Changed", 2) : null; }); Require(num2 == 13, "Expected thirteen creature sector/effect/inventory API calls, found " + num2); int num3 = 0; foreach (MethodDefinition item2 in Methods()) { Instruction[] array = item2.Body.Instructions.ToArray(); foreach (Instruction val2 in array) { object operand = val2.Operand; FieldReference val3 = (FieldReference)((operand is FieldReference) ? operand : null); if (val3 != null && !(((MemberReference)((MemberReference)val3).DeclaringType).FullName != "Minimap") && !(((MemberReference)val3).Name != "noForest")) { Require(val2.OpCode == OpCodes.Ldfld, "Unexpected minimap color access"); FieldDefinition val4 = ((IEnumerable<FieldDefinition>)GameType("Minimap").Fields).Single((FieldDefinition x) => ((MemberReference)x).Name == "s_noForestColor"); Require(val4.IsStatic && ((MemberReference)((FieldReference)val4).FieldType).FullName == "UnityEngine.Color", "Minimap replacement must be static Color"); val2.OpCode = OpCodes.Pop; val2.Operand = null; item2.Body.GetILProcessor().InsertAfter(val2, Instruction.Create(OpCodes.Ldsfld, Import((FieldReference)(object)val4))); num3++; } } } Require(num3 == 1, "Expected one minimap color access"); UpgradeMultiplier("CreatureLevelControl.ItemControl/PatchCookingStationItemMultiplier", "multiplyItemSpawn", "CookingStation", "SpawnItem", 4, "cheated"); UpgradeMultiplier("CreatureLevelControl.ItemControl/PatchCraftingMultiplier", "multiplyItemAdd", "Inventory", "AddItem", 10, "pickedUp"); } private void UpgradeMultiplier(string typeName, string helperName, string gameType, string gameName, int newCount, string parameterName) { //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Expected O, but got Unknown //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Expected O, but got Unknown //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04d5: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_04fb: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) TypeDefinition val = Type(typeName); MethodDefinition val2 = ((IEnumerable<MethodDefinition>)val.Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == helperName); MethodDefinition val3 = ((IEnumerable<MethodDefinition>)GameType(gameType).Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == gameName && ((MethodReference)m).Parameters.Count == newCount && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).FullName == "System.String"); bool flag = gameType == "Inventory"; Require(string.Join(",", ((IEnumerable<ParameterDefinition>)((MethodReference)val3).Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName)) == (flag ? "System.String,System.Int32,System.Int32,System.Int32,System.Int64,System.String,Vector2i,System.Boolean,System.Boolean,System.Boolean" : "System.String,System.Int32,UnityEngine.Vector3,System.Boolean"), "Unexpected multiplier API signature"); Require(((MethodReference)val2).Parameters.Count == (flag ? 8 : 4), "Unexpected multiplier wrapper arity"); List<ParameterDefinition> list = new List<ParameterDefinition>(); if (flag) { ParameterDefinition tail = ((MethodReference)val2).Parameters[7]; Require(((IEnumerable<Instruction>)val2.Body.Instructions).Count((Instruction i) => i.OpCode == OpCodes.Ldarg_S && i.Operand == tail) == 1, "Unexpected crafting tail use"); ((ParameterReference)tail).Name = "position"; ((ParameterReference)tail).ParameterType = mod.ImportReference(((ParameterReference)((MethodReference)val3).Parameters[6]).ParameterType); string[] array = new string[3] { "cheated", "pickedUp", "dropIfFullInv" }; for (int num = 0; num < array.Length; num++) { ParameterDefinition val4 = new ParameterDefinition(array[num], (ParameterAttributes)0, mod.TypeSystem.Boolean); ((MethodReference)val2).Parameters.Add(val4); list.Add(val4); } } else { ParameterDefinition val5 = new ParameterDefinition(parameterName, (ParameterAttributes)0, mod.TypeSystem.Boolean); ((MethodReference)val2).Parameters.Add(val5); list.Add(val5); } int num2 = 0; Instruction[] array2 = val2.Body.Instructions.ToArray(); foreach (Instruction val6 in array2) { object operand = val6.Operand; MethodReference val7 = (MethodReference)((operand is MethodReference) ? operand : null); if (val7 == null || ((MemberReference)((MemberReference)val7).DeclaringType).FullName != gameType || ((MemberReference)val7).Name != gameName) { continue; } Require(val7.Parameters.Count == (flag ? 7 : 3), "Unexpected multiplier call"); OpCode opCode = val6.OpCode; val6.OpCode = OpCodes.Ldarg; val6.Operand = list[0]; ILProcessor iLProcessor = val2.Body.GetILProcessor(); Instruction val8 = val6; foreach (ParameterDefinition item in list.Skip(1)) { Instruction val9 = Instruction.Create(OpCodes.Ldarg, item); iLProcessor.InsertAfter(val8, val9); val8 = val9; } iLProcessor.InsertAfter(val8, Instruction.Create(opCode, Import((MethodReference)(object)val3))); num2++; } Require(num2 == 1, "Expected one multiplier output call"); MethodDefinition obj = ((IEnumerable<MethodDefinition>)val.Methods).Single((MethodDefinition m) => m.IsConstructor && m.IsStatic); Require(((IEnumerable<Instruction>)obj.Body.Instructions).Count((Instruction i) => i.OpCode == OpCodes.Stsfld) == 2, "Unexpected multiplier initializer side effects"); obj.Body = new MethodBody(obj); ILProcessor iLProcessor2 = obj.Body.GetILProcessor(); ModuleDefinition mainModule = mod.AssemblyResolver.Resolve((AssemblyNameReference)mod.TypeSystem.CoreLibrary).MainModule; MethodReference val10 = mod.ImportReference((MethodReference)(object)((IEnumerable<MethodDefinition>)mainModule.GetType("System.Reflection.MethodBase").Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "GetMethodFromHandle" && ((MethodReference)m).Parameters.Count == 1)); TypeReference val11 = mod.ImportReference((TypeReference)(object)mainModule.GetType("System.Reflection.MethodInfo")); FieldDefinition val12 = ((IEnumerable<FieldDefinition>)val.Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == ((gameType == "Inventory") ? "ItemAdder" : "ItemSpawner")); FieldDefinition val13 = ((IEnumerable<FieldDefinition>)val.Fields).Single((FieldDefinition f) => ((MemberReference)f).Name == ((gameType == "Inventory") ? "ItemAddMultiplier" : "ItemSpawnMultiplier")); iLProcessor2.Emit(OpCodes.Ldtoken, Import((MethodReference)(object)val3)); iLProcessor2.Emit(OpCodes.Call, val10); iLProcessor2.Emit(OpCodes.Castclass, val11); iLProcessor2.Emit(OpCodes.Stsfld, (FieldReference)(object)val12); iLProcessor2.Emit(OpCodes.Ldtoken, (MethodReference)(object)val2); iLProcessor2.Emit(OpCodes.Call, val10); iLProcessor2.Emit(OpCodes.Castclass, val11); iLProcessor2.Emit(OpCodes.Stsfld, (FieldReference)(object)val13); iLProcessor2.Emit(OpCodes.Ret); } } internal static class BuildTarget { public const string Name = "AdvancedTerrainCompatibility"; public const string TargetFile = "TerrainTools.dll"; } }