Decompiled source of Diversity Fix v1.0.0

patchers/DiversityFix.Patcher.dll

Decompiled 12 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 BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DiversityFix.Patcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DiversityFix.Patcher")]
[assembly: AssemblyTitle("DiversityFix.Patcher")]
[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 DiversityFix
{
	public static class Fixer
	{
		private static bool IsPcb(MethodReference m)
		{
			return ((MemberReference)((MemberReference)m).DeclaringType).FullName == "GameNetcodeStuff.PlayerControllerB";
		}

		private static bool IsOld(MethodReference m)
		{
			if (!IsPcb(m) || ((!(((MemberReference)m).Name == "KillPlayer") || m.Parameters.Count != 5) && (!(((MemberReference)m).Name == "HasLineOfSightToPosition") || m.Parameters.Count != 4) && (!(((MemberReference)m).Name == "DropAllHeldItemsServerRpc") || m.Parameters.Count != 0)))
			{
				if (((MemberReference)((MemberReference)m).DeclaringType).FullName == "SpawnableEnemyWithRarity" && ((MemberReference)m).Name == ".ctor")
				{
					return m.Parameters.Count == 0;
				}
				return false;
			}
			return true;
		}

		private static IEnumerable<TypeDefinition> AllTypes(IEnumerable<TypeDefinition> ts)
		{
			foreach (TypeDefinition t in ts)
			{
				yield return t;
				foreach (TypeDefinition item in AllTypes((IEnumerable<TypeDefinition>)t.NestedTypes))
				{
					yield return item;
				}
			}
		}

		private static bool DoorNeedsFix(ModuleDefinition mod)
		{
			return mod.GetTypeReferences().Any(delegate(TypeReference t)
			{
				if (t.Namespace == "DunGen")
				{
					IMetadataScope scope = t.Scope;
					AssemblyNameReference val = (AssemblyNameReference)(object)((scope is AssemblyNameReference) ? scope : null);
					if (val != null)
					{
						return val.Name == "Assembly-CSharp";
					}
				}
				return false;
			});
		}

		public static bool NeedsPatch(ModuleDefinition mod)
		{
			if (!DoorNeedsFix(mod))
			{
				return mod.GetMemberReferences().OfType<MethodReference>().Any(IsOld);
			}
			return true;
		}

		public static List<string> Apply(ModuleDefinition mod, ModuleDefinition game)
		{
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: 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_02de: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			TypeDefinition type = game.GetType("GameNetcodeStuff.PlayerControllerB");
			TypeDefinition type2 = game.GetType("SpawnableEnemyWithRarity");
			MethodReference val = Imp(type, (MethodDefinition m) => ((MemberReference)m).Name == "KillPlayer" && ((MethodReference)m).Parameters.Count == 6);
			MethodReference val2 = Imp(type, (MethodDefinition m) => ((MemberReference)m).Name == "HasLineOfSightToPosition" && ((MethodReference)m).Parameters.Count == 5);
			MethodReference val3 = Imp(type, (MethodDefinition m) => ((MemberReference)m).Name == "DropAllHeldItemsAndSyncNonexact" && ((MethodReference)m).Parameters.Count == 0);
			MethodReference val4 = Imp(type2, (MethodDefinition m) => m.IsConstructor && !m.IsStatic && ((MethodReference)m).Parameters.Count == 2);
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			foreach (TypeDefinition item in AllTypes((IEnumerable<TypeDefinition>)mod.Types).ToList())
			{
				foreach (MethodDefinition item2 in ((IEnumerable<MethodDefinition>)item.Methods).Where((MethodDefinition m) => m.HasBody))
				{
					MethodBody body = item2.Body;
					if (!((IEnumerable<Instruction>)body.Instructions).Any(delegate(Instruction i)
					{
						object operand2 = i.Operand;
						MethodReference val11 = (MethodReference)((operand2 is MethodReference) ? operand2 : null);
						return val11 != null && IsOld(val11);
					}))
					{
						continue;
					}
					ILProcessor iLProcessor = body.GetILProcessor();
					MethodBodyRocks.SimplifyMacros(body);
					foreach (Instruction item3 in ((IEnumerable<Instruction>)body.Instructions).ToList())
					{
						object operand = item3.Operand;
						MethodReference val5 = (MethodReference)((operand is MethodReference) ? operand : null);
						if (val5 != null && IsOld(val5))
						{
							if (((MemberReference)val5).Name == "KillPlayer" && val != null)
							{
								Instruction val6 = iLProcessor.Create(item3.OpCode, val);
								item3.OpCode = OpCodes.Ldc_I4_0;
								item3.Operand = null;
								iLProcessor.InsertAfter(item3, val6);
								num++;
							}
							else if (((MemberReference)val5).Name == "HasLineOfSightToPosition" && val2 != null)
							{
								Instruction val7 = iLProcessor.Create(item3.OpCode, val2);
								item3.OpCode = OpCodes.Ldc_I4_M1;
								item3.Operand = null;
								iLProcessor.InsertAfter(item3, val7);
								num2++;
							}
							else if (((MemberReference)val5).Name == "DropAllHeldItemsServerRpc" && val3 != null)
							{
								item3.Operand = val3;
								num3++;
							}
							else if (((MemberReference)val5).Name == ".ctor" && item3.OpCode == OpCodes.Newobj && val4 != null)
							{
								Instruction val8 = iLProcessor.Create(OpCodes.Ldc_I4_0);
								Instruction val9 = iLProcessor.Create(OpCodes.Newobj, val4);
								item3.OpCode = OpCodes.Ldnull;
								item3.Operand = null;
								iLProcessor.InsertAfter(item3, val8);
								iLProcessor.InsertAfter(val8, val9);
								num4++;
							}
						}
					}
					body.MaxStackSize += 2;
					MethodBodyRocks.OptimizeMacros(body);
					list.Add("patched " + ((MemberReference)item).FullName + "::" + ((MemberReference)item2).Name);
				}
			}
			int num5 = 0;
			if (DoorNeedsFix(mod))
			{
				AssemblyNameReference val10 = ((IEnumerable<AssemblyNameReference>)mod.AssemblyReferences).FirstOrDefault((Func<AssemblyNameReference, bool>)((AssemblyNameReference a) => a.Name == "DunGen"));
				if (val10 == null)
				{
					val10 = new AssemblyNameReference("DunGen", new Version(0, 0, 0, 0));
					mod.AssemblyReferences.Add(val10);
				}
				foreach (TypeReference item4 in mod.GetTypeReferences().Where(delegate(TypeReference t)
				{
					if (t.Namespace == "DunGen")
					{
						IMetadataScope scope = t.Scope;
						AssemblyNameReference val11 = (AssemblyNameReference)(object)((scope is AssemblyNameReference) ? scope : null);
						if (val11 != null)
						{
							return val11.Name == "Assembly-CSharp";
						}
					}
					return false;
				}).ToList())
				{
					item4.Scope = (IMetadataScope)(object)val10;
					num5++;
				}
			}
			list.Add($"KillPlayer:{num} HasLineOfSight:{num2} DropAll:{num3} ctor:{num4} DunGen types:{num5}");
			return list;
			MethodReference Imp(TypeDefinition t, Func<MethodDefinition, bool> f)
			{
				MethodDefinition val11 = ((t != null) ? ((IEnumerable<MethodDefinition>)t.Methods).FirstOrDefault(f) : null);
				if (val11 != null)
				{
					return mod.ImportReference((MethodReference)(object)val11);
				}
				return null;
			}
		}

		public static List<string> PatchFile(string path, string assemblyCSharpPath, IEnumerable<string> searchDirs)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			DefaultAssemblyResolver val = new DefaultAssemblyResolver();
			foreach (string searchDir in searchDirs)
			{
				if (Directory.Exists(searchDir))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(searchDir);
				}
			}
			using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(path));
			ModuleDefinition val2 = ModuleDefinition.ReadModule((Stream)memoryStream, new ReaderParameters
			{
				AssemblyResolver = (IAssemblyResolver)(object)val,
				ReadingMode = (ReadingMode)2,
				ReadSymbols = false
			});
			try
			{
				if (!NeedsPatch(val2))
				{
					return new List<string>();
				}
				ModuleDefinition val3 = ModuleDefinition.ReadModule(assemblyCSharpPath, new ReaderParameters
				{
					AssemblyResolver = (IAssemblyResolver)(object)val,
					ReadingMode = (ReadingMode)2
				});
				try
				{
					List<string> result = Apply(val2, val3);
					string text = path + ".fixtmp";
					val2.Write(text);
					File.Copy(text, path, overwrite: true);
					File.Delete(text);
					return result;
				}
				finally
				{
					((IDisposable)val3)?.Dispose();
				}
			}
			finally
			{
				((IDisposable)val2)?.Dispose();
			}
		}
	}
	public static class DiversityFixPatcher
	{
		public static IEnumerable<string> TargetDLLs { get; } = new string[0];

		public static void Patch(AssemblyDefinition assembly)
		{
		}

		public static void Initialize()
		{
			ManualLogSource val = Logger.CreateLogSource("DiversityFix");
			try
			{
				string assemblyCSharpPath = Path.Combine(Paths.ManagedPath, "Assembly-CSharp.dll");
				string[] files = Directory.GetFiles(Paths.PluginPath, "Diversity Remastered.dll", SearchOption.AllDirectories);
				foreach (string text in files)
				{
					try
					{
						List<string> list = Fixer.PatchFile(text, assemblyCSharpPath, new string[3]
						{
							Paths.ManagedPath,
							Paths.BepInExAssemblyDirectory,
							Path.GetDirectoryName(text)
						});
						if (list.Count == 0)
						{
							val.LogInfo((object)("Diversity already compatible: " + text));
							continue;
						}
						val.LogMessage((object)("Diversity patched for current game version: " + text));
						foreach (string item in list)
						{
							val.LogInfo((object)item);
						}
					}
					catch (Exception ex)
					{
						val.LogError((object)("Could not patch " + text + ": " + ex));
					}
				}
			}
			catch (Exception ex2)
			{
				val.LogError((object)ex2);
			}
		}
	}
}