Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FastTools v1.4.4
FastTools.dll
Decompiled 3 days agousing System; 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 ConditionalConfigSync; 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 © 2026 Crystal Ferrai")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f56f1a49-d0ab-40c0-a18f-7787796b5b83")] [assembly: AssemblyFileVersion("1.4.4.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.4.4.0")] namespace FastTools; [BepInPlugin("dev.crystal.fasttools", "Fast Tools", "1.4.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [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("GetBuildStamina")] [HarmonyPostfix] private static void GetBuildStamina_Postfix(Player __instance, ref float __result) { __result *= StaminaUseMultiplier.Value; } } [HarmonyPatch(typeof(Player))] private static class Player_Placement_Patches { private enum TranspilerState { Searching, Calculating, Searching2, Checking, Checking2, Checking3, Replacing } [HarmonyPatch("UpdatePlacement")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> UpdatePlacement_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { LocalBuilder stamina = generator.DeclareLocal(typeof(float)); stamina.SetLocalSymInfo("stamina"); yield return new CodeInstruction(OpCodes.Ldc_R4, (object)0f); yield return new CodeInstruction(OpCodes.Stloc, (object)stamina.LocalIndex); FieldInfo sharedField = typeof(ItemData).GetField("m_shared"); FieldInfo attackField = typeof(SharedData).GetField("m_attack"); FieldInfo attackStaminaField = typeof(Attack).GetField("m_attackStamina"); TranspilerState state = TranspilerState.Searching; CodeInstruction instruction1 = null; CodeInstruction instruction2 = null; CodeInstruction instruction3 = null; foreach (CodeInstruction instruction4 in instructions) { switch (state) { case TranspilerState.Searching: if (instruction4.opcode == OpCodes.Call && ((MethodInfo)instruction4.operand).Name.Equals("GetRightItem")) { state = TranspilerState.Calculating; } yield return instruction4; break; case TranspilerState.Calculating: yield return instruction4; yield return new CodeInstruction(OpCodes.Ldloc_0, (object)null); yield return new CodeInstruction(OpCodes.Ldfld, (object)sharedField); yield return new CodeInstruction(OpCodes.Ldfld, (object)attackField); yield return new CodeInstruction(OpCodes.Ldfld, (object)attackStaminaField); yield return new CodeInstruction(OpCodes.Ldc_R4, (object)StaminaUseMultiplier.Value); yield return new CodeInstruction(OpCodes.Mul, (object)null); yield return new CodeInstruction(OpCodes.Stloc, (object)stamina.LocalIndex); state = TranspilerState.Searching2; break; case TranspilerState.Searching2: if (instruction4.opcode == OpCodes.Ldloc_0) { instruction1 = instruction4; state = TranspilerState.Checking; } else { yield return instruction4; } break; case TranspilerState.Checking: if (instruction4.opcode == OpCodes.Ldfld && ((FieldInfo)instruction4.operand).Name == sharedField.Name) { instruction2 = instruction4; state = TranspilerState.Checking2; } else { yield return instruction1; yield return instruction4; state = TranspilerState.Searching2; } break; case TranspilerState.Checking2: if (instruction4.opcode == OpCodes.Ldfld && ((FieldInfo)instruction4.operand).Name == attackField.Name) { instruction3 = instruction4; state = TranspilerState.Checking3; break; } yield return instruction1; yield return instruction2; yield return instruction4; state = TranspilerState.Searching2; break; case TranspilerState.Checking3: if (instruction4.opcode == OpCodes.Ldfld && ((FieldInfo)instruction4.operand).Name == attackStaminaField.Name) { state = TranspilerState.Replacing; break; } yield return instruction1; yield return instruction2; yield return instruction3; yield return instruction4; state = TranspilerState.Searching2; break; case TranspilerState.Replacing: yield return new CodeInstruction(OpCodes.Ldloc, (object)stamina.LocalIndex); yield return instruction4; state = TranspilerState.Searching2; break; } } } } public const string ModId = "dev.crystal.fasttools"; public const string ModName = "Fast Tools"; public const string ModVersion = "1.4.4.0"; internal static readonly ConfigSync ConfigSync; 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() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown ConfigSync = new ConfigSync("dev.crystal.fasttools") { DisplayName = "Fast Tools", CurrentVersion = "1.4.4.0", MinimumRequiredVersion = "1.4.4.0", ModRequired = false, ModRequirementMode = (ModRequirementMode)1 }; sPlayers = new List<Player>(); } private void Awake() { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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. [The value may be enforced on a server via sync policy.]"); PlaceDelay.SettingChanged += Delay_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(PlaceDelay, (ConfigSyncMode)1, false); 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. [The value may be enforced on a server via sync policy.]"); RemoveDelay.SettingChanged += Delay_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(RemoveDelay, (ConfigSyncMode)1, false); 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. [The value will be enforced on a server.]"); StaminaUseMultiplier.SettingChanged += StaminaUseMultiplier_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(StaminaUseMultiplier, (ConfigSyncMode)0); 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)); } }