using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using BepInEx; using Mono.Cecil; using Mono.Collections.Generic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace WesleyInteriorsCompat.Preloader; public static class Patcher { private const string MoonConfigFileName = "JacobG5.WesleyMoonScripts.cfg"; public static IEnumerable TargetDLLs => new string[1] { "Assembly-CSharp.dll" }; public static void Initialize() { DisableWesleyMoonProgression(); } public static void Patch(AssemblyDefinition assembly) { if (assembly == null || !string.Equals(((AssemblyNameReference)assembly.Name).Name, "Assembly-CSharp", StringComparison.Ordinal)) { return; } try { string dunGenPath = Path.Combine(Paths.ManagedPath, "DunGen.dll"); int num = AddDunGenForwarders(assembly, dunGenPath, WriteLog); WriteLog("Added " + num + " DunGen type forwarder(s) to Assembly-CSharp. No Wesley files were changed on disk."); } catch (Exception ex) { WriteLog("Could not add DunGen type forwarders: " + ex); } } public static int AddDunGenForwarders(AssemblyDefinition assembly, string dunGenPath, Action log) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown if (assembly == null) { throw new ArgumentNullException("assembly"); } if (string.IsNullOrEmpty(dunGenPath) || !File.Exists(dunGenPath)) { throw new FileNotFoundException("DunGen.dll was not found.", dunGenPath); } AssemblyDefinition val = null; try { val = AssemblyDefinition.ReadAssembly(dunGenPath); ModuleDefinition mainModule = assembly.MainModule; AssemblyNameReference val2 = FindOrAddDunGenReference(mainModule, val.Name); int num = 0; Enumerator enumerator = val.MainModule.Types.GetEnumerator(); try { while (enumerator.MoveNext()) { TypeDefinition current = enumerator.Current; if (current.IsPublic && IsDunGenNamespace(((TypeReference)current).Namespace)) { if (ContainsDirectType(mainModule, ((TypeReference)current).Namespace, ((MemberReference)current).Name)) { Log(log, "Skipped a conflicting Assembly-CSharp type: " + ((MemberReference)current).FullName); } else if (!ContainsForwarder(mainModule, ((TypeReference)current).Namespace, ((MemberReference)current).Name)) { ExportedType val3 = new ExportedType(((TypeReference)current).Namespace, ((MemberReference)current).Name, mainModule, (IMetadataScope)(object)val2); val3.Attributes = (TypeAttributes)2097153; mainModule.ExportedTypes.Add(val3); num++; } } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } return num; } finally { if (val != null) { val.Dispose(); } } } private static AssemblyNameReference FindOrAddDunGenReference(ModuleDefinition targetModule, AssemblyNameDefinition sourceAssemblyName) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_006b: Expected O, but got Unknown Enumerator enumerator = targetModule.AssemblyReferences.GetEnumerator(); try { while (enumerator.MoveNext()) { AssemblyNameReference current = enumerator.Current; if (string.Equals(current.Name, ((AssemblyNameReference)sourceAssemblyName).Name, StringComparison.Ordinal)) { return current; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } AssemblyNameReference val = new AssemblyNameReference(((AssemblyNameReference)sourceAssemblyName).Name, ((AssemblyNameReference)sourceAssemblyName).Version); targetModule.AssemblyReferences.Add(val); return val; } private static bool ContainsDirectType(ModuleDefinition module, string namespaceName, string typeName) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Enumerator enumerator = module.Types.GetEnumerator(); try { while (enumerator.MoveNext()) { TypeDefinition current = enumerator.Current; if (string.Equals(((TypeReference)current).Namespace, namespaceName, StringComparison.Ordinal) && string.Equals(((MemberReference)current).Name, typeName, StringComparison.Ordinal)) { return true; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } return false; } private static bool ContainsForwarder(ModuleDefinition module, string namespaceName, string typeName) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Enumerator enumerator = module.ExportedTypes.GetEnumerator(); try { while (enumerator.MoveNext()) { ExportedType current = enumerator.Current; if (current.DeclaringType == null && string.Equals(current.Namespace, namespaceName, StringComparison.Ordinal) && string.Equals(current.Name, typeName, StringComparison.Ordinal)) { return true; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } return false; } private static bool IsDunGenNamespace(string namespaceName) { return !string.IsNullOrEmpty(namespaceName) && (string.Equals(namespaceName, "DunGen", StringComparison.Ordinal) || namespaceName.StartsWith("DunGen.", StringComparison.Ordinal)); } private static void DisableWesleyMoonProgression() { try { Directory.CreateDirectory(Paths.ConfigPath); string path = Path.Combine(Paths.ConfigPath, "JacobG5.WesleyMoonScripts.cfg"); if (!File.Exists(path)) { File.WriteAllText(path, "## Written by Wesley Interiors Compatibility Pack.\r\n## Keeps Wesley moon progression disabled.\r\n\r\n[Core]\r\n\r\nLockMoons = false\r\n", Encoding.UTF8); WriteLog("Created Wesley Moon Scripts configuration with progression locks disabled."); return; } string text = File.ReadAllText(path); string text2 = Regex.Replace(text, "(?m)^\\s*LockMoons\\s*=\\s*.*$", "LockMoons = false"); if (string.Equals(text, text2, StringComparison.Ordinal)) { if (!text2.EndsWith("\n", StringComparison.Ordinal)) { text2 += Environment.NewLine; } text2 = text2 + "LockMoons = false" + Environment.NewLine; } if (!string.Equals(text, text2, StringComparison.Ordinal)) { File.WriteAllText(path, text2, Encoding.UTF8); WriteLog("Set Wesley Moon Scripts LockMoons = false."); } } catch (Exception ex) { WriteLog("Could not update Wesley Moon Scripts configuration: " + ex.Message); } } private static void Log(Action log, string message) { log?.Invoke(message); } private static void WriteLog(string message) { Console.WriteLine("[WesleyInteriorsCompat] " + message); } }