Decompiled source of Faster Everything v0.1.1

plugins/FasterEverything/FasterEverything.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.EntityLogic;
using UnityEngine;
using UnityEngine.Networking;

[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("FasterEverything")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("FasterEverything")]
[assembly: AssemblyTitle("FasterEverything")]
[assembly: AssemblyVersion("0.1.1.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 FasterEverything
{
	[BepInPlugin("local.ror2.fastereverything", "Faster Everything", "0.1.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "local.ror2.fastereverything";

		private static Plugin instance;

		private Harmony harmony;

		private ConfigEntry<float> maxDelay;

		private readonly Dictionary<string, ConfigEntry<bool>> features = new Dictionary<string, ConfigEntry<bool>>();

		private static readonly Dictionary<FieldInfo, string> timingFields = new Dictionary<FieldInfo, string>();

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			instance = this;
			maxDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "Maximum delay", 0.1f, new ConfigDescription("Maximum cosmetic interaction delay in seconds. Costs and reward counts remain vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 5f), Array.Empty<object>()));
			string[] array = new string[8] { "Printers", "Scrappers", "Chance shrines", "Blood shrines", "Healing shrines", "Cauldrons", "Cleansing pools", "Chests" };
			foreach (string text in array)
			{
				features[text] = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", text, true, "Shorten this interaction's waiting period.");
			}
			harmony = new Harmony("local.ror2.fastereverything");
			AddState("EntityStates.Duplicator.Duplicating", "Printers", "initialDelayDuration", "timeBetweenStartAndDropDroplet");
			AddState("EntityStates.Scrapper.WaitToBeginScrapping", "Scrappers", "duration");
			AddState("EntityStates.Scrapper.Scrapping", "Scrappers", "duration");
			AddState("EntityStates.Scrapper.ScrappingToIdle", "Scrappers", "duration");
			AddState("EntityStates.DroneScrapper.WaitToBeginScrappingDrone", "Scrappers", "duration");
			AddState("EntityStates.DroneScrapper.DroneScrapping", "Scrappers", "duration");
			AddState("EntityStates.DroneScrapper.DroneScrappingToIdle", "Scrappers", "duration");
			AddState("EntityStates.Barrel.Opening", "Chests", "duration");
			AddState("EntityStates.HallowedCauldron.DrainingItems", "Cauldrons", "delayAfterDoneDrainingHexes");
			Type[] array2 = new Type[3]
			{
				typeof(ShrineChanceBehavior),
				typeof(ShrineBloodBehavior),
				typeof(ShrineHealingBehavior)
			};
			foreach (Type type in array2)
			{
				Patch(AccessTools.Method(type, "FixedUpdate", (Type[])null, (Type[])null), "ShrineTick");
			}
			Patch(AccessTools.Method(typeof(DelayedEvent), "CallDelayed", (Type[])null, (Type[])null), "Delayed");
			Patch(AccessTools.Method(typeof(ChestBehavior), "ItemDrop", (Type[])null, (Type[])null), "ChestDrop", null, "RestoreChestVelocity");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Faster Everything loaded. Purchase availability and reward delivery remain controlled by the game.");
		}

		private void AddState(string typeName, string category, params string[] fields)
		{
			Type type = typeof(CharacterBody).Assembly.GetType(typeName);
			if (type == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Optional state absent: " + typeName));
				return;
			}
			string[] array = fields;
			foreach (string text in array)
			{
				FieldInfo fieldInfo = AccessTools.Field(type, text);
				if (fieldInfo?.FieldType == typeof(float) && fieldInfo.IsStatic)
				{
					timingFields[fieldInfo] = category;
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Timing field absent: " + typeName + "." + text));
				}
			}
			array = new string[2] { "OnEnter", "FixedUpdate" };
			foreach (string name in array)
			{
				MethodInfo method = type.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					Patch(method, null, "Timing");
				}
			}
		}

		private void Patch(MethodInfo method, string prefix = null, string transpiler = null, string postfix = null)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (method == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Patch target missing.");
				return;
			}
			try
			{
				harmony.Patch((MethodBase)method, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), postfix, (Type[])null), (transpiler == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), transpiler, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Installed: " + method.DeclaringType.FullName + "." + method.Name));
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Could not patch {method}: {arg}");
			}
		}

		public static float Shorten(float original, string category)
		{
			if (!instance.features.TryGetValue(category, out var value) || !value.Value || !(original > 0f))
			{
				return original;
			}
			return Mathf.Min(original, instance.maxDelay.Value);
		}

		private static IEnumerable<CodeInstruction> Timing(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (instruction.opcode == OpCodes.Ldsfld && instruction.operand is FieldInfo key && timingFields.TryGetValue(key, out var value))
				{
					yield return new CodeInstruction(OpCodes.Ldstr, (object)value);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Plugin), "Shorten", (Type[])null, (Type[])null));
				}
			}
		}

		private static void ShrineTick(object __instance, ref float ___refreshTimer)
		{
			if (NetworkServer.active)
			{
				string category = ((__instance is ShrineChanceBehavior) ? "Chance shrines" : ((__instance is ShrineBloodBehavior) ? "Blood shrines" : "Healing shrines"));
				___refreshTimer = Shorten(___refreshTimer, category);
			}
		}

		private static void Delayed(DelayedEvent __instance, ref float timer)
		{
			PurchaseInteraction componentInParent = ((Component)__instance).GetComponentInParent<PurchaseInteraction>();
			if (Object.op_Implicit((Object)(object)componentInParent))
			{
				string name = ((Object)((Component)componentInParent).gameObject).name;
				if (name.StartsWith("LunarCauldron", StringComparison.OrdinalIgnoreCase))
				{
					timer = Shorten(timer, "Cauldrons");
				}
				else if (name.StartsWith("ShrineCleanse", StringComparison.OrdinalIgnoreCase))
				{
					timer = Shorten(timer, "Cleansing pools");
				}
			}
		}

		private static void ChestDrop(ChestBehavior __instance, out Vector2 __state)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			__state = new Vector2(__instance.dropUpVelocityStrength, __instance.dropForwardVelocityStrength);
			if (NetworkServer.active && instance.features["Chests"].Value)
			{
				__instance.dropUpVelocityStrength = 0f;
				__instance.dropForwardVelocityStrength = 0f;
			}
		}

		private static void RestoreChestVelocity(ChestBehavior __instance, Vector2 __state)
		{
			//IL_0001: 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)
			__instance.dropUpVelocityStrength = __state.x;
			__instance.dropForwardVelocityStrength = __state.y;
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}
	}
}