Decompiled source of SkipIntro v1.0.0

plugins/SkipIntro/SoDSkipIntro.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("SoDSkipIntro")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("SoDSkipIntro")]
[assembly: AssemblyTitle("SoDSkipIntro")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 SoDSkipIntro
{
	[BepInPlugin("sm3gm.sod.skipintro", "Skip Intro", "1.0.0")]
	public sealed class Plugin : BasePlugin
	{
		public const string VER = "1.0.0";

		internal static ManualLogSource L;

		internal static ConfigEntry<bool> SkipPressAnyKey;

		internal static ConfigEntry<bool> RemoveLogos;

		internal static ConfigEntry<string> Controls;

		public override void Load()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			L = ((BasePlugin)this).Log;
			SkipPressAnyKey = ((BasePlugin)this).Config.Bind<bool>("Startup", "SkipPressAnyKeyScreen", true, "Go straight to the main menu instead of waiting on the press-any-key screen.");
			Controls = ((BasePlugin)this).Config.Bind<string>("Startup", "Controls", "Auto", "Which controls to tell the game you use: Auto (controller when one is connected), Controller or KeyboardMouse.");
			RemoveLogos = ((BasePlugin)this).Config.Bind<bool>("Startup", "RemoveLogos", true, "Remove the studio logos at launch (takes effect from the next launch). Off puts them back.");
			new Harmony("sm3gm.sod.skipintro").PatchAll(typeof(Patches));
			Logos.Apply();
			ManualLogSource l = L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Skip Intro ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded");
			}
			l.LogInfo(val);
		}
	}
	internal static class Logos
	{
		private struct Known
		{
			public string Original;

			public string Patched;

			public long Offset;
		}

		private static readonly Known[] known = new Known[1]
		{
			new Known
			{
				Original = "5ff34b22602e8229956eb4187139d5c82bb9c36a9833cf755d3b6d60a92f6eb2",
				Patched = "dfc436196ae33b947ee334c54ddba4502fd2f186a69e229ab1114377b58f7957",
				Offset = 4212L
			}
		};

		internal static void Apply()
		{
			try
			{
				string text = Path.Combine(Paths.GameRootPath, "Shadows of Doubt_Data", "globalgamemanagers");
				if (!File.Exists(text))
				{
					Plugin.L.LogWarning((object)"[LOGOS] game settings file not found, logos left alone");
					return;
				}
				byte[] array = File.ReadAllBytes(text);
				string text2 = Sha(array);
				bool value = Plugin.RemoveLogos.Value;
				Known[] array2 = Logos.known;
				for (int i = 0; i < array2.Length; i++)
				{
					Known known = array2[i];
					if (text2 == (value ? known.Patched : known.Original))
					{
						Plugin.L.LogInfo((object)(value ? "[LOGOS] logos already removed" : "[LOGOS] logos are on, as set"));
						return;
					}
					if (text2 != (value ? known.Original : known.Patched))
					{
						continue;
					}
					if (value)
					{
						string text3 = Path.Combine(Paths.ConfigPath, "SkipIntro");
						Directory.CreateDirectory(text3);
						string path = Path.Combine(text3, "globalgamemanagers.original");
						if (!File.Exists(path))
						{
							File.WriteAllBytes(path, array);
						}
					}
					array[known.Offset] = ((!value) ? ((byte)1) : ((byte)0));
					if (Sha(array) != (value ? known.Patched : known.Original))
					{
						Plugin.L.LogWarning((object)"[LOGOS] check failed, nothing written");
						return;
					}
					Write(text, array);
					Plugin.L.LogInfo((object)(value ? "[LOGOS] logos removed from the next launch on (backup in BepInEx/config/SkipIntro)" : "[LOGOS] logos put back from the next launch on"));
					return;
				}
				Plugin.L.LogInfo((object)"[LOGOS] unknown game version, logos left alone (an update to this mod will support it)");
			}
			catch (Exception ex)
			{
				Plugin.L.LogWarning((object)("[LOGOS] " + ex.Message));
			}
		}

		private static void Write(string file, byte[] data)
		{
			try
			{
				File.WriteAllBytes(file, data);
				return;
			}
			catch (IOException)
			{
			}
			string text = file + ".skipintro-old";
			if (File.Exists(text))
			{
				File.Delete(text);
			}
			File.Move(file, text);
			try
			{
				File.WriteAllBytes(file, data);
			}
			catch
			{
				File.Move(text, file);
				throw;
			}
		}

		private static string Sha(byte[] d)
		{
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(d)).Replace("-", "").ToLowerInvariant();
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		[HarmonyPatch(typeof(ControlDetectController), "Start")]
		private static void Start(ControlDetectController __instance)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			try
			{
				if (Plugin.SkipPressAnyKey.Value)
				{
					bool flag = Plugin.Controls.Value.Equals("Controller", StringComparison.OrdinalIgnoreCase) || (Plugin.Controls.Value.Equals("Auto", StringComparison.OrdinalIgnoreCase) && PadConnected());
					PlayerPrefs.SetInt("controlMethod", (!flag) ? 1 : 0);
					__instance.loadSceneTriggered = true;
					ManualLogSource l = Plugin.L;
					bool flag2 = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(48, 1, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[START] press-any-key screen skipped, controls: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? "controller" : "keyboard and mouse");
					}
					l.LogInfo(val);
				}
			}
			catch (Exception ex)
			{
				Plugin.L.LogWarning((object)("[START] " + ex.Message));
			}
		}

		private static bool PadConnected()
		{
			try
			{
				if (!(Type.GetType("UnityEngine.Input, UnityEngine.InputLegacyModule")?.GetMethod("GetJoystickNames")?.Invoke(null, null) is IEnumerable enumerable))
				{
					return false;
				}
				foreach (object item in enumerable)
				{
					if (item != null && !string.IsNullOrWhiteSpace(item.ToString()))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
}