Decompiled source of CyberSeedSetter v1.1.0

CyberSeedSetter.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameConsole;
using GameConsole.CommandTree;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using plog;
using plog.Models;

[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("CyberSeedSetter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+7b2a14acc58900f012365f438b8953c91793e7da")]
[assembly: AssemblyProduct("CyberSeedSetter")]
[assembly: AssemblyTitle("CyberSeedSetter")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 CyberSeedSetter
{
	[HarmonyPatch(typeof(EndlessGrid))]
	public static class EndlessGridPatcher
	{
		[CompilerGenerated]
		private sealed class <Random_Range_Replacer>d__7 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private MethodBase method;

			public MethodBase <>3__method;

			private IEnumerator<CodeInstruction> <>7__wrap1;

			private CodeInstruction <inst>5__3;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Random_Range_Replacer>d__7(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 2u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = null;
				<inst>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Expected O, but got Unknown
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>7__wrap1 = instructions.GetEnumerator();
						<>1__state = -3;
						goto IL_0125;
					case 1:
						<>1__state = -3;
						<inst>5__3.operand = m_EndlessGridPatcher_Random_Range_Int;
						goto IL_00ff;
					case 2:
						<>1__state = -3;
						<inst>5__3.operand = m_EndlessGridPatcher_Random_Range_Float;
						goto IL_00ff;
					case 3:
						{
							<>1__state = -3;
							<inst>5__3 = null;
							goto IL_0125;
						}
						IL_0125:
						if (<>7__wrap1.MoveNext())
						{
							<inst>5__3 = <>7__wrap1.Current;
							if (CodeInstructionExtensions.Calls(<inst>5__3, m_Random_Range_Int))
							{
								<>2__current = new CodeInstruction(OpCodes.Ldstr, (object)method.Name);
								<>1__state = 1;
								return true;
							}
							if (CodeInstructionExtensions.Calls(<inst>5__3, m_Random_Range_Float))
							{
								<>2__current = new CodeInstruction(OpCodes.Ldstr, (object)method.Name);
								<>1__state = 2;
								return true;
							}
							goto IL_00ff;
						}
						<>m__Finally1();
						<>7__wrap1 = null;
						return false;
						IL_00ff:
						<>2__current = <inst>5__3;
						<>1__state = 3;
						return true;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap1 != null)
				{
					<>7__wrap1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<Random_Range_Replacer>d__7 <Random_Range_Replacer>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<Random_Range_Replacer>d__ = this;
				}
				else
				{
					<Random_Range_Replacer>d__ = new <Random_Range_Replacer>d__7(0);
				}
				<Random_Range_Replacer>d__.instructions = <>3__instructions;
				<Random_Range_Replacer>d__.method = <>3__method;
				return <Random_Range_Replacer>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private static readonly MethodInfo m_Random_Range_Int = AccessTools.Method(typeof(Random), "Range", new Type[2]
		{
			typeof(int),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo m_Random_Range_Float = AccessTools.Method(typeof(Random), "Range", new Type[2]
		{
			typeof(float),
			typeof(float)
		}, (Type[])null);

		private static readonly MethodInfo m_EndlessGridPatcher_Random_Range_Int = new Func<int, int, string, int>(Random_Range_Int).Method;

		private static readonly MethodInfo m_EndlessGridPatcher_Random_Range_Float = new Func<float, float, string, float>(Random_Range_Float).Method;

		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		private static void InitRandom()
		{
			RandomManager.Initialize(CheatsManager.KeepCheatsEnabled && MonoSingleton<PrefsManager>.Instance.GetBool("cheat.cyberseedsetter.seed-override", false));
		}

		private static int Random_Range_Int(int min, int max, string methodName)
		{
			return RandomManager.RandomInstance.Range(min, max);
		}

		private static float Random_Range_Float(float min, float max, string methodName)
		{
			return RandomManager.RandomInstance.Range(min, max);
		}

		[IteratorStateMachine(typeof(<Random_Range_Replacer>d__7))]
		public static IEnumerable<CodeInstruction> Random_Range_Replacer(IEnumerable<CodeInstruction> instructions, MethodBase method)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Random_Range_Replacer>d__7(-2)
			{
				<>3__instructions = instructions,
				<>3__method = method
			};
		}
	}
	[BepInPlugin("com.10-days-till-xmas.cyberseedsetter", "CyberSeedSetter", "1.1.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public sealed class PluginConfigs
		{
			public readonly ConfigEntry<int> rngSeed = config.Bind<int>("general", "RNG Seed", 0, "sets the seed for the random number generator, leave null for a random seed");

			public PluginConfigs(ConfigFile config)
			{
			}
		}

		internal static ManualLogSource Logger { get; private set; }

		internal static PluginConfigs Configs { get; private set; }

		private void Awake()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin com.10-days-till-xmas.cyberseedsetter is loaded!");
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)4;
			Configs = new PluginConfigs(((BaseUnityPlugin)this).Config);
			Harmony harmony = new Harmony("com.10-days-till-xmas.cyberseedsetter");
			harmony.PatchAll();
			MethodInfo m_EndlessGridPatcher_Random = new Func<IEnumerable<CodeInstruction>, MethodBase, IEnumerable<CodeInstruction>>(EndlessGridPatcher.Random_Range_Replacer).Method;
			CollectionExtensions.Do<MethodInfo>(from m in AccessTools.GetDeclaredMethods(typeof(EndlessGrid))
				where MethodBaseExtensions.HasMethodBody((MethodBase)m) && m.MemberType == MemberTypes.Method && !m.IsSpecialName
				select m, (Action<MethodInfo>)delegate(MethodInfo method)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(m_EndlessGridPatcher_Random), (HarmonyMethod)null, (HarmonyMethod)null);
			});
		}
	}
	public static class RandomManager
	{
		public static SeededRandom RandomInstance { get; private set; }

		public static void Initialize(bool seeded)
		{
			RandomInstance = (seeded ? new SeededRandom(Plugin.Configs.rngSeed.Value) : new SeededRandom());
			Plugin.Logger.LogInfo((object)$"Initializing RandomManager with seed = {RandomInstance.Seed}");
		}
	}
	public sealed class SeededRandom
	{
		private readonly Random random;

		public int Seed { get; }

		public SeededRandom(int seed)
		{
			Seed = seed;
			random = new Random(seed);
			base..ctor();
		}

		public SeededRandom()
			: this(Random.Range(int.MinValue, int.MaxValue))
		{
		}

		public int Range(int minValue, int maxValue)
		{
			return random.Next(minValue, maxValue);
		}

		public float Range(float minValue, float maxValue)
		{
			return (float)random.NextDouble() * (maxValue - minValue) + minValue;
		}
	}
	internal static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.10-days-till-xmas.cyberseedsetter";

		public const string PLUGIN_NAME = "CyberSeedSetter";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace CyberSeedSetter.ConsoleCommands
{
	[HarmonyPatch(typeof(Console))]
	public class ConsolePatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void AwakePostfix(Console __instance)
		{
			Plugin.Logger.LogInfo((object)"Registering SeedCommands");
			__instance.RegisterCommand((ICommand)(object)new SeedCommands(__instance));
		}
	}
	public sealed class SeedCommands : CommandRoot, IConsoleLogger
	{
		public override string Name => "Set Seed Command";

		public override string Description => "Commands for setting/getting the RNG seed for Cybergrind wave creation.";

		public Logger Log => new Logger(((CommandRoot)this).Name);

		private Node[] SetterNodes => (Node[])(object)new Node[3]
		{
			(Node)CommandRoot.Leaf<int>("set", (Action<int>)Set, false),
			(Node)CommandRoot.Leaf<string>("set-str", (Action<string>)SetStr, false),
			(Node)CommandRoot.Leaf("paste", (Action)Paste, false)
		};

		private Node[] GetterNodes => (Node[])(object)new Node[2]
		{
			(Node)CommandRoot.Leaf("get", (Action)Get, false),
			(Node)CommandRoot.Leaf("copy", (Action)Copy, false)
		};

		public SeedCommands(Console con)
			: base(con)
		{
		}

		protected override Branch BuildTree(Console con)
		{
			if (!(SceneHelper.CurrentScene != "Endless"))
			{
				return CommandRoot.Branch("cybergrind-seed", SetterNodes);
			}
			Node[] setterNodes = SetterNodes;
			Node[] getterNodes = GetterNodes;
			int num = 0;
			Node[] array = (Node[])(object)new Node[setterNodes.Length + getterNodes.Length];
			ReadOnlySpan<Node> readOnlySpan = new ReadOnlySpan<Node>(setterNodes);
			readOnlySpan.CopyTo(new Span<Node>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			ReadOnlySpan<Node> readOnlySpan2 = new ReadOnlySpan<Node>(getterNodes);
			readOnlySpan2.CopyTo(new Span<Node>(array).Slice(num, readOnlySpan2.Length));
			num += readOnlySpan2.Length;
			return CommandRoot.Branch("cybergrind-seed", array);
		}

		private static void Set(int seed)
		{
			Plugin.Configs.rngSeed.Value = seed;
		}

		private void SetStr(string seed)
		{
			Set(ParseSeed(seed, delegate(string s, int v)
			{
				Log.Info($"Parsed seed value: \"{s}\" -> {v}", (IEnumerable<Tag>)null, (string)null, (object)null);
			}, delegate(string s, int v)
			{
				Log.Info($"Hashed seed value: \"{s}\" -> {v}", (IEnumerable<Tag>)null, (string)null, (object)null);
			}));
		}

		private void Get()
		{
			Log.Info($"Current seed value: {RandomManager.RandomInstance.Seed}", (IEnumerable<Tag>)null, (string)null, (object)null);
		}

		private void Copy()
		{
			Log.Info($"Copied seed value to clipboard: ({RandomManager.RandomInstance.Seed})", (IEnumerable<Tag>)null, (string)null, (object)null);
			GUIUtility.systemCopyBuffer = RandomManager.RandomInstance.Seed.ToString(CultureInfo.CurrentCulture);
		}

		private void Paste()
		{
			SetStr(GUIUtility.systemCopyBuffer);
		}

		private static int ParseSeed(string seed, Action<string, int>? onParsed = null, Action<string, int>? onFailed = null)
		{
			if (int.TryParse(seed, NumberStyles.Number, CultureInfo.CurrentCulture, out var result))
			{
				onParsed?.Invoke(seed, result);
			}
			else
			{
				result = seed.GetHashCode();
				onFailed?.Invoke(seed, result);
			}
			return result;
		}
	}
}
namespace CyberSeedSetter.Cheats
{
	[HarmonyPatch(typeof(CheatsManager))]
	public static class CheatsManagerPatcher
	{
		[HarmonyTranspiler]
		[HarmonyPatch("Start")]
		private static IEnumerable<CodeInstruction> StartTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
			val.Start().MatchForward(true, (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"meta", (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(CheatsManager), "RegisterCheat", (Type[])null, (Type[])null), (string)null)
			}).Insert((CodeInstruction[])(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				CodeInstruction.Call((Expression<Action>)(() => RegisterCheats(null)))
			});
			return val.InstructionEnumeration();
		}

		private static void RegisterCheats(CheatsManager __instance)
		{
			if (!(SceneHelper.CurrentScene != "Endless"))
			{
				Plugin.Logger.LogInfo((object)"Registering SeedOverrideCheat");
				__instance.RegisterCheat((ICheat)(object)new SeedOverrideCheat(), "meta");
			}
		}
	}
	public sealed class SeedOverrideCheat : ICheat
	{
		public const string IDENTIFIER = "cyberseedsetter.seed-override";

		public string LongName => "Cybergrind Seed Override";

		public string Identifier => "cyberseedsetter.seed-override";

		public string ButtonEnabledOverride => null;

		public string ButtonDisabledOverride => null;

		public string Icon => "warning";

		public bool DefaultState => false;

		public StatePersistenceMode PersistenceMode => (StatePersistenceMode)1;

		public bool IsActive { get; private set; }

		public void Enable(CheatsManager manager)
		{
			IsActive = true;
			MonoSingleton<PrefsManager>.Instance.SetBool("cheat.ultrakill.keep-enabled", true);
			MonoSingleton<SubtitleController>.Instance.DisplaySubtitle("Restart the level with keep cheats enabled to apply the seed", (AudioSource)null, false);
		}

		public void Disable()
		{
			IsActive = false;
			MonoSingleton<SubtitleController>.Instance.DisplaySubtitle("Restart the level to play without the seed", (AudioSource)null, false);
		}
	}
}