Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ItemDrawers v1.2.6
kg_ItemDrawers.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Managers; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; using kg_ItemDrawers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("kg_ItemDrawers")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("kg_ItemDrawers")] [assembly: AssemblyTitle("kg_ItemDrawers")] [assembly: AssemblyVersion("1.0.0.0")] [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 kg_ItemDrawers { internal static class BuildBridge { private const float BuildRange = 20f; private static bool _applied; internal static void Apply(Harmony harmony) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown if (_applied) { return; } _applied = true; MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "HaveRequirements")) { MethodInfo method = typeof(BuildBridge).GetMethod("HaveRequirementsPostfix", BindingFlags.Static | BindingFlags.NonPublic); try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ItemDrawers.Instance.Log.LogInfo((object)("BuildBridge: patched HaveRequirements(" + string.Join(", ", GetParamTypes(methodInfo)) + ")")); } catch (Exception ex) { ItemDrawers.Instance.Log.LogWarning((object)("BuildBridge: failed to patch HaveRequirements: " + ex.Message)); } } } methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != "ConsumeResources")) { MethodInfo method2 = typeof(BuildBridge).GetMethod("ConsumeResourcesPrefix", BindingFlags.Static | BindingFlags.NonPublic); try { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ItemDrawers.Instance.Log.LogInfo((object)("BuildBridge: patched ConsumeResources(" + string.Join(", ", GetParamTypes(methodInfo2)) + ")")); } catch (Exception ex2) { ItemDrawers.Instance.Log.LogWarning((object)("BuildBridge: failed to patch ConsumeResources: " + ex2.Message)); } } } } private static string[] GetParamTypes(MethodInfo mi) { ParameterInfo[] parameters = mi.GetParameters(); string[] array = new string[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = parameters[i].ParameterType.Name; } return array; } [UsedImplicitly] private static void HaveRequirementsPostfix(Player __instance, ref bool __result, object[] __args) { if (__result || (Object)(object)__instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return; } Requirement[] array = null; int quality = 0; if (__args != null) { foreach (object obj in __args) { Piece val = (Piece)((obj is Piece) ? obj : null); if (val != null && val?.m_resources != null) { array = val.m_resources; continue; } Recipe val2 = (Recipe)((obj is Recipe) ? obj : null); if (val2 != null && val2?.m_resources != null) { array = val2.m_resources; } else if (obj is Requirement[] array2) { array = array2; } else if (obj is int num) { quality = num; } } } if (array != null) { CheckAndSupplement(__instance, array, quality, ref __result); } } private static void CheckAndSupplement(Player player, Requirement[] resources, int quality, ref bool __result) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (resources == null || (Object)(object)ObjectDB.instance == (Object)null) { return; } List<DrawerComponent> list = FindNearbyDrawers(((Component)player).transform.position); if (list.Count == 0) { return; } foreach (Requirement val in resources) { if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0) { int num = val.m_amount * (quality + 1); string name = val.m_resItem.m_itemData.m_shared.m_name; Inventory inventory = ((Humanoid)player).GetInventory(); int num2 = ((inventory != null) ? inventory.CountItems(name, -1, true) : 0); int num3 = CountInDrawers(list, name); if (num2 + num3 < num) { return; } } } __result = true; } [UsedImplicitly] private static void ConsumeResourcesPrefix(Player __instance, object[] __args) { if ((Object)(object)__instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return; } Requirement[] array = null; int quality = 0; if (__args != null) { foreach (object obj in __args) { Piece val = (Piece)((obj is Piece) ? obj : null); if (val != null && val?.m_resources != null) { array = val.m_resources; continue; } Recipe val2 = (Recipe)((obj is Recipe) ? obj : null); if (val2 != null && val2?.m_resources != null) { array = val2.m_resources; } else if (obj is Requirement[] array2) { array = array2; } else if (obj is int num) { quality = num; } } } if (array != null) { ConsumeFromDrawers(__instance, array, quality); } } private static void ConsumeFromDrawers(Player player, Requirement[] resources, int quality) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (resources == null || (Object)(object)ObjectDB.instance == (Object)null) { return; } List<DrawerComponent> list = FindNearbyDrawers(((Component)player).transform.position); if (list.Count == 0) { return; } foreach (Requirement val in resources) { if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0) { int num = val.m_amount * (quality + 1); string name = val.m_resItem.m_itemData.m_shared.m_name; Inventory inventory = ((Humanoid)player).GetInventory(); int num2 = ((inventory != null) ? inventory.CountItems(name, -1, true) : 0); int num3 = num - num2; if (num3 > 0) { WithdrawFromDrawers(list, name, num3); } } } } private static List<DrawerComponent> FindNearbyDrawers(Vector3 pos) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) List<DrawerComponent> list = new List<DrawerComponent>(); foreach (DrawerComponent allDrawer in DrawerComponent.AllDrawers) { if ((Object)(object)allDrawer == (Object)null || (Object)(object)allDrawer._znv == (Object)null || !allDrawer._znv.IsValid()) { continue; } Component val = (Component)(object)allDrawer; if ((Object)(object)val == (Object)null) { continue; } try { if (Vector3.Distance(val.transform.position, pos) <= 20f) { list.Add(allDrawer); } } catch { } } return list; } private static int CountInDrawers(List<DrawerComponent> drawers, string itemName) { if ((Object)(object)ObjectDB.instance == (Object)null) { return 0; } int num = 0; foreach (DrawerComponent drawer in drawers) { if ((Object)(object)drawer == (Object)null || (Object)(object)drawer._znv == (Object)null || !drawer._znv.IsValid()) { continue; } ZDO zDO = drawer._znv.GetZDO(); if (zDO == null) { continue; } string text = zDO.GetString("Prefab", ""); if (string.IsNullOrEmpty(text)) { continue; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); if (!((Object)(object)itemPrefab == (Object)null)) { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData.m_shared.m_name == itemName) { num += zDO.GetInt("Amount", 0) + DrawerComponent.CountEnchantedFromZdo(zDO); } } } return num; } private static int WithdrawFromDrawers(List<DrawerComponent> drawers, string itemName, int needed) { if ((Object)(object)ObjectDB.instance == (Object)null) { return 0; } int num = 0; foreach (DrawerComponent drawer in drawers) { if (num >= needed) { break; } if ((Object)(object)drawer == (Object)null || (Object)(object)drawer._znv == (Object)null || !drawer._znv.IsValid()) { continue; } ZDO zDO = drawer._znv.GetZDO(); if (zDO == null) { continue; } string text = zDO.GetString("Prefab", ""); if (string.IsNullOrEmpty(text)) { continue; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); if ((Object)(object)itemPrefab == (Object)null) { continue; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && !(component.m_itemData.m_shared.m_name != itemName)) { int num2 = zDO.GetInt("Amount", 0); int num3 = Mathf.Min(needed - num, num2); if (num3 > 0) { drawer._znv.InvokeRPC("ForceRemove", new object[1] { num3 }); num += num3; } } } return num; } } public class DrawerComponent : MonoBehaviour, Interactable, Hoverable { private struct DrawerOptions : ISerializableParameter { public DrawerComponent drawer; public Color32 color; public int pickupRange; public void Serialize(ref ZPackage pkg) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) pkg.Write(Utils.ColorToVec3(color)); pkg.Write(pickupRange); } public void Deserialize(ref ZPackage pkg) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) color = Utils.Vec3ToColor(pkg.ReadVector3()); pickupRange = pkg.ReadInt(); } } [HarmonyPatch] private static class IsVisible { [HarmonyTargetMethods] [UsedImplicitly] private static IEnumerable<MethodInfo> Methods() { yield return AccessTools.Method(typeof(TextInput), "IsVisible", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(StoreGui), "IsVisible", (Type[])null, (Type[])null); } [HarmonyPostfix] [UsedImplicitly] private static void SetTrue(ref bool __result) { __result |= ShowUI; } } [CompilerGenerated] private static class DisplayClassO { public static WindowFunction CachedWindow; } [CompilerGenerated] private static class <>O { public static WindowFunction <0>__Window; } public static readonly List<DrawerComponent> AllDrawers = new List<DrawerComponent>(); private static readonly FieldInfo F_s_instances = AccessTools.Field(typeof(ItemDrop), "s_instances"); private static Sprite _defaultSprite; private static Sprite _circleSprite; private Image _image; private TMP_Text _text; private Transform _stars; private TMP_Text _starsText; private Transform _starIcon; private Image _rarityCircle; private static bool ShowUI; private static DrawerOptions CurrentOptions; private static bool _effectsLogged; public ZNetView _znv { get; private set; } public string CurrentPrefab { get { return _znv.GetZDO().GetString("Prefab", ""); } set { _znv.GetZDO().Set("Prefab", value); } } public int CurrentAmount { get { return _znv.GetZDO().GetInt("Amount", 0); } set { _znv.GetZDO().Set("Amount", value); } } public int PickupRange { get { return _znv.GetZDO().GetInt("PickupRange", ItemDrawers.DrawerPickupRange.Value); } set { _znv.GetZDO().Set("PickupRange", value); } } public int Quality { get { return _znv.GetZDO().GetInt("Quality", 1); } set { _znv.GetZDO().Set("Quality", value); } } private string EnchantedData { get { return _znv.GetZDO().GetString("EnchantedB64", ""); } set { _znv.GetZDO().Set("EnchantedB64", value ?? ""); } } public int EnchantedCount { get { ZNetView znv = _znv; return CountEnchantedFromZdo((znv != null) ? znv.GetZDO() : null); } } public int TotalCount => CurrentAmount + EnchantedCount; private Color CurrentColor { get { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //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_0024: Unknown result type (might be due to invalid IL or missing references) return Color32.op_Implicit(Utils.Vec3ToColor(_znv.GetZDO().GetVec3("Color", ItemDrawers.DefaultColor.Value))); } set { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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) _znv.GetZDO().Set("Color", Utils.ColorToVec3(Color32.op_Implicit(value))); } } public bool ItemValid { get { if (!string.IsNullOrEmpty(CurrentPrefab)) { return (Object)(object)ObjectDB.instance.GetItemPrefab(CurrentPrefab) != (Object)null; } return false; } } private int ItemMaxStack => ObjectDB.instance.GetItemPrefab(CurrentPrefab).GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize; private string LocalizedName { get { if (EnchantedCount > 0) { List<(string, ItemData)> enchantedItems = GetEnchantedItems(); if (enchantedItems.Count > 0) { string epicLootDisplayName = Utils.GetEpicLootDisplayName(enchantedItems[0].Item2); if (!string.IsNullOrEmpty(epicLootDisplayName)) { return epicLootDisplayName; } } } return ObjectDB.instance.GetItemPrefab(CurrentPrefab).GetComponent<ItemDrop>().m_itemData.m_shared.m_name.Localize(); } } private bool DoRepeat { get { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown if (Object.op_Implicit((Object)Player.m_localPlayer) && ItemValid) { return PickupRange > 0; } return false; } } public List<(string prefabName, ItemData item)> GetEnchantedItems() { string enchantedData = EnchantedData; if (string.IsNullOrEmpty(enchantedData)) { return new List<(string, ItemData)>(); } byte[] bytes; try { bytes = Convert.FromBase64String(enchantedData); } catch { return new List<(string, ItemData)>(); } return Utils.DeserializeNamedItemList(bytes, (string name) => ObjectDB.instance.GetItemPrefab(name)); } private void SetEnchantedItems(List<(string prefabName, ItemData item)> items) { ZDO zDO = _znv.GetZDO(); if (items == null || items.Count == 0) { EnchantedData = ""; zDO.Set("EncCount", 0); return; } byte[] array = Utils.SerializeNamedItemList(items); if (array == null || array.Length == 0) { EnchantedData = ""; zDO.Set("EncCount", 0); } else { EnchantedData = Convert.ToBase64String(array); zDO.Set("EncCount", items.Count); } } public static int CountEnchantedFromZdo(ZDO zdo) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (zdo == null) { return 0; } string text = zdo.GetString("EnchantedB64", ""); if (string.IsNullOrEmpty(text)) { if (zdo.IsOwner() && zdo.GetInt("EncCount", 0) != 0) { zdo.Set("EncCount", 0); } return 0; } int num = zdo.GetInt("EncCount", 0); if (num > 0) { return num; } try { byte[] array = Convert.FromBase64String(text); if (array == null || array.Length < 4) { return 0; } int num2 = new ZPackage(array).ReadInt(); if (num2 < 0) { return 0; } if (num2 > 0 && zdo.IsOwner()) { zdo.Set("EncCount", num2); } return num2; } catch { return 0; } } private void InvokeUpdateIcon() { //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) string currentPrefab = CurrentPrefab; int totalCount = TotalCount; int quality = Quality; ZDO zDO = _znv.GetZDO(); if (zDO != null) { zDO.Set("Total", totalCount); } if (ItemDrawers.RarityColorEnabled != null && ItemDrawers.RarityColorEnabled.Value && EnchantedCount > 0 && !string.IsNullOrEmpty(currentPrefab) && ItemValidCheck(currentPrefab)) { List<(string, ItemData)> enchantedItems = GetEnchantedItems(); if (enchantedItems.Count > 0) { ItemData item = enchantedItems[0].Item2; int epicLootRarity = Utils.GetEpicLootRarity(item); ItemDrawers.DLog($"InvokeUpdateIcon: rarity={epicLootRarity} encCount={EnchantedCount} customDataKeys={(item?.m_customData?.Count).GetValueOrDefault()} prefab={currentPrefab}"); if (epicLootRarity > 0) { Color rarityColor = Utils.GetRarityColor(epicLootRarity); Vector3 val = Utils.ColorToVec3(Color32.op_Implicit(rarityColor)); zDO.Set("RarityColor", val); ItemDrawers.DLog($"InvokeUpdateIcon: rarity={epicLootRarity} color=({rarityColor.r},{rarityColor.g},{rarityColor.b}) vec=({val.x},{val.y},{val.z}) applied"); } else { ItemDrawers.DLog("InvokeUpdateIcon: rarity<=0, no color set. customData keys: " + string.Join(",", item?.m_customData?.Keys ?? new Dictionary<string, string>().Keys)); } } else { ItemDrawers.DLog($"InvokeUpdateIcon: GetEnchantedItems returned {enchantedItems.Count} items, encCount={EnchantedCount}"); } } else if (EnchantedCount <= 0) { zDO.Set("RarityColor", new Vector3(-1f, -1f, -1f)); } if (string.IsNullOrEmpty(currentPrefab) || !ItemValidCheck(currentPrefab)) { _znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { "", 0, 0 }); } else { _znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { currentPrefab, totalCount, quality }); } } public bool ItemValidCheck(string prefab) { if (!string.IsNullOrEmpty(prefab)) { return (Object)(object)ObjectDB.instance.GetItemPrefab(prefab) != (Object)null; } return false; } private void OnDestroy() { AllDrawers.Remove(this); } private static void PurgeLegacyEnchantedByteArray(ZDO zdo) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (zdo == null) { return; } try { int stableHashCode = StringExtensionMethods.GetStableHashCode("EnchantedData"); FieldInfo fieldInfo = AccessTools.Field(typeof(ZDOExtraData), "s_byteArrays"); if (fieldInfo == null) { return; } object value = fieldInfo.GetValue(null); if (value == null) { return; } MethodInfo methodInfo = AccessTools.Method(value.GetType(), "TryGetValue", (Type[])null, (Type[])null); if (methodInfo == null) { return; } object[] array = new object[2] { zdo.m_uid, null }; if ((bool)methodInfo.Invoke(value, array)) { object obj = array[1]; if (obj != null) { AccessTools.Method(obj.GetType(), "Remove", new Type[1] { typeof(int) }, (Type[])null)?.Invoke(obj, new object[1] { stableHashCode }); } } } catch (Exception ex) { try { ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogWarning((object)("PurgeLegacyEnchantedByteArray: " + ex.Message)); } } } catch { } } } private static Sprite GetCircleSprite() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_00e2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_circleSprite != (Object)null) { return _circleSprite; } int num = 32; Texture2D val = new Texture2D(num, num, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; Color32[] array = (Color32[])(object)new Color32[num * num]; float num2 = (float)num / 2f; float num3 = (float)num / 2f - 1f; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { float num4 = (float)j + 0.5f - num2; float num5 = (float)i + 0.5f - num2; float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5); if (num6 <= num3) { array[i * num + j] = Color32.op_Implicit(Color.white); } else if (num6 <= num3 + 1f) { float num7 = Mathf.Clamp01(num3 + 1f - num6); array[i * num + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num7 * 255f)); } else { array[i * num + j] = new Color32((byte)0, (byte)0, (byte)0, (byte)0); } } } val.SetPixels32(array); val.Apply(); _circleSprite = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f); return _circleSprite; } private void CreateRarityCircle(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0079: 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_00ba: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("RarityCircle"); val.transform.SetParent(parent, false); RectTransform val2 = val.GetComponent<RectTransform>(); if ((Object)(object)val2 == (Object)null) { val2 = val.AddComponent<RectTransform>(); } val2.anchorMin = new Vector2(1f, 1f); val2.anchorMax = new Vector2(1f, 1f); val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = new Vector2(16f, 16f); val2.anchoredPosition = new Vector2(-8f, -8f); _rarityCircle = val.AddComponent<Image>(); _rarityCircle.sprite = GetCircleSprite(); ((Graphic)_rarityCircle).color = Color.white; ((Graphic)_rarityCircle).raycastTarget = false; ((Component)_rarityCircle).gameObject.SetActive(false); } private void Awake() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) _znv = ((Component)this).GetComponent<ZNetView>(); if (_znv.IsValid()) { AllDrawers.Add(this); _image = ((Component)((Component)this).transform.Find("Cube/Canvas/Image")).GetComponent<Image>(); if ((Object)(object)_defaultSprite == (Object)null) { _defaultSprite = _image.sprite; } _text = ((Component)((Component)this).transform.Find("Cube/Canvas/Text")).GetComponent<TMP_Text>(); if ((Object)(object)ItemDrawers.NorseFont != (Object)null) { _text.font = ItemDrawers.NorseFont; } _text.fontSize /= 2f; ((Graphic)_text).color = CurrentColor; _stars = ((Component)this).transform.Find("Cube/Canvas/Stars"); _starsText = ((Component)_stars.Find("Quality")).GetComponent<TMP_Text>(); _starIcon = _stars.Find("Img"); CreateRarityCircle(((Component)_image).transform); ApplyTextEffects(_text); ApplyTextEffects(_starsText); PurgeLegacyEnchantedByteArray(_znv.GetZDO()); if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && !_znv.IsOwner()) { _znv.ClaimOwnership(); ItemDrawers.DLog("Awake: claimed ZDO ownership on server for drawer"); } _znv.Register<string, int, int>("AddItem_Request", (Action<long, string, int, int>)RPC_AddItem); _znv.Register<string, int, int>("AddItem_Player", (Action<long, string, int, int>)RPC_AddItem_Player); _znv.Register<int>("WithdrawItem_Request", (Action<long, int>)RPC_WithdrawItem_Request); _znv.Register<string, int, int>("UpdateIcon", (Action<long, string, int, int>)RPC_UpdateIcon); _znv.Register<int>("ForceRemove", (Action<long, int>)RPC_ForceRemove); _znv.Register<DrawerOptions>("ApplyOptions", (Action<long, DrawerOptions>)RPC_ApplyOptions); _znv.Register<string, int, string>("AddEnchanted_Request", (Action<long, string, int, string>)RPC_AddEnchanted); _znv.Register<string>("AddEnchanted_Player", (Action<long, string>)RPC_AddEnchanted_Player); _znv.Register<int>("WithdrawEnchanted_Request", (Action<long, int>)RPC_WithdrawEnchanted_Request); RPC_UpdateIcon(0L, CurrentPrefab, TotalCount, Quality); float num = Random.Range(2.5f, 3f); ((MonoBehaviour)this).InvokeRepeating("Repeat", num, num); } } private static void ApplyTextEffects(TMP_Text text) { //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)text == (Object)null) { return; } try { Material fontMaterial = text.fontMaterial; if ((Object)(object)fontMaterial == (Object)null) { return; } Shader val = Shader.Find("TextMeshPro/Distance Field") ?? Shader.Find("Hidden/TextMeshPro/Distance Field"); if ((Object)(object)val != (Object)null && (Object)(object)fontMaterial.shader != (Object)(object)val) { string text2 = (((Object)(object)fontMaterial.shader != (Object)null) ? ((Object)fontMaterial.shader).name : "null"); fontMaterial.shader = val; if (!_effectsLogged) { _effectsLogged = true; ItemDrawers.Instance.Log.LogInfo((object)("ApplyTextEffects: shader was '" + text2 + "', switched to '" + ((Object)val).name + "'")); } } else if ((Object)(object)val == (Object)null && !_effectsLogged) { _effectsLogged = true; ItemDrawers.Instance.Log.LogInfo((object)"ApplyTextEffects: full SDF shader not found — outline/shadow will not work."); } if (ItemDrawers.TextOutlineEnabled != null && ItemDrawers.TextOutlineEnabled.Value) { fontMaterial.EnableKeyword("OUTLINE_ON"); fontMaterial.SetFloat("_OutlineWidth", ItemDrawers.TextOutlineWidth.Value); fontMaterial.SetColor("_OutlineColor", ItemDrawers.TextOutlineColor.Value); fontMaterial.SetFloat("_OutlineSoftness", 0f); } if (ItemDrawers.TextShadowEnabled != null && ItemDrawers.TextShadowEnabled.Value) { fontMaterial.EnableKeyword("UNDERLAY_ON"); fontMaterial.SetColor("_UnderlayColor", ItemDrawers.TextShadowColor.Value); fontMaterial.SetFloat("_UnderlayOffsetX", ItemDrawers.TextShadowOffset.Value); fontMaterial.SetFloat("_UnderlayOffsetY", 0f - ItemDrawers.TextShadowOffset.Value); fontMaterial.SetFloat("_UnderlaySoftness", ItemDrawers.TextShadowSoftness.Value); fontMaterial.SetFloat("_UnderlayDilate", 0f); } text.havePropertiesChanged = true; ((Graphic)text).SetAllDirty(); } catch (Exception ex) { try { ItemDrawers.Instance.Log.LogInfo((object)("ApplyTextEffects: " + ex.Message)); } catch { } } } private void RPC_ApplyOptions(long sender, DrawerOptions options) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) if (_znv.IsOwner()) { CurrentColor = Color32.op_Implicit(options.color); PickupRange = Mathf.Min(ItemDrawers.MaxDrawerPickupRange.Value, options.pickupRange); } ((Graphic)_text).color = Color32.op_Implicit(options.color); } private void RPC_ForceRemove(long sender, int amount) { if (_znv.IsOwner() && amount > 0) { int currentAmount = CurrentAmount; amount = Mathf.Min(amount, CurrentAmount); CurrentAmount -= amount; ItemDrawers.DLog($"ForceRemove: {CurrentPrefab} -{amount} ({currentAmount}->{CurrentAmount}) enc={EnchantedCount} sender={sender}"); if (CurrentAmount <= 0 && EnchantedCount <= 0) { CurrentPrefab = ""; CurrentAmount = 0; Quality = 1; } InvokeUpdateIcon(); } } private void RPC_WithdrawItem_Request(long sender, int amount) { if (CurrentAmount <= 0 || !ItemValid) { if (EnchantedCount <= 0) { CurrentPrefab = ""; CurrentAmount = 0; Quality = 1; } InvokeUpdateIcon(); } else if (amount > 0) { amount = Mathf.Min(amount, CurrentAmount); CurrentAmount -= amount; _znv.InvokeRPC(sender, "AddItem_Player", new object[3] { CurrentPrefab, amount, Quality }); InvokeUpdateIcon(); } } private void RPC_AddItem_Player(long _, string prefab, int amount, int quality) { Utils.InstantiateItem(ZNetScene.instance.GetPrefab(prefab), amount, quality); } private void RPC_UpdateIcon(long _, string prefab, int amount, int quality) { //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) int num = amount; if (string.IsNullOrEmpty(prefab) || !ItemValidCheck(prefab)) { _image.sprite = _defaultSprite; ((Component)_stars).gameObject.SetActive(false); ((Component)_text).gameObject.SetActive(false); if ((Object)(object)_text != (Object)null) { _text.text = ""; } if ((Object)(object)_rarityCircle != (Object)null) { ((Component)_rarityCircle).gameObject.SetActive(false); } return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab); if ((Object)(object)itemPrefab == (Object)null) { ((Component)_text).gameObject.SetActive(false); return; } _image.sprite = itemPrefab.GetComponent<ItemDrop>().m_itemData.GetIcon(); _text.text = ((num > 0) ? num.ToString() : "0"); _text.ForceMeshUpdate(false, false); ((Component)_text).gameObject.SetActive(true); ((Component)_stars).gameObject.SetActive(quality > 1); if (quality > 1) { _starsText.text = quality.ToString(); _starIcon.localPosition = new Vector3((quality >= 10) ? 9f : 0f, 5.25f, 0f); } if (ItemDrawers.RarityColorEnabled != null && ItemDrawers.RarityColorEnabled.Value && (Object)(object)_rarityCircle != (Object)null) { ZNetView znv = _znv; ZDO val = ((znv != null) ? znv.GetZDO() : null); if (val != null) { Vector3 vec = val.GetVec3("RarityColor", new Vector3(-1f, -1f, -1f)); if (vec.x >= 0f && vec.y >= 0f && vec.z >= 0f) { Color32 val2 = Utils.Vec3ToColor(vec); ((Graphic)_rarityCircle).color = Color32.op_Implicit(val2); ((Component)_rarityCircle).gameObject.SetActive(true); object[] obj = new object[11] { vec.x, vec.y, vec.z, val2.r, val2.g, val2.b, val2.a, ((Component)_rarityCircle).gameObject.activeSelf, null, null, null }; Transform parent = ((Component)_rarityCircle).transform.parent; obj[8] = ((parent != null) ? ((Object)parent).name : null); RectTransform rectTransform = ((Graphic)_rarityCircle).rectTransform; float num2; Rect rect; if (rectTransform == null) { num2 = 0f; } else { rect = rectTransform.rect; num2 = ((Rect)(ref rect)).width; } obj[9] = num2; RectTransform rectTransform2 = ((Graphic)_rarityCircle).rectTransform; float num3; if (rectTransform2 == null) { num3 = 0f; } else { rect = rectTransform2.rect; num3 = ((Rect)(ref rect)).height; } obj[10] = num3; ItemDrawers.DLog(string.Format("RPC_UpdateIcon: SHOW circle RarityColor=({0},{1},{2}) color32=({3},{4},{5},{6}) active={7} parent={8} size={9}x{10}", obj)); } else { ((Component)_rarityCircle).gameObject.SetActive(false); ItemDrawers.DLog($"RPC_UpdateIcon: HIDE circle RarityColor=({vec.x},{vec.y},{vec.z}) (no rarity)"); } } } else if ((Object)(object)_rarityCircle != (Object)null) { ((Component)_rarityCircle).gameObject.SetActive(false); } if ((Object)(object)_text != (Object)null) { ((Graphic)_text).color = CurrentColor; } } private void RPC_AddItem(long sender, string prefab, int amount, int quality) { if (!_znv.IsOwner()) { ItemDrawers.DLog($"AddItem ignore: not owner prefab={prefab} x{amount}"); return; } if (amount <= 0 || string.IsNullOrEmpty(prefab)) { ItemDrawers.DLog($"AddItem REJECT: amount={amount} prefab={prefab}"); return; } quality = Math.Max(1, quality); if (TotalCount <= 0 && !string.IsNullOrEmpty(CurrentPrefab) && CurrentPrefab != prefab) { CurrentPrefab = ""; CurrentAmount = 0; Quality = 1; SetEnchantedItems(null); } string currentPrefab = CurrentPrefab; if (!string.IsNullOrEmpty(currentPrefab) && TotalCount > 0 && (currentPrefab != prefab || Quality != quality)) { ItemDrawers.DLog($"AddItem REJECT mismatch: have={currentPrefab} q{Quality} got={prefab} q{quality} x{amount} — returning"); _znv.InvokeRPC(sender, "AddItem_Player", new object[3] { prefab, amount, quality }); } else { CurrentAmount = ((TotalCount > 0 || CurrentAmount > 0) ? (CurrentAmount + amount) : amount); CurrentPrefab = prefab; Quality = quality; ItemDrawers.DLog($"AddItem OK: {prefab} +{amount} q{quality} => Amount={CurrentAmount} Total={TotalCount}"); InvokeUpdateIcon(); } } private void RPC_AddEnchanted(long sender, string prefab, int quality, string itemDataBase64) { //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) ItemDrawers.DLog($"RPC_AddEnchanted ENTRY: sender={sender} prefab={prefab} q{quality} b64len={itemDataBase64?.Length ?? 0}"); if (!_znv.IsOwner() || string.IsNullOrEmpty(itemDataBase64)) { ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogWarning((object)$"RPC_AddEnchanted: rejected (owner={_znv.IsOwner()}, empty={string.IsNullOrEmpty(itemDataBase64)})"); } } return; } quality = Math.Max(1, quality); byte[] array = null; try { array = Convert.FromBase64String(itemDataBase64); } catch (Exception ex) { ItemDrawers instance2 = ItemDrawers.Instance; if (instance2 != null) { ManualLogSource log2 = instance2.Log; if (log2 != null) { log2.LogWarning((object)("RPC_AddEnchanted: base64 decode failed: " + ex.Message)); } } return; } if (array == null || array.Length == 0) { ItemDrawers instance3 = ItemDrawers.Instance; if (instance3 != null) { ManualLogSource log3 = instance3.Log; if (log3 != null) { log3.LogWarning((object)$"RPC_AddEnchanted: decoded bytes empty (len={((array != null) ? array.Length : 0)})"); } } return; } ItemDrawers.DLog($"RPC_AddEnchanted: decoded {array.Length} bytes"); string currentPrefab = CurrentPrefab; if (ItemValid && !string.IsNullOrEmpty(currentPrefab) && currentPrefab != prefab) { if (CurrentAmount > 0) { Utils.InstantiateAtPos(ZNetScene.instance.GetPrefab(currentPrefab), CurrentAmount, Quality, ((Component)this).transform.position + Vector3.up * 1.5f); CurrentAmount = 0; } List<(string, ItemData)> enchantedItems = GetEnchantedItems(); if (enchantedItems.Count > 0) { foreach (var item3 in enchantedItems) { string item = item3.Item1; ItemData item2 = item3.Item2; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); if ((Object)(object)itemPrefab != (Object)null) { Utils.DropEnchantedItem(itemPrefab, item2, ((Component)this).transform.position + Vector3.up * 1.5f); } } SetEnchantedItems(new List<(string, ItemData)>()); } } CurrentPrefab = prefab; Quality = quality; GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(prefab); if ((Object)(object)itemPrefab2 == (Object)null) { ItemDrawers instance4 = ItemDrawers.Instance; if (instance4 != null) { ManualLogSource log4 = instance4.Log; if (log4 != null) { log4.LogWarning((object)("RPC_AddEnchanted: prefab '" + prefab + "' not found in ObjectDB!")); } } return; } ItemData val = Utils.DeserializeItemData(array, itemPrefab2); if (val == null) { ItemDrawers instance5 = ItemDrawers.Instance; if (instance5 != null) { ManualLogSource log5 = instance5.Log; if (log5 != null) { log5.LogWarning((object)("RPC_AddEnchanted: DeserializeItemData returned null for prefab '" + prefab + "'!")); } } return; } ItemDrawers.DLog($"RPC_AddEnchanted: deserialized OK, customData keys={val.m_customData?.Count ?? 0}"); List<(string, ItemData)> enchantedItems2 = GetEnchantedItems(); if (ItemDrawers.StackOnlySameEnchantment != null && ItemDrawers.StackOnlySameEnchantment.Value && enchantedItems2.Count > 0 && !Utils.CustomDataEquals(enchantedItems2[0].Item2?.m_customData, val.m_customData)) { ItemDrawers instance6 = ItemDrawers.Instance; if (instance6 != null) { ManualLogSource log6 = instance6.Log; if (log6 != null) { log6.LogInfo((object)("RPC_AddEnchanted REJECT: enchantment mismatch (drawer has different enchantment for " + prefab + ")")); } } byte[] array2 = Utils.SerializeItemData(val); if (array2 != null && array2.Length != 0) { string text = Convert.ToBase64String(array2); _znv.InvokeRPC(sender, "AddEnchanted_Player", new object[1] { text }); } } else { enchantedItems2.Add((prefab, val)); SetEnchantedItems(enchantedItems2); ItemDrawers.DLog($"AddEnchanted OK: {prefab} q{quality} enc={enchantedItems2.Count} EncCount={EnchantedCount} EnchantedB64={EnchantedData.Length} chars customDataKeys={val.m_customData?.Count ?? 0}"); InvokeUpdateIcon(); } } private void RPC_AddEnchanted_Player(long _, string itemDataBase64) { ItemDrawers.DLog($"RPC_AddEnchanted_Player ENTRY: b64len={itemDataBase64?.Length ?? 0}"); if (string.IsNullOrEmpty(itemDataBase64)) { return; } byte[] array = null; try { array = Convert.FromBase64String(itemDataBase64); } catch (Exception ex) { ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogWarning((object)("RPC_AddEnchanted_Player: base64 decode failed: " + ex.Message)); } } return; } if (array == null || array.Length == 0) { return; } string currentPrefab = CurrentPrefab; if (string.IsNullOrEmpty(currentPrefab)) { ItemDrawers instance2 = ItemDrawers.Instance; if (instance2 != null) { ManualLogSource log2 = instance2.Log; if (log2 != null) { log2.LogWarning((object)"RPC_AddEnchanted_Player: CurrentPrefab is empty!"); } } return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(currentPrefab); if ((Object)(object)itemPrefab == (Object)null) { ItemDrawers instance3 = ItemDrawers.Instance; if (instance3 != null) { ManualLogSource log3 = instance3.Log; if (log3 != null) { log3.LogWarning((object)("RPC_AddEnchanted_Player: prefab '" + currentPrefab + "' not found!")); } } return; } ItemData val = Utils.DeserializeItemData(array, itemPrefab); if (val == null) { ItemDrawers instance4 = ItemDrawers.Instance; if (instance4 != null) { ManualLogSource log4 = instance4.Log; if (log4 != null) { log4.LogWarning((object)"RPC_AddEnchanted_Player: DeserializeItemData returned null!"); } } } else { ItemDrawers.DLog($"RPC_AddEnchanted_Player: deserialized OK, customData keys={val.m_customData?.Count ?? 0}"); Utils.InstantiateEnchantedItem(itemPrefab, val); } } private void RPC_WithdrawEnchanted_Request(long sender, int amount) { List<(string, ItemData)> enchantedItems = GetEnchantedItems(); ItemDrawers.DLog($"RPC_WithdrawEnchanted_Request: sender={sender} amount={amount} listCount={enchantedItems.Count}"); int num = Math.Min(amount, enchantedItems.Count); if (num <= 0) { if (CurrentAmount <= 0) { CurrentPrefab = ""; CurrentAmount = 0; Quality = 1; } InvokeUpdateIcon(); return; } for (int i = 0; i < num; i++) { var (text, val) = enchantedItems[enchantedItems.Count - 1]; enchantedItems.RemoveAt(enchantedItems.Count - 1); byte[] array = Utils.SerializeItemData(val); if (array == null || array.Length == 0) { ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogWarning((object)("RPC_WithdrawEnchanted: SerializeItemData failed for " + text + "!")); } } } else { string text2 = Convert.ToBase64String(array); ItemDrawers.DLog($"RPC_WithdrawEnchanted: sending {text} bytes={array.Length} b64={text2.Length} customDataKeys={val.m_customData?.Count ?? 0}"); _znv.InvokeRPC(sender, "AddEnchanted_Player", new object[1] { text2 }); } } SetEnchantedItems(enchantedItems); ItemDrawers.DLog($"RPC_WithdrawEnchanted: done, remaining enc={enchantedItems.Count}"); if (enchantedItems.Count == 0 && CurrentAmount <= 0) { CurrentPrefab = ""; Quality = 1; } InvokeUpdateIcon(); } private void Repeat() { //IL_0053: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_znv == (Object)null || !_znv.IsValid() || !_znv.IsOwner() || !DoRepeat) { return; } string currentPrefab = CurrentPrefab; int quality = Quality; Vector3 vector = ((Component)this).transform.position + Vector3.up; IEnumerable<ItemDrop> enumerable = (IEnumerable<ItemDrop>)F_s_instances.GetValue(null); if (enumerable == null) { return; } foreach (ItemDrop item in enumerable.Where((ItemDrop drop) => Vector3.Distance(((Component)drop).transform.position, vector) < (float)PickupRange)) { string name = ((Object)item.m_itemData.m_dropPrefab).name; if (name != currentPrefab || item.m_itemData.m_quality != quality) { continue; } if (!item.CanPickup(false)) { item.RequestOwn(); continue; } Object.Instantiate<GameObject>(ItemDrawers.Explosion, ((Component)item).transform.position, Quaternion.identity); int stack = item.m_itemData.m_stack; ZNetView component = ((Component)item).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { continue; } if (!component.IsOwner()) { item.RequestOwn(); continue; } if (Utils.HasCustomData(item.m_itemData)) { List<(string, ItemData)> enchantedItems = GetEnchantedItems(); if (ItemDrawers.StackOnlySameEnchantment != null && ItemDrawers.StackOnlySameEnchantment.Value && enchantedItems.Count > 0 && !Utils.CustomDataEquals(enchantedItems[0].Item2?.m_customData, item.m_itemData.m_customData)) { ItemDrawers.DLog("Repeat: SKIP auto-pickup — enchantment mismatch for " + name); continue; } enchantedItems.Add((name, item.m_itemData)); SetEnchantedItems(enchantedItems); } else { CurrentAmount += stack; } ZNetScene.instance.Destroy(((Component)item).gameObject); InvokeUpdateIcon(); } } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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 (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return true; } if (((Character)user).IsCrouching()) { CurrentOptions.drawer = this; CurrentOptions.color = Color32.op_Implicit(CurrentColor); CurrentOptions.pickupRange = PickupRange; ShowUI = true; return true; } if (!ItemValid) { return false; } if (Input.GetKey((KeyCode)308)) { if (EnchantedCount > 0) { _znv.InvokeRPC("WithdrawEnchanted_Request", new object[1] { 1 }); } else { _znv.InvokeRPC("WithdrawItem_Request", new object[1] { 1 }); } return true; } if (Input.GetKey((KeyCode)304)) { int quality = Quality; int num = Utils.CustomCountItems(CurrentPrefab, quality); if (num <= 0) { return true; } Utils.CustomRemoveItems(CurrentPrefab, num, quality); _znv.InvokeRPC("AddItem_Request", new object[3] { CurrentPrefab, num, quality }); return true; } if (EnchantedCount > 0) { _znv.InvokeRPC("WithdrawEnchanted_Request", new object[1] { 1 }); } else { _znv.InvokeRPC("WithdrawItem_Request", new object[1] { ItemMaxStack }); } return true; } public bool UseItem(Humanoid user, ItemData item) { string prefabName = Utils.GetPrefabName(item); if (string.IsNullOrEmpty(prefabName)) { ItemDrawers.DLog("UseItem REJECT: cannot resolve prefab (dropPrefab=" + (((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : "null") + " shared=" + item?.m_shared?.m_name + ")"); if (user != null) { ((Character)user).Message((MessageType)2, ModLocalization.MsgUnknownItem.Localize(), 0, (Sprite)null); } return false; } if (ItemDrawers.ExcludeSet.Contains(prefabName) && !Player.m_debugMode) { ItemDrawers.DLog("UseItem REJECT: excluded " + prefabName); if (user != null) { ((Character)user).Message((MessageType)2, string.Format(ModLocalization.MsgExcluded.Localize(), prefabName), 0, (Sprite)null); } return false; } bool flag = TotalCount <= 0; if (!string.IsNullOrEmpty(CurrentPrefab) && !flag && (CurrentPrefab != prefabName || Quality != item.m_quality)) { ItemDrawers.DLog($"UseItem REJECT: drawer has {CurrentPrefab} q{Quality}, item is {prefabName} q{item.m_quality}"); if (user != null) { ((Character)user).Message((MessageType)2, string.Format(ModLocalization.MsgHasPrefab.Localize(), CurrentPrefab), 0, (Sprite)null); } return false; } int stack = item.m_stack; if (stack <= 0) { ItemDrawers.DLog("UseItem REJECT: stack<=0"); return false; } if (Utils.HasCustomData(item)) { if (ItemDrawers.StackOnlySameEnchantment != null && ItemDrawers.StackOnlySameEnchantment.Value && EnchantedCount > 0) { List<(string, ItemData)> enchantedItems = GetEnchantedItems(); if (enchantedItems.Count > 0 && !Utils.CustomDataEquals(enchantedItems[0].Item2?.m_customData, item.m_customData)) { ItemDrawers.DLog("UseItem REJECT: enchantment mismatch (drawer has different enchantment for " + prefabName + ")"); if (user != null) { ((Character)user).Message((MessageType)2, ModLocalization.MsgDiffEnchant.Localize(), 0, (Sprite)null); } return false; } } byte[] array = Utils.SerializeItemData(item); if (array == null || array.Length == 0) { ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogWarning((object)"UseItem: SerializeItemData failed — item not removed."); } } return false; } string text = Convert.ToBase64String(array); ItemDrawers.DLog($"UseItem ENCHANTED: {prefabName} q{item.m_quality} keys={item.m_customData.Count} bytes={array.Length} b64={text.Length}"); user.GetInventory().RemoveItem(item); _znv.InvokeRPC("AddEnchanted_Request", new object[3] { prefabName, item.m_quality, text }); return true; } ItemDrawers.DLog($"UseItem VANILLA: {prefabName} x{stack} q{item.m_quality} → AddItem_Request (drawerAmount={CurrentAmount})"); user.GetInventory().RemoveItem(item); _znv.InvokeRPC("AddItem_Request", new object[3] { prefabName, stack, Math.Max(1, item.m_quality) }); return true; } public string GetHoverText() { StringBuilder stringBuilder = new StringBuilder(); if (((Character)Player.m_localPlayer).IsCrouching()) { stringBuilder.AppendLine("[<color=yellow><b>$KEY_Use</b></color>] " + ModLocalization.HoverOpenSettings.Localize()); return stringBuilder.ToString().Localize(); } if (!ItemValid) { stringBuilder.AppendLine("<color=yellow><b>" + ModLocalization.HoverUseHotbar.Localize() + "</b></color>"); return stringBuilder.ToString().Localize(); } int quality = Quality; string text = ((quality > 1) ? (" (" + string.Format(ModLocalization.HoverQuality.Localize(), quality) + ")") : ""); int totalCount = TotalCount; stringBuilder.AppendLine($"<color=yellow><b>{LocalizedName}{text}</b></color> ({totalCount})"); stringBuilder.AppendLine("<color=yellow><b>" + ModLocalization.HoverUseHotbar.Localize() + "</b></color>\n"); if (totalCount <= 0) { stringBuilder.AppendLine("[<color=yellow><b>$KEY_Use</b></color>] " + ModLocalization.HoverClear.Localize()); stringBuilder.AppendLine($"[<color=yellow><b>Left Shift + $KEY_Use</b></color>] {ModLocalization.HoverDepositAll.Localize()} <color=yellow><b>{LocalizedName}</b></color> ({Utils.CustomCountItems(CurrentPrefab, quality)})"); return stringBuilder.ToString().Localize(); } stringBuilder.AppendLine($"[<color=yellow><b>$KEY_Use</b></color>] {ModLocalization.HoverWithdrawStack.Localize()} ({ItemMaxStack})"); stringBuilder.AppendLine("[<color=yellow><b>Left Alt + $KEY_Use</b></color>] " + ModLocalization.HoverWithdrawSingle.Localize()); stringBuilder.AppendLine($"[<color=yellow><b>Left Shift + $KEY_Use</b></color>] {ModLocalization.HoverDepositAll.Localize()} <color=yellow><b>{LocalizedName}{text}</b></color> ({Utils.CustomCountItems(CurrentPrefab, quality)})"); return stringBuilder.ToString().Localize(); } public string GetHoverName() { return ModLocalization.HoverName.Localize(); } public static void ProcessInput() { if (Input.GetKeyDown((KeyCode)27) && ShowUI) { ShowUI = false; Menu.instance.OnClose(); } } public static void ProcessGUI() { //IL_000a: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_008e: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown if (!ShowUI) { return; } GUI.backgroundColor = Color.white; Rect val = new Rect((float)Screen.width / 2f - 150f, (float)Screen.height / 2f - 150f, 300f, 300f); object obj = DisplayClassO.CachedWindow; if (obj == null) { object obj2 = <>O.<0>__Window; if (obj2 == null) { WindowFunction val2 = Window; <>O.<0>__Window = val2; obj2 = (object)val2; } DisplayClassO.CachedWindow = (WindowFunction)obj2; obj = obj2; } GUI.Window(218102318, val, (WindowFunction)obj, ModLocalization.GuiTitle.Localize()); } private static void Window(int id) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) if ((Object)CurrentOptions.drawer == (Object)null || !CurrentOptions.drawer._znv.IsValid()) { ShowUI = false; return; } GUILayout.Label($"{ModLocalization.GuiCurrentDrawer.Localize()} <color=yellow><b>{CurrentOptions.drawer.LocalizedName}</b></color> ({CurrentOptions.drawer.CurrentAmount})", Array.Empty<GUILayoutOption>()); byte r = CurrentOptions.color.r; byte g = CurrentOptions.color.g; byte b = CurrentOptions.color.b; GUILayout.Label($"{ModLocalization.GuiTextColor.Localize()} <color=#{r:X2}{g:X2}{b:X2}><b>0123456789</b></color>", Array.Empty<GUILayoutOption>()); GUILayout.Label($"R: {r}", Array.Empty<GUILayoutOption>()); r = (byte)GUILayout.HorizontalSlider((float)(int)r, 0f, 255f, Array.Empty<GUILayoutOption>()); GUILayout.Label($"G: {g}", Array.Empty<GUILayoutOption>()); g = (byte)GUILayout.HorizontalSlider((float)(int)g, 0f, 255f, Array.Empty<GUILayoutOption>()); GUILayout.Label($"B: {b}", Array.Empty<GUILayoutOption>()); b = (byte)GUILayout.HorizontalSlider((float)(int)b, 0f, 255f, Array.Empty<GUILayoutOption>()); CurrentOptions.color = new Color32(r, g, b, byte.MaxValue); int pickupRange = CurrentOptions.pickupRange; GUILayout.Space(16f); GUILayout.Label(string.Format(ModLocalization.GuiPickupRange.Localize() + " <color={0}><b>{1}</b></color>", (pickupRange > 0) ? "lime" : "red", pickupRange), Array.Empty<GUILayoutOption>()); pickupRange = (int)GUILayout.HorizontalSlider((float)pickupRange, 0f, (float)ItemDrawers.MaxDrawerPickupRange.Value, Array.Empty<GUILayoutOption>()); CurrentOptions.pickupRange = pickupRange; GUILayout.Space(16f); if (GUILayout.Button("<color=lime>" + ModLocalization.GuiApply.Localize() + "</color>", Array.Empty<GUILayoutOption>())) { CurrentOptions.drawer._znv.InvokeRPC(ZNetView.Everybody, "ApplyOptions", new object[1] { CurrentOptions }); ShowUI = false; } } } public static class EpicLootDisplayNamePatch { private static bool _initialized; private static bool _enabled; private static MethodInfo _tryGetLegendaryInfo; private static MethodInfo _getMagicItemMethod; private static FieldInfo _magicItemDisplayNameField; private static FieldInfo _magicItemLegendaryIDField; public static bool IsEnabled => _enabled; public static void Init(Harmony harmonyInstance = null) { //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Expected O, but got Unknown if (_initialized) { return; } _initialized = true; try { Assembly assembly = Array.Find(AppDomain.CurrentDomain.GetAssemblies(), (Assembly a) => a.GetName().Name == "EpicLoot"); if (assembly == null) { ItemDrawers.DLog("EpicLootDisplayNamePatch: EpicLoot not found, patch disabled"); return; } Type type = assembly.GetType("EpicLoot.LegendarySystem.UniqueLegendaryHelper") ?? assembly.GetType("EpicLoot.UniqueLegendaryHelper"); Type type2 = assembly.GetType("EpicLoot.ItemDataExtensions"); Type type3 = assembly.GetType("EpicLoot.MagicItem"); if (type == null || type2 == null || type3 == null) { ItemDrawers.DLog("EpicLootDisplayNamePatch: required types not found"); return; } _tryGetLegendaryInfo = type.GetMethod("TryGetLegendaryInfo", BindingFlags.Static | BindingFlags.Public); _getMagicItemMethod = type2.GetMethod("GetMagicItem", new Type[1] { typeof(ItemData) }); _magicItemDisplayNameField = type3.GetField("DisplayName", BindingFlags.Instance | BindingFlags.Public); _magicItemLegendaryIDField = type3.GetField("LegendaryID", BindingFlags.Instance | BindingFlags.Public); if (_tryGetLegendaryInfo == null || _getMagicItemMethod == null || _magicItemDisplayNameField == null || _magicItemLegendaryIDField == null) { ItemDrawers.DLog("EpicLootDisplayNamePatch: required members not found"); return; } MethodInfo method = type2.GetMethod("GetDisplayName", new Type[1] { typeof(ItemData) }); if (method == null) { ItemDrawers.DLog("EpicLootDisplayNamePatch: GetDisplayName method not found"); return; } MethodInfo method2 = typeof(EpicLootDisplayNamePatch).GetMethod("PostfixDisplayName", BindingFlags.Static | BindingFlags.NonPublic); Harmony val = (Harmony)(((object)harmonyInstance) ?? ((object)/*isinst with value type is only supported in some contexts*/)); if (val == null) { ItemDrawers.DLog("EpicLootDisplayNamePatch: harmony instance not available"); return; } val.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _enabled = true; ItemDrawers.DLog("EpicLootDisplayNamePatch: patch applied successfully"); } catch (Exception arg) { ItemDrawers.DLog($"EpicLootDisplayNamePatch init failed: {arg}"); } } private static void PostfixDisplayName(ref string __result, ItemData itemData) { if (!_enabled || itemData == null) { return; } try { object obj = _getMagicItemMethod.Invoke(null, new object[1] { itemData }); if (obj == null) { return; } string text = (string)_magicItemLegendaryIDField.GetValue(obj); if (string.IsNullOrEmpty(text)) { return; } object[] array = new object[2] { text, null }; if (!(bool)_tryGetLegendaryInfo.Invoke(null, array)) { return; } object obj2 = array[1]; if (obj2 == null) { return; } FieldInfo field = obj2.GetType().GetField("Name", BindingFlags.Instance | BindingFlags.Public); if (field == null) { return; } string text2 = (string)field.GetValue(obj2); if (string.IsNullOrEmpty(text2)) { return; } string text3 = (string)_magicItemDisplayNameField.GetValue(obj); if (text2 == text3) { return; } string text4 = ""; if (!string.IsNullOrEmpty(text3) && !string.IsNullOrEmpty(__result)) { int num = __result.IndexOf(text3, StringComparison.Ordinal); if (num >= 0) { text4 = __result.Substring(num + text3.Length); } } ItemDrawers.DLog("EpicLootDisplayNamePatch: replacing '" + text3 + "' with '" + text2 + "' for LegendaryID=" + text); __result = text2 + text4; } catch (Exception ex) { ItemDrawers.DLog("EpicLootDisplayNamePatch postfix failed: " + ex.Message); } } } [BepInPlugin("kg.ItemDrawers", "Cybrp ItemDrawers", "1.2.6")] public class ItemDrawers : BaseUnityPlugin { private const string TiffanyAnsi = "\u001b[38;2;10;186;181m"; private const string AnsiReset = "\u001b[0m"; private const int StdOutputHandle = -11; private const uint EnableVirtualTerminalProcessing = 4u; public static readonly byte[] BuildStampBytes = new byte[16] { 66, 82, 79, 72, 69, 73, 77, 95, 73, 68, 95, 49, 95, 48, 95, 51 }; public static ItemDrawers Instance; private static Harmony _harmony; public static ConfigEntry<int> DrawerPickupRange; public static ConfigEntry<int> MaxDrawerPickupRange; public static ConfigEntry<Vector3> DefaultColor; public static ConfigEntry<string> ExcludeList; public static ConfigEntry<bool> CfgDepositLogs; public static HashSet<string> ExcludeSet = new HashSet<string>(); public static ConfigEntry<bool> TextOutlineEnabled; public static ConfigEntry<float> TextOutlineWidth; public static ConfigEntry<Color> TextOutlineColor; public static ConfigEntry<bool> TextShadowEnabled; public static ConfigEntry<Color> TextShadowColor; public static ConfigEntry<float> TextShadowOffset; public static ConfigEntry<float> TextShadowSoftness; public static ConfigEntry<bool> StackOnlySameEnchantment; public static ConfigEntry<bool> RarityColorEnabled; public static GameObject Explosion; public static TMP_FontAsset NorseFont; private static AssetBundle _bundle; private static readonly string[] DrawerPrefabNames = new string[7] { "kg_ItemDrawer_Wood", "kg_ItemDrawer_Stone", "kg_ItemDrawer_Marble", "kg_ItemDrawerPanel_Wood", "kg_ItemDrawerPanel_Stone", "kg_ItemDrawerPanel_Marble", "kg_ItemDrawer_NoModel" }; private static readonly (string name, string item, int amount)[] DrawerRecipes = new(string, string, int)[7] { ("$piece_kg_ItemDrawer_Wood", "Wood", 10), ("$piece_kg_ItemDrawer_Stone", "Stone", 10), ("$piece_kg_ItemDrawer_Marble", "BlackMarble", 10), ("$piece_kg_ItemDrawerPanel_Wood", "Wood", 10), ("$piece_kg_ItemDrawerPanel_Stone", "Stone", 10), ("$piece_kg_ItemDrawerPanel_Marble", "BlackMarble", 10), ("$piece_kg_ItemDrawer_NoModel", "GreydwarfEye", 10) }; private static bool _epicLootPatchApplied; public static string BuildStamp => Encoding.ASCII.GetString(BuildStampBytes); internal ManualLogSource Log => ((BaseUnityPlugin)this).Logger; internal static IReadOnlyList<string> AllDrawerPrefabNames => DrawerPrefabNames; internal static IReadOnlyList<(string name, string item, int amount)> AllDrawerRecipes => DrawerRecipes; [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode); private static void TryEnableVirtualTerminal() { //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) try { if (((object)Application.platform/*cast due to .constrained prefix*/).ToString().Contains("Windows")) { IntPtr stdHandle = GetStdHandle(-11); if (!(stdHandle == IntPtr.Zero) && !(stdHandle == new IntPtr(-1)) && GetConsoleMode(stdHandle, out var lpMode) && (lpMode & 4) == 0) { SetConsoleMode(stdHandle, lpMode | 4); } } } catch { } } private static TextWriter GetBepInExConsoleStream() { try { Type type = AccessTools.TypeByName("BepInEx.ConsoleManager"); if (type == null) { return null; } return AccessTools.Property(type, "ConsoleStream")?.GetValue(null) as TextWriter; } catch { return null; } } private static void SetBepInExConsoleColor(ConsoleColor color) { try { AccessTools.Method(AccessTools.TypeByName("BepInEx.ConsoleManager"), "SetConsoleColor", new Type[1] { typeof(ConsoleColor) }, (Type[])null)?.Invoke(null, new object[1] { color }); } catch { } } private static void PrintLoadBanner() { string[] array = new string[3] { "█▀▀\u2003█▄█\u2003█▄▄\u2003█▀█\u2003█▀█\u2003 \u2003▄▄\u2003 \u2003█\u2003▀█▀\u2003█▀▀\u2003█▀▄▀█\u2003█▀▄\u2003█▀█\u2003▄▀█\u2003█░█░█\u2003█▀▀\u2003█▀█\u2003█▀", "█▄▄\u2003░█░\u2003█▄█\u2003█▀▄\u2003█▀▀\u2003 \u2003░░\u2003 \u2003█\u2003░█░\u2003██▄\u2003█░▀░█\u2003█▄▀\u2003█▀▄\u2003█▀█\u2003▀▄▀▄▀\u2003██▄\u2003█▀▄\u2003▄█", " Cybrp ItemDrawers v1.2.6" }; try { TryEnableVirtualTerminal(); TextWriter bepInExConsoleStream = GetBepInExConsoleStream(); string[] array2; if (bepInExConsoleStream != null) { bepInExConsoleStream.WriteLine(); array2 = array; foreach (string text in array2) { bepInExConsoleStream.WriteLine("\u001b[38;2;10;186;181m" + text + "\u001b[0m"); } bepInExConsoleStream.WriteLine(); bepInExConsoleStream.Flush(); return; } SetBepInExConsoleColor(ConsoleColor.Cyan); Console.Out.WriteLine(); array2 = array; foreach (string value in array2) { Console.Out.WriteLine(value); } Console.Out.WriteLine(); SetBepInExConsoleColor(ConsoleColor.Gray); } catch { } } internal static void DLog(string msg) { if (CfgDepositLogs == null || !CfgDepositLogs.Value) { return; } ItemDrawers instance = Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogInfo((object)msg); } } } private void Awake() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Expected O, but got Unknown //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Expected O, but got Unknown //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Expected O, but got Unknown //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Expected O, but got Unknown Instance = this; PrintLoadBanner(); PieceManager.Instance.AddPieceCategory("itemdrawers"); ExcludeList = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ExcludeList", "", "List of items to exclude in the drawer. Leave blank to include all items."); ExcludeList.SettingChanged += ResetList; ResetList(null, null); DrawerPickupRange = ((BaseUnityPlugin)this).Config.Bind<int>("General", "DrawerPickupRange", 4, "Range at which you can pick up items from the drawer."); MaxDrawerPickupRange = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxDrawerPickupRange", 100, "Maximum range at which you can pick up items from the drawer."); DefaultColor = ((BaseUnityPlugin)this).Config.Bind<Vector3>("General", "DefaultColor", new Vector3(0.039f, 0.729f, 0.71f), "Default color of the drawer text."); TextOutlineEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("TextEffects", "OutlineEnabled", true, "Draw a black outline around the item-count digits for readability."); TextOutlineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("TextEffects", "OutlineWidth", 0.15f, new ConfigDescription("Outline thickness (0.0–1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); TextOutlineColor = ((BaseUnityPlugin)this).Config.Bind<Color>("TextEffects", "OutlineColor", Color.black, "Outline color."); TextShadowEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("TextEffects", "ShadowEnabled", true, "Draw a drop shadow under the item-count digits for readability."); TextShadowColor = ((BaseUnityPlugin)this).Config.Bind<Color>("TextEffects", "ShadowColor", new Color(0f, 0f, 0f, 0.6f), "Shadow color (alpha controls opacity)."); TextShadowOffset = ((BaseUnityPlugin)this).Config.Bind<float>("TextEffects", "ShadowOffset", 0.4f, new ConfigDescription("Shadow offset distance (0.0–1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); TextShadowSoftness = ((BaseUnityPlugin)this).Config.Bind<float>("TextEffects", "ShadowSoftness", 0.15f, new ConfigDescription("Shadow softness/blur (0.0–1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); StackOnlySameEnchantment = ((BaseUnityPlugin)this).Config.Bind<bool>("Enchanted", "StackOnlySameEnchantment", true, "When true, enchanted/modded items only stack in a drawer if their m_customData (enchantments, effects) are identical. When false, all enchanted items of the same prefab+quality stack together."); RarityColorEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Enchanted", "RarityColorEnabled", true, "When true, the drawer text color changes based on EpicLoot rarity (Magic=blue, Rare=yellow, Epic=purple, Legendary=teal, Mythic=orange). Overrides the default text color for enchanted drawers."); _bundle = LoadAssetBundle("kg_itemdrawers"); Explosion = _bundle.LoadAsset<GameObject>("kg_ItemDrawer_Explosion"); NorseFont = NorseFontLoader.Load(); StationAuto.CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "Enabled", true, "Master switch for auto-feed/deposit. Off = station integration does nothing."); StationAuto.CfgRadius = ((BaseUnityPlugin)this).Config.Bind<float>("StationAuto", "Radius", 8f, new ConfigDescription("Range (m) to search ItemDrawers around a station.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); StationAuto.CfgSmelterRadius = ((BaseUnityPlugin)this).Config.Bind<float>("StationAuto", "SmelterRadius", 15f, new ConfigDescription("Range (m) for smelters/kilns pulling from ItemDrawers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); StationAuto.CfgFeed = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "FeedFromDrawers", true, "Stations pull fuel/materials directly from nearby ItemDrawers (only from matching non-empty drawers)."); StationAuto.CfgDeposit = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "DepositToDrawers", true, "Cooking stations/beehives/sap collectors push finished output into matching nearby drawers."); StationAuto.CfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "DebugLogs", false, "Verbose logging."); StationAuto.VReflect.Init(); QuickStackBridge.CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "Enabled", true, "Master switch."); QuickStackBridge.CfgQuickStackToDrawers = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "QuickStackToDrawers", true, "Quick Stack (P) also deposits stackable items into matching nearby ItemDrawers (NOT into empty drawers)."); QuickStackBridge.CfgRestockFromDrawers = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "RestockFromDrawers", true, "Restock (L) also tops up partially filled stacks from matching nearby ItemDrawers."); QuickStackBridge.CfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "DebugLogs", false, "Verbose logging."); CfgDepositLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DepositLogs", true, "Log UseItem / AddItem / ForceRemove / AddEnchanted with reasons."); ModLocalization.Init(); Harmony val = new Harmony("kg.ItemDrawers"); _harmony = val; val.PatchAll(Assembly.GetExecutingAssembly()); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Cybrp ItemDrawers {BuildStamp} (v1.2.6) loaded. stamp[0]={BuildStampBytes[0]} FeedFromDrawers={StationAuto.CfgFeed.Value}"); AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoaded; TryInitQuickStackBridge(); TryInitEpicLootPatch(); AppDomain.CurrentDomain.AssemblyLoad += OnEpicLootLoaded; } private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args) { if (!(args.LoadedAssembly.GetName().Name != "QuickStackStore")) { TryInitQuickStackBridge(); AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoaded; } } private static void TryInitQuickStackBridge() { if (!QuickStackBridge.QssReflect.Ready) { QuickStackBridge.QssReflect.Init(); if (QuickStackBridge.QssReflect.Ready) { QuickStackBridgePatch.Apply(_harmony); RestockBridgePatch.Apply(_harmony); Instance.Log.LogInfo((object)"QuickStackBridge patches applied (deferred)."); } } } private static void TryInitEpicLootPatch() { if (!_epicLootPatchApplied && !(Array.Find(AppDomain.CurrentDomain.GetAssemblies(), (Assembly a) => a.GetName().Name == "EpicLoot") == null)) { EpicLootDisplayNamePatch.Init(_harmony); _epicLootPatchApplied = EpicLootDisplayNamePatch.IsEnabled; if (_epicLootPatchApplied) { Instance.Log.LogInfo((object)"EpicLootDisplayNamePatch applied (deferred)."); } } } private static void OnEpicLootLoaded(object sender, AssemblyLoadEventArgs args) { if (!(args.LoadedAssembly.GetName().Name != "EpicLoot")) { TryInitEpicLootPatch(); AppDomain.CurrentDomain.AssemblyLoad -= OnEpicLootLoaded; } } private void OnGUI() { DrawerComponent.ProcessGUI(); } private void Update() { DrawerComponent.ProcessInput(); ModLocalization.TryDeferredRegister(); } private void ResetList(object sender, EventArgs e) { ExcludeSet = new HashSet<string>(ExcludeList.Value.Replace(" ", "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)); } private static AssetBundle LoadAssetBundle(string filename) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().First((string s) => s.EndsWith(filename + ".bundle") || s.EndsWith(filename)); using Stream stream = executingAssembly.GetManifestResourceStream(name); return AssetBundle.LoadFromStream(stream); } internal static GameObject GetDrawerPrefab(string name) { return _bundle.LoadAsset<GameObject>(name); } } public static class ModLocalization { private static readonly Dictionary<string, Dictionary<string, string>> _translations = new Dictionary<string, Dictionary<string, string>>(); private static string _currentLanguage = "English"; public static readonly string HoverName = "$broheim_id_hover_name"; public static readonly string MsgUnknownItem = "$broheim_id_msg_unknown"; public static readonly string MsgExcluded = "$broheim_id_msg_excluded"; public static readonly string MsgHasPrefab = "$broheim_id_msg_has_prefab"; public static readonly string MsgDiffEnchant = "$broheim_id_msg_diff_enchant"; public static readonly string HoverOpenSettings = "$broheim_id_hover_open_settings"; public static readonly string HoverUseHotbar = "$broheim_id_hover_use_hotbar"; public static readonly string HoverQuality = "$broheim_id_hover_quality"; public static readonly string HoverClear = "$broheim_id_hover_clear"; public static readonly string HoverDepositAll = "$broheim_id_hover_deposit_all"; public static readonly string HoverWithdrawStack = "$broheim_id_hover_withdraw_stack"; public static readonly string HoverWithdrawSingle = "$broheim_id_hover_withdraw_single"; public static readonly string GuiTitle = "$broheim_id_gui_title"; public static readonly string GuiCurrentDrawer = "$broheim_id_gui_current_drawer"; public static readonly string GuiTextColor = "$broheim_id_gui_text_color"; public static readonly string GuiPickupRange = "$broheim_id_gui_pickup_range"; public static readonly string GuiApply = "$broheim_id_gui_apply"; private static int _initAttempts = 0; private static string _overrideLanguage = null; private static readonly FieldInfo F_m_translations = typeof(Localization).GetField("m_translations", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo M_AddWord = typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(string), typeof(string) }, null); private static readonly MethodInfo M_GetSelectedLanguage = typeof(Localization).GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); private static readonly FieldInfo F_m_language = typeof(Localization).GetField("m_language", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static bool _loggedLanguageSource; public static void Init() { LoadEmbedded(); RegisterCurrent(); } public static void OnLanguageChanged(string lang = null) { if (!string.IsNullOrEmpty(lang)) { _overrideLanguage = lang; } RegisterCurrent(); } public static void TryDeferredRegister() { if (_initAttempts < 5) { _initAttempts++; RegisterCurrent(); } } private static void LoadEmbedded() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (!text.StartsWith("kg_ItemDrawers.Translations.")) { continue; } string text2 = text.Substring("kg_ItemDrawers.Translations.".Length); if (text2.EndsWith(".json")) { text2 = text2.Substring(0, text2.Length - 5); } try { using Stream stream = executingAssembly.GetManifestResourceStream(text); using StreamReader streamReader = new StreamReader(stream); Dictionary<string, string> dictionary = ParseSimpleJson(streamReader.ReadToEnd()); _translations[text2] = dictionary; ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogInfo((object)$"ModLocalization: loaded {dictionary.Count} tokens for '{text2}'"); } } } catch (Exception ex) { ItemDrawers instance2 = ItemDrawers.Instance; if (instance2 != null) { ManualLogSource log2 = instance2.Log; if (log2 != null) { log2.LogWarning((object)("ModLocalization: failed to load '" + text + "': " + ex.Message)); } } } } if (_translations.ContainsKey("English")) { return; } ItemDrawers instance3 = ItemDrawers.Instance; if (instance3 != null) { ManualLogSource log3 = instance3.Log; if (log3 != null) { log3.LogWarning((object)"ModLocalization: English.json not found — using empty fallback"); } } _translations["English"] = new Dictionary<string, string>(); } private static void RegisterCurrent() { _currentLanguage = GetCurrentLanguage(); Dictionary<string, string> forLanguage = GetForLanguage(_currentLanguage); if (Localization.instance == null) { ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogWarning((object)"ModLocalization: Localization.instance is null — deferring registration"); } } return; } int num = 0; if (M_AddWord != null) { foreach (KeyValuePair<string, string> item in forLanguage) { try { string text = (item.Key.StartsWith("$") ? item.Key.Substring(1) : item.Key); M_AddWord.Invoke(Localization.instance, new object[2] { text, item.Value }); num++; } catch { } } } if (num == 0 && F_m_translations != null) { Dictionary<string, string> dictionary = (Dictionary<string, string>)F_m_translations.GetValue(Localization.instance); if (dictionary != null) { foreach (KeyValuePair<string, string> item2 in forLanguage) { string key = (item2.Key.StartsWith("$") ? item2.Key.Substring(1) : item2.Key); dictionary[key] = item2.Value; num++; } } else { ItemDrawers instance2 = ItemDrawers.Instance; if (instance2 != null) { ManualLogSource log2 = instance2.Log; if (log2 != null) { log2.LogWarning((object)"ModLocalization: m_translations dictionary is null"); } } } } if (num == 0) { FieldInfo[] fields = typeof(Localization).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); string arg = string.Join(", ", fields.Select((FieldInfo f) => f.Name + ":" + f.FieldType.Name)); ItemDrawers instance3 = ItemDrawers.Instance; if (instance3 != null) { ManualLogSource log3 = instance3.Log; if (log3 != null) { log3.LogWarning((object)$"ModLocalization: FAILED to register tokens. AddWord={M_AddWord != null}, m_translations={F_m_translations != null}. Fields: {arg}"); } } return; } ItemDrawers instance4 = ItemDrawers.Instance; if (instance4 != null) { ManualLogSource log4 = instance4.Log; if (log4 != null) { log4.LogInfo((object)string.Format("ModLocalization: registered {0} tokens for language '{1}' (method: {2})", num, _currentLanguage, (M_AddWord != null) ? "AddWord" : "reflection")); } } } private static string GetCurrentLanguage() { if (!string.IsNullOrEmpty(_overrideLanguage)) { return _overrideLanguage; } try { Localization instance = Localization.instance; if (instance == null) { return "English"; } if (M_GetSelectedLanguage != null) { string text = M_GetSelectedLanguage.Invoke(instance, null) as string; if (!string.IsNullOrEmpty(text)) { LogLanguageSourceOnce("GetSelectedLanguage", text); return text; } } if (F_m_language != null) { string text2 = F_m_language.GetValue(instance) as string; if (!string.IsNullOrEmpty(text2)) { LogLanguageSourceOnce("m_language", text2); return text2; } } } catch (Exception ex) { ItemDrawers instance2 = ItemDrawers.Instance; if (instance2 != null) { ManualLogSource log = instance2.Log; if (log != null) { log.LogWarning((object)("ModLocalization: GetCurrentLanguage failed: " + ex.Message)); } } } return "English"; } private static void LogLanguageSourceOnce(string source, string lang) { if (_loggedLanguageSource) { return; } _loggedLanguageSource = true; ItemDrawers instance = ItemDrawers.Instance; if (instance != null) { ManualLogSource log = instance.Log; if (log != null) { log.LogInfo((object)("ModLocalization: language from " + source + " = '" + lang + "'")); } } } private static Dictionary<string, string> GetForLanguage(string lang) { if (_translations.TryGetValue(lang, out var value) && value.Count > 0) { return value; } if (_translations.TryGetValue("English", out var value2) && value2.Count > 0) { return value2; } return new Dictionary<string, string>(); } private static Dictionary<string, string> ParseSimpleJson(string json) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (string.IsNullOrEmpty(json)) { return dictionary; } json = json.Trim(); if (json.StartsWith("{")) { json = json.Substring(1); } if (json.EndsWith("}")) { json = json.Substring(0, json.Length - 1); } int i = 0; while (i < json.Length) { for (; i < json.Length && (json[i] == ' ' || json[i] == ',' || json[i] == '\n' || json[i] == '\r' || json[i] == '\t'); i++) { } if (i >= json.Length || json[i] != '"') { break; } string key = ReadString(json, ref i); for (; i < json.Length && json[i] != ':'; i++) { } for (i++; i < json.Length && (json[i] == ' ' || json[i] == '\n' || json[i] == '\r' || json[i] == '\t'); i++) { } if (i < json.Length && json[i] == '"') { string value = ReadString(json, ref i); dictionary[key] = value; } } return dictionary; } private static string ReadString(string json, ref int i) { i++; StringBuilder stringBuilder = new StringBuilder(); while (i < json.Length) { char c = json[i]; if (c == '\\' && i + 1 < json.Length) { char c2 = json[i + 1]; switch (c2) { case 'n': stringBuilder.Append('\n'); break; case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case '"': stringBuilder.Append('"'); break; case '\\': stringBuilder.Append('\\'); break; case '/': stringBuilder.Append('/'); break; default: stringBuilder.Append(c2); break; } i += 2; } else { if (c == '"') { i++; break; } stringBuilder.Append(c); i++; } } return stringBuilder.ToString(); } } [HarmonyPatch(typeof(Localization), "SetupLanguage")] internal static class LocalizationLanguageChangePatch { [HarmonyPostfix] internal static void Postfix(string language) { try { ModLocalization.OnLanguageChanged(language); } catch { } } } public static class NorseFontLoader { private static TMP_FontAsset _cached; private static bool _tried; public static TMP_FontAsset Load() { if (_tried) { return _cached; } _tried = true; try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string s) => s.EndsWith("Norse-Bold.ttf") || s.EndsWith("Norse-Bold")); if (text == null) { ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: Norse-Bold.ttf not found in embedded resources."); return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); byte[] bytes = memoryStream.ToArray(); string text2 = Path.Combine(Application.temporaryCachePath, "Cybrp_Norse-Bold.ttf"); File.WriteAllBytes(text2, bytes); try { MethodInfo methodInfo = (from m in typeof(TMP_FontAsset).GetMethods(BindingFlags.Static | BindingFlags.Public) where m.Name == "CreateFontAsset" && m.GetParameters().Length == 7 && m.GetParameters()[0].ParameterType == typeof(string) select m).FirstOrDefault(); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; array[0] = text2; array[1] = 0; array[2] = 90; array[3] = 9; Type parameterType = parameters[4].ParameterType; array[4] = Enum.ToObject(parameterType, 4165); array[5] = 1024; array[6] = 1024; object? obj = methodInfo.Invoke(null, array); TMP_FontAsset val = (TMP_FontAsset)((obj is TMP_FontAsset) ? obj : null); if ((Object)(object)val != (Object)null) { val.atlasPopulationMode = (AtlasPopulationMode)1; Object.DontDestroyOnLoad((Object)(object)val); _cached = val; ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: loaded Norse font via file path (Strategy 1)."); return _cached; } } } catch (Exception ex) { ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: Strategy 1 failed (" + ex.Message + ").")); } try { Font val2 = Font.CreateDynamicFontFromOSFont(text2, 90); if ((Object)(object)val2 != (Object)null) { val2.RequestCharactersInTexture("0123456789", 90); MethodInfo method = typeof(TMP_FontAsset).GetMethod("CreateFontAsset", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Font) }, null); if (method != null) { object? obj2 = method.Invoke(null, new object[1] { val2 }); TMP_FontAsset val3 = (TMP_FontAsset)((obj2 is TMP_FontAsset) ? obj2 : null); if ((Object)(object)val3 != (Object)null) { val3.atlasPopulationMode = (AtlasPopulationMode)1; Object.DontDestroyOnLoad((Object)(object)val3); Object.DontDestroyOnLoad((Object)(object)val2); _cached = val3; ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: loaded Norse font via Unity Font (Strategy 2)."); return _cached; } } } } catch (Exception ex2) { ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: Strategy 2 failed (" + ex2.Message + ").")); } try { Font val4 = Font.CreateDynamicFontFromOSFont("Norse-Bold", 90); if ((Object)(object)val4 != (Object)null) { val4.RequestCharactersInTexture("0123456789", 90); MethodInfo method2 = typeof(TMP_FontAsset).GetMethod("CreateFontAsset", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Font) }, null); if (method2 != null) { object? obj3 = method2.Invoke(null, new object[1] { val4 }); TMP_FontAsset val5 = (TMP_FontAsset)((obj3 is TMP_FontAsset) ? obj3 : null); if ((Object)(object)val5 != (Object)null) { val5.atlasPopulationMode = (AtlasPopulationMode)1; Object.DontDestroyOnLoad((Object)(object)val5); Object.DontDestroyOnLoad((Object)(object)val4); _cached = val5; ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: loaded Norse font via OS font name (Strategy 3)."); return _cached; } } } } catch (Exception ex3) { ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: Strategy 3 failed (" + ex3.Message + ").")); } ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: all strategies failed, using default font with size/color changes only."); return null; } catch (Exception ex4) { ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: could not load Norse font (" + ex4.Message + "), using default font with size/color changes.")); return null; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetScene_Awake_Patch { private static readonly FieldInfo F_namedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs"); private static readonly FieldInfo F_prefabs = AccessTools.Field(typeof(ZNetScene), "m_prefabs"); [UsedImplicitly] private static void Postfix(ZNetScene __instance) { //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)F_namedPrefabs.GetValue(__instance); List<GameObject> list = (List<GameObject>)F_prefabs.GetValue(__instance); dictionary[StringExtensionMethods.GetStableHashCode(((Object)ItemDrawers.Explosion).name)] = ItemDrawers.Explosion; foreach (string allDrawerPrefabName in ItemDrawers.AllDrawerPrefabNames) { GameObject drawerPrefab = ItemDrawers.GetDrawerPrefab(allDrawerPrefabName); if ((Object)(object)drawerPrefab == (Object)null) { ItemDrawers.Instance.Log.LogWarning((object)("Drawer prefab '" + allDrawerPrefabName + "' not found in AssetBundle!")); continue; } Piece val = drawerPrefab.GetComponent<Piece>(); if ((Object)(object)val == (Object)null) { val = drawerPrefab.AddComponent<Piece>(); } if (allDrawerPrefabName.Contains("Wood") || allDrawerPrefabName.Contains("NoModel")) { GameObject prefab = __instance.GetPrefab("woodwall"); if ((Object)(object)prefab != (Object)null) { val.m_placeEffect = prefab.GetComponent<Piece>().m_placeEffect; } } else if (allDrawerPrefabName.Contains("Stone")) { GameObject prefab2 = __instance.GetPrefab("stone_wall_1x1"); if ((Object)(object)prefab2 != (Object)null) { val.m_placeEffect = prefab2.GetComponent<Piece>().m_placeEffect; } } else if (allDrawerPrefabName.Contains("Marble")) { GameObject prefab3 = __instance.GetPrefab("blackmarble_1x1"); if ((Object)(object)prefab3 != (Object)null) { val.m_placeEffect = prefab3.GetComponent<Piece>().m_placeEffect; } } if ((Object)(object)drawerPrefab.GetComponent<DrawerComponent>() == (Object)null) { drawerPrefab.AddComponent<DrawerComponent>(); } int stableHashCode = StringExtensionMethods.GetStableHashCode(allDrawerPrefabName); dictionary[stableHashCode] = drawerPrefab; if (!list.Contains(drawerPrefab)) { list.Add(drawerPrefab); } } PieceCategory category = (PieceCategory)(((??)PieceManager.Instance.GetPieceCategory("itemdrawers")) ?? 4); foreach (string allDrawerPrefabName2 in ItemDrawers.AllDrawerPrefabNames) { GameObject drawerPrefab2 = ItemDrawers.GetDrawerPrefab(allDrawerPrefabName2); if (!((Object)(object)drawerPrefab2 == (Object)null)) { Piece component = drawerPrefab2.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { component.m_category = category; } } } ItemDrawers.Instance.Log.LogInfo((object)$"Cybrp ItemDrawers: registered {ItemDrawers.AllDrawerPrefabNames.Count} drawer prefabs."); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDB_Awake_Patch { [UsedImplicitly] private static void Postfix(ObjectDB __instance) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown if ((Object)(object)__instance.GetItemPrefab("YmirRemains") == (Object)null) { return; } GameObject itemPrefab = __instance.GetItemPrefab("Hammer"); if ((Object)(object)itemPrefab == (Object)null) { return; } PieceTable val = itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces; if ((Object)(object)val == (Object)null) { return; } IReadOnlyList<(string, string, int)> allDrawerRecipes = ItemDrawers.AllDrawerRecipes; IReadOnlyList<string> allDrawerPrefabNames = ItemDrawers.AllDrawerPrefabNames; for (int i = 0; i < allDrawerPrefabNames.Count && i < allDrawerRecipes.Count; i++) { string text = allDrawerPrefabNames[i]; (string, string, int) tuple = allDrawerRecipes[i]; string item = tuple.Item1; string item2 = tuple.Item2; int item3 = tuple.Item3; GameObject drawerPrefab = ItemDrawers.GetDrawerPrefab(text); if ((Object)(object)drawerPrefab == (Object)null) { continue; } Piece component = drawerPrefab.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { continue; } component.m_name