Decompiled source of SenpaisChest v2.2.4
SenpaisChest.dll
Decompiled 16 hours 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using PSS; using SenpaisChest.ChestLabels; using SenpaisChest.ChestLabels.Extensions; using SenpaisChest.Config; using SenpaisChest.Data; using SenpaisChest.Integration; using SenpaisChest.UI; using SunHavenMuseumUtilityTracker; using SunHavenMuseumUtilityTracker.Data; using SunhavenMods.Shared; using SunhavenTodo; using SunhavenTodo.Data; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; using Wish; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SenpaisChest")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+215d19542340737939c33a78dbefe54932fcbb1c")] [assembly: AssemblyProduct("SenpaisChest")] [assembly: AssemblyTitle("SenpaisChest")] [assembly: InternalsVisibleTo("HavenDevTools")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SunhavenMods.Shared { public static class VersionChecker { public class VersionCheckResult { public bool Success { get; set; } public bool UpdateAvailable { get; set; } public string CurrentVersion { get; set; } public string LatestVersion { get; set; } public string ModName { get; set; } public string NexusUrl { get; set; } public string Changelog { get; set; } public string ErrorMessage { get; set; } } private class VersionCheckRunner : MonoBehaviour { public void StartCheck(string pluginGuid, string currentVersion, Action<VersionCheckResult> onComplete) { ((MonoBehaviour)this).StartCoroutine(CheckVersionCoroutine(pluginGuid, currentVersion, onComplete)); } private IEnumerator CheckVersionCoroutine(string pluginGuid, string currentVersion, Action<VersionCheckResult> onComplete) { VersionCheckResult result = new VersionCheckResult { CurrentVersion = currentVersion }; UnityWebRequest www = UnityWebRequest.Get("https://azraelgodking.github.io/SunhavenMod/versions.json"); try { www.timeout = 10; yield return www.SendWebRequest(); if ((int)www.result == 2 || (int)www.result == 3) { result.Success = false; result.ErrorMessage = "Network error: " + www.error; LogWarning(result.ErrorMessage); onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); yield break; } try { string json = www.downloadHandler.text; string modPattern = "\"" + Regex.Escape(pluginGuid) + "\"\\s*:\\s*\\{([^}]+)\\}"; Match modMatch = Regex.Match(json, modPattern, RegexOptions.Singleline); if (!modMatch.Success) { result.Success = false; result.ErrorMessage = "Mod '" + pluginGuid + "' not found in versions.json"; LogWarning(result.ErrorMessage); onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); yield break; } string modJson = modMatch.Groups[1].Value; result.LatestVersion = ExtractJsonString(modJson, "version"); result.ModName = ExtractJsonString(modJson, "name"); result.NexusUrl = ExtractJsonString(modJson, "nexus"); result.Changelog = ExtractJsonString(modJson, "changelog"); if (string.IsNullOrEmpty(result.LatestVersion)) { result.Success = false; result.ErrorMessage = "Could not parse version from response"; LogWarning(result.ErrorMessage); onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); yield break; } result.Success = true; result.UpdateAvailable = CompareVersions(currentVersion, result.LatestVersion) < 0; if (result.UpdateAvailable) { Log("Update available for " + result.ModName + ": " + currentVersion + " -> " + result.LatestVersion); } else { Log(result.ModName + " is up to date (v" + currentVersion + ")"); } } catch (Exception ex) { result.Success = false; result.ErrorMessage = "Parse error: " + ex.Message; LogError(result.ErrorMessage); } } finally { ((IDisposable)www)?.Dispose(); } onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); } private string ExtractJsonString(string json, string key) { string pattern = "\"" + key + "\"\\s*:\\s*(?:\"([^\"]*)\"|null)"; Match match = Regex.Match(json, pattern); return match.Success ? match.Groups[1].Value : null; } } private const string VersionsUrl = "https://azraelgodking.github.io/SunhavenMod/versions.json"; private static ManualLogSource _logger; public static void CheckForUpdate(string pluginGuid, string currentVersion, ManualLogSource logger = null, Action<VersionCheckResult> onComplete = null) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) _logger = logger; VersionCheckRunner versionCheckRunner = new GameObject("VersionChecker").AddComponent<VersionCheckRunner>(); Object.DontDestroyOnLoad((Object)(object)((Component)versionCheckRunner).gameObject); SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(((Component)versionCheckRunner).gameObject); versionCheckRunner.StartCheck(pluginGuid, currentVersion, onComplete); } public static int CompareVersions(string v1, string v2) { if (string.IsNullOrEmpty(v1) || string.IsNullOrEmpty(v2)) { return 0; } v1 = v1.TrimStart('v', 'V'); v2 = v2.TrimStart('v', 'V'); string[] array = v1.Split(new char[1] { '.' }); string[] array2 = v2.Split(new char[1] { '.' }); int num = Math.Max(array.Length, array2.Length); for (int i = 0; i < num; i++) { int result; int num2 = ((i < array.Length && int.TryParse(array[i], out result)) ? result : 0); int result2; int num3 = ((i < array2.Length && int.TryParse(array2[i], out result2)) ? result2 : 0); if (num2 < num3) { return -1; } if (num2 > num3) { return 1; } } return 0; } internal static void Log(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)("[VersionChecker] " + message)); } } internal static void LogWarning(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[VersionChecker] " + message)); } } internal static void LogError(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogError((object)("[VersionChecker] " + message)); } } } public static class VersionCheckerExtensions { public static void NotifyUpdateAvailable(this VersionChecker.VersionCheckResult result, ManualLogSource logger = null) { if (!result.UpdateAvailable) { return; } string text = result.ModName + " update available: v" + result.LatestVersion; try { Type type = ReflectionHelper.FindWishType("NotificationStack"); if (type != null) { Type type2 = ReflectionHelper.FindType("SingletonBehaviour`1", "Wish"); if (type2 != null) { Type type3 = type2.MakeGenericType(type); object obj = type3.GetProperty("Instance")?.GetValue(null); if (obj != null) { MethodInfo method = type.GetMethod("SendNotification", new Type[5] { typeof(string), typeof(int), typeof(int), typeof(bool), typeof(bool) }); if (method != null) { method.Invoke(obj, new object[5] { text, 0, 1, false, true }); return; } } } } } catch (Exception ex) { if (logger != null) { logger.LogWarning((object)("Failed to send native notification: " + ex.Message)); } } if (logger != null) { logger.LogWarning((object)("[UPDATE AVAILABLE] " + text)); } if (!string.IsNullOrEmpty(result.NexusUrl) && logger != null) { logger.LogWarning((object)("Download at: " + result.NexusUrl)); } } } public static class SceneRootSurvivor { private static readonly object Lock = new object(); private static readonly List<string> NoKillSubstrings = new List<string>(); private static Harmony _harmony; public static void TryRegisterPersistentRunnerGameObject(GameObject go) { if (!((Object)(object)go == (Object)null)) { TryAddNoKillListSubstring(((Object)go).name); } } public static void TryAddNoKillListSubstring(string nameSubstring) { if (string.IsNullOrEmpty(nameSubstring)) { return; } lock (Lock) { bool flag = false; for (int i = 0; i < NoKillSubstrings.Count; i++) { if (string.Equals(NoKillSubstrings[i], nameSubstring, StringComparison.OrdinalIgnoreCase)) { flag = true; break; } } if (!flag) { NoKillSubstrings.Add(nameSubstring); } } EnsurePatched(); } private static void EnsurePatched() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown if (_harmony != null) { return; } lock (Lock) { if (_harmony == null) { MethodInfo methodInfo = AccessTools.Method(typeof(Scene), "GetRootGameObjects", Type.EmptyTypes, (Type[])null); if (!(methodInfo == null)) { string text = typeof(SceneRootSurvivor).Assembly.GetName().Name ?? "Unknown"; Harmony val = new Harmony("SunhavenMods.SceneRootSurvivor." + text); val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(SceneRootSurvivor), "OnGetRootGameObjectsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _harmony = val; } } } } private static void OnGetRootGameObjectsPostfix(ref GameObject[] __result) { if (__result == null || __result.Length == 0) { return; } List<string> list; lock (Lock) { if (NoKillSubstrings.Count == 0) { return; } list = new List<string>(NoKillSubstrings); } List<GameObject> list2 = new List<GameObject>(__result); for (int i = 0; i < list.Count; i++) { string noKill = list[i]; list2.RemoveAll((GameObject a) => (Object)(object)a != (Object)null && ((Object)a).name.IndexOf(noKill, StringComparison.OrdinalIgnoreCase) >= 0); } __result = list2.ToArray(); } } public static class ReflectionHelper { public static readonly BindingFlags AllBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; public static Type FindType(string typeName, params string[] namespaces) { Type type = AccessTools.TypeByName(typeName); if (type != null) { return type; } foreach (string text in namespaces) { type = AccessTools.TypeByName(text + "." + typeName); if (type != null) { return type; } } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == typeName || t.FullName == typeName); if (type != null) { return type; } } catch (ReflectionTypeLoadException) { } } return null; } public static Type FindWishType(string typeName) { return FindType(typeName, "Wish"); } public static object GetStaticValue(Type type, string memberName) { if (type == null) { return null; } PropertyInfo property = type.GetProperty(memberName, AllBindingFlags); if (property != null && property.GetMethod != null) { return property.GetValue(null); } FieldInfo field = type.GetField(memberName, AllBindingFlags); if (field != null) { return field.GetValue(null); } return null; } public static object GetSingletonInstance(Type type) { if (type == null) { return null; } string[] array = new string[5] { "Instance", "instance", "_instance", "Singleton", "singleton" }; string[] array2 = array; foreach (string memberName in array2) { object staticValue = GetStaticValue(type, memberName); if (staticValue != null) { return staticValue; } } return null; } public static object GetInstanceValue(object instance, string memberName) { if (instance == null) { return null; } Type type = instance.GetType(); while (type != null) { PropertyInfo property = type.GetProperty(memberName, AllBindingFlags); if (property != null && property.GetMethod != null) { return property.GetValue(instance); } FieldInfo field = type.GetField(memberName, AllBindingFlags); if (field != null) { return field.GetValue(instance); } type = type.BaseType; } return null; } public static bool SetInstanceValue(object instance, string memberName, object value) { if (instance == null) { return false; } Type type = instance.GetType(); while (type != null) { PropertyInfo property = type.GetProperty(memberName, AllBindingFlags); if (property != null && property.SetMethod != null) { property.SetValue(instance, value); return true; } FieldInfo field = type.GetField(memberName, AllBindingFlags); if (field != null) { field.SetValue(instance, value); return true; } type = type.BaseType; } return false; } public static object InvokeMethod(object instance, string methodName, params object[] args) { if (instance == null) { return null; } Type type = instance.GetType(); Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes; MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null); if (methodInfo == null) { methodInfo = type.GetMethod(methodName, AllBindingFlags); } if (methodInfo == null) { return null; } return methodInfo.Invoke(instance, args); } public static object InvokeStaticMethod(Type type, string methodName, params object[] args) { if (type == null) { return null; } Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes; MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null); if (methodInfo == null) { methodInfo = type.GetMethod(methodName, AllBindingFlags); } if (methodInfo == null) { return null; } return methodInfo.Invoke(null, args); } public static FieldInfo[] GetAllFields(Type type) { if (type == null) { return Array.Empty<FieldInfo>(); } FieldInfo[] fields = type.GetFields(AllBindingFlags); IEnumerable<FieldInfo> second; if (!(type.BaseType != null) || !(type.BaseType != typeof(object))) { second = Enumerable.Empty<FieldInfo>(); } else { IEnumerable<FieldInfo> allFields = GetAllFields(type.BaseType); second = allFields; } return fields.Concat(second).Distinct().ToArray(); } public static PropertyInfo[] GetAllProperties(Type type) { if (type == null) { return Array.Empty<PropertyInfo>(); } PropertyInfo[] properties = type.GetProperties(AllBindingFlags); IEnumerable<PropertyInfo> second; if (!(type.BaseType != null) || !(type.BaseType != typeof(object))) { second = Enumerable.Empty<PropertyInfo>(); } else { IEnumerable<PropertyInfo> allProperties = GetAllProperties(type.BaseType); second = allProperties; } return (from p in properties.Concat(second) group p by p.Name into g select g.First()).ToArray(); } public static T TryGetValue<T>(object instance, string memberName, T defaultValue = default(T)) { try { object instanceValue = GetInstanceValue(instance, memberName); if (instanceValue is T result) { return result; } if (instanceValue != null && typeof(T).IsAssignableFrom(instanceValue.GetType())) { return (T)instanceValue; } return defaultValue; } catch { return defaultValue; } } } public static class ItemSearch { private static readonly ManualLogSource _log = Logger.CreateLogSource("ItemSearch"); private static object _dbInstance; private static FieldInfo _dictField; private static readonly List<KeyValuePair<int, string>> _bufferExact = new List<KeyValuePair<int, string>>(); private static readonly List<KeyValuePair<int, string>> _bufferStartsWith = new List<KeyValuePair<int, string>>(); private static readonly List<KeyValuePair<int, string>> _bufferContains = new List<KeyValuePair<int, string>>(); public static string FormatDisplay(string name, int itemId) { if (string.IsNullOrEmpty(name)) { return $"#{itemId}"; } return $"{name} (#{itemId})"; } public static List<KeyValuePair<int, string>> SearchItems(string query, int maxResults = 50) { List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>(); if (string.IsNullOrEmpty(query) || query.Trim().Length < 2) { return list; } try { Dictionary<int, ItemSellInfo> itemDictionary = GetItemDictionary(); if (itemDictionary == null) { return list; } string text = query.Trim().ToLowerInvariant(); int result; bool flag = int.TryParse(query.Trim(), out result); _bufferExact.Clear(); _bufferStartsWith.Clear(); _bufferContains.Clear(); foreach (KeyValuePair<int, ItemSellInfo> item2 in itemDictionary) { int key = item2.Key; string text2 = item2.Value?.name; if (!string.IsNullOrEmpty(text2)) { KeyValuePair<int, string> item = new KeyValuePair<int, string>(key, text2); string text3 = text2.ToLowerInvariant(); if (flag && key == result) { _bufferExact.Add(item); } else if (text3 == text) { _bufferExact.Add(item); } else if (text3.StartsWith(text)) { _bufferStartsWith.Add(item); } else if (text3.Contains(text)) { _bufferContains.Add(item); } else if (flag && key.ToString().Contains(query.Trim())) { _bufferContains.Add(item); } } } _bufferStartsWith.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => string.Compare(a.Value, b.Value, StringComparison.OrdinalIgnoreCase)); _bufferContains.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => string.Compare(a.Value, b.Value, StringComparison.OrdinalIgnoreCase)); list.AddRange(_bufferExact); list.AddRange(_bufferStartsWith); list.AddRange(_bufferContains); if (list.Count > maxResults) { list.RemoveRange(maxResults, list.Count - maxResults); } } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogDebug((object)("[ItemSearch] SearchItems error: " + ex.Message)); } } return list; } public static string GetItemName(int itemId) { try { Dictionary<int, ItemSellInfo> itemDictionary = GetItemDictionary(); if (itemDictionary == null || !itemDictionary.ContainsKey(itemId)) { return null; } return itemDictionary[itemId]?.name; } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogDebug((object)$"[ItemSearch] GetItemName({itemId}): {ex.Message}"); } return null; } } public static ItemSellInfo GetItemSellInfo(int itemId) { try { Dictionary<int, ItemSellInfo> itemDictionary = GetItemDictionary(); if (itemDictionary != null && itemDictionary.TryGetValue(itemId, out var value)) { return value; } } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogDebug((object)$"[ItemSearch] GetItemSellInfo({itemId}): {ex.Message}"); } } return null; } private static Dictionary<int, ItemSellInfo> GetItemDictionary() { try { if (_dbInstance != null) { object dbInstance = _dbInstance; Object val = (Object)((dbInstance is Object) ? dbInstance : null); if (val == null || !(val == (Object)null)) { goto IL_006e; } } _dbInstance = null; _dictField = null; _dbInstance = GetSingletonInstance("Wish.ItemInfoDatabase"); if (_dbInstance != null) { _dictField = _dbInstance.GetType().GetField("allItemSellInfos", BindingFlags.Instance | BindingFlags.Public); } goto IL_006e; IL_006e: if (_dbInstance == null || _dictField == null) { return null; } return _dictField.GetValue(_dbInstance) as Dictionary<int, ItemSellInfo>; } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogDebug((object)("[ItemSearch] GetItemDictionary: " + ex.Message)); } return null; } } private static object GetSingletonInstance(string typeName) { try { Type type = AccessTools.TypeByName("Wish.SingletonBehaviour`1"); if (type == null) { return null; } Type type2 = AccessTools.TypeByName(typeName); if (type2 == null) { return null; } Type type3 = type.MakeGenericType(type2); return type3.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)?.GetValue(null); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogDebug((object)("[ItemSearch] GetSingletonInstance(" + typeName + "): " + ex.Message)); } return null; } } } public static class TextInputFocusGuard { private const float DefaultPollIntervalSeconds = 0.25f; private static float _nextPollTime = -1f; private static bool _cachedDefer; private static bool _tmpTypeLookupDone; private static Type _tmpInputFieldType; private static bool _qcLookupDone; private static Type _qcType; private static PropertyInfo _qcInstanceProp; private static PropertyInfo _qcIsActiveProp; private static FieldInfo _qcIsActiveField; public static bool ShouldDeferModHotkeys(ManualLogSource debugLog = null, float pollIntervalSeconds = 0.25f) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextPollTime) { return _cachedDefer; } _nextPollTime = realtimeSinceStartup + Mathf.Max(0.05f, pollIntervalSeconds); bool flag = false; try { if (GUIUtility.keyboardControl != 0) { flag = true; } if (!flag) { EventSystem current = EventSystem.current; GameObject val = ((current != null) ? current.currentSelectedGameObject : null); if ((Object)(object)val != (Object)null) { if ((Object)(object)val.GetComponent<InputField>() != (Object)null) { flag = true; } else if (TryGetTmpInputField(val)) { flag = true; } } } if (!flag && IsQuantumConsoleActive()) { flag = true; } } catch (Exception ex) { if (debugLog != null) { debugLog.LogDebug((object)("[TextInputFocusGuard] " + ex.Message)); } } _cachedDefer = flag; return flag; } private static bool TryGetTmpInputField(GameObject go) { if (!_tmpTypeLookupDone) { _tmpTypeLookupDone = true; _tmpInputFieldType = AccessTools.TypeByName("TMPro.TMP_InputField"); } if (_tmpInputFieldType == null) { return false; } return (Object)(object)go.GetComponent(_tmpInputFieldType) != (Object)null; } private static bool IsQuantumConsoleActive() { try { if (!_qcLookupDone) { _qcLookupDone = true; _qcType = AccessTools.TypeByName("QFSW.QC.QuantumConsole"); if (_qcType != null) { _qcInstanceProp = AccessTools.Property(_qcType, "Instance"); _qcIsActiveProp = AccessTools.Property(_qcType, "IsActive"); _qcIsActiveField = AccessTools.Field(_qcType, "isActive") ?? AccessTools.Field(_qcType, "_isActive"); } } if (_qcType == null) { return false; } object obj = _qcInstanceProp?.GetValue(null); if (obj == null) { return false; } if (_qcIsActiveProp != null && _qcIsActiveProp.PropertyType == typeof(bool)) { return (bool)_qcIsActiveProp.GetValue(obj); } if (_qcIsActiveField != null && _qcIsActiveField.FieldType == typeof(bool)) { return (bool)_qcIsActiveField.GetValue(obj); } } catch { } return false; } } } namespace SenpaisChest { [BepInPlugin("com.azraelgodking.senpaischest", "Senpai's Chest", "2.2.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private static SmartChestManager _staticManager; private static SmartChestSaveSystem _staticSaveSystem; private static SmartChestUI _staticUI; private static SmartChestConfig _staticConfig; private static MuseumTodoIntegration _museumTodoIntegration; internal static Chest CurrentInteractingChest; private static string _gameplaySessionCharacter; private static bool _applicationQuitting; private static readonly Dictionary<int, float> _sceneDiscardSuppressByHandle = new Dictionary<int, float>(); private const float SceneDiscardSuppressSeconds = 20f; private Harmony _harmony; private SmartChestManager _manager; private SmartChestSaveSystem _saveSystem; private SmartChestUI _ui; private SmartChestConfig _config; private static GameObject _persistentRunner; private static SmartChestPersistentRunner _updateRunner; private bool _wasInMenuScene = true; private static GameObject _pendingChestPanel; private static Chest _pendingChest; private static int _pendingChestButtonFrames; private const string SenpaisChestConfigPanelName = "SenpaisChest_ConfigPanel"; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } public static ConfigFile ConfigFile { get; private set; } private void Awake() { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_01f1: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; ConfigFile = CreateNamedConfig(); Log.LogInfo((object)"Loading Senpai's Chest v2.2.4"); CreatePersistentRunner(); try { _config = new SmartChestConfig(); _config.Initialize(ConfigFile); _staticConfig = _config; _config.UIScale.SettingChanged += delegate { float scale = Mathf.Clamp(_config.UIScale.Value, 0.5f, 2.5f); _staticUI?.SetScale(scale); }; _manager = new SmartChestManager(); _saveSystem = new SmartChestSaveSystem(_manager); _staticManager = _manager; _staticSaveSystem = _saveSystem; GameObject val = new GameObject("SenpaisChest_UI"); Object.DontDestroyOnLoad((Object)(object)val); _ui = val.AddComponent<SmartChestUI>(); _ui.Initialize(_manager); _ui.SetScale(Mathf.Clamp(_config.UIScale.Value, 0.5f, 2.5f)); _staticUI = _ui; _harmony = new Harmony("com.azraelgodking.senpaischest"); ApplyPatches(); InitializeIntegrations(); SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.activeSceneChanged += OnActiveSceneChanged; if (_config.CheckForUpdates.Value) { VersionChecker.CheckForUpdate("com.azraelgodking.senpaischest", "2.2.4", Log, delegate(VersionChecker.VersionCheckResult result) { result.NotifyUpdateAvailable(Log); }); } Log.LogInfo((object)"Senpai's Chest loaded successfully!"); Log.LogInfo((object)string.Format("Press {0}{1} to configure a chest while interacting with it", _config.RequireCtrlModifier.Value ? "Ctrl+" : "", _config.ToggleKey.Value)); if (_config.EnableChestLabels.Value) { Log.LogInfo((object)"Chest Labels enabled - labels shown above Chest and BankChest (not Hoppers/Animal Feeders)"); } } catch (Exception arg) { Log.LogError((object)string.Format("Failed to load {0}: {1}", "Senpai's Chest", arg)); } } private void CreatePersistentRunner() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown if ((Object)(object)_persistentRunner != (Object)null) { Log.LogInfo((object)"PersistentRunner already exists"); return; } _persistentRunner = new GameObject("SenpaisChest_PersistentRunner"); Object.DontDestroyOnLoad((Object)(object)_persistentRunner); ((Object)_persistentRunner).hideFlags = (HideFlags)61; SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(_persistentRunner); _updateRunner = _persistentRunner.AddComponent<SmartChestPersistentRunner>(); Log.LogInfo((object)"Created hidden PersistentRunner"); } private static ConfigFile CreateNamedConfig() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "SenpaisChest.cfg"); string text2 = Path.Combine(Paths.ConfigPath, "com.azraelgodking.senpaischest.cfg"); try { if (!File.Exists(text) && File.Exists(text2)) { File.Copy(text2, text); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[Config] Migration to SenpaisChest.cfg failed: " + ex.Message)); } } return new ConfigFile(text, true); } public static void EnsureUIComponentsExist() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown try { if ((Object)(object)_persistentRunner == (Object)null || (Object)(object)_updateRunner == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[EnsureUI] Recreating PersistentRunner..."); } _persistentRunner = new GameObject("SenpaisChest_PersistentRunner"); Object.DontDestroyOnLoad((Object)(object)_persistentRunner); ((Object)_persistentRunner).hideFlags = (HideFlags)61; SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(_persistentRunner); _updateRunner = _persistentRunner.AddComponent<SmartChestPersistentRunner>(); } if ((Object)(object)_staticUI == (Object)null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"[EnsureUI] Recreating SmartChestUI..."); } GameObject val = new GameObject("SenpaisChest_UI"); Object.DontDestroyOnLoad((Object)(object)val); _staticUI = val.AddComponent<SmartChestUI>(); _staticUI.Initialize(_staticManager); _staticUI.SetScale(Mathf.Clamp(_staticConfig.UIScale.Value, 0.5f, 2.5f)); } } catch (Exception ex) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogError((object)("[EnsureUI] Error recreating UI: " + ex.Message)); } } } private void InitializeIntegrations() { try { Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos; bool flag = pluginInfos.ContainsKey("com.azraelgodking.sunhavenmuseumutilitytracker"); bool flag2 = pluginInfos.ContainsKey("com.azraelgodking.sunhaventodo"); if (flag && flag2) { _museumTodoIntegration = new MuseumTodoIntegration(); return; } if (!flag) { Log.LogInfo((object)"[Integrations] S.M.U.T. not found"); } if (!flag2) { Log.LogInfo((object)"[Integrations] SunhavenTodo not found"); } Log.LogInfo((object)"[Integrations] Museum todo integration disabled (requires both S.M.U.T. and Todo)"); } catch (Exception ex) { Log.LogWarning((object)("[Integrations] Error initializing: " + ex.Message)); } } private void ApplyPatches() { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Expected O, but got Unknown //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Expected O, but got Unknown //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Expected O, but got Unknown //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Expected O, but got Unknown //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Expected O, but got Unknown try { PatchMethod(typeof(Player), "InitializeAsOwner", typeof(Plugin), "OnPlayerInitialized"); PatchMethod(typeof(Chest), "Interact", typeof(Plugin), "OnChestInteract", new Type[1] { typeof(int) }); MethodInfo methodInfo = AccessTools.Method(typeof(Chest), "EndInteract", new Type[1] { typeof(int) }, (Type[])null); if (methodInfo != null) { HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnChestEndInteract_Prefix", (Type[])null, (Type[])null)); _harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Chest.EndInteract (prefix)"); } else { Log.LogWarning((object)"Could not find method Chest.EndInteract"); } Type type = AccessTools.TypeByName("Wish.UIHandler"); Type type2 = AccessTools.TypeByName("Wish.IExternalUIHandler"); if (type != null && type2 != null) { MethodInfo methodInfo2 = AccessTools.Method(type, "OpenUI", new Type[5] { typeof(GameObject), typeof(Transform), typeof(bool), typeof(bool), type2 }, (Type[])null); if (methodInfo2 != null) { HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnUIHandlerOpenUI_Postfix", (Type[])null, (Type[])null)); _harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched UIHandler.OpenUI (postfix)"); } else { Log.LogWarning((object)"Could not find method UIHandler.OpenUI"); } } else { Log.LogWarning((object)"Could not find Wish.UIHandler or Wish.IExternalUIHandler for chest button integration"); } MethodInfo methodInfo3 = AccessTools.Method(typeof(Input), "GetKeyDown", new Type[1] { typeof(KeyCode) }, (Type[])null); if (methodInfo3 != null) { _harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnInputGetKeyDown_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Input.GetKeyDown (prefix)"); } MethodInfo methodInfo4 = AccessTools.Method(typeof(Input), "GetKey", new Type[1] { typeof(KeyCode) }, (Type[])null); if (methodInfo4 != null) { _harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnInputGetKey_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Input.GetKey (prefix)"); } MethodInfo methodInfo5 = AccessTools.Method(typeof(Input), "GetButtonDown", new Type[1] { typeof(string) }, (Type[])null); if (methodInfo5 != null) { _harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnInputGetButtonDown_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Input.GetButtonDown (prefix)"); } Type type3 = AccessTools.TypeByName("Wish.PlayerInput"); if (type3 != null) { MethodInfo methodInfo6 = AccessTools.Method(type3, "GetButtonDown", new Type[1] { typeof(string) }, (Type[])null); if (methodInfo6 != null) { _harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnPlayerInputGetButtonDown_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched PlayerInput.GetButtonDown(string) (prefix)"); } else { Log.LogWarning((object)"Could not find method PlayerInput.GetButtonDown(string)"); } } else { Log.LogWarning((object)"Could not find Wish.PlayerInput type for UICancel blocking"); } MethodInfo methodInfo7 = AccessTools.Method(typeof(Chest), "OnDisable", (Type[])null, (Type[])null); if (methodInfo7 != null) { _harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnChestOnDisable_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Chest.OnDisable (cleanup when chest removed from world)"); } ApplyChestLabelPatches(); Log.LogInfo((object)"Harmony patches applied successfully"); } catch (Exception arg) { Log.LogError((object)$"Failed to apply patches: {arg}"); } } private void ApplyChestLabelPatches() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown Type typeFromHandle = typeof(ChestLabelPatch); MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "SetMeta_Postfix", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeFromHandle, "OnEnable_Postfix", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeFromHandle, "InteractionPoint_Postfix", (Type[])null, (Type[])null); string[] array = new string[3] { "SetMeta", "ReceiveNewMeta", "SaveMeta" }; foreach (string text in array) { MethodInfo methodInfo4 = AccessTools.Method(typeof(Chest), text, (Type[])null, (Type[])null); if (methodInfo4 != null) { _harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)("Patched Chest." + text + " (labels)")); } } MethodInfo methodInfo5 = AccessTools.Method(typeof(Chest), "OnEnable", (Type[])null, (Type[])null); if (methodInfo5 != null) { _harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Chest.OnEnable (labels)"); } MethodInfo methodInfo6 = AccessTools.Method(typeof(Chest), "get_InteractionPoint", (Type[])null, (Type[])null); if (methodInfo6 != null) { _harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Chest.get_InteractionPoint (labels)"); } } private void PatchMethod(Type targetType, string methodName, Type patchType, string patchMethodName, Type[] parameters = null) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown MethodInfo methodInfo = ((parameters != null) ? AccessTools.Method(targetType, methodName, parameters, (Type[])null) : AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null)); if (methodInfo == null) { Log.LogWarning((object)("Could not find method " + targetType.Name + "." + methodName)); return; } MethodInfo methodInfo2 = AccessTools.Method(patchType, patchMethodName, (Type[])null, (Type[])null); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)("Patched " + targetType.Name + "." + methodName)); } private static void OnPlayerInitialized(Player __instance) { try { if ((Object)(object)__instance != (Object)(object)Player.Instance) { return; } EnsureUIComponentsExist(); string text = null; CharacterData currentCharacter = GameSave.CurrentCharacter; if (currentCharacter != null) { text = currentCharacter.characterName; } if (string.IsNullOrEmpty(text)) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"Player initialized but no character name found"); } return; } ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)("Player initialized: " + text)); } _staticManager?.SetCharacterName(text); _museumTodoIntegration?.Reset(); SmartChestSaveData data = _staticSaveSystem?.Load(text); _staticManager?.LoadData(data); _gameplaySessionCharacter = text; } catch (Exception arg) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogError((object)$"Error in OnPlayerInitialized: {arg}"); } } } private static void OnChestInteract(Chest __instance, int interactType) { if (interactType != 0) { return; } CurrentInteractingChest = __instance; try { Type type = ((object)__instance).GetType(); FieldInfo field = type.GetField("ui", BindingFlags.Instance | BindingFlags.NonPublic); if (!(field != null)) { return; } object? value = field.GetValue(__instance); GameObject val = (GameObject)((value is GameObject) ? value : null); if (val != null && (Object)(object)val != (Object)null) { _pendingChestPanel = val; _pendingChest = __instance; _pendingChestButtonFrames = 3; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"[SenpaisChest] Scheduled embedded panel from Chest.Interact (will add in 3 frames) - UI active: {val.activeInHierarchy}"); } } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogDebug((object)("[SenpaisChest] Could not schedule chest button: " + ex.Message)); } } } private static void OnChestOnDisable_Postfix(Chest __instance) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) try { if (_applicationQuitting || !Application.isPlaying || (Object)(object)__instance == (Object)null) { return; } GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null) { return; } Scene scene = gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { return; } if (IsDiscardedSceneSuppressed(scene)) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("[SenpaisChest] OnDisable: skip rule removal (scene '" + ((Scene)(ref scene)).name + "' discarded)")); } return; } string chestId = SmartChestManager.GetChestId(__instance); if (!string.IsNullOrEmpty(chestId) && _staticManager != null && _staticManager.RemoveSmartChest(chestId)) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)("[SenpaisChest] Removed smart chest rules (chest left world): " + chestId)); } } } catch (Exception ex) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogError((object)("[SenpaisChest] OnChestOnDisable_Postfix: " + ex.Message)); } } } private static bool OnInputGetKeyDown_Prefix(KeyCode key, ref bool __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)key != 8) { return true; } if (!SmartChestConfig.StaticBlockInputWhenTyping) { return true; } if (!SmartChestUI.ShouldBlockGameInput(_staticUI)) { return true; } __result = false; return false; } private static bool OnInputGetKey_Prefix(KeyCode key, ref bool __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)key != 8) { return true; } if (!SmartChestConfig.StaticBlockInputWhenTyping) { return true; } if (!SmartChestUI.ShouldBlockGameInput(_staticUI)) { return true; } __result = false; return false; } private static bool OnInputGetButtonDown_Prefix(string buttonName, ref bool __result) { if (string.IsNullOrEmpty(buttonName)) { return true; } if (!buttonName.Equals("Cancel", StringComparison.OrdinalIgnoreCase)) { return true; } if (!SmartChestConfig.StaticBlockInputWhenTyping) { return true; } if (!SmartChestUI.ShouldBlockGameInput(_staticUI)) { return true; } __result = false; return false; } private static bool OnPlayerInputGetButtonDown_Prefix(string button, ref bool __result) { if (!SmartChestConfig.StaticBlockInputWhenTyping) { return true; } if (!SmartChestUI.ShouldBlockGameInput(_staticUI)) { return true; } if (button == "UICancel" || button == "Close") { __result = false; return false; } return true; } private static bool OnChestEndInteract_Prefix(Chest __instance, int interactType) { if ((Object)(object)CurrentInteractingChest == (Object)(object)__instance && (Object)(object)_staticUI != (Object)null && _staticUI.IsVisible && !_staticUI.IsEmbedded) { return false; } if ((Object)(object)CurrentInteractingChest == (Object)(object)__instance) { CurrentInteractingChest = null; _staticUI?.Hide(); } return true; } private static void OnUIHandlerOpenUI_Postfix(object __instance, GameObject ui, Transform parent, bool playAudio, bool animate, object externalUIHandler) { if ((Object)(object)ui == (Object)null || externalUIHandler == null) { return; } Chest val = (Chest)((externalUIHandler is Chest) ? externalUIHandler : null); if (val == null) { return; } try { _pendingChestPanel = ui; _pendingChest = val; _pendingChestButtonFrames = 3; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"[SenpaisChest] Scheduled embedded panel (will add in 3 frames) - UI active: {ui.activeInHierarchy}"); } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[SenpaisChest] Failed to schedule embedded panel: " + ex.Message)); } } } internal static void ProcessPendingChestButton() { //IL_0174: Unknown result type (might be due to invalid IL or missing references) if (_pendingChestButtonFrames <= 0 || (Object)(object)_pendingChestPanel == (Object)null || (Object)(object)_pendingChest == (Object)null) { return; } _pendingChestButtonFrames--; if (_pendingChestButtonFrames != 0) { return; } GameObject pendingChestPanel = _pendingChestPanel; Chest pendingChest = _pendingChest; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"[SenpaisChest] Processing pending panel: panel={(Object)(object)pendingChestPanel != (Object)null}, active={((pendingChestPanel != null) ? new bool?(pendingChestPanel.activeInHierarchy) : null)}, chest={(Object)(object)pendingChest != (Object)null}"); } if ((Object)(object)pendingChestPanel == (Object)null || !pendingChestPanel.activeInHierarchy) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)$"[SenpaisChest] Skip add panel: panel null or inactive (panel={(Object)(object)pendingChestPanel != (Object)null}, active={((pendingChestPanel != null) ? new bool?(pendingChestPanel.activeInHierarchy) : null)})"); } _pendingChestPanel = null; _pendingChest = null; return; } Canvas componentInParent = pendingChestPanel.GetComponentInParent<Canvas>(); ManualLogSource log3 = Log; if (log3 != null) { log3.LogInfo((object)$"[SenpaisChest] Chest UI state - Canvas: {(Object)(object)componentInParent != (Object)null}, Canvas active: {((componentInParent != null) ? new bool?(((Component)componentInParent).gameObject.activeInHierarchy) : null)}, RenderMode: {((componentInParent != null) ? new RenderMode?(componentInParent.renderMode) : null)}"); } try { AddSenpaisChestNotePanel(pendingChestPanel, pendingChest); } catch (Exception ex) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)("[SenpaisChest] Failed to add embedded panel: " + ex.Message + "\n" + ex.StackTrace)); } } finally { _pendingChestPanel = null; _pendingChest = null; } } private static void AddSenpaisChestNotePanel(GameObject chestUiRoot, Chest chest) { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)chestUiRoot == (Object)null || !chestUiRoot.activeInHierarchy) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)$"[SenpaisChest] Cannot add panel: chestUiRoot is null or inactive (null={(Object)(object)chestUiRoot == (Object)null}, active={((chestUiRoot != null) ? new bool?(chestUiRoot.activeInHierarchy) : null)})"); } return; } Transform val = chestUiRoot.transform.Find("SenpaisChest_ConfigPanel"); if ((Object)(object)val != (Object)null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)$"[SenpaisChest] Panel already exists, reusing - active: {((Component)val).gameObject.activeInHierarchy}"); } SmartChestUI uI = GetUI(); if ((Object)(object)uI != (Object)null) { uI.ShowNoteForChest(chest, ((Component)val).gameObject); } return; } Canvas componentInParent = chestUiRoot.GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[SenpaisChest] Chest UI root is not under a Canvas, cannot create embedded panel"); } return; } Transform transform = chestUiRoot.transform; try { GameObject val2 = new GameObject("SenpaisChest_ConfigPanel"); val2.transform.SetParent(transform, false); val2.transform.SetAsLastSibling(); val2.SetActive(true); RectTransform val3 = val2.AddComponent<RectTransform>(); val3.anchorMin = new Vector2(0.5f, 0f); val3.anchorMax = new Vector2(0.5f, 0f); val3.pivot = new Vector2(0.5f, 0f); val3.anchoredPosition = Vector2.zero; val3.sizeDelta = new Vector2(340f, 34f); ManualLogSource log4 = Log; if (log4 != null) { log4.LogInfo((object)$"[SenpaisChest] Panel RectTransform - anchorMin={val3.anchorMin}, anchorMax={val3.anchorMax}, sizeDelta={val3.sizeDelta}, rect={val3.rect}"); } CanvasGroup val4 = val2.AddComponent<CanvasGroup>(); val4.blocksRaycasts = false; val4.interactable = false; val4.alpha = 1f; LayoutRebuilder.ForceRebuildLayoutImmediate(val3); Rect rect = val3.rect; if (!(((Rect)(ref rect)).width <= 0f)) { rect = val3.rect; if (!(((Rect)(ref rect)).height <= 0f)) { SmartChestUI uI2 = GetUI(); if ((Object)(object)uI2 != (Object)null) { uI2.ShowNoteForChest(chest, val2); ManualLogSource log5 = Log; if (log5 != null) { log5.LogInfo((object)$"[SenpaisChest] Added note panel (Press F9 to configure) - chestUiRoot active: {chestUiRoot.activeInHierarchy}, panel active: {val2.activeInHierarchy}, rect: {val3.rect}"); } } else { ManualLogSource log6 = Log; if (log6 != null) { log6.LogWarning((object)"[SenpaisChest] UI component is null, cannot show embedded panel"); } } return; } } ManualLogSource log7 = Log; if (log7 != null) { rect = val3.rect; object arg = ((Rect)(ref rect)).width; rect = val3.rect; log7.LogWarning((object)$"[SenpaisChest] Panel rect is invalid (width={arg}, height={((Rect)(ref rect)).height}), waiting one more frame"); } _pendingChestPanel = chestUiRoot; _pendingChest = chest; _pendingChestButtonFrames = 1; } catch (Exception arg2) { ManualLogSource log8 = Log; if (log8 != null) { log8.LogError((object)$"[SenpaisChest] Exception creating embedded panel: {arg2}"); } } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { bool flag = ((Scene)(ref scene)).name == "MainMenu" || ((Scene)(ref scene)).name == "Menu"; if (flag && !_wasInMenuScene) { Log.LogInfo((object)"Returned to menu, saving data..."); _staticSaveSystem?.Save(); _gameplaySessionCharacter = null; } else if (!flag) { string currentCharacterName = GetCurrentCharacterName(); if (!string.IsNullOrEmpty(currentCharacterName)) { if (string.Equals(_gameplaySessionCharacter, currentCharacterName, StringComparison.Ordinal)) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("[SenpaisChest] Skip disk reload on scene '" + ((Scene)(ref scene)).name + "' — '" + currentCharacterName + "' already active")); } } else { _staticManager?.SetCharacterName(currentCharacterName); SmartChestSaveData data = _staticSaveSystem?.Load(currentCharacterName); _staticManager?.LoadData(data); _gameplaySessionCharacter = currentCharacterName; ManualLogSource log2 = Log; if (log2 != null) { log2.LogDebug((object)("[SenpaisChest] Loaded smart chest data from disk for '" + currentCharacterName + "' on scene load")); } } } } _wasInMenuScene = flag; } private void OnDestroy() { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"Plugin OnDestroy called — static references preserved"); } _staticSaveSystem?.Save(); } private void OnApplicationQuit() { _applicationQuitting = true; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"Application quitting — saving data"); } _staticSaveSystem?.Save(); } private static bool IsDiscardedSceneSuppressed(Scene scene) { if (!((Scene)(ref scene)).IsValid()) { return false; } float realtimeSinceStartup = Time.realtimeSinceStartup; int[] array = null; int num = 0; foreach (KeyValuePair<int, float> item in _sceneDiscardSuppressByHandle) { if (!(item.Value > realtimeSinceStartup)) { if (array == null) { array = new int[_sceneDiscardSuppressByHandle.Count]; } array[num++] = item.Key; } } for (int i = 0; i < num; i++) { _sceneDiscardSuppressByHandle.Remove(array[i]); } float value; return _sceneDiscardSuppressByHandle.TryGetValue(((Scene)(ref scene)).handle, out value) && realtimeSinceStartup < value; } private static void OnActiveSceneChanged(Scene previous, Scene next) { if (((Scene)(ref previous)).IsValid()) { _sceneDiscardSuppressByHandle[((Scene)(ref previous)).handle] = Time.realtimeSinceStartup + 20f; } } internal static SmartChestManager GetManager() { return _staticManager; } internal static SmartChestSaveSystem GetSaveSystem() { return _staticSaveSystem; } internal static string GetCurrentCharacterName() { try { CharacterData currentCharacter = GameSave.CurrentCharacter; return (currentCharacter != null) ? currentCharacter.characterName : null; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("[SenpaisChest] GetCurrentCharacterName: " + ex.Message)); } return null; } } internal static SmartChestUI GetUI() { return _staticUI; } internal static SmartChestConfig GetConfig() { return _staticConfig; } internal static MuseumTodoIntegration GetMuseumTodoIntegration() { return _museumTodoIntegration; } } public class SmartChestPersistentRunner : MonoBehaviour { private float _scanTimer; private float _autoSaveTimer; private float _chestLabelScanTimer; private const float AUTO_SAVE_INTERVAL = 300f; private const float CHEST_LABEL_SCAN_INTERVAL = 2f; private int _lastCountdownSecond = -1; private void Update() { Plugin.ProcessPendingChestButton(); SmartChestConfig config = Plugin.GetConfig(); if (config != null && config.EnableChestLabels.Value) { _chestLabelScanTimer += Time.unscaledDeltaTime; if (_chestLabelScanTimer >= 2f) { _chestLabelScanTimer = 0f; Chest[] array = Object.FindObjectsOfType<Chest>(); Chest[] array2 = array; foreach (Chest val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { ChestLabelPatch.EnsureLabel(val); } } } } SmartChestManager manager = Plugin.GetManager(); if (config == null || manager == null) { return; } float unscaledDeltaTime = Time.unscaledDeltaTime; float scanInterval = config.GetScanInterval(); _scanTimer += unscaledDeltaTime; float num = scanInterval - _scanTimer; int num2 = (int)Math.Ceiling(num); if (num2 >= 1 && num2 <= 10 && num2 != _lastCountdownSecond) { _lastCountdownSecond = num2; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Scan] Next scan in {num2}..."); } } if (_scanTimer >= scanInterval) { _scanTimer = 0f; _lastCountdownSecond = -1; try { manager.ExecuteScan(config.MaxItemsPerScan.Value, config.EnableNotifications.Value); Plugin.GetMuseumTodoIntegration()?.OnScanComplete(); } catch (Exception arg) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"Error during scan: {arg}"); } } } _autoSaveTimer += unscaledDeltaTime; if (_autoSaveTimer >= 300f) { _autoSaveTimer = 0f; if (manager.IsDirty) { Plugin.GetSaveSystem()?.Save(); } } DetectHotkey(config); } private void DetectHotkey(SmartChestConfig config) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (TextInputFocusGuard.ShouldDeferModHotkeys(Plugin.Log)) { return; } KeyCode staticToggleKey = SmartChestConfig.StaticToggleKey; bool staticRequireCtrl = SmartChestConfig.StaticRequireCtrl; if (Input.GetKeyDown(staticToggleKey) && (!staticRequireCtrl || Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305))) { SmartChestUI uI = Plugin.GetUI(); if (!((Object)(object)uI == (Object)null) && (Object)(object)Plugin.CurrentInteractingChest != (Object)null) { uI.ToggleForChest(Plugin.CurrentInteractingChest); } } } private void OnDestroy() { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[PersistentRunner] OnDestroy called — this should NOT happen!"); } } } public static class PluginInfo { public const string PLUGIN_GUID = "com.azraelgodking.senpaischest"; public const string PLUGIN_NAME = "Senpai's Chest"; public const string PLUGIN_VERSION = "2.2.4"; } } namespace SenpaisChest.UI { [DefaultExecutionOrder(-30000)] public class SmartChestUI : MonoBehaviour { private const string PAUSE_ID = "SenpaisChest_Config"; private SmartChestManager _manager; private bool _isVisible; private Chest _currentChest; private SmartChestData _currentData; private string _chestId; private float _scale = 1f; private const float BASE_WINDOW_WIDTH = 420f; private const float BASE_WINDOW_HEIGHT = 500f; private const float BASE_GROUPS_WIDTH = 400f; private const float BASE_GROUPS_HEIGHT = 450f; private Rect _windowRect = new Rect(100f, 100f, 420f, 500f); private GameObject _notePanelRoot; private Rect _noteRect; private bool _noteRectDirty = true; private float _contentHeight = 500f; private int _selectedRuleType; private string _itemIdInput = ""; private int _selectedCategory; private int _selectedItemType; private int _selectedProperty; private int _selectedGroup; private string _lastSearchQuery = ""; private List<KeyValuePair<int, string>> _searchResults = new List<KeyValuePair<int, string>>(); private Vector2 _searchScrollPos; private int _selectedItemId = -1; private string _selectedItemName = ""; private bool _groupsWindowVisible; private Rect _groupsWindowRect; private ItemGroup _editingGroup; private string _newGroupName = ""; private string _groupItemSearch = ""; private string _groupItemSearchLast = ""; private List<KeyValuePair<int, string>> _groupSearchResults = new List<KeyValuePair<int, string>>(); private Vector2 _groupSearchScroll; private Vector2 _groupListScroll; private Vector2 _groupItemsScroll; private static readonly string[] RuleTypeNames = new string[5] { "By Item", "By Category", "By Item Type", "By Property", "By Group" }; private static readonly string[] BaseCategoryNames = new string[6] { "Equip", "Use", "Craftable", "Monster", "Furniture", "Quest" }; private static readonly string[] CategoryNamesWithMuseum = new string[7] { "Equip", "Use", "Craftable", "Monster", "Furniture", "Quest", "Undonated Items" }; private static readonly string[] ItemTypeNames = new string[9] { "Normal", "Armor", "Food", "Fish", "Crop", "WateringCan", "Animal", "Pet", "Tool" }; private static readonly string[] PropertyNames = new string[8] { "isGem", "isForageable", "isAnimalProduct", "isMeal", "isFruit", "isArtisanryItem", "isPotion", "isNotDonated" }; private static readonly string[] PropertyDisplayNames = new string[8] { "Gems", "Forageables", "Animal Products", "Meals", "Fruits", "Artisanry Items", "Potions", "Museum (Not Donated)" }; internal const string SearchFieldControlName = "SmartChestItemSearch"; internal const string GroupSearchFieldControlName = "SmartChestGroupItemSearch"; private readonly Color _bgDark = new Color(0.15f, 0.16f, 0.24f, 1f); private readonly Color _borderGold = new Color(0.75f, 0.65f, 0.3f, 1f); private readonly Color _goldText = new Color(0.95f, 0.85f, 0.35f, 1f); private readonly Color _whiteText = new Color(0.95f, 0.95f, 0.95f, 1f); private readonly Color _dimText = new Color(0.6f, 0.6f, 0.7f, 1f); private readonly Color _greenActive = new Color(0.2f, 0.55f, 0.45f, 1f); private readonly Color _greenHover = new Color(0.25f, 0.65f, 0.52f, 1f); private readonly Color _greenBright = new Color(0.3f, 0.7f, 0.55f, 1f); private readonly Color _redDanger = new Color(0.75f, 0.2f, 0.2f, 1f); private readonly Color _redHover = new Color(0.85f, 0.28f, 0.28f, 1f); private readonly Color _btnInactive = new Color(0.22f, 0.24f, 0.34f, 1f); private readonly Color _btnHover = new Color(0.3f, 0.32f, 0.44f, 1f); private readonly Color _ruleBoxColor = new Color(0.18f, 0.19f, 0.28f, 1f); private readonly Color _fieldBg = new Color(0.12f, 0.13f, 0.22f, 1f); private readonly Color _museumHighlight = new Color(0.35f, 0.65f, 0.85f, 1f); private readonly Color _parchmentLight = new Color(0.96f, 0.93f, 0.86f, 0.98f); private readonly Color _parchment = new Color(0.92f, 0.87f, 0.78f, 0.97f); private readonly Color _parchmentDark = new Color(0.85f, 0.78f, 0.65f, 0.95f); private readonly Color _woodDark = new Color(0.35f, 0.25f, 0.15f); private readonly Color _woodMedium = new Color(0.5f, 0.38f, 0.25f); private readonly Color _woodLight = new Color(0.65f, 0.52f, 0.38f); private readonly Color _goldPale = new Color(0.92f, 0.82f, 0.55f); private readonly Color _goldRich = new Color(0.72f, 0.55f, 0.2f); private readonly Color _borderWood = new Color(0.45f, 0.35f, 0.22f, 0.9f); private readonly Color _chestTextDark = new Color(0.08f, 0.06f, 0.05f, 1f); private readonly Color _chestTextDim = new Color(0.14f, 0.11f, 0.09f, 1f); private readonly Color _crimsonTitle = new Color(0.52f, 0.18f, 0.12f, 1f); private readonly Color _crimsonTitleLight = new Color(0.58f, 0.22f, 0.16f, 1f); private readonly Color _innerBorderCrimson = new Color(0.42f, 0.18f, 0.14f, 1f); private Texture2D _solidBg; private Texture2D _windowBg; private Texture2D _ruleBg; private Texture2D _btnInactiveTex; private Texture2D _btnHoverTex; private Texture2D _btnActiveTex; private Texture2D _btnActiveHoverTex; private Texture2D _redBtnTex; private Texture2D _redBtnHoverTex; private Texture2D _greenBtnTex; private Texture2D _greenBtnHoverTex; private Texture2D _closeBtnTex; private Texture2D _closeBtnHoverTex; private Texture2D _fieldBgTex; private Texture2D _chestParchmentBg; private Texture2D _chestWoodBorderTex; private Texture2D _chestRuleBoxTex; private Texture2D _chestSelectorTex; private Texture2D _chestSelectorHoverTex; private Texture2D _chestSelectorActiveTex; private Texture2D _chestAddBtnTex; private Texture2D _chestAddBtnHoverTex; private Texture2D _chestWoodBtnTex; private Texture2D _chestWoodBtnHoverTex; private Texture2D _chestDangerBtnTex; private Texture2D _chestDangerBtnHoverTex; private Texture2D _chestFieldBgTex; private Texture2D _chestGoldLineTex; private Texture2D _noteBannerBg; private Texture2D _noteBannerBorderTex; private Texture2D _configTitleBarTex; private Texture2D _configContentBg; private Texture2D _configGoldSeparatorTex; private Texture2D _configSectionHeaderTex; private Texture2D _configSearchFieldTex; private Texture2D _configRemoveBtnTex; private Texture2D _configRemoveBtnHoverTex; private Texture2D _configCloseBtnTex; private Texture2D _configCloseBtnHoverTex; private Texture2D _configWindowBg; private Texture2D _configInnerBorderTex; private GUIStyle _windowStyle; private GUIStyle _titleStyle; private GUIStyle _chestTitleStyle; private GUIStyle _chestLabelStyle; private GUIStyle _chestLabelBoldStyle; private GUIStyle _chestLabelDimStyle; private GUIStyle _chestSectionHeaderStyle; private GUIStyle _chestToggleStyle; private GUIStyle _sectionHeaderStyle; private GUIStyle _labelStyle; private GUIStyle _labelBoldStyle; private GUIStyle _labelDimStyle; private GUIStyle _ruleBoxStyle; private GUIStyle _ruleTextStyle; private GUIStyle _removeRuleBtnStyle; private GUIStyle _closeButtonStyle; private GUIStyle _toggleStyle; private GUIStyle _textFieldStyle; private GUIStyle _selectorStyle; private GUIStyle _selectorActiveStyle; private GUIStyle _addButtonStyle; private GUIStyle _dangerButtonStyle; private GUIStyle _closeBottomButtonStyle; private GUIStyle _searchResultStyle; private GUIStyle _searchResultSelectedStyle; private GUIStyle _chestRuleBoxStyle; private GUIStyle _chestRuleTextStyle; private GUIStyle _chestSelectorStyle; private GUIStyle _chestSelectorActiveStyle; private GUIStyle _chestAddButtonStyle; private GUIStyle _chestDangerButtonStyle; private GUIStyle _chestCloseButtonStyle; private GUIStyle _chestSearchFieldStyle; private GUIStyle _chestRemoveRuleBtnStyle; private GUIStyle _chestSearchResultStyle; private GUIStyle _chestSearchResultSelectedStyle; private GUIStyle _noteBannerStyle; private GUIStyle _configTitleStyle; private GUIStyle _configSectionHeaderBoxStyle; private GUIStyle _configSearchFieldStyle; private GUIStyle _configRemoveButtonStyle; private GUIStyle _configCloseBottomStyle; private GUIStyle _configWindowStyle; private bool _stylesInitialized; private float WindowWidth => 420f * _scale; private float WindowHeight => 500f * _scale; private float GroupsWindowWidth => 400f * _scale; private float GroupsWindowHeight => 450f * _scale; public bool IsVisible => _isVisible; public bool IsEmbedded => false; private float Scaled(float value) { return value * _scale; } private int ScaledFont(int baseSize) { return Mathf.Max(8, Mathf.RoundToInt((float)baseSize * _scale)); } private int ScaledInt(float value) { return Mathf.RoundToInt(value * _scale); } internal static bool ShouldBlockGameInput(SmartChestUI ui) { if ((Object)(object)ui == (Object)null || !ui.IsVisible) { return false; } string nameOfFocusedControl = GUI.GetNameOfFocusedControl(); return nameOfFocusedControl == "SmartChestItemSearch" || nameOfFocusedControl == "SmartChestGroupItemSearch"; } public void Initialize(SmartChestManager manager) { //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) //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) _manager = manager; _windowRect = new Rect(100f, 100f, WindowWidth, WindowHeight); _groupsWindowRect = new Rect(150f, 150f, GroupsWindowWidth, GroupsWindowHeight); } public void SetScale(float scale) { _scale = Mathf.Clamp(scale, 0.5f, 2.5f); _stylesInitialized = false; ((Rect)(ref _windowRect)).width = WindowWidth; ((Rect)(ref _windowRect)).height = WindowHeight; ((Rect)(ref _groupsWindowRect)).width = GroupsWindowWidth; ((Rect)(ref _groupsWindowRect)).height = GroupsWindowHeight; } public void Show() { _isVisible = true; } public void Hide() { _isVisible = false; BlockGameInput(block: false); Chest currentChest = _currentChest; _currentChest = null; _currentData = null; _notePanelRoot = null; _noteRectDirty = true; Plugin.CurrentInteractingChest = null; SaveIfDirty(); if (!((Object)(object)currentChest != (Object)null)) { return; } try { currentChest.EndInteract(0); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[SmartChestUI] EndInteract on close: " + ex.Message)); } } } public void HideConfig() { SaveIfDirty(); _isVisible = false; _groupsWindowVisible = false; BlockGameInput(block: false); } private void BlockGameInput(bool block) { try { if ((Object)(object)Player.Instance != (Object)null) { if (block) { Player.Instance.AddPauseObject("SenpaisChest_Config"); } else { Player.Instance.RemovePauseObject("SenpaisChest_Config"); } } Type type = Type.GetType("PlayerInput, Assembly-CSharp"); if (type != null) { type.GetMethod(block ? "DisableInput" : "EnableInput", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null)?.Invoke(null, new object[1] { "SenpaisChest_Config" }); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[SmartChestUI] BlockGameInput failed: " + ex.Message)); } } } public void Toggle() { if (_isVisible) { Hide(); } else { Show(); } } public void ToggleForChest(Chest chest) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if (_isVisible && (Object)(object)_currentChest == (Object)(object)chest) { HideConfig(); return; } _currentChest = chest; _chestId = SmartChestManager.GetChestId(chest); if (string.IsNullOrEmpty(_chestId)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"Cannot configure chest: no valid ID"); } return; } string chestName = GetChestName(chest); _currentData = _manager.GetOrCreateSmartChest(_chestId, chestName); _selectedRuleType = 0; _itemIdInput = ""; _lastSearchQuery = ""; _searchResults.Clear(); _selectedItemId = -1; _selectedItemName = ""; _searchScrollPos = Vector2.zero; _selectedCategory = 0; _selectedItemType = 0; _selectedProperty = 0; _isVisible = true; BlockGameInput(block: true); PositionWindowNextToChestPanel(); } public void ShowNoteForChest(Chest chest, GameObject panelRoot) { _currentChest = chest; _chestId = SmartChestManager.GetChestId(chest); if (string.IsNullOrEmpty(_chestId)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[SmartChestUI] Cannot show note: no valid chest ID"); } return; } _currentData = null; _notePanelRoot = panelRoot; _noteRectDirty = true; _isVisible = false; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogDebug((object)$"[SmartChestUI] ShowNoteForChest: chest={(Object)(object)chest != (Object)null}, panelRoot={(Object)(object)panelRoot != (Object)null}"); } } private void PositionWindowNextToChestPanel() { if (!((Object)(object)_currentChest == (Object)null)) { float num = Scaled(8f); float height = Mathf.Min(Scaled(400f), (float)Screen.height - num); ((Rect)(ref _windowRect)).width = WindowWidth; ((Rect)(ref _windowRect)).height = height; ((Rect)(ref _windowRect)).x = Mathf.Clamp(((float)Screen.width - ((Rect)(ref _windowRect)).width) * 0.5f, 0f, (float)Screen.width - ((Rect)(ref _windowRect)).width); ((Rect)(ref _windowRect)).y = num; } } private string GetChestName(Chest chest) { return SmartChestManager.GetChestName(chest); } private void OnGUI() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: 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_025a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_010d: Unknown result type (might be due to invalid IL or missing references) if (!_stylesInitialized) { InitializeStyles(); } if ((Object)(object)_notePanelRoot != (Object)null && !_isVisible) { if (!_notePanelRoot.activeInHierarchy) { _notePanelRoot = null; return; } if (_noteRectDirty || (int)Event.current.type == 8) { _noteRect = GetScreenRectFromTransform(_notePanelRoot.transform); _noteRectDirty = false; } Rect val = _noteRect; if (((Rect)(ref val)).width <= 0f || ((Rect)(ref val)).height <= 0f) { ((Rect)(ref val))..ctor(((float)Screen.width - Scaled(340f)) * 0.5f, Scaled(8f), Scaled(340f), Scaled(34f)); } val = ClampRectToScreen(val); GUI.BeginGroup(val); DrawNoteContent(((Rect)(ref val)).width, ((Rect)(ref val)).height); GUI.EndGroup(); } else if (_isVisible && _currentData != null) { float num = (float)Screen.height - Scaled(40f); ((Rect)(ref _windowRect)).width = WindowWidth; ((Rect)(ref _windowRect)).height = Mathf.Clamp(_contentHeight, Scaled(300f), num); ((Rect)(ref _windowRect)).x = Mathf.Clamp(((Rect)(ref _windowRect)).x, 0f, (float)Screen.width - ((Rect)(ref _windowRect)).width); ((Rect)(ref _windowRect)).y = Mathf.Clamp(((Rect)(ref _windowRect)).y, 0f, (float)Screen.height - ((Rect)(ref _windowRect)).height); _windowRect = GUI.Window("com.azraelgodking.senpaischest".GetHashCode(), _windowRect, new WindowFunction(DrawWindow), "", _configWindowStyle); if (_groupsWindowVisible) { _groupsWindowRect = GUI.Window("com.azraelgodking.senpaischest".GetHashCode() + 1, _groupsWindowRect, new WindowFunction(DrawGroupsWindow), "Manage Groups", _configWindowStyle); } } } private static Rect GetScreenRectFromTransform(Transform transform) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { return new Rect(0f, 0f, 400f, 400f); } Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>(); Vector3[] array = (Vector3[])(object)new Vector3[4]; val.GetWorldCorners(array); Vector2 val2 = default(Vector2); Vector2 val3 = default(Vector2); if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode == 0) { ((Vector2)(ref val2))..ctor(array[0].x, array[0].y); ((Vector2)(ref val3))..ctor(array[2].x, array[2].y); } else { Camera val4 = (((Object)(object)componentInParent != (Object)null) ? componentInParent.worldCamera : Camera.main); val2 = RectTransformUtility.WorldToScreenPoint(val4, array[0]); val3 = RectTransformUtility.WorldToScreenPoint(val4, array[2]); } float x = val2.x; float num = (float)Screen.height - val3.y; float num2 = val3.x - val2.x; float num3 = val3.y - val2.y; Rect result = default(Rect); ((Rect)(ref result))..ctor(x, num, num2, num3); return result; } private static Rect ClampRectToScreen(Rect rect) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Min(((Rect)(ref rect)).width, (float)Screen.width); float num2 = Mathf.Min(((Rect)(ref rect)).height, (float)Screen.height); float num3 = Mathf.Clamp(((Rect)(ref rect)).x, 0f, (float)Screen.width - num); float num4 = Mathf.Clamp(((Rect)(ref rect)).y, 0f, (float)Screen.height - num2); return new Rect(num3, num4, num, num2); } private void DrawWindow(int windowId) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) DrawConfigContent(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height), withWindowChrome: true); } private void DrawConfigContent(Rect rect, bool withWindowChrome) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039a: 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_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_067d: Unknown result type (might be due to invalid IL or missing references) //IL_0682: Unknown result type (might be due to invalid IL or missing references) //IL_0684: Unknown result type (might be due to invalid IL or missing references) //IL_06fa: Unknown result type (might be due to invalid IL or missing references) //IL_06ff: Unknown result type (might be due to invalid IL or missing references) //IL_0701: Unknown result type (might be due to invalid IL or missing references) //IL_087f: Unknown result type (might be due to invalid IL or missing references) //IL_0884: Unknown result type (might be due to invalid IL or missing references) //IL_0886: Unknown result type (might be due to invalid IL or missing references) //IL_08e4: Unknown result type (might be due to invalid IL or missing references) //IL_08e9: Unknown result type (might be due to invalid IL or missing references) //IL_08eb: Unknown result type (might be due to invalid IL or missing references) //IL_0b10: Unknown result type (might be due to invalid IL or missing references) //IL_0b16: Invalid comparison between Unknown and I4 //IL_0ab3: Unknown result type (might be due to invalid IL or missing references) //IL_0ab9: Invalid comparison between Unknown and I4 //IL_09ca: Unknown result type (might be due to invalid IL or missing references) //IL_09cf: Unknown result type (might be due to invalid IL or missing references) //IL_09d1: Unknown result type (might be due to invalid IL or missing references) //IL_0b1d: Unknown result type (might be due to invalid IL or missing references) //IL_0b23: Invalid comparison between Unknown and I4 //IL_0aff: Unknown result type (might be due to invalid IL or missing references) //IL_0ac2: Unknown result type (might be due to invalid IL or missing references) //IL_0ac7: Unknown result type (might be due to invalid IL or missing references) if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 27) { Event.current.Use(); HideConfig(); return; } bool flag = !withWindowChrome; bool flag2 = withWindowChrome; if (withWindowChrome) { float num = Scaled(36f); float num2 = Scaled(5f); float num3 = Scaled(1f); if ((Object)(object)_configInnerBorderTex != (Object)null) { float num4 = num2; float num5 = num2; float num6 = ((Rect)(ref rect)).width - num2 * 2f; float num7 = ((Rect)(ref rect)).height - num2 * 2f; GUI.DrawTexture(new Rect(num4, num5, num6, num3), (Texture)(object)_configInnerBorderTex); GUI.DrawTexture(new Rect(num4, num5 + num7 - num3, num6, num3), (Texture)(object)_configInnerBorderTex); GUI.DrawTexture(new Rect(num4, num5, num3, num7), (Texture)(object)_configInnerBorderTex); GUI.DrawTexture(new Rect(num4 + num6 - num3, num5, num3, num7), (Texture)(object)_configInnerBorderTex); } if ((Object)(object)_configTitleBarTex != (Object)null) { GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref rect)).width, num), (Texture)(object)_configTitleBarTex); } GUILayout.BeginArea(new Rect(0f, 0f, ((Rect)(ref rect)).width, num)); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.Label("Senpai's Chest Config", _configTitleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.FlexibleSpace(); if (GUILayout.Button("X", _closeButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(Scaled(28f)), GUILayout.Height(Scaled(24f)) })) { HideConfig(); } GUILayout.Space(Scaled(4f)); GUILayout.EndHorizontal(); GUILayout.EndArea(); GUILayout.Space(num + Scaled(2f)); if ((Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect2 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - Scaled(24f), Scaled(2f)); GUI.DrawTexture(rect2, (Texture)(object)_configGoldSeparatorTex); } GUILayout.Space(Scaled(8f)); } if (withWindowChrome) { GUILayout.Space(4f); } float num8 = (flag ? ((((Rect)(ref rect)).width - 8f) / 2f) : 0f); if (flag) { GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(((Rect)(ref rect)).width) }); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num8) }); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); bool flag3 = GUILayout.Toggle(_currentData.IsEnabled, " Smart Chest Enabled", flag2 ? _chestToggleStyle : _toggleStyle, Array.Empty<GUILayoutOption>()); if (flag3 != _currentData.IsEnabled) { _currentData.IsEnabled = flag3; _manager.MarkDirty(); SaveIfDirty(); } GUILayout.EndHorizontal(); if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect3 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f); GUI.DrawTexture(rect3, (Texture)(object)_configGoldSeparatorTex); GUILayout.Space(6f); } else { GUILayout.Space((float)(flag ? 4 : 8)); } GUIStyle val = (flag2 ? _configSectionHeaderBoxStyle : (flag ? _chestSectionHeaderStyle : _sectionHeaderStyle)); GUILayout.Label("Item Rules", val, Array.Empty<GUILayoutOption>()); GUILayout.Space((float)(flag ? 2 : 4)); if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect4 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f); GUI.DrawTexture(rect4, (Texture)(object)_configGoldSeparatorTex); GUILayout.Space(4f); } if (_currentData.Rules.Count == 0) { GUILayout.Label(" No rules configured. Add rules below.", flag2 ? _chestLabelDimStyle : (flag ? _chestLabelDimStyle : _labelDimStyle), Array.Empty<GUILayoutOption>()); } else { float num9 = (flag ? 24f : 36f); float num10 = (flag ? 100f : 180f); float num11 = Mathf.Min((float)_currentData.Rules.Count * num9, num10); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num11) }); int num12 = -1; for (int i = 0; i < _currentData.Rules.Count; i++) { GUIStyle val2 = (flag2 ? _chestRuleBoxStyle : (flag ? _chestRuleBoxStyle : _ruleBoxStyle)); GUIStyle val3 = (flag2 ? _chestRuleTextStyle : (flag ? _chestRuleTextStyle : _ruleTextStyle)); GUIStyle val4 = (flag2 ? _chestRemoveRuleBtnStyle : (flag ? _chestRemoveRuleBtnStyle : _removeRuleBtnStyle)); GUILayout.BeginHorizontal(val2, Array.Empty<GUILayoutOption>()); GUILayout.Label($"{i + 1}. {GetRuleDisplayText(_currentData.Rules[i])}", val3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button("X", val4, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(26f), GUILayout.Height(22f) })) { num12 = i; } GUILayout.EndHorizontal(); GUILayout.Space((float)(flag ? 1 : 2)); } GUILayout.EndVertical(); if (num12 >= 0) { _currentData.Rules.RemoveAt(num12); _manager.MarkDirty(); SaveIfDirty(); } } if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect5 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f); GUI.DrawTexture(rect5, (Texture)(object)_configGoldSeparatorTex); GUILayout.Space(8f); } else { GUILayout.Space((float)(flag ? 4 : 10)); } GUILayout.Label("Add New Rule", val, Array.Empty<GUILayoutOption>()); GUILayout.Space((float)(flag ? 2 : 6)); if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect6 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f); GUI.DrawTexture(rect6, (Texture)(object)_configGoldSeparatorTex); GUILayout.Space(4f); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); DrawSelectorButton(0, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28))); DrawSelectorButton(1, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28))); DrawSelectorButton(2, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28))); GUILayout.EndHorizontal(); GUILayout.Space((float)(flag ? 1 : 2)); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); DrawSelectorButton(3, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28))); DrawSelectorButton(4, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28))); if (GUILayout.Button("Manage Groups", flag2 ? _configCloseBottomStyle : _closeBottomButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height((float)((flag2 || flag) ? 22 : 26)) })) { _groupsWindowVisible = true; } GUILayout.EndHorizontal(); GUILayout.Space((float)(flag ? 4 : 8)); if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect7 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f); GUI.DrawTexture(rect7, (Texture)(object)_configGoldSeparatorTex); GUILayout.Space(4f); } DrawRuleInput(flag2 || flag, flag2); GUILayout.Space((float)(flag ? 4 : 8)); if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect8 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f); GUI.DrawTexture(rect8, (Texture)(object)_configGoldSeparatorTex); GUILayout.Space(6f); } GUIStyle val5 = (flag2 ? _chestAddButtonStyle : (flag ? _chestAddButtonStyle : _addButtonStyle)); if (GUILayout.Button("Add Rule", val5, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height((float)((flag2 || flag) ? 24 : 30)) })) { AddRule(); } if (flag) { GUILayout.EndVertical(); GUILayout.Space(8f); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num8) }); DrawEmbeddedRightColumn(flag); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } else { if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null) { Rect rect9 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f); GUI.DrawTexture(rect9, (Texture)(object)_configGoldSeparatorTex); GUILayout.Space(8f); } else { GUILayout.Space(12f); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Remove Smart Chest", flag2 ? _configRemoveButtonStyle : _dangerButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) })) { _manager.RemoveSmartChest(_chestId); SaveIfDirty(); HideConfig(); } GUILayout.Space(8f); if (GUILayout.Button("Close", flag2 ? _configCloseBottomStyle : _closeBottomButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) })) { HideConfig(); } GUILayout.EndHorizontal(); } if (withWindowChrome) { if ((int)Event.current.type == 7) { Rect lastRect = GUILayoutUtility.GetLastRect(); _contentHeight = ((Rect)(ref lastRect)).yMax + Scaled(24f); } GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref rect)).width, Scaled(28f))); } if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 8) { Event.current.Use(); } } private void DrawEmbeddedRightColumn(bool compact) { GUILayout.Space(4f); GUILayout.Label("Summary", _chestSectionHeaderStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); int valueOrDefault = (_currentData?.Rules?.Count).GetValueOrDefault(); SmartChestData currentData = _currentData; string arg = ((currentData != null && currentData.IsEnabled) ? "Active" : "Disabled"); GUILayout.BeginVertical(_chestRuleBoxStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label($"Rules: {valueOrDefault} | Status: {arg}", _chestLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (valueOrDefault > 0) { GUILayout.Label("Accepts:", _chestLabelBoldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); for (int i = 0; i < valueOrDefault; i++) { GUILayout.Label(" • " + GetRuleDisplayText(_currentData.Rules[i]), _chestLabelDimStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); } } GUILayout.EndVertical(); GUILayout.Space(4f); GUILayout.Label("Tips", _chestSectionHeaderStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.BeginVertical(_chestRuleBoxStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("• Rules filter auto-sort. Multiple = AND.", _chestRuleTextStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.Label("• Transfer SAME/ALL applies rules.", _chestRuleTextStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.EndVertical(); GUILayout.Space(8f); if (GUILayout.Button("Remove Smart Chest", _chestDangerButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(20f), GUILayout.ExpandWidth(true) })) { _manager.RemoveSmartChest(_chestId); SaveIfDirty(); HideConfig(); } GUILayout.Space(2f); if (GUILayout.Button("Close", _chestCloseButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(20f), GUILayout.ExpandWidth(true) })) { HideConfig(); } } private void DrawGroupsWindow(int windowId) { //IL_017e: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_06e6: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_054c: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_0569: Unknown result type (might be due to invalid IL or missing references) if (!_stylesInitialized) { InitializeStyles(); } GUIStyle chestLabelBoldStyle = _chestLabelBoldStyle; GUIStyle chestLabelStyle = _chestLabelStyle; GUIStyle chestLabelDimStyle = _chestLabelDimStyle; GUILayout.Label("Create or edit groups. Use 'By Group' when adding rules to attach a group to a chest.", chestLabelDimStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.Space(6f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); _newGroupName = GUILayout.TextField(_newGroupName ?? "", _configSearchFieldStyle ?? _chestSearchFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true)