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 PaganFastCrafting v1.1.0
plugins/PaganFastCrafting.dll
Decompiled 4 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("PaganFastCrafting")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PaganFastCrafting")] [assembly: AssemblyTitle("PaganFastCrafting")] [assembly: AssemblyVersion("1.0.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 PaganFastCrafting { [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] internal static class CraftingPatch { private enum StationSkill { Crafting, Blacksmithing, Cooking, Magic } private static readonly SkillType BlacksmithingSkill = (SkillType)Math.Abs(StableHash("Blacksmithing")); private static readonly FieldRef<InventoryGui, Recipe> CraftRecipeRef = AccessTools.FieldRefAccess<InventoryGui, Recipe>("m_craftRecipe"); private static readonly Dictionary<string, StationSkill> StationMap = new Dictionary<string, StationSkill> { { "piece_workbench", StationSkill.Crafting }, { "forge", StationSkill.Blacksmithing }, { "blackforge", StationSkill.Blacksmithing }, { "piece_stonecutter", StationSkill.Crafting }, { "piece_artisanstation", StationSkill.Crafting }, { "piece_cauldron", StationSkill.Cooking }, { "piece_magetable", StationSkill.Magic }, { "ForgeOfAgesDO", StationSkill.Blacksmithing }, { "HunterTableDO", StationSkill.Crafting }, { "MunitionsBenchDO", StationSkill.Crafting }, { "NavalWorkshopDO", StationSkill.Crafting }, { "MagicWeaverDO", StationSkill.Magic }, { "EssenceCauldronDO", StationSkill.Cooking } }; private static readonly HashSet<SkillType> ExcludedItemSkills = new HashSet<SkillType> { (SkillType)100, (SkillType)101, (SkillType)102, (SkillType)103, (SkillType)108, (SkillType)110, (SkillType)106, (SkillType)104, (SkillType)13, (SkillType)107, (SkillType)105, (SkillType)0, (SkillType)999 }; private static readonly HashSet<ItemType> CombatItemTypes = new HashSet<ItemType> { (ItemType)3, (ItemType)4, (ItemType)5, (ItemType)9, (ItemType)14, (ItemType)20, (ItemType)22 }; private const float VanillaBase = 2f; private static void Prefix(InventoryGui __instance, Player player) { if ((Object)(object)player == (Object)null) { return; } string value = Plugin.Mode.Value; if (!value.Equals("Off", StringComparison.OrdinalIgnoreCase)) { __instance.m_craftDurationSkillMaxDecrease = 0f; float num; if (value.Equals("Flat", StringComparison.OrdinalIgnoreCase)) { num = Plugin.FlatDuration.Value; } else { float speedSkillFactor = GetSpeedSkillFactor(__instance, player); num = Mathf.Lerp(2f, Plugin.SkillDurationAtMax.Value, speedSkillFactor); } __instance.m_craftDuration = num; __instance.m_multiCraftDuration = 6f * (num / 2f); } } private static float GetSpeedSkillFactor(InventoryGui gui, Player player) { Recipe recipe = CraftRecipeRef.Invoke(gui); float itemPoolFactor = GetItemPoolFactor(recipe, player); float stationSkillFactor = GetStationSkillFactor(recipe, player); return Mathf.Max(itemPoolFactor, stationSkillFactor); } private static float GetItemPoolFactor(Recipe? recipe, Player player) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) SharedData val = recipe?.m_item?.m_itemData?.m_shared; if (val == null) { return 0f; } float num = 0f; if (CombatItemTypes.Contains(val.m_itemType) && !ExcludedItemSkills.Contains(val.m_skillType)) { num = Mathf.Max(num, ((Character)player).GetSkillFactor(val.m_skillType)); } if (Plugin.BlacksmithingLoaded && IsBlacksmithingItem(val)) { num = Mathf.Max(num, ((Character)player).GetSkillFactor(BlacksmithingSkill)); } return num; } private static float GetStationSkillFactor(Recipe? recipe, Player player) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) CraftingStation val = recipe?.m_craftingStation; if ((Object)(object)val == (Object)null) { return ((Character)player).GetSkillFactor((SkillType)107); } string name = ((Object)((Component)val).gameObject).name; if (!StationMap.TryGetValue(name, out var value)) { value = StationSkill.Crafting; } if (value == StationSkill.Blacksmithing && !Plugin.BlacksmithingLoaded) { value = StationSkill.Crafting; } return value switch { StationSkill.Blacksmithing => ((Character)player).GetSkillFactor(BlacksmithingSkill), StationSkill.Cooking => ((Character)player).GetSkillFactor((SkillType)105), StationSkill.Magic => Mathf.Max(((Character)player).GetSkillFactor((SkillType)9), ((Character)player).GetSkillFactor((SkillType)10)), _ => ((Character)player).GetSkillFactor((SkillType)107), }; } private static bool IsBlacksmithingItem(SharedData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected I4, but got Unknown switch ((int)item.m_itemType) { case 4: case 5: case 6: case 7: case 11: case 12: case 14: case 17: case 22: return true; case 3: return !item.m_attack.m_consumeItem; default: return false; } } private static int StableHash(string str) { int num = 5381; int num2 = num; for (int i = 0; i < str.Length && str[i] != 0; i += 2) { num = ((num << 5) + num) ^ str[i]; if (i == str.Length - 1 || str[i + 1] == '\0') { break; } num2 = ((num2 << 5) + num2) ^ str[i + 1]; } return num + num2 * 1566083941; } } [BepInPlugin("pagan.fastcrafting", "PaganFastCrafting", "1.0.7")] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "pagan.fastcrafting"; public const string PluginName = "PaganFastCrafting"; public const string PluginVersion = "1.0.7"; private static readonly Dictionary<string, string> VersionHistory = new Dictionary<string, string> { { "1.0.0", "Initial build — flat and skill modes, station map, Blacksmithing soft dep" }, { "1.0.1", "Fixed enum arithmetic in IsBlacksmithingItem switch (CS0266)" }, { "1.0.2", "Fixed FieldAccessException: m_craftRecipe via AccessTools.FieldRefAccess; item skill pool with Max()" }, { "1.0.3", "Fixed station skill fallback: use recipe.m_craftingStation instead of GetCurrentCraftingStation()" }, { "1.0.4", "ItemType whitelist gates m_skillType pool; station always contributes via Max(); fixed IsBlacksmithingItem comments" }, { "1.0.5", "Fixed DO mod station prefab names; null station defaults to Crafting skill; added EssenceCauldronDO and NavalWorkshopDO" }, { "1.0.6", "EssenceCauldronDO corrected to Cooking skill (food/potions, not magic)" }, { "1.0.7", "Soft detect original FasterCrafting mod — warn and disable gracefully instead of hard incompatibility block" } }; internal static ConfigEntry<string> Mode = null; internal static ConfigEntry<float> FlatDuration = null; internal static ConfigEntry<float> SkillDurationAtMax = null; internal static bool BlacksmithingLoaded; private static readonly Harmony _harmony = new Harmony("pagan.fastcrafting"); private void Awake() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown Mode = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Mode", "Skill", new ConfigDescription("Controls crafting speed behavior.\n off = vanilla, this mod does nothing.\n flat = every craft takes FlatDuration seconds regardless of skill.\n skill = crafting speed scales with the relevant skill per station.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Off", "Flat", "Skill" }), Array.Empty<object>())); FlatDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Flat", "FlatDuration", 0.5f, new ConfigDescription("Duration in seconds for every craft when Mode = flat.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>())); SkillDurationAtMax = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillDurationAtMax", 0.85f, new ConfigDescription("Seconds a craft takes at skill 100. Skill 0 always uses the vanilla base of 2.0s.\n 0.85 = matches vanilla's own maximum skill bonus — safe starting point.\n Lower values = faster crafting at high skill. Minimum allowed: 0.1s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 0.85f), Array.Empty<object>())); if (Chainloader.PluginInfos.ContainsKey("1010101110.fastercrafting")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[PaganFastCrafting] Original FasterCrafting mod detected — PaganFastCrafting is disabled to avoid conflict. Remove FasterCrafting to use PaganFastCrafting."); return; } BlacksmithingLoaded = Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.blacksmithing"); if (BlacksmithingLoaded) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[PaganFastCrafting] Blacksmithing mod detected — forge-type stations use Blacksmithing skill."); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[PaganFastCrafting] Blacksmithing mod not detected — forge-type stations fall back to Crafting skill."); } _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[PaganFastCrafting] v1.0.7 loaded. Mode = " + Mode.Value)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[PaganFastCrafting] " + VersionHistory["1.0.7"])); } private void OnDestroy() { _harmony.UnpatchSelf(); } } }