Decompiled source of FastTools v1.2.3

FastTools.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FastTools")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Crystal")]
[assembly: AssemblyProduct("FastTools")]
[assembly: AssemblyCopyright("Copyright © 2023 Crystal Ferrai")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f56f1a49-d0ab-40c0-a18f-7787796b5b83")]
[assembly: AssemblyFileVersion("1.2.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.2.3.0")]
namespace FastTools;

[BepInPlugin("dev.crystal.fasttools", "Fast Tools", "1.2.3.0")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class FastToolsPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Player))]
	private static class Player_Patches
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void Awake_Postfix(Player __instance)
		{
			__instance.m_placeDelay = PlaceDelay.Value;
			__instance.m_removeDelay = RemoveDelay.Value;
			sPlayers.Add(__instance);
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroy_Prefix(Player __instance)
		{
			sPlayers.Remove(__instance);
		}
	}

	[HarmonyPatch(typeof(Player))]
	private static class Player_Placement_Patches
	{
		private enum TranspilerState
		{
			Searching,
			Calculating,
			Searching2,
			Checking,
			Checking2,
			Checking3,
			Replacing
		}

		[CompilerGenerated]
		private sealed class <UpdatePlacement_Transpiler>d__1 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private ILGenerator generator;

			public ILGenerator <>3__generator;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private LocalBuilder <stamina>5__2;

			private FieldInfo <sharedField>5__3;

			private FieldInfo <attackField>5__4;

			private FieldInfo <attackStaminaField>5__5;

			private TranspilerState <state>5__6;

			private CodeInstruction <instruction1>5__7;

			private CodeInstruction <instruction2>5__8;

			private CodeInstruction <instruction3>5__9;

			private IEnumerator<CodeInstruction> <>7__wrap9;

			private CodeInstruction <instruction>5__11;

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

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

			[DebuggerHidden]
			public <UpdatePlacement_Transpiler>d__1(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 - 3) <= 20u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<stamina>5__2 = null;
				<sharedField>5__3 = null;
				<attackField>5__4 = null;
				<attackStaminaField>5__5 = null;
				<instruction1>5__7 = null;
				<instruction2>5__8 = null;
				<instruction3>5__9 = null;
				<>7__wrap9 = null;
				<instruction>5__11 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: Expected O, but got Unknown
				//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Expected O, but got Unknown
				//IL_0260: Unknown result type (might be due to invalid IL or missing references)
				//IL_026a: Expected O, but got Unknown
				//IL_028c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0296: Expected O, but got Unknown
				//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c2: Expected O, but got Unknown
				//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ee: Expected O, but got Unknown
				//IL_0319: Unknown result type (might be due to invalid IL or missing references)
				//IL_0323: Expected O, but got Unknown
				//IL_0341: Unknown result type (might be due to invalid IL or missing references)
				//IL_034b: Expected O, but got Unknown
				//IL_0378: Unknown result type (might be due to invalid IL or missing references)
				//IL_0382: Expected O, but got Unknown
				//IL_0664: Unknown result type (might be due to invalid IL or missing references)
				//IL_066e: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<stamina>5__2 = generator.DeclareLocal(typeof(float));
						<stamina>5__2.SetLocalSymInfo("stamina");
						<>2__current = new CodeInstruction(OpCodes.Ldc_R4, (object)0f);
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -1;
						<>2__current = new CodeInstruction(OpCodes.Stloc, (object)<stamina>5__2.LocalIndex);
						<>1__state = 2;
						return true;
					case 2:
						<>1__state = -1;
						<sharedField>5__3 = typeof(ItemData).GetField("m_shared");
						<attackField>5__4 = typeof(SharedData).GetField("m_attack");
						<attackStaminaField>5__5 = typeof(Attack).GetField("m_attackStamina");
						<state>5__6 = TranspilerState.Searching;
						<instruction1>5__7 = null;
						<instruction2>5__8 = null;
						<instruction3>5__9 = null;
						<>7__wrap9 = instructions.GetEnumerator();
						<>1__state = -3;
						goto IL_06b0;
					case 3:
						<>1__state = -3;
						goto IL_06a9;
					case 4:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Ldloc_0, (object)null);
						<>1__state = 5;
						return true;
					case 5:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Ldfld, (object)<sharedField>5__3);
						<>1__state = 6;
						return true;
					case 6:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Ldfld, (object)<attackField>5__4);
						<>1__state = 7;
						return true;
					case 7:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Ldfld, (object)<attackStaminaField>5__5);
						<>1__state = 8;
						return true;
					case 8:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Ldc_R4, (object)StaminaUseMultiplier.Value);
						<>1__state = 9;
						return true;
					case 9:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Mul, (object)null);
						<>1__state = 10;
						return true;
					case 10:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Stloc, (object)<stamina>5__2.LocalIndex);
						<>1__state = 11;
						return true;
					case 11:
						<>1__state = -3;
						<state>5__6 = TranspilerState.Searching2;
						goto IL_06a9;
					case 12:
						<>1__state = -3;
						goto IL_06a9;
					case 13:
						<>1__state = -3;
						<>2__current = <instruction>5__11;
						<>1__state = 14;
						return true;
					case 14:
						<>1__state = -3;
						<state>5__6 = TranspilerState.Searching2;
						goto IL_06a9;
					case 15:
						<>1__state = -3;
						<>2__current = <instruction2>5__8;
						<>1__state = 16;
						return true;
					case 16:
						<>1__state = -3;
						<>2__current = <instruction>5__11;
						<>1__state = 17;
						return true;
					case 17:
						<>1__state = -3;
						<state>5__6 = TranspilerState.Searching2;
						goto IL_06a9;
					case 18:
						<>1__state = -3;
						<>2__current = <instruction2>5__8;
						<>1__state = 19;
						return true;
					case 19:
						<>1__state = -3;
						<>2__current = <instruction3>5__9;
						<>1__state = 20;
						return true;
					case 20:
						<>1__state = -3;
						<>2__current = <instruction>5__11;
						<>1__state = 21;
						return true;
					case 21:
						<>1__state = -3;
						<state>5__6 = TranspilerState.Searching2;
						goto IL_06a9;
					case 22:
						<>1__state = -3;
						<>2__current = <instruction>5__11;
						<>1__state = 23;
						return true;
					case 23:
						{
							<>1__state = -3;
							<state>5__6 = TranspilerState.Searching2;
							goto IL_06a9;
						}
						IL_06b0:
						if (<>7__wrap9.MoveNext())
						{
							<instruction>5__11 = <>7__wrap9.Current;
							switch (<state>5__6)
							{
							case TranspilerState.Searching:
								if (<instruction>5__11.opcode == OpCodes.Call && ((MethodInfo)<instruction>5__11.operand).Name.Equals("GetRightItem"))
								{
									<state>5__6 = TranspilerState.Calculating;
								}
								<>2__current = <instruction>5__11;
								<>1__state = 3;
								return true;
							case TranspilerState.Calculating:
								<>2__current = <instruction>5__11;
								<>1__state = 4;
								return true;
							case TranspilerState.Searching2:
								if (<instruction>5__11.opcode == OpCodes.Ldloc_0)
								{
									<instruction1>5__7 = <instruction>5__11;
									<state>5__6 = TranspilerState.Checking;
									break;
								}
								<>2__current = <instruction>5__11;
								<>1__state = 12;
								return true;
							case TranspilerState.Checking:
								if (<instruction>5__11.opcode == OpCodes.Ldfld && ((FieldInfo)<instruction>5__11.operand).Name == <sharedField>5__3.Name)
								{
									<instruction2>5__8 = <instruction>5__11;
									<state>5__6 = TranspilerState.Checking2;
									break;
								}
								<>2__current = <instruction1>5__7;
								<>1__state = 13;
								return true;
							case TranspilerState.Checking2:
								if (<instruction>5__11.opcode == OpCodes.Ldfld && ((FieldInfo)<instruction>5__11.operand).Name == <attackField>5__4.Name)
								{
									<instruction3>5__9 = <instruction>5__11;
									<state>5__6 = TranspilerState.Checking3;
									break;
								}
								<>2__current = <instruction1>5__7;
								<>1__state = 15;
								return true;
							case TranspilerState.Checking3:
								if (<instruction>5__11.opcode == OpCodes.Ldfld && ((FieldInfo)<instruction>5__11.operand).Name == <attackStaminaField>5__5.Name)
								{
									<state>5__6 = TranspilerState.Replacing;
									break;
								}
								<>2__current = <instruction1>5__7;
								<>1__state = 18;
								return true;
							case TranspilerState.Replacing:
								<>2__current = new CodeInstruction(OpCodes.Ldloc, (object)<stamina>5__2.LocalIndex);
								<>1__state = 22;
								return true;
							}
							goto IL_06a9;
						}
						<>m__Finally1();
						<>7__wrap9 = null;
						return false;
						IL_06a9:
						<instruction>5__11 = null;
						goto IL_06b0;
					}
				}
				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__wrap9 != null)
				{
					<>7__wrap9.Dispose();
				}
			}

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

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

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

		[IteratorStateMachine(typeof(<UpdatePlacement_Transpiler>d__1))]
		[HarmonyPatch("UpdatePlacement")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> UpdatePlacement_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <UpdatePlacement_Transpiler>d__1(-2)
			{
				<>3__instructions = instructions,
				<>3__generator = generator
			};
		}
	}

	public const string ModId = "dev.crystal.fasttools";

	public static ConfigEntry<float> PlaceDelay;

	public static ConfigEntry<float> RemoveDelay;

	public static ConfigEntry<float> StaminaUseMultiplier;

	private static Harmony sPlayerHarmony;

	private static Harmony sPlayerPlacementHarmony;

	private static readonly List<Player> sPlayers;

	static FastToolsPlugin()
	{
		sPlayers = new List<Player>();
	}

	private void Awake()
	{
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Expected O, but got Unknown
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		PlaceDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Tools", "PlaceDelay", 0.25f, "The delay time for placing items, in seconds. Allowed range 0-10. Game default is 0.4.");
		PlaceDelay.SettingChanged += Delay_SettingChanged;
		RemoveDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Tools", "RemoveDelay", 0.15f, "The delay time for removing items, in seconds. Allowed range 0-10. Game default is 0.25.");
		RemoveDelay.SettingChanged += Delay_SettingChanged;
		StaminaUseMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Tools", "StaminaUseMultiplier", 1f, "Multiplier to apply to the stamina cost of using a placement tool (hammer, hoe, cultivator). Game default is 1.0.");
		StaminaUseMultiplier.SettingChanged += StaminaUseMultiplier_SettingChanged;
		ClampConfig();
		sPlayerHarmony = new Harmony("dev.crystal.fasttools_Player");
		sPlayerPlacementHarmony = new Harmony("dev.crystal.fasttools_Player_Placement");
		sPlayerHarmony.PatchAll(typeof(Player_Patches));
		sPlayerPlacementHarmony.PatchAll(typeof(Player_Placement_Patches));
	}

	private void OnDestroy()
	{
		sPlayerHarmony.UnpatchSelf();
		sPlayerPlacementHarmony.UnpatchSelf();
		sPlayers.Clear();
	}

	private static void ClampConfig()
	{
		if (PlaceDelay.Value < 0f)
		{
			PlaceDelay.Value = 0f;
		}
		if (PlaceDelay.Value > 10f)
		{
			PlaceDelay.Value = 10f;
		}
		if (RemoveDelay.Value < 0f)
		{
			RemoveDelay.Value = 0f;
		}
		if (RemoveDelay.Value > 10f)
		{
			RemoveDelay.Value = 10f;
		}
		if (StaminaUseMultiplier.Value < 0f)
		{
			StaminaUseMultiplier.Value = 0f;
		}
		if (StaminaUseMultiplier.Value > 10f)
		{
			StaminaUseMultiplier.Value = 10f;
		}
	}

	private void Delay_SettingChanged(object sender, EventArgs e)
	{
		ClampConfig();
		foreach (Player sPlayer in sPlayers)
		{
			sPlayer.m_placeDelay = PlaceDelay.Value;
			sPlayer.m_removeDelay = RemoveDelay.Value;
		}
	}

	private void StaminaUseMultiplier_SettingChanged(object sender, EventArgs e)
	{
		sPlayerPlacementHarmony.UnpatchSelf();
		sPlayerPlacementHarmony.PatchAll(typeof(Player_Placement_Patches));
	}
}