Decompiled source of Sora M1 Fix v1.0.0

BepInEx/plugins/Sora_M1_Fix/SoraM1Fix.dll

Decompiled an hour 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 Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;

[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("SoraM1Fix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SoraM1Fix")]
[assembly: AssemblyTitle("SoraM1Fix")]
[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 SoraM1Fix
{
	[BepInPlugin("ezeus.sora.m1fix", "Sora M1 Fix", "1.0.0")]
	[BepInDependency("com.Dragonyck.Sora", "1.0.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Manipulator <>9__4_0;

			public static Manipulator <>9__4_1;

			internal void <Awake>b__4_0(ILContext il)
			{
				TimingPatch.Apply(il.Body, constructor: false);
			}

			internal void <Awake>b__4_1(ILContext il)
			{
				TimingPatch.Apply(il.Body, constructor: true);
			}
		}

		public const string Id = "ezeus.sora.m1fix";

		private const string SoraId = "com.Dragonyck.Sora";

		private ILHook enterHook;

		private ILHook constructorHook;

		private void Awake()
		{
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			try
			{
				PluginInfo val = Chainloader.PluginInfos["com.Dragonyck.Sora"];
				string text;
				using (FileStream inputStream = File.OpenRead(val.Location))
				{
					using SHA256 sHA = SHA256.Create();
					text = BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "");
				}
				if (text == "90D1D6D8E250AB877CBAAFA3081DAD8BAF12CCF569219E0DBB6FF73676252411")
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Sora already contains the equivalent local M1 repair; no extra patch is needed.");
					return;
				}
				if (text != "893C8387E863E159952A0AE489979A1FB3A03371B3AE912D133C3EAF910B60A4")
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Sora M1 Fix supports the original Dragonyck-Sora-1.0.6 DLL. This different build was left unchanged.");
					return;
				}
				Type? type = ((object)val.Instance).GetType().Assembly.GetType("Sora.Primary", throwOnError: true);
				MethodInfo method = type.GetMethod("OnEnter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method == null || constructor == null)
				{
					throw new MissingMethodException("Sora.Primary entry points were not found.");
				}
				object obj = <>c.<>9__4_0;
				if (obj == null)
				{
					Manipulator val2 = delegate(ILContext il)
					{
						TimingPatch.Apply(il.Body, constructor: false);
					};
					<>c.<>9__4_0 = val2;
					obj = (object)val2;
				}
				enterHook = new ILHook((MethodBase)method, (Manipulator)obj);
				object obj2 = <>c.<>9__4_1;
				if (obj2 == null)
				{
					Manipulator val3 = delegate(ILContext il)
					{
						TimingPatch.Apply(il.Body, constructor: true);
					};
					<>c.<>9__4_1 = val3;
					obj2 = (object)val3;
				}
				constructorHook = new ILHook((MethodBase)constructor, (Manipulator)obj2);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Sora M1 repair active: original combo timing, hit force and hit pause restored (5 legacy reads). Sora.dll on disk is unchanged.");
			}
			catch (Exception ex)
			{
				RemoveHooks();
				((BaseUnityPlugin)this).Logger.LogError((object)("Sora M1 repair could not be applied; its hooks were removed. " + ex));
			}
		}

		private void OnDestroy()
		{
			RemoveHooks();
		}

		private void RemoveHooks()
		{
			ILHook obj = constructorHook;
			if (obj != null)
			{
				obj.Dispose();
			}
			constructorHook = null;
			ILHook obj2 = enterHook;
			if (obj2 != null)
			{
				obj2.Dispose();
			}
			enterHook = null;
		}
	}
	internal static class TimingPatch
	{
		internal const string OriginalSha256 = "893C8387E863E159952A0AE489979A1FB3A03371B3AE912D133C3EAF910B60A4";

		internal const string RepairedSha256 = "90D1D6D8E250AB877CBAAFA3081DAD8BAF12CCF569219E0DBB6FF73676252411";

		private static readonly Dictionary<string, float> Values = new Dictionary<string, float>
		{
			["baseComboAttackDuration"] = 0.6f,
			["baseFinisherAttackDuration"] = 1f,
			["baseEarlyExitDuration"] = 0.15f,
			["forceMagnitude"] = 600f,
			["hitPauseDuration"] = 0.05f
		};

		internal static int Apply(MethodBody body, bool constructor)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			string[] array = ((!constructor) ? new string[3] { "baseComboAttackDuration", "baseFinisherAttackDuration", "baseEarlyExitDuration" } : new string[2] { "forceMagnitude", "hitPauseDuration" });
			Instruction[] reads = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i)
			{
				//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)
				if (i.OpCode == OpCodes.Ldsfld)
				{
					object operand = i.Operand;
					FieldReference val2 = (FieldReference)((operand is FieldReference) ? operand : null);
					if (val2 != null)
					{
						return ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "EntityStates.Merc.GroundLight";
					}
				}
				return false;
			}).ToArray();
			if (reads.Length != array.Length || array.Any((string name) => reads.Count((Instruction i) => ((MemberReference)(FieldReference)i.Operand).Name == name) != 1))
			{
				throw new InvalidOperationException("Unexpected Sora primary IL; no timing changes applied to " + ((MemberReference)body.Method).FullName);
			}
			Instruction[] array2 = reads;
			foreach (Instruction val in array2)
			{
				float num2 = Values[((MemberReference)(FieldReference)val.Operand).Name];
				val.OpCode = OpCodes.Ldc_R4;
				val.Operand = num2;
			}
			return reads.Length;
		}
	}
}