using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [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("FletchersForge")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Disassemble arrows into shafts and heads; reforge in the field with the Fletcher's knife.")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("FletchersForge")] [assembly: AssemblyTitle("FletchersForge")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [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 FletchersForge { internal static class ArrowAssemblyRegistry { internal sealed class ArrowPair { public string ShaftPrefab; public string HeadPrefab; public string ArrowPrefab; } private static readonly Dictionary ArrowToParts = new Dictionary(); private static readonly Dictionary ShaftHeadToArrow = new Dictionary(); internal static void Initialize() { Register("ArrowWood", "FF_ShaftStandard", null, "ArrowWood"); Register("ArrowFire", "FF_ShaftStandard", "FF_HeadFire", "ArrowFire"); Register("ArrowFlint", "FF_ShaftStandard", "FF_HeadFlint", "ArrowFlint"); Register("ArrowBronze", "FF_ShaftStandard", "FF_HeadBronze", "ArrowBronze"); Register("ArrowIron", "FF_ShaftStandard", "FF_HeadIron", "ArrowIron"); Register("ArrowSilver", "FF_ShaftStandard", "FF_HeadSilver", "ArrowSilver"); Register("ArrowObsidian", "FF_ShaftStandard", "FF_HeadObsidian", "ArrowObsidian"); Register("ArrowPoison", "FF_ShaftStandard", "FF_HeadPoison", "ArrowPoison"); Register("ArrowFrost", "FF_ShaftStandard", "FF_HeadFrost", "ArrowFrost"); Register("ArrowNeedle", "FF_ShaftNeedle", "FF_HeadNeedle", "ArrowNeedle"); Register("ArrowCarapace", "FF_ShaftStandard", "FF_HeadCarapace", "ArrowCarapace"); Register("ArrowCharred", "FF_ShaftAsh", "FF_HeadCharred", "ArrowCharred"); } private static void Register(string arrow, string shaft, string head, string arrowPrefab) { ArrowToParts[arrow] = new ArrowPair { ShaftPrefab = shaft, HeadPrefab = head, ArrowPrefab = arrowPrefab }; ShaftHeadToArrow[Key(shaft, head)] = arrowPrefab; } internal static bool TryGetParts(string arrowPrefabName, out string shaftPrefab, out string headPrefab) { shaftPrefab = null; headPrefab = null; if (!ArrowToParts.TryGetValue(arrowPrefabName, out var value)) { return false; } shaftPrefab = value.ShaftPrefab; headPrefab = value.HeadPrefab; return true; } internal static bool TryGetArrow(string shaftPrefab, string headPrefab, out string arrowPrefab) { if (ShaftHeadToArrow.TryGetValue(Key(shaftPrefab, headPrefab), out arrowPrefab)) { return true; } arrowPrefab = null; return false; } internal static bool IsArrowPrefab(string prefabName) { return ArrowToParts.ContainsKey(prefabName); } internal static bool IsShaftPrefab(string prefabName) { if (!(prefabName == "FF_ShaftStandard") && !(prefabName == "FF_ShaftNeedle")) { return prefabName == "FF_ShaftAsh"; } return true; } internal static bool IsHeadPrefab(string prefabName) { return prefabName.StartsWith("FF_Head", StringComparison.Ordinal); } internal static bool IsKnifePrefab(string prefabName) { return prefabName == "FF_FletchersKnife"; } private static string Key(string shaft, string head) { return shaft + "|" + (head ?? string.Empty); } } internal static class ChestSnapHarmony { internal static void Apply(Harmony harmony) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown Type type = AccessTools.TypeByName("ChestSnap.Helpers.SnappointHelper"); if (type == null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)"ChestSnap compat: SnappointHelper type not found."); } return; } int num = 0; MethodInfo methodInfo = AccessTools.Method(type, "RecreateSnappoints", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ChestSnapCompatPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogInfo((object)"ChestSnap compat: patched RecreateSnappoints."); } } MethodInfo methodInfo2 = AccessTools.Method(type, "RecreateSnappointsRoutine", (Type[])null, (Type[])null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(ChestSnapCompatPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; ManualLogSource log3 = FletchersForgePlugin.Log; if (log3 != null) { log3.LogInfo((object)"ChestSnap compat: patched RecreateSnappointsRoutine."); } } Type type2 = type.GetNestedTypes(BindingFlags.NonPublic).FirstOrDefault((Type t) => t.Name == "<>c"); if (type2 != null) { MethodInfo methodInfo3 = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "b__2_9"); if (methodInfo3 != null) { harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(ChestSnapNullViewPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; ManualLogSource log4 = FletchersForgePlugin.Log; if (log4 != null) { log4.LogInfo((object)"ChestSnap compat: patched null-view lambda."); } } MethodInfo methodInfo4 = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "b__2_8"); if (methodInfo4 != null) { harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(ChestSnapNullArrayPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; ManualLogSource log5 = FletchersForgePlugin.Log; if (log5 != null) { log5.LogInfo((object)"ChestSnap compat: patched GameObject[] lambda."); } } } Type type3 = type.GetNestedTypes(BindingFlags.NonPublic).FirstOrDefault((Type t) => t.Name.StartsWith("d", StringComparison.Ordinal)); if (type3 != null) { MethodInfo methodInfo5 = AccessTools.Method(type3, "MoveNext", (Type[])null, (Type[])null); if (methodInfo5 != null) { harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ChestSnapMoveNextFinalizerPatch), "Finalizer", (Type[])null), (HarmonyMethod)null); num++; ManualLogSource log6 = FletchersForgePlugin.Log; if (log6 != null) { log6.LogInfo((object)"ChestSnap compat: patched MoveNext finalizer."); } } } ManualLogSource log7 = FletchersForgePlugin.Log; if (log7 != null) { log7.LogInfo((object)$"ChestSnap compat: {num} patch(es) applied."); } } } internal static class ComponentDropVisualUtility { private static GameObject GetBoxPrefab() { GameObject prefab = PrefabManager.Instance.GetPrefab("CargoCrate"); if ((Object)(object)prefab != (Object)null) { return prefab; } string[] headDropBoxPrefabFallbacks = ModConstants.HeadDropBoxPrefabFallbacks; foreach (string text in headDropBoxPrefabFallbacks) { prefab = PrefabManager.Instance.GetPrefab(text); if ((Object)(object)prefab != (Object)null) { return prefab; } } return null; } internal static void ApplyHeadDropVisual(CustomItem item, string sourceArrow) { if (!((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null)) { ApplyShipwreckBoxVisual(((Component)item.ItemDrop).gameObject); } } internal static void ApplyShaftDropVisual(CustomItem item, string sourceArrow, bool ashTint = false) { if (!((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null)) { ApplyArrowPartDropVisual(((Component)item.ItemDrop).gameObject, sourceArrow, isHead: false, ashTint); } } private static void ApplyShipwreckBoxVisual(GameObject dropPrefab) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) GameObject boxPrefab = GetBoxPrefab(); if ((Object)(object)boxPrefab == (Object)null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)"No box prefab found for head drop visual; keeping iron scrap mesh."); } return; } RemoveDropVisual(dropPrefab); GameObject val = new GameObject("FF_DropVisual"); val.transform.SetParent(dropPrefab.transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one * 0.25f; if (!CopyMeshHierarchyFromRoot(boxPrefab.transform, val.transform)) { Object.Destroy((Object)(object)val); EnableVanillaDropRenderers(dropPrefab); ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogWarning((object)("No box mesh copied for " + ((Object)dropPrefab).name + "; keeping iron scrap mesh.")); } return; } AlignDropVisualToGround(val.transform); DisableVanillaDropRenderers(dropPrefab); EnsureDropPhysics(dropPrefab); ManualLogSource log3 = FletchersForgePlugin.Log; if (log3 != null) { log3.LogInfo((object)$"Applied box drop visual ({0.25f:P0}) for {((Object)dropPrefab).name} from '{((Object)boxPrefab).name}'."); } } private static void ApplyArrowPartDropVisual(GameObject dropPrefab, string sourceArrow, bool isHead, bool ashTint = false) { GameObject val = (isHead ? IconRigUtility.BuildHeadIconRig(sourceArrow, 1f) : IconRigUtility.BuildShaftIconRig(sourceArrow, ashTint)); if ((Object)(object)val == (Object)null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)("Could not build drop visual for " + ((Object)dropPrefab).name + " from " + sourceArrow + ".")); } EnableVanillaDropRenderers(dropPrefab); return; } bool num = TryCopyMeshVisual(dropPrefab, val, isHead); Object.Destroy((Object)(object)val); if (!num) { EnableVanillaDropRenderers(dropPrefab); ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogWarning((object)("No mesh copied for drop visual on " + ((Object)dropPrefab).name + ".")); } return; } DisableVanillaDropRenderers(dropPrefab); EnsureDropPhysics(dropPrefab); ManualLogSource log3 = FletchersForgePlugin.Log; if (log3 != null) { log3.LogInfo((object)("Applied drop visual for " + ((Object)dropPrefab).name + ".")); } } private static void RemoveDropVisual(GameObject dropPrefab) { Transform val = dropPrefab.transform.Find("FF_DropVisual"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } private static bool TryCopyMeshVisual(GameObject dropPrefab, GameObject rig, bool isHead) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) RemoveDropVisual(dropPrefab); GameObject val = new GameObject("FF_DropVisual"); val.transform.SetParent(dropPrefab.transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.Euler(0f, 0f, 90f); val.transform.localScale = Vector3.one * (isHead ? 0.28f : 0.22f); bool flag = false; Renderer[] componentsInChildren = rig.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && CopyRendererMesh(val2, val.transform)) { flag = true; } } if (!flag) { Object.Destroy((Object)(object)val); } return flag; } private static bool CopyMeshHierarchyFromRoot(Transform sourceRoot, Transform destRoot) { bool result = false; Renderer[] componentsInChildren = ((Component)sourceRoot).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && CopyRendererMeshRelative(val, sourceRoot, destRoot)) { result = true; } } return result; } private static bool CopyRendererMeshRelative(Renderer source, Transform sourceRoot, Transform destRoot) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) Mesh val = null; if (source is MeshRenderer) { MeshFilter component = ((Component)source).GetComponent(); if ((Object)(object)component != (Object)null) { val = component.sharedMesh; } } else { SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null); if (val2 != null) { val = val2.sharedMesh; } } if ((Object)(object)val == (Object)null) { return false; } GameObject val3 = new GameObject(((Object)source).name); val3.transform.SetParent(destRoot, false); val3.transform.localPosition = sourceRoot.InverseTransformPoint(((Component)source).transform.position); val3.transform.localRotation = Quaternion.Inverse(sourceRoot.rotation) * ((Component)source).transform.rotation; Vector3 lossyScale = ((Component)source).transform.lossyScale; Vector3 lossyScale2 = sourceRoot.lossyScale; val3.transform.localScale = new Vector3(SafeDivide(lossyScale.x, lossyScale2.x), SafeDivide(lossyScale.y, lossyScale2.y), SafeDivide(lossyScale.z, lossyScale2.z)); val3.AddComponent().sharedMesh = val; ((Renderer)val3.AddComponent()).sharedMaterials = source.sharedMaterials; return true; } private static bool CopyRendererMesh(Renderer source, Transform parent) { //IL_0045: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) Mesh val = null; if (source is MeshRenderer) { MeshFilter component = ((Component)source).GetComponent(); if ((Object)(object)component != (Object)null) { val = component.sharedMesh; } } else { SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null); if (val2 != null) { val = val2.sharedMesh; } } if ((Object)(object)val == (Object)null) { return false; } GameObject val3 = new GameObject(((Object)source).name); val3.transform.SetParent(parent, false); val3.transform.localPosition = ((Component)source).transform.localPosition; val3.transform.localRotation = ((Component)source).transform.localRotation; val3.transform.localScale = ((Component)source).transform.localScale; val3.AddComponent().sharedMesh = val; ((Renderer)val3.AddComponent()).sharedMaterials = source.sharedMaterials; return true; } private static void DisableVanillaDropRenderers(GameObject dropPrefab) { Transform val = dropPrefab.transform.Find("FF_DropVisual"); Renderer[] componentsInChildren = dropPrefab.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val)) { val2.enabled = false; } } } private static void EnableVanillaDropRenderers(GameObject dropPrefab) { Transform val = dropPrefab.transform.Find("FF_DropVisual"); Renderer[] componentsInChildren = dropPrefab.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val)) { val2.enabled = true; } } } private static void EnsureDropPhysics(GameObject dropPrefab) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) Collider[] componentsInChildren = dropPrefab.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null) { val.enabled = true; } } Rigidbody component = dropPrefab.GetComponent(); if ((Object)(object)component != (Object)null) { component.isKinematic = false; component.useGravity = true; } if ((Object)(object)dropPrefab.GetComponent() == (Object)null) { SphereCollider obj = dropPrefab.AddComponent(); obj.radius = 0.045f; obj.center = Vector3.zero; } } private static void AlignDropVisualToGround(Transform visualRoot) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; Renderer[] componentsInChildren = ((Component)visualRoot).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { MeshFilter component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null)) { Bounds bounds = component.sharedMesh.bounds; Vector3 val2 = Vector3.Scale(((Bounds)(ref bounds)).extents, ((Component)val).transform.localScale); float num2 = (((Component)val).transform.localPosition + Vector3.Scale(((Bounds)(ref bounds)).center, ((Component)val).transform.localScale)).y - val2.y; num = Mathf.Min(num, num2); } } if (num < float.MaxValue && !Mathf.Approximately(num, 0f)) { visualRoot.localPosition = new Vector3(0f, 0f - num, 0f); } } private static float SafeDivide(float value, float divisor) { if (!Mathf.Approximately(divisor, 0f)) { return value / divisor; } return value; } } internal static class FletchBenchButtonUi { private const string TakeAllLabelKey = "$inventory_takeall"; private const string StackAllLabelKey = "$inventory_stackall"; internal static void Update(InventoryGui gui, bool benchOpen) { if ((Object)(object)gui == (Object)null) { return; } bool flag = !benchOpen && gui.IsContainerOpen(); bool flag2 = benchOpen && InventoryGui.IsVisible(); if ((Object)(object)gui.m_takeAllButton != (Object)null) { ((Component)gui.m_takeAllButton).gameObject.SetActive(flag || flag2); if (flag2) { SetButtonLabel(gui.m_takeAllButton, GetReforgeLabel()); } else if (flag) { RestoreVanillaLabel(gui.m_takeAllButton, "$inventory_takeall", "Take all"); } } if ((Object)(object)gui.m_stackAllButton != (Object)null) { ((Component)gui.m_stackAllButton).gameObject.SetActive(flag || flag2); if (flag2) { SetButtonLabel(gui.m_stackAllButton, GetSplitLabel()); } else if (flag) { RestoreVanillaLabel(gui.m_stackAllButton, "$inventory_stackall", "Place stacks"); } } } private static string GetReforgeLabel() { string text = Localization.instance.Localize("$FF_Reforge"); if (!string.IsNullOrEmpty(text) && !text.StartsWith("$", StringComparison.Ordinal)) { return text; } return "Reforge"; } private static string GetSplitLabel() { string text = Localization.instance.Localize("$FF_Split"); if (!string.IsNullOrEmpty(text) && !text.StartsWith("$", StringComparison.Ordinal)) { return text; } return "Split"; } private static void RestoreVanillaLabel(Button button, string locKey, string fallback) { string text = Localization.instance.Localize(locKey); if (string.IsNullOrEmpty(text) || text.StartsWith("$", StringComparison.Ordinal)) { text = fallback; } SetButtonLabel(button, text); } private static void SetButtonLabel(Button button, string label) { TMP_Text componentInChildren = ((Component)button).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = label; } } } internal static class FletchBenchInventory { private static Inventory inventory; internal static Inventory Inventory => inventory; internal static void Initialize() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (inventory == null) { Sprite val = null; GameObject prefab = PrefabManager.Instance.GetPrefab("chest"); Container val2 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent() : null); if ((Object)(object)val2 != (Object)null) { val = val2.m_bkg; } inventory = new Inventory("$FF_FletchContainer", val, 2, 1); ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)"Initialized virtual Fletcher bench inventory."); } } } internal static void ClearSlots() { if (inventory != null) { inventory.RemoveAll(); } } } [BepInPlugin("hardwire99.fletchersforge", "Fletchers Forge", "0.1.30")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class FletchersForgePlugin : BaseUnityPlugin { internal static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); if (!ModConfig.Enabled.Value) { Log.LogInfo((object)"Fletchers Forge is disabled in config."); return; } harmony = new Harmony("hardwire99.fletchersforge"); harmony.PatchAll(typeof(FletchersForgePlugin).Assembly); ChestSnapHarmony.Apply(harmony); LocalizationRegistrar.Initialize(); ((Component)this).gameObject.AddComponent(); PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; ItemManager.OnItemsRegisteredFejd += OnItemsRegisteredFejd; ItemManager.OnItemsRegistered += OnItemsRegisteredWorld; Log.LogInfo((object)"Fletchers Forge 0.1.30 loaded."); Log.LogInfo((object)$"Legacy bench prefab hash: {ModConstants.LegacyContainerPrefabHash}"); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; ItemManager.OnItemsRegisteredFejd -= OnItemsRegisteredFejd; ItemManager.OnItemsRegistered -= OnItemsRegisteredWorld; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private static void OnVanillaPrefabsAvailable() { ItemRegistrar.RegisterAll(); RecipeRegistrar.RegisterAll(); PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; } private static void OnItemsRegisteredFejd() { ItemRegistrar.ApplyDeferredIcons(); } private static void OnItemsRegisteredWorld() { ItemRegistrar.ApplyDeferredIcons(); } } internal static class FletchersKnifeConfigurator { internal static void Configure(SharedData shared) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) shared.m_itemType = (ItemType)19; shared.m_toolTier = 0; shared.m_weight = 0.25f; shared.m_teleportable = true; shared.m_maxStackSize = 1; shared.m_maxQuality = 1; shared.m_value = 0; shared.m_useDurability = true; shared.m_maxDurability = 1f; shared.m_durabilityDrain = 1f; shared.m_blockPower = 0f; shared.m_blockPowerPerLevel = 0f; shared.m_armor = 0f; shared.m_armorPerLevel = 0f; shared.m_attackStatusEffect = null; shared.m_attackStatusEffectChance = 0f; shared.m_equipStatusEffect = null; shared.m_secondaryAttack = null; shared.m_damages = default(DamageTypes); shared.m_damages.m_pierce = 1f; shared.m_damagesPerLevel = default(DamageTypes); GameObject prefab = PrefabManager.Instance.GetPrefab("KnifeCopper"); ItemDrop val = ((prefab != null) ? prefab.GetComponent() : null); if (val?.m_itemData?.m_shared?.m_attack == null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)"Fletcher's knife: KnifeCopper attack template missing."); } } else { shared.m_attack = CloneAttack(val.m_itemData.m_shared.m_attack); shared.m_attack.m_damageMultiplier = 1f; shared.m_attack.m_raiseSkillAmount = 0f; shared.m_attack.m_attackStamina = 0f; shared.m_attack.m_selfDamage = 0; } } private static Attack CloneAttack(Attack source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown Attack val = new Attack(); FieldInfo[] fields = typeof(Attack).GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(val, fieldInfo.GetValue(source)); } return val; } } internal static class FletchersKnifeHelper { private static readonly MethodInfo GetRightItemMethod = typeof(Humanoid).GetMethod("GetRightItem", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo GetLeftItemMethod = typeof(Humanoid).GetMethod("GetLeftItem", BindingFlags.Instance | BindingFlags.NonPublic); internal static bool IsKnifeInHand(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (!IsKnife(GetHandItem(player, GetRightItemMethod))) { return IsKnife(GetHandItem(player, GetLeftItemMethod)); } return true; } internal static bool IsKnifeEquipped(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (IsKnife(GetHandItem(player, GetRightItemMethod)) || IsKnife(GetHandItem(player, GetLeftItemMethod))) { return true; } if (((Humanoid)player).GetInventory() == null) { return false; } foreach (ItemData equippedItem in ((Humanoid)player).GetInventory().GetEquippedItems()) { if (IsKnife(equippedItem)) { return true; } } return false; } private static ItemData GetHandItem(Player player, MethodInfo method) { if (method == null) { return null; } object? obj = method.Invoke(player, null); return (ItemData)((obj is ItemData) ? obj : null); } private static bool IsKnife(ItemData item) { if ((Object)(object)item?.m_dropPrefab == (Object)null) { return false; } return ArrowAssemblyRegistry.IsKnifePrefab(((Object)item.m_dropPrefab).name); } } internal static class FletchLegacyCleanup { private static readonly int LegacyContainerPrefabHash = ModConstants.LegacyContainerPrefabHash; private static readonly int LegacyUnknownPrefabHash = 555343901; private static bool fullPurgeCompleted; private static readonly MethodInfo HandleDestroyedZdoMethod = AccessTools.Method(typeof(ZDOMan), "HandleDestroyedZDO", (Type[])null, (Type[])null); internal static void RunAfterWorldZdosLoaded() { fullPurgeCompleted = false; Run(forceFullPurge: true); } internal static void Run(bool forceFullPurge = false) { SanitizeNullZNetViews(); if (!forceFullPurge && fullPurgeCompleted) { return; } int found; int remaining; int num = PurgeLegacyZdosFromWorldSave(out found, out remaining); int num2 = PurgeRuntimeInstances(); int num3 = PurgeNamedObjects(); int num4 = SanitizeNullZNetViews(); if (forceFullPurge || num > 0 || num2 > 0 || num3 > 0) { fullPurgeCompleted = true; } ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)($"Legacy bench cleanup: found {found} ZDO(s), removed {num} from world save, " + $"{remaining} remain in memory, {num2} scene view(s) cleared, {num3} named object(s) destroyed. " + $"Tracked hashes: {LegacyContainerPrefabHash}, {LegacyUnknownPrefabHash}. " + $"IsServer={(Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()}.")); } if (found == 0) { ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogInfo((object)"No legacy bench ZDOs in world save — phantom bench cleanup is complete for this world."); } } if (num > 0) { ManualLogSource log3 = FletchersForgePlugin.Log; if (log3 != null) { log3.LogInfo((object)"Run console command 'save' to persist ZDO removal."); } } else if (found > 0) { ManualLogSource log4 = FletchersForgePlugin.Log; if (log4 != null) { log4.LogWarning((object)"Legacy bench ZDO(s) were found but could not be removed. Load as world host and try fletcher.cleanup again."); } } if (remaining > 0) { ManualLogSource log5 = FletchersForgePlugin.Log; if (log5 != null) { log5.LogWarning((object)$"{remaining} legacy bench ZDO(s) still in memory after cleanup. ChestSnap errors may continue until they are removed and saved."); } } if (num4 > 0) { ManualLogSource log6 = FletchersForgePlugin.Log; if (log6 != null) { log6.LogInfo((object)$"Removed {num4} stale ZNetView entries from ZNetScene for ChestSnap."); } } } internal static int SanitizeNullZNetViews() { if ((Object)(object)ZNetScene.instance == (Object)null) { return 0; } Dictionary value = Traverse.Create((object)ZNetScene.instance).Field>("m_instances").Value; if (value == null) { return 0; } List list = new List(); foreach (KeyValuePair item in value) { if (item.Key == null || !IsLiveZNetView(item.Value)) { list.Add(item.Key); } } foreach (ZDO item2 in list) { if (item2 != null) { value.Remove(item2); } } return list.Count; } internal static bool IsLiveZNetView(ZNetView view) { if ((Object)(object)view == (Object)null) { return false; } try { return (Object)(object)((Component)view).gameObject != (Object)null; } catch (NullReferenceException) { return false; } } private static int PurgeLegacyZdosFromWorldSave(out int found, out int remaining) { found = 0; remaining = 0; if (ZDOMan.instance == null) { return 0; } HashSet hashSet = new HashSet(); CollectZdosByPrefabName("FF_FletchContainer", hashSet); CollectZdosByPrefabHash(hashSet); found = hashSet.Count; int num = 0; foreach (ZDO item in hashSet) { if (ForceDestroyZdo(item)) { num++; } } remaining = CountLegacyZdos(); return num; } private static int CountLegacyZdos() { HashSet hashSet = new HashSet(); CollectZdosByPrefabName("FF_FletchContainer", hashSet); CollectZdosByPrefabHash(hashSet); return hashSet.Count; } private static void CollectZdosByPrefabName(string prefabName, HashSet output) { if (ZDOMan.instance == null || string.IsNullOrEmpty(prefabName)) { return; } List list = new List(); int num = 0; while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefabName, list, ref num)) { foreach (ZDO item in list) { if (item != null) { output.Add(item); } } list.Clear(); } foreach (ZDO item2 in list) { if (item2 != null) { output.Add(item2); } } } private static void CollectZdosByPrefabHash(HashSet output) { foreach (ZDO item in EnumerateAllZdos()) { if (item != null) { int prefab = item.GetPrefab(); if (prefab == LegacyContainerPrefabHash || prefab == LegacyUnknownPrefabHash) { output.Add(item); } } } } private static IEnumerable EnumerateAllZdos() { if (ZDOMan.instance == null) { return new List(); } HashSet seen = new HashSet(); List list = new List(); Traverse val = Traverse.Create((object)ZDOMan.instance); if ((val.Field("m_objectsByID").GetValue() ?? val.Field("m_objectsById").GetValue()) is IDictionary dictionary) { foreach (object value in dictionary.Values) { AddUniqueZdo(list, seen, (ZDO)((value is ZDO) ? value : null)); } } else { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)"Legacy cleanup could not read ZDOMan m_objectsByID."); } } if (val.Field("m_objectsByOutsideSector").GetValue() is IDictionary dictionary2) { foreach (object value2 in dictionary2.Values) { CollectZdosFromBucket(list, seen, value2); } } if (val.Field("m_objectsBySector").GetValue() is List[] array) { List[] array2 = array; foreach (List bucket in array2) { CollectZdosFromBucket(list, seen, bucket); } } return list; } private static void CollectZdosFromBucket(List all, HashSet seen, object bucket) { if (!(bucket is List list)) { return; } foreach (ZDO item in list) { AddUniqueZdo(all, seen, item); } } private static void AddUniqueZdo(List all, HashSet seen, ZDO zdo) { if (zdo != null && !seen.Contains(zdo)) { seen.Add(zdo); all.Add(zdo); } } private static int PurgeRuntimeInstances() { if ((Object)(object)ZNetScene.instance == (Object)null) { return 0; } Dictionary value = Traverse.Create((object)ZNetScene.instance).Field>("m_instances").Value; if (value == null) { return 0; } int num = 0; List list = new List(); foreach (KeyValuePair item in value) { ZDO key = item.Key; ZNetView value2 = item.Value; if ((Object)(object)value2 == (Object)null || (Object)(object)((Component)value2).gameObject == (Object)null) { if (key != null) { list.Add(key); } num++; } else if (key != null && (key.GetPrefab() == LegacyContainerPrefabHash || key.GetPrefab() == LegacyUnknownPrefabHash)) { Object.Destroy((Object)(object)((Component)value2).gameObject); list.Add(key); num++; } } foreach (ZDO item2 in list) { value.Remove(item2); } return num; } private static int PurgeNamedObjects() { int num = 0; GameObject[] array = Resources.FindObjectsOfTypeAll(); foreach (GameObject val in array) { if (!((Object)(object)val == (Object)null)) { string name = ((Object)val).name; if (name == "FF_FletchContainer" || name == "FF_FletchWorkbenchRuntime") { Object.Destroy((Object)(object)val); num++; } } } return num; } private static bool ForceDestroyZdo(ZDO zdo) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || ZDOMan.instance == null) { return false; } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject val = ZNetScene.instance.FindInstance(zdo.m_uid); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } Traverse.Create((object)ZNetScene.instance).Field>("m_instances").Value?.Remove(zdo); } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && HandleDestroyedZdoMethod != null) { HandleDestroyedZdoMethod.Invoke(ZDOMan.instance, new object[1] { zdo.m_uid }); return ZDOMan.instance.GetZDO(zdo.m_uid) == null; } if (zdo.IsOwner()) { ZDOMan.instance.DestroyZDO(zdo); return true; } ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)$"Could not remove legacy bench ZDO {zdo.m_uid} (not owner; load world as host)."); } return false; } } internal static class FletchOperations { internal static bool TryReforge(Player player, Inventory inv, out string message) { message = string.Empty; if ((Object)(object)player == (Object)null || inv == null) { message = "No workbench."; return false; } ItemData itemAt = inv.GetItemAt(0, 0); ItemData itemAt2 = inv.GetItemAt(1, 0); if (itemAt == null) { message = "Place a shaft or arrow in the first slot."; return false; } string prefabName = (((Object)(object)itemAt.m_dropPrefab != (Object)null) ? ((Object)itemAt.m_dropPrefab).name : string.Empty); if (ArrowAssemblyRegistry.IsArrowPrefab(prefabName)) { return TryRehead(player, inv, itemAt, itemAt2, out message); } if (ArrowAssemblyRegistry.IsShaftPrefab(prefabName)) { return TryAssemble(player, inv, itemAt, itemAt2, out message); } message = "Invalid item in first slot."; return false; } internal static bool TrySplit(Player player, Inventory inv, out string message) { message = string.Empty; if ((Object)(object)player == (Object)null || inv == null) { message = "No workbench."; return false; } ItemData itemAt = inv.GetItemAt(0, 0); ItemData itemAt2 = inv.GetItemAt(1, 0); if (itemAt == null) { message = "Place arrows in the first slot."; return false; } if (itemAt2 != null) { message = "Clear the head slot before splitting."; return false; } if (!ArrowAssemblyRegistry.TryGetParts(((Object)(object)itemAt.m_dropPrefab != (Object)null) ? ((Object)itemAt.m_dropPrefab).name : string.Empty, out var shaftPrefab, out var headPrefab)) { message = "That item cannot be split."; return false; } int num = Mathf.Min(20, itemAt.m_stack); if (!TryGiveComponents(player, shaftPrefab, headPrefab, num)) { message = "Inventory full."; return false; } itemAt.m_stack -= num; if (itemAt.m_stack <= 0) { inv.RemoveItem(itemAt); } message = $"Split {num} arrows."; return true; } private static bool TryAssemble(Player player, Inventory inv, ItemData shaftItem, ItemData headItem, out string message) { message = string.Empty; string name = ((Object)shaftItem.m_dropPrefab).name; string headPrefab = (((Object)(object)headItem?.m_dropPrefab != (Object)null) ? ((Object)headItem.m_dropPrefab).name : null); if (!ArrowAssemblyRegistry.TryGetArrow(name, headPrefab, out var arrowPrefab)) { if (headItem == null) { message = "Place an arrowhead in the second slot."; } else { message = "Those parts do not match."; } return false; } int num = Mathf.Min(20, shaftItem.m_stack); if (headItem != null) { num = Mathf.Min(num, headItem.m_stack); } if (!GiveArrows(player, arrowPrefab, num)) { message = "Inventory full."; return false; } shaftItem.m_stack -= num; if (shaftItem.m_stack <= 0) { inv.RemoveItem(shaftItem); } if (headItem != null) { headItem.m_stack -= num; if (headItem.m_stack <= 0) { inv.RemoveItem(headItem); } } message = $"Reforged {num} arrows."; return true; } private static bool TryRehead(Player player, Inventory inv, ItemData arrowItem, ItemData newHeadItem, out string message) { message = string.Empty; if (newHeadItem == null) { message = "Place a new arrowhead in the second slot."; return false; } if (!ArrowAssemblyRegistry.TryGetParts(((Object)arrowItem.m_dropPrefab).name, out var shaftPrefab, out var headPrefab)) { message = "That arrow cannot be reforged."; return false; } string name = ((Object)newHeadItem.m_dropPrefab).name; if (!ArrowAssemblyRegistry.TryGetArrow(shaftPrefab, name, out var arrowPrefab)) { message = "That head does not fit this arrow."; return false; } int num = Mathf.Min(new int[3] { 20, arrowItem.m_stack, newHeadItem.m_stack }); if (!GiveArrows(player, arrowPrefab, num)) { message = "Inventory full."; return false; } if (!string.IsNullOrEmpty(headPrefab) && !GiveComponents(player, headPrefab, num)) { message = "Inventory full."; return false; } arrowItem.m_stack -= num; newHeadItem.m_stack -= num; if (arrowItem.m_stack <= 0) { inv.RemoveItem(arrowItem); } if (newHeadItem.m_stack <= 0) { inv.RemoveItem(newHeadItem); } message = $"Reforged {num} arrows."; return true; } private static bool TryGiveComponents(Player player, string shaftPrefab, string headPrefab, int count) { if (!GiveComponents(player, shaftPrefab, count)) { return false; } if (!string.IsNullOrEmpty(headPrefab) && !GiveComponents(player, headPrefab, count)) { return false; } return true; } private static bool GiveComponents(Player player, string prefabName, int count) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName); if ((Object)(object)itemPrefab == (Object)null) { return false; } return ((Humanoid)player).GetInventory().AddItem(itemPrefab, count); } private static bool GiveArrows(Player player, string arrowPrefabName, int count) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(arrowPrefabName); if ((Object)(object)itemPrefab == (Object)null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogError((object)("Arrow prefab missing: " + arrowPrefabName)); } return false; } return ((Humanoid)player).GetInventory().AddItem(itemPrefab, count); } } internal static class FletchSlotRules { internal static bool CanAccept(int gridX, int gridY, string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return true; } if (gridX == 0 && gridY == 0) { if (!ArrowAssemblyRegistry.IsShaftPrefab(prefabName)) { return ArrowAssemblyRegistry.IsArrowPrefab(prefabName); } return true; } if (gridX == 1 && gridY == 0) { return ArrowAssemblyRegistry.IsHeadPrefab(prefabName); } return false; } } internal sealed class FletchUiBehaviour : MonoBehaviour { private void OnGUI() { FletchUiService.DrawBenchOverlay(); } } internal static class FletchUiService { private static bool benchUiOpen; private static string statusMessage = string.Empty; private static float statusUntil; internal static bool IsBenchUiOpen => benchUiOpen; internal static bool IsFletchContainerOpen { get { if (benchUiOpen && (Object)(object)InventoryGui.instance != (Object)null) { return InventoryGui.IsVisible(); } return false; } } internal static bool IsFletchInventory(Inventory inventory) { Inventory inventory2 = FletchBenchInventory.Inventory; if (inventory2 != null) { return inventory2 == inventory; } return false; } internal static void Open(Player player) { if (!FletchersKnifeHelper.IsKnifeInHand(player) || IsFletchContainerOpen) { return; } FletchBenchInventory.Initialize(); if (FletchBenchInventory.Inventory == null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogError((object)"Virtual Fletcher bench is not ready."); } return; } if ((Object)(object)InventoryGui.instance == (Object)null) { ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogError((object)"InventoryGui not available."); } return; } InventoryGui instance = InventoryGui.instance; FletchBenchInventory.ClearSlots(); if (InventoryGui.IsVisible()) { instance.Hide(); } InventoryGuiAccess.SetHiddenFrames(instance, 10); InventoryGuiAccess.SetAnimatorVisible(instance, visible: true); InventoryGuiAccess.SetActiveGroup(instance, 1); InventoryGuiAccess.SetFirstContainerUpdate(instance, value: true); benchUiOpen = true; if ((Object)(object)InventoryGui.instance != (Object)null) { FletchBenchButtonUi.Update(InventoryGui.instance, benchOpen: true); } ManualLogSource log3 = FletchersForgePlugin.Log; if (log3 != null) { log3.LogInfo((object)"Opened virtual Fletcher bench UI."); } } internal static void NotifyGuiClosed() { benchUiOpen = false; FletchBenchInventory.ClearSlots(); } internal static void Close() { if (benchUiOpen || IsFletchContainerOpen) { benchUiOpen = false; FletchBenchInventory.ClearSlots(); if ((Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible()) { InventoryGui.instance.Hide(); } } } internal static void TryReforge(Player player) { if (IsFletchContainerOpen && FletchBenchInventory.Inventory != null) { FletchOperations.TryReforge(player, FletchBenchInventory.Inventory, out var message); SetStatus(message); } } internal static void TrySplit(Player player) { if (IsFletchContainerOpen && FletchBenchInventory.Inventory != null) { FletchOperations.TrySplit(player, FletchBenchInventory.Inventory, out var message); SetStatus(message); } } internal static void DrawBenchOverlay() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (IsFletchContainerOpen && TryGetContainerScreenRect(out var rect) && Time.time < statusUntil && !string.IsNullOrEmpty(statusMessage)) { GUI.Label(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - 52f, ((Rect)(ref rect)).width - 24f, 20f), statusMessage); } } internal static void SetStatus(string message) { statusMessage = message; statusUntil = Time.time + 3f; } private static bool TryGetContainerScreenRect(out Rect rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance?.m_container == (Object)null) { return false; } RectTransform container = instance.m_container; Vector3[] array = (Vector3[])(object)new Vector3[4]; container.GetWorldCorners(array); Canvas componentInParent = ((Component)container).GetComponentInParent(); Camera val = null; if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) { val = componentInParent.worldCamera; } Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, array[0]); Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, array[2]); float x = val2.x; float num = (float)Screen.height - val3.y; float num2 = val3.x - val2.x; float num3 = val3.y - val2.y; rect = new Rect(x, num, num2, num3); if (num2 > 0f) { return num3 > 0f; } return false; } } internal static class HeadIconAssets { private const string IconFolderName = "Icons"; private const string EmbeddedIconFolder = "EmbeddedIcons"; private static readonly Dictionary Cache = new Dictionary(); private static readonly Dictionary SourceCache = new Dictionary(); private static MethodInfo imageConversionLoadImage; private static bool loggedEmbeddedResources; internal static void ClearCache() { Cache.Clear(); SourceCache.Clear(); } internal static bool TryApplyCustomHeadIcon(CustomItem item) { if ((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null) { return false; } string text = (((Object)(object)item.ItemPrefab != (Object)null) ? ((Object)item.ItemPrefab).name : ((Object)((Component)item.ItemDrop).gameObject).name); Sprite orLoad = GetOrLoad(text); if ((Object)(object)orLoad == (Object)null) { return false; } item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { orLoad }; IconRigUtility.SyncIconsToObjectDb(text, item.ItemDrop.m_itemData.m_shared.m_icons); string text2 = "custom"; if (SourceCache.TryGetValue(text, out var value)) { text2 = value; } ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)$"Applied {text2} icon for {text} ({((Texture)orLoad.texture).width}x{((Texture)orLoad.texture).height})."); } return true; } internal static string GetIconsFolderPath() { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath, "Icons"); } private static Sprite GetOrLoad(string prefabName) { if (Cache.TryGetValue(prefabName, out var value)) { return value; } Sprite val = null; string value2 = "none"; if (ModConfig.UseEmbeddedHeadIcons.Value) { val = LoadEmbeddedSprite(prefabName); if ((Object)(object)val != (Object)null) { value2 = "embedded DLL"; } } if ((Object)(object)val == (Object)null && ModConfig.AllowExternalHeadIconOverrides.Value) { val = LoadFilesystemSprite(prefabName); if ((Object)(object)val != (Object)null) { value2 = "external Icons folder"; } } Cache[prefabName] = val; SourceCache[prefabName] = value2; return val; } private static Sprite LoadEmbeddedSprite(string prefabName) { Assembly assembly = typeof(FletchersForgePlugin).Assembly; string value = prefabName + ".png"; string text = null; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith(value, StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { if (!loggedEmbeddedResources) { loggedEmbeddedResources = true; ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)("Embedded icon resources: " + string.Join(", ", assembly.GetManifestResourceNames()))); } } return null; } using Stream stream = assembly.GetManifestResourceStream(text); if (stream == null) { return null; } return CreateSpriteFromPng(ReadAllBytes(stream), prefabName); } private static Sprite LoadFilesystemSprite(string prefabName) { string text = Path.Combine(GetIconsFolderPath(), prefabName + ".png"); if (!File.Exists(text)) { return null; } try { return CreateSpriteFromPng(File.ReadAllBytes(text), prefabName); } catch (IOException ex) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)("Failed to load icon " + text + ": " + ex.Message)); } return null; } } private static Sprite CreateSpriteFromPng(byte[] bytes, string prefabName) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadPng(val, bytes)) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)("Could not decode PNG for " + prefabName + ".")); } return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0); } private static byte[] ReadAllBytes(Stream stream) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } private static bool TryLoadPng(Texture2D texture, byte[] bytes) { MethodInfo methodInfo = GetImageConversionLoadImage(); if (methodInfo == null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)"ImageConversion.LoadImage is unavailable; cannot load PNG icons."); } return false; } object[] parameters = ((methodInfo.GetParameters().Length != 3) ? new object[2] { texture, bytes } : new object[3] { texture, bytes, false }); return (bool)methodInfo.Invoke(null, parameters); } private static MethodInfo GetImageConversionLoadImage() { if (imageConversionLoadImage != null) { return imageConversionLoadImage; } Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); if (type == null) { return null; } imageConversionLoadImage = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, null); if (imageConversionLoadImage == null) { imageConversionLoadImage = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); } return imageConversionLoadImage; } } internal static class HeadIconGenerator { private static readonly Dictionary ArrowTipColors = new Dictionary { { "ArrowFire", new Color(0.95f, 0.45f, 0.12f) }, { "ArrowFlint", new Color(0.55f, 0.52f, 0.48f) }, { "ArrowBronze", new Color(0.78f, 0.48f, 0.22f) }, { "ArrowIron", new Color(0.62f, 0.66f, 0.72f) }, { "ArrowSilver", new Color(0.82f, 0.86f, 0.92f) }, { "ArrowObsidian", new Color(0.22f, 0.2f, 0.28f) }, { "ArrowPoison", new Color(0.42f, 0.72f, 0.28f) }, { "ArrowFrost", new Color(0.45f, 0.78f, 0.95f) }, { "ArrowNeedle", new Color(0.68f, 0.7f, 0.74f) }, { "ArrowCarapace", new Color(0.58f, 0.32f, 0.62f) }, { "ArrowCharred", new Color(0.18f, 0.18f, 0.2f) } }; internal static Sprite CreateForArrow(string sourceArrow) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!ArrowTipColors.TryGetValue(sourceArrow, out var value)) { ((Color)(ref value))..ctor(0.65f, 0.65f, 0.65f); } return CreateArrowheadSprite(value); } private static Sprite CreateArrowheadSprite(Color tipColor) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color val3 = default(Color); ((Color)(ref val3))..ctor(tipColor.r * 0.55f, tipColor.g * 0.55f, tipColor.b * 0.55f, 1f); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num = (float)j / 64f; float num2 = (float)i / 64f; bool flag = num >= 0.38f && num2 >= 0.22f && num <= 0.92f && num2 <= 0.88f && num - 0.38f >= (num2 - 0.22f) * 0.55f; bool flag2 = flag && num >= 0.38f && num <= 0.5f; val.SetPixel(j, i, flag2 ? val3 : (flag ? tipColor : val2)); } } val.Apply(); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0); } } internal static class IconRigUtility { private static readonly string[] HeadNameTokens = new string[17] { "head", "tip", "flint", "iron", "bronze", "silver", "obsidian", "fire", "poison", "frost", "needle", "carapace", "charred", "resin", "stone", "metal", "arrowhead" }; private static readonly string[] ShaftNameTokens = new string[5] { "shaft", "stick", "wood", "body", "arrowwood" }; private static readonly string[] FeatherNameTokens = new string[3] { "feather", "fletch", "vane" }; internal static void ApplyShaftIcon(CustomItem item, string sourceArrow, bool ashTint = false) { GameObject target = BuildShaftIconRig(sourceArrow, ashTint); ApplyRenderedIcon(item, target); } internal static void ApplyHeadIcon(CustomItem item, string sourceArrow) { GameObject target = BuildHeadIconRig(sourceArrow); ApplyRenderedIcon(item, target); } internal static void ApplyRenderedIcon(CustomItem item, GameObject target) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null || (Object)(object)target == (Object)null) { return; } try { Sprite val = RenderManager.Instance.Render(target, RenderManager.IsometricRotation); if ((Object)(object)val != (Object)null) { item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons); return; } ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)("Icon render returned null for " + ((Object)target).name + ".")); } } catch (Exception ex) { ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogWarning((object)("Icon render failed for " + ((Object)target).name + ": " + ex.Message)); } } finally { if ((Object)(object)target != (Object)(object)((Component)item.ItemDrop).gameObject) { Object.Destroy((Object)(object)target); } } } internal static bool HasUsableIcons(Sprite[] icons) { if (icons == null || icons.Length == 0) { return false; } foreach (Sprite val in icons) { if ((Object)(object)val != (Object)null && (Object)(object)val.texture != (Object)null) { return true; } } return false; } internal static void ApplyHeadIconFromTip(CustomItem item, string sourceArrow) { if (HeadIconAssets.TryApplyCustomHeadIcon(item)) { return; } Sprite val = HeadIconGenerator.CreateForArrow(sourceArrow); if ((Object)(object)val != (Object)null) { item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons); } else if (!ApplyCroppedArrowTipIcon(item, sourceArrow)) { GameObject val2 = BuildHeadIconRig(sourceArrow); if ((Object)(object)val2 != (Object)null) { ApplyRenderedIcon(item, val2); SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons); } } } internal static bool ApplyCroppedArrowTipIcon(CustomItem item, string sourceArrow) { if ((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null) { return false; } GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(sourceArrow) : PrefabManager.Instance.GetPrefab(sourceArrow)); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if (val2?.m_itemData?.m_shared?.m_icons == null || val2.m_itemData.m_shared.m_icons.Length == 0) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)("No arrow icon to crop for " + sourceArrow + ".")); } return false; } Sprite val3 = CropSpriteToArrowTip(val2.m_itemData.m_shared.m_icons[0], sourceArrow); if ((Object)(object)val3 == (Object)null) { return false; } item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 }; SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons); return true; } internal static Sprite CropSpriteToArrowTip(Sprite source, string sourceArrow) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null || (Object)(object)source.texture == (Object)null) { return null; } Rect rect = source.rect; int num; float num2; if (sourceArrow != null) { num = ((sourceArrow.IndexOf("Needle", StringComparison.OrdinalIgnoreCase) >= 0) ? 1 : 0); if (num != 0) { num2 = 0.52f; goto IL_0047; } } else { num = 0; } num2 = 0.42f; goto IL_0047; IL_0047: float num3 = num2; float num4 = ((num != 0) ? 0.22f : 0.3f); float num5 = ((num != 0) ? 0.46f : 0.56f); float num6 = ((num != 0) ? 0.72f : 0.62f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + ((Rect)(ref rect)).width * num3, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height * num4, ((Rect)(ref rect)).width * num5, ((Rect)(ref rect)).height * num6); return Sprite.Create(source.texture, val, new Vector2(0.5f, 0.5f), source.pixelsPerUnit, 0u, (SpriteMeshType)0); } internal static void SyncIconsToObjectDb(string prefabName, Sprite[] icons) { if (!((Object)(object)ObjectDB.instance == (Object)null) && icons != null && icons.Length != 0) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); if (val?.m_itemData?.m_shared != null) { val.m_itemData.m_shared.m_icons = icons; } } } internal static GameObject BuildShaftIconRig(string sourceArrow, bool ashTint) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab(sourceArrow); if ((Object)(object)prefab == (Object)null) { return null; } GameObject val = Object.Instantiate(prefab); ((Object)val).name = "IconRig_Shaft_" + sourceArrow; PrepareIconRig(val); Transform[] componentsInChildren = val.GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)(object)val.transform) && IsHeadPart(((Object)val2).name)) { ((Component)val2).gameObject.SetActive(false); } } if (ashTint) { TintRenderers(val, new Color(0.38f, 0.38f, 0.42f, 1f)); } return val; } internal static GameObject BuildHeadIconRig(string sourceArrow, float headScale = 1.5f) { //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab(sourceArrow); if ((Object)(object)prefab == (Object)null) { return null; } GameObject val = Object.Instantiate(prefab); ((Object)val).name = "IconRig_Head_" + sourceArrow; PrepareIconRig(val); Transform[] componentsInChildren = val.GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)(object)val.transform) && (IsShaftPart(((Object)val2).name) || IsFeatherPart(((Object)val2).name))) { ((Component)val2).gameObject.SetActive(false); } } Renderer[] componentsInChildren2 = val.GetComponentsInChildren(true); List list = new List(); Renderer[] array = componentsInChildren2; foreach (Renderer val3 in array) { if ((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.activeInHierarchy) { list.Add(val3); } } if (list.Count > 1) { IsolateTipRenderers(list); } list.Clear(); array = val.GetComponentsInChildren(true); foreach (Renderer val4 in array) { if ((Object)(object)val4 != (Object)null && ((Component)val4).gameObject.activeInHierarchy) { list.Add(val4); } } if (list.Count == 0) { Object.Destroy((Object)(object)val); return null; } array = val.GetComponentsInChildren(true); foreach (Renderer val5 in array) { if (!((Object)(object)val5 == (Object)null) && ((Component)val5).gameObject.activeInHierarchy) { Transform transform = ((Component)val5).transform; transform.localScale *= headScale; } } return val; } private static void IsolateTipRenderers(List renderers) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = renderers[0].bounds; for (int i = 1; i < renderers.Count; i++) { ((Bounds)(ref bounds)).Encapsulate(renderers[i].bounds); } Vector3 primaryAxis = GetPrimaryAxis(((Bounds)(ref bounds)).size); float num = float.MaxValue; float num2 = float.MinValue; Bounds bounds2; foreach (Renderer renderer in renderers) { bounds2 = renderer.bounds; float num3 = Vector3.Dot(((Bounds)(ref bounds2)).center - ((Bounds)(ref bounds)).center, primaryAxis); num = Mathf.Min(num, num3); num2 = Mathf.Max(num2, num3); } float num4 = num + (num2 - num) * 0.45f; foreach (Renderer renderer2 in renderers) { bounds2 = renderer2.bounds; if (Vector3.Dot(((Bounds)(ref bounds2)).center - ((Bounds)(ref bounds)).center, primaryAxis) < num4) { ((Component)renderer2).gameObject.SetActive(false); } } } private static Vector3 GetPrimaryAxis(Vector3 size) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (size.y >= size.x && size.y >= size.z) { return Vector3.up; } if (size.z >= size.x && size.z >= size.y) { return Vector3.forward; } return Vector3.right; } private static void PrepareIconRig(GameObject rig) { Collider[] componentsInChildren = rig.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } Rigidbody[] componentsInChildren2 = rig.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].isKinematic = true; } ZNetView[] componentsInChildren3 = rig.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { ((Behaviour)componentsInChildren3[i]).enabled = false; } } private static void TintRenderers(GameObject rig, Color color) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = rig.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { Material material = val.material; if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } } } } private static bool IsHeadPart(string name) { string text = name.ToLowerInvariant(); string[] headNameTokens = HeadNameTokens; foreach (string value in headNameTokens) { if (text.Contains(value)) { return true; } } return false; } private static bool IsShaftPart(string name) { string text = name.ToLowerInvariant(); string[] shaftNameTokens = ShaftNameTokens; foreach (string value in shaftNameTokens) { if (text.Contains(value)) { return true; } } return false; } private static bool IsFeatherPart(string name) { string text = name.ToLowerInvariant(); string[] featherNameTokens = FeatherNameTokens; foreach (string value in featherNameTokens) { if (text.Contains(value)) { return true; } } return false; } } internal static class InventoryGuiAccess { private static readonly MethodInfo SetActiveGroupMethod = typeof(InventoryGui).GetMethod("SetActiveGroup", BindingFlags.Instance | BindingFlags.NonPublic); internal static void SetActiveGroup(InventoryGui gui, int index, bool playSound = false) { if (!((Object)(object)gui == (Object)null) && !(SetActiveGroupMethod == null)) { SetActiveGroupMethod.Invoke(gui, new object[2] { index, playSound }); } } internal static void SetAnimatorVisible(InventoryGui gui, bool visible) { object value = Traverse.Create((object)gui).Field("m_animator").GetValue(); if (value != null) { Traverse.Create(value).Method("SetBool", new object[2] { "visible", visible }).GetValue(); } } internal static void SetHiddenFrames(InventoryGui gui, int frames) { Traverse.Create((object)gui).Field("m_hiddenFrames").SetValue((object)frames); } internal static void SetContainerName(InventoryGui gui, string localizedName) { object value = Traverse.Create((object)gui).Field("m_containerName").GetValue(); if (value != null) { Traverse.Create(value).Property("text", (object[])null).SetValue((object)localizedName); } } internal static ItemData GetDragItem(InventoryGui gui) { return Traverse.Create((object)gui).Field("m_dragItem").Value; } internal static bool GetFirstContainerUpdate(InventoryGui gui) { return Traverse.Create((object)gui).Field("m_firstContainerUpdate").Value; } internal static void SetFirstContainerUpdate(InventoryGui gui, bool value) { Traverse.Create((object)gui).Field("m_firstContainerUpdate").SetValue((object)value); } internal static void ResetContainerHold(InventoryGui gui) { Traverse.Create((object)gui).Field("m_containerHoldTime").SetValue((object)0f); Traverse.Create((object)gui).Field("m_containerHoldState").SetValue((object)0); } } internal static class ItemRegistrar { private static CustomItem knifeItem; internal static void RegisterAll() { ArrowAssemblyRegistry.Initialize(); RegisterShaft("FF_ShaftStandard", "$FF_ShaftStandard", "$FF_ShaftStandard_desc", 0.05f); RegisterShaft("FF_ShaftNeedle", "$FF_ShaftNeedle", "$FF_ShaftNeedle_desc", 0.05f, "ArrowNeedle"); RegisterShaft("FF_ShaftAsh", "$FF_ShaftAsh", "$FF_ShaftAsh_desc", 0.05f, "ArrowWood", ashTint: true); RegisterHead("FF_HeadFire", "$FF_HeadFire", "ArrowFire"); RegisterHead("FF_HeadFlint", "$FF_HeadFlint", "ArrowFlint"); RegisterHead("FF_HeadBronze", "$FF_HeadBronze", "ArrowBronze"); RegisterHead("FF_HeadIron", "$FF_HeadIron", "ArrowIron"); RegisterHead("FF_HeadSilver", "$FF_HeadSilver", "ArrowSilver"); RegisterHead("FF_HeadObsidian", "$FF_HeadObsidian", "ArrowObsidian"); RegisterHead("FF_HeadPoison", "$FF_HeadPoison", "ArrowPoison"); RegisterHead("FF_HeadFrost", "$FF_HeadFrost", "ArrowFrost"); RegisterHead("FF_HeadNeedle", "$FF_HeadNeedle", "ArrowNeedle"); RegisterHead("FF_HeadCarapace", "$FF_HeadCarapace", "ArrowCarapace"); RegisterHead("FF_HeadCharred", "$FF_HeadCharred", "ArrowCharred"); RegisterKnife(); } internal static void ApplyDeferredIcons() { HeadIconAssets.ClearCache(); if (ModConfig.AllowExternalHeadIconOverrides.Value) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)("External head icon overrides enabled: " + HeadIconAssets.GetIconsFolderPath())); } } ApplyWoodShaftIcon("FF_ShaftStandard"); ApplyWoodShaftIcon("FF_ShaftAsh", ashTint: true); ApplyShaftIcon("FF_ShaftNeedle", "ArrowNeedle"); ApplyHeadIcon("FF_HeadFire", "ArrowFire"); ApplyHeadIcon("FF_HeadFlint", "ArrowFlint"); ApplyHeadIcon("FF_HeadBronze", "ArrowBronze"); ApplyHeadIcon("FF_HeadIron", "ArrowIron"); ApplyHeadIcon("FF_HeadSilver", "ArrowSilver"); ApplyHeadIcon("FF_HeadObsidian", "ArrowObsidian"); ApplyHeadIcon("FF_HeadPoison", "ArrowPoison"); ApplyHeadIcon("FF_HeadFrost", "ArrowFrost"); ApplyHeadIcon("FF_HeadNeedle", "ArrowNeedle"); ApplyHeadIcon("FF_HeadCarapace", "ArrowCarapace"); ApplyHeadIcon("FF_HeadCharred", "ArrowCharred"); if (knifeItem != null) { GameObject val = Object.Instantiate(((Component)knifeItem.ItemDrop).gameObject); ((Object)val).name = "IconRig_FF_FletchersKnife"; IconRigUtility.ApplyRenderedIcon(knifeItem, val); Object.Destroy((Object)(object)val); } ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogInfo((object)"Applied deferred item icons."); } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { RefreshInventoryIcons(localPlayer); } } private static void RefreshInventoryIcons(Player player) { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } foreach (ItemData allItem in inventory.GetAllItems()) { if ((Object)(object)allItem?.m_dropPrefab == (Object)null || allItem.m_shared == null) { continue; } string name = ((Object)allItem.m_dropPrefab).name; if (name.StartsWith("FF_", StringComparison.Ordinal)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); if (val?.m_itemData?.m_shared?.m_icons != null && IconRigUtility.HasUsableIcons(val.m_itemData.m_shared.m_icons)) { allItem.m_shared.m_icons = val.m_itemData.m_shared.m_icons; } } } } private static void RegisterShaft(string prefabName, string locName, string locDesc, float weight, string iconSourceArrow = "ArrowWood", bool ashTint = false) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown ItemConfig val = new ItemConfig { Name = locName, Description = locDesc }; CustomItem val2 = new CustomItem(prefabName, "IronScrap", val); ItemManager.Instance.AddItem(val2); ApplyMaterialStats(val2, weight, 100); ComponentDropVisualUtility.ApplyShaftDropVisual(val2, iconSourceArrow, ashTint); ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)("Registered shaft " + prefabName + ".")); } } private static void RegisterHead(string prefabName, string locName, string iconSourceArrow) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown ItemConfig val = new ItemConfig { Name = locName, Description = locName }; CustomItem val2 = new CustomItem(prefabName, "IronScrap", val); ItemManager.Instance.AddItem(val2); ApplyMaterialStats(val2, 0.05f, 200); ComponentDropVisualUtility.ApplyHeadDropVisual(val2, iconSourceArrow); ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)("Registered head " + prefabName + ".")); } } private static void RegisterKnife() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ItemConfig val = new ItemConfig { Name = "$FF_FletchersKnife", Description = "$FF_FletchersKnife_desc" }; knifeItem = new CustomItem("FF_FletchersKnife", "KnifeBlackMetal", val); FletchersKnifeConfigurator.Configure(knifeItem.ItemDrop.m_itemData.m_shared); ApplyKnifeVisuals(((Component)knifeItem.ItemDrop).gameObject); ItemManager.Instance.AddItem(knifeItem); ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)"Registered Fletcher's knife."); } } private static void ApplyWoodShaftIcon(string prefabName, bool ashTint = false) { CustomItem item = ItemManager.Instance.GetItem(prefabName); if (item != null) { GameObject val = IconRigUtility.BuildShaftIconRig("ArrowWood", ashTint); if (!((Object)(object)val == (Object)null)) { IconRigUtility.ApplyRenderedIcon(item, val); Object.Destroy((Object)(object)val); IconRigUtility.SyncIconsToObjectDb(prefabName, item.ItemDrop.m_itemData.m_shared.m_icons); } } } private static void ApplyShaftIcon(string prefabName, string sourceArrow) { CustomItem item = ItemManager.Instance.GetItem(prefabName); if (item != null) { GameObject val = IconRigUtility.BuildShaftIconRig(sourceArrow, ashTint: false); if (!((Object)(object)val == (Object)null)) { IconRigUtility.ApplyRenderedIcon(item, val); Object.Destroy((Object)(object)val); IconRigUtility.SyncIconsToObjectDb(prefabName, item.ItemDrop.m_itemData.m_shared.m_icons); } } } private static void ApplyHeadIcon(string prefabName, string sourceArrow) { CustomItem item = ItemManager.Instance.GetItem(prefabName); if (item != null) { IconRigUtility.ApplyHeadIconFromTip(item, sourceArrow); } } private static void ApplyMaterialStats(CustomItem item, float weight, int stackSize) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) SharedData shared = item.ItemDrop.m_itemData.m_shared; shared.m_itemType = (ItemType)1; shared.m_weight = weight; shared.m_maxStackSize = stackSize; shared.m_teleportable = true; shared.m_value = 0; } private static void ApplyKnifeVisuals(GameObject knifePrefab) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) Transform val = knifePrefab.transform.Find("attach"); if ((Object)(object)val == (Object)null) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)"Fletcher's knife has no attach point; kitbash skipped."); } return; } HideBlackmetalBlade(val); GameObject prefab = PrefabManager.Instance.GetPrefab("KnifeChitin"); if ((Object)(object)prefab == (Object)null) { ManualLogSource log2 = FletchersForgePlugin.Log; if (log2 != null) { log2.LogWarning((object)"KnifeChitin prefab not found; kitbash skipped."); } return; } Transform val2 = PrefabPathUtility.FindFirstChild(prefab.transform, "attach_skin", "attach", "attach/mesh"); if ((Object)(object)val2 == (Object)null) { val2 = PrefabPathUtility.FindRendererChild(prefab.transform); } if ((Object)(object)val2 == (Object)null) { ManualLogSource log3 = FletchersForgePlugin.Log; if (log3 != null) { log3.LogWarning((object)"Could not find Abyssal razor blade mesh for kitbash."); } return; } GameObject obj = Object.Instantiate(((Component)val2).gameObject, val); ((Object)obj).name = "FF_AbyssalBlade"; obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; obj.transform.localScale = Vector3.one * 0.75f; TintBladeCopper(obj.transform); ManualLogSource log4 = FletchersForgePlugin.Log; if (log4 != null) { log4.LogInfo((object)"Applied Fletcher's knife blade kitbash."); } } private static void HideBlackmetalBlade(Transform attach) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown Transform val = attach.Find("mesh"); if ((Object)(object)val != (Object)null && ((Object)val).name != "FF_AbyssalBlade") { ((Component)val).gameObject.SetActive(false); return; } foreach (Transform item in attach) { Transform val2 = item; if (!(((Object)val2).name == "FF_AbyssalBlade") && !((Object)val2).name.ToLowerInvariant().Contains("handle") && (Object)(object)((Component)val2).GetComponent() != (Object)null) { ((Component)val2).gameObject.SetActive(false); } } } private static void TintBladeCopper(Transform bladeRoot) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(0.72f, 0.45f, 0.2f, 1f); Renderer[] componentsInChildren = ((Component)bladeRoot).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { Material material = val2.material; if (material.HasProperty("_Color")) { material.SetColor("_Color", val); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", val); } } } } } internal static class LocalizationRegistrar { internal static void Initialize() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; string text2 = "FF_ModName"; localization.AddTranslation(ref text, ref text2, "Fletchers Forge"); text = "English"; text2 = "FF_FletchersKnife"; localization.AddTranslation(ref text, ref text2, "Fletcher's knife"); text = "English"; text2 = "FF_FletchersKnife_desc"; localization.AddTranslation(ref text, ref text2, "Field tool for the Fletcher's bench. Hold it ready to open the bench, then reforge or split arrows. Not meant for combat — 1 damage and breaks after one swing."); text = "English"; text2 = "FF_ShaftStandard"; localization.AddTranslation(ref text, ref text2, "Arrow shaft"); text = "English"; text2 = "FF_ShaftStandard_desc"; localization.AddTranslation(ref text, ref text2, "A wooden arrow shaft with fletching."); text = "English"; text2 = "FF_ShaftNeedle"; localization.AddTranslation(ref text, ref text2, "Needle arrow shaft"); text = "English"; text2 = "FF_ShaftNeedle_desc"; localization.AddTranslation(ref text, ref text2, "A feathered shaft for needle arrows."); text = "English"; text2 = "FF_ShaftAsh"; localization.AddTranslation(ref text, ref text2, "Ashwood arrow shaft"); text = "English"; text2 = "FF_ShaftAsh_desc"; localization.AddTranslation(ref text, ref text2, "A dark ashwood shaft with fletching."); text = "English"; text2 = "FF_HeadFire"; localization.AddTranslation(ref text, ref text2, "Fire arrowhead"); text = "English"; text2 = "FF_HeadFlint"; localization.AddTranslation(ref text, ref text2, "Flint arrowhead"); text = "English"; text2 = "FF_HeadBronze"; localization.AddTranslation(ref text, ref text2, "Bronze arrowhead"); text = "English"; text2 = "FF_HeadIron"; localization.AddTranslation(ref text, ref text2, "Iron arrowhead"); text = "English"; text2 = "FF_HeadSilver"; localization.AddTranslation(ref text, ref text2, "Silver arrowhead"); text = "English"; text2 = "FF_HeadObsidian"; localization.AddTranslation(ref text, ref text2, "Obsidian arrowhead"); text = "English"; text2 = "FF_HeadPoison"; localization.AddTranslation(ref text, ref text2, "Poison arrowhead"); text = "English"; text2 = "FF_HeadFrost"; localization.AddTranslation(ref text, ref text2, "Frost arrowhead"); text = "English"; text2 = "FF_HeadNeedle"; localization.AddTranslation(ref text, ref text2, "Needle arrowhead"); text = "English"; text2 = "FF_HeadCarapace"; localization.AddTranslation(ref text, ref text2, "Carapace arrowhead"); text = "English"; text2 = "FF_HeadCharred"; localization.AddTranslation(ref text, ref text2, "Charred arrowhead"); text = "English"; text2 = "FF_FletchContainer"; localization.AddTranslation(ref text, ref text2, "Fletcher's bench"); text = "English"; text2 = "FF_Reforge"; localization.AddTranslation(ref text, ref text2, "Reforge"); text = "English"; text2 = "FF_Split"; localization.AddTranslation(ref text, ref text2, "Split"); text = "English"; text2 = "FF_Preview"; localization.AddTranslation(ref text, ref text2, "Result"); text = "English"; text2 = "FF_OpenBenchHint"; localization.AddTranslation(ref text, ref text2, "[{0}] Fletcher's bench"); } } internal static class ModConfig { internal static ConfigEntry Enabled; internal static ConfigEntry UseEmbeddedHeadIcons; internal static ConfigEntry AllowExternalHeadIconOverrides; internal static ConfigEntry ReforgeKey; internal static ConfigEntry SplitKey; internal static void Bind(ConfigFile config) { Enabled = config.Bind("General", "Enabled", true, "Enable Fletchers Forge. When false, the mod does not register items, recipes, or UI."); UseEmbeddedHeadIcons = config.Bind("Icons", "UseEmbeddedHeadIcons", true, "Load arrowhead inventory icons bundled inside FletchersForge.dll."); AllowExternalHeadIconOverrides = config.Bind("Icons", "AllowExternalHeadIconOverrides", false, "When true, PNG files in the plugin Icons folder override embedded icons."); ReforgeKey = config.Bind("Controls", "Reforge", (KeyCode)0, "While the Fletcher's bench is open: reforge / assemble / rehead. None disables the hotkey (use the button)."); SplitKey = config.Bind("Controls", "Split", (KeyCode)0, "While the Fletcher's bench is open: split arrows. None disables the hotkey (use the button)."); } } internal static class ModConstants { public const string ModGuid = "hardwire99.fletchersforge"; public const string ModName = "Fletchers Forge"; public const string ModVersion = "0.1.30"; public const string HeadDropBoxPrimaryPrefab = "CargoCrate"; public static readonly string[] HeadDropBoxPrefabFallbacks = new string[2] { "dvergrprops_crate", "shipwreck_karve_chest" }; public const float HeadDropBoxScale = 0.25f; public const string FletchersKnife = "FF_FletchersKnife"; public const string FletchContainer = "FF_FletchContainer"; internal static readonly int LegacyContainerPrefabHash = StringExtensionMethods.GetStableHashCode("FF_FletchContainer"); public const string ShaftStandard = "FF_ShaftStandard"; public const string ShaftNeedle = "FF_ShaftNeedle"; public const string ShaftAsh = "FF_ShaftAsh"; public const string HeadFire = "FF_HeadFire"; public const string HeadFlint = "FF_HeadFlint"; public const string HeadBronze = "FF_HeadBronze"; public const string HeadIron = "FF_HeadIron"; public const string HeadSilver = "FF_HeadSilver"; public const string HeadObsidian = "FF_HeadObsidian"; public const string HeadPoison = "FF_HeadPoison"; public const string HeadFrost = "FF_HeadFrost"; public const string HeadNeedle = "FF_HeadNeedle"; public const string HeadCarapace = "FF_HeadCarapace"; public const string HeadCharred = "FF_HeadCharred"; public const float ShaftWeight = 0.05f; public const float HeadWeight = 0.05f; public const float KnifeWeight = 0.25f; public const int ShaftStackSize = 100; public const int HeadStackSize = 200; public const int BatchSize = 20; } internal static class ChestSnapCompatPatch { private static bool sanitizedThisSession; internal static void Prefix() { if (sanitizedThisSession) { return; } sanitizedThisSession = true; int num = FletchLegacyCleanup.SanitizeNullZNetViews(); if (num > 0) { ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogInfo((object)$"ChestSnap compat: removed {num} stale ZNetView entries before snappoint scan."); } } } } internal static class ChestSnapMoveNextFinalizerPatch { private static bool logged; internal static Exception Finalizer(Exception __exception) { if (__exception is NullReferenceException) { if (!logged) { logged = true; ManualLogSource log = FletchersForgePlugin.Log; if (log != null) { log.LogWarning((object)"ChestSnap snappoint scan hit a stale world object and was aborted (harmless)."); } } return null; } return __exception; } } internal static class ChestSnapNullArrayPatch { internal static void Postfix(ref GameObject[] __result) { if (__result != null && __result.Length != 0) { GameObject[] array = __result.Where((GameObject gameObject) => (Object)(object)gameObject != (Object)null).ToArray(); if (array.Length != __result.Length) { __result = array; } } } } internal static class ChestSnapNullViewPatch { internal static bool Prefix(KeyValuePair g, ref GameObject __result) { if (!FletchLegacyCleanup.IsLiveZNetView(g.Value)) { __result = null; return false; } return true; } } internal static class PrefabPathUtility { internal static Transform FindFirstChild(Transform root, params string[] relativePaths) { if ((Object)(object)root == (Object)null) { return null; } foreach (string text in relativePaths) { Transform val = root.Find(text); if ((Object)(object)val != (Object)null) { return val; } } return null; } internal static Transform FindRendererChild(Transform root, bool skipInactive = false) { if ((Object)(object)root == (Object)null) { return null; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)(object)root) && (!skipInactive || ((Component)val).gameObject.activeSelf) && (Object)(object)((Component)val).GetComponent() != (Object)null) { return val; } } return null; } } internal static class RecipeRegistrar { internal static void RegisterAll() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Expected O, but got Unknown //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Expected O, but got Unknown //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown RegisterShaftRecipe("FF_ShaftStandard", 1, new RequirementConfig("Wood", 8, 0, true), new RequirementConfig("Feathers", 2, 0, true)); RegisterShaftRecipe("FF_ShaftNeedle", 4, new RequirementConfig("Feathers", 2, 0, true)); RegisterShaftRecipe("FF_ShaftAsh", 3, new RequirementConfig("Blackwood", 8, 0, true), new RequirementConfig("Feathers", 2, 0, true)); RegisterHeadRecipe("FF_HeadFire", CraftingStations.Workbench, 2, new RequirementConfig("Resin", 8, 0, true)); RegisterHeadRecipe("FF_HeadFlint", CraftingStations.Workbench, 2, new RequirementConfig("Flint", 2, 0, true)); RegisterHeadRecipe("FF_HeadBronze", CraftingStations.Forge, 1, new RequirementConfig("Bronze", 1, 0, true)); RegisterHeadRecipe("FF_HeadIron", CraftingStations.Forge, 2, new RequirementConfig("Iron", 1, 0, true)); RegisterHeadRecipe("FF_HeadSilver", CraftingStations.Forge, 3, new RequirementConfig("Silver", 1, 0, true)); RegisterHeadRecipe("FF_HeadObsidian", CraftingStations.Workbench, 3, new RequirementConfig("Obsidian", 4, 0, true)); RegisterHeadRecipe("FF_HeadPoison", CraftingStations.Workbench, 3, new RequirementConfig("Obsidian", 4, 0, true), new RequirementConfig("Ooze", 2, 0, true)); RegisterHeadRecipe("FF_HeadFrost", CraftingStations.Workbench, 4, new RequirementConfig("Obsidian", 4, 0, true), new RequirementConfig("FreezeGland", 1, 0, true)); RegisterHeadRecipe("FF_HeadNeedle", CraftingStations.Workbench, 4, new RequirementConfig("Needle", 4, 0, true)); RegisterHeadRecipe("FF_HeadCarapace", CraftingStations.BlackForge, 1, new RequirementConfig("Carapace", 4, 0, true)); RegisterHeadRecipe("FF_HeadCharred", CraftingStations.BlackForge, 3, new RequirementConfig("CharredBone", 4, 0, true)); RegisterKnifeRecipe(); } private static void RegisterShaftRecipe(string item, int minLevel, params RequirementConfig[] requirements) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown RecipeConfig val = new RecipeConfig { Name = "Recipe_" + item, Item = item, Amount = 20, CraftingStation = CraftingStations.Workbench, MinStationLevel = minLevel, Requirements = requirements }; ItemManager.Instance.AddRecipe(new CustomRecipe(val)); } private static void RegisterHeadRecipe(string item, string station, int minLevel, params RequirementConfig[] requirements) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown RecipeConfig val = new RecipeConfig { Name = "Recipe_" + item, Item = item, Amount = 20, CraftingStation = station, MinStationLevel = minLevel, Requirements = requirements }; ItemManager.Instance.AddRecipe(new CustomRecipe(val)); } private static void RegisterKnifeRecipe() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown RecipeConfig val = new RecipeConfig(); val.Name = "Recipe_FF_FletchersKnife"; val.Item = "FF_FletchersKnife"; val.Amount = 1; val.CraftingStation = CraftingStations.Forge; val.MinStationLevel = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("FineWood", 1, 0, true), new RequirementConfig("Copper", 1, 0, true), new RequirementConfig("LeatherScraps", 1, 0, true) }; RecipeConfig val2 = val; ItemManager.Instance.AddRecipe(new CustomRecipe(val2)); } } } namespace FletchersForge.Patches { [HarmonyPatch(typeof(Player), "Update")] internal static class PlayerUpdateFletchPatch { private static bool knifeWasInHand; [HarmonyPostfix] private static void Postfix(Player __instance) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !((Character)__instance).IsOwner()) { return; } bool flag = FletchersKnifeHelper.IsKnifeInHand(__instance); if (flag && !knifeWasInHand) { FletchUiService.Open(__instance); } else if (!flag && knifeWasInHand) { FletchUiService.Close(); } knifeWasInHand = flag; if (FletchUiService.IsFletchContainerOpen) { if ((int)ModConfig.ReforgeKey.Value != 0 && ZInput.GetKeyDown(ModConfig.ReforgeKey.Value, true)) { FletchUiService.TryReforge(__instance); } if ((int)ModConfig.SplitKey.Value != 0 && ZInput.GetKeyDown(ModConfig.SplitKey.Value, true)) { FletchUiService.TrySplit(__instance); } } } } [HarmonyPatch(typeof(InventoryGui), "Update")] internal static class InventoryGuiUpdateFletchPatch { [HarmonyPostfix] private static void Postfix(InventoryGui __instance) { bool isBenchUiOpen = FletchUiService.IsBenchUiOpen; FletchBenchButtonUi.Update(__instance, isBenchUiOpen); object value = Traverse.Create((object)__instance).Field("m_containerWeight").GetValue(); if (value != null) { GameObject value2 = Traverse.Create(value).Property("gameObject", (object[])null).Value; if ((Object)(object)value2 != (Object)null) { value2.SetActive(!isBenchUiOpen && __instance.IsContainerOpen()); } } if (isBenchUiOpen && !((Object)(object)__instance.m_container == (Object)null)) { HideContainerActionButtons(__instance.m_container, isBenchUiOpen); } } private static void HideContainerActionButtons(RectTransform containerRoot, bool benchOpen) { Transform[] componentsInChildren = ((Component)containerRoot).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string text = ((Object)val).name.ToLowerInvariant(); if ((!benchOpen || (!text.Contains("takeall") && !text.Contains("stackall"))) && (text.Contains("reclaim") || text.Contains("takeall") || text.Contains("stackall") || text.Contains("place stacks") || text.Contains("placestacks") || text.Contains("quickstack") || text.Contains("sortcontainer") || text.Contains("restock"))) { ((Component)val).gameObject.SetActive(false); } } } } } [HarmonyPatch(typeof(InventoryGui), "OnTakeAll")] internal static class InventoryGuiOnTakeAllFletchPatch { [HarmonyPrefix] private static bool Prefix() { if (!FletchUiService.IsBenchUiOpen) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { FletchUiService.TryReforge(localPlayer); } return false; } } [HarmonyPatch(typeof(InventoryGui), "OnStackAll")] internal static class InventoryGuiOnStackAllFletchPatch { [HarmonyPrefix] private static bool Prefix() { if (!FletchUiService.IsBenchUiOpen) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { FletchUiService.TrySplit(localPlayer); } return false; } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryGuiHideFletchPatch { [HarmonyPostfix] private static void Postfix() { if (FletchUiService.IsBenchUiOpen) { FletchUiService.NotifyGuiClosed(); } } } [HarmonyPatch(typeof(InventoryGui), "IsContainerOpen")] internal static class InventoryGuiIsContainerOpenFletchPatch { [HarmonyPostfix] private static void Postfix(ref bool __result) { if (FletchUiService.IsBenchUiOpen) { __result = true; } } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] internal static class InventoryGuiUpdateContainerFletchPatch { [HarmonyPrefix] private static bool Prefix(InventoryGui __instance, Player player) { if (!FletchUiService.IsBenchUiOpen || FletchBenchInventory.Inventory == null) { return true; } if (!InventoryGui.IsVisible()) { return true; } Inventory inventory = FletchBenchInventory.Inventory; ((Component)__instance.m_container).gameObject.SetActive(true); __instance.ContainerGrid.UpdateInventory(inventory, (Player)null, InventoryGuiAccess.GetDragItem(__instance)); InventoryGuiAccess.SetContainerName(__instance, Localization.instance.Localize(inventory.GetName())); if (InventoryGuiAccess.GetFirstContainerUpdate(__instance)) { __instance.ContainerGrid.ResetView(); InventoryGuiAccess.SetFirstContainerUpdate(__instance, value: false); InventoryGuiAccess.ResetContainerHold(__instance); } return false; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(Vector2i) })] internal static class InventoryAddItemGridFletchPatch { [HarmonyPrefix] private static bool Prefix(Inventory __instance, ItemData item, Vector2i pos, ref bool __result) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!FletchUiService.IsFletchInventory(__instance) || (Object)(object)item?.m_dropPrefab == (Object)null) { return true; } if (!FletchSlotRules.CanAccept(pos.x, pos.y, ((Object)item.m_dropPrefab).name)) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[] { typeof(ItemData), typeof(int) })] internal static class InventoryCanAddItemFletchPatch { [HarmonyPrefix] private static bool Prefix(Inventory __instance, ItemData item, ref bool __result) { if (!FletchUiService.IsFletchInventory(__instance) || (Object)(object)item?.m_dropPrefab == (Object)null) { return true; } if (!FletchSlotRules.CanAccept(0, 0, ((Object)item.m_dropPrefab).name) && !FletchSlotRules.CanAccept(1, 0, ((Object)item.m_dropPrefab).name)) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class PlayerSpawnCleanupPatch { private static bool spawnCleanupDone; [HarmonyPostfix] private static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && ((Character)__instance).IsOwner() && !spawnCleanupDone) { spawnCleanupDone = true; FletchLegacyCleanup.Run(); } } } [HarmonyPatch(typeof(Terminal), "Awake")] internal static class TerminalAwakeFletchCleanupPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEventFailable <>9__0_0; internal object b__0_0(ConsoleEventArgs args) { FletchLegacyCleanup.Run(forceFullPurge: true); HeadIconAssets.ClearCache(); ItemRegistrar.ApplyDeferredIcons(); args.Context.AddString("Fletcher legacy cleanup finished. Icons refreshed. Type 'save' to persist."); return true; } } [HarmonyPostfix] private static void Postfix() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEventFailable val = delegate(ConsoleEventArgs args) { FletchLegacyCleanup.Run(forceFullPurge: true); HeadIconAssets.ClearCache(); ItemRegistrar.ApplyDeferredIcons(); args.Context.AddString("Fletcher legacy cleanup finished. Icons refreshed. Type 'save' to persist."); return true; }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("fletcher.cleanup", "Remove phantom fletcher bench objects from the world save.", (ConsoleEventFailable)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } [HarmonyPatch(typeof(ZDOMan), "Load")] internal static class ZDOManLoadCleanupPatch { [HarmonyPostfix] private static void Postfix() { FletchLegacyCleanup.RunAfterWorldZdosLoaded(); } } }