Decompiled source of PaganFastCrafting v1.1.0

plugins/PaganFastCrafting.dll

Decompiled 4 hours ago
using 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();
		}
	}
}