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.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SenpaisChest")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+871217776acdadbaabcc0e4af36feeef0cd58101")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace SunhavenMods.Shared
{
public static class ConfigFileHelper
{
public static ConfigFile CreateNamedConfig(string pluginGuid, string configFileName, Action<string> logWarning = null)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
string text = Path.Combine(Paths.ConfigPath, configFileName);
string text2 = Path.Combine(Paths.ConfigPath, pluginGuid + ".cfg");
try
{
if (!File.Exists(text) && File.Exists(text2))
{
File.Copy(text2, text);
}
}
catch (Exception ex)
{
logWarning?.Invoke("[Config] Migration to " + configFileName + " failed: " + ex.Message);
}
return new ConfigFile(text, true);
}
public static bool ReplacePluginConfig(BaseUnityPlugin plugin, ConfigFile newConfig, Action<string> logWarning = null)
{
if ((Object)(object)plugin == (Object)null || newConfig == null)
{
return false;
}
try
{
Type typeFromHandle = typeof(BaseUnityPlugin);
PropertyInfo property = typeFromHandle.GetProperty("Config", BindingFlags.Instance | BindingFlags.Public);
if (property != null && property.CanWrite)
{
property.SetValue(plugin, newConfig, null);
return true;
}
FieldInfo field = typeFromHandle.GetField("<Config>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(plugin, newConfig);
return true;
}
FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType == typeof(ConfigFile))
{
fieldInfo.SetValue(plugin, newConfig);
return true;
}
}
}
catch (Exception ex)
{
logWarning?.Invoke("[Config] ReplacePluginConfig failed: " + ex.Message);
}
return false;
}
}
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; }
}
public class ModHealthSnapshot
{
public string PluginGuid { get; set; }
public DateTime LastCheckUtc { get; set; }
public int ExceptionCount { get; set; }
public string LastError { get; set; }
}
private class VersionCheckRunner : MonoBehaviour
{
private ManualLogSource _pluginLog;
public void StartCheck(string pluginGuid, string currentVersion, ManualLogSource pluginLog, Action<VersionCheckResult> onComplete)
{
_pluginLog = pluginLog;
((MonoBehaviour)this).StartCoroutine(CheckVersionCoroutine(pluginGuid, currentVersion, onComplete));
}
private void LogInfo(string message)
{
ManualLogSource pluginLog = _pluginLog;
if (pluginLog != null)
{
pluginLog.LogInfo((object)("[VersionChecker] " + message));
}
}
private void LogWarningMsg(string message)
{
ManualLogSource pluginLog = _pluginLog;
if (pluginLog != null)
{
pluginLog.LogWarning((object)("[VersionChecker] " + message));
}
}
private void LogErrorMsg(string message)
{
ManualLogSource pluginLog = _pluginLog;
if (pluginLog != null)
{
pluginLog.LogError((object)("[VersionChecker] " + message));
}
}
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;
RecordHealthError(pluginGuid, result.ErrorMessage);
LogWarningMsg(result.ErrorMessage);
onComplete?.Invoke(result);
Object.Destroy((Object)(object)((Component)this).gameObject);
yield break;
}
try
{
string text = www.downloadHandler.text;
Match match = GetModPattern(pluginGuid).Match(text);
if (!match.Success)
{
result.Success = false;
result.ErrorMessage = "Mod '" + pluginGuid + "' not found in versions.json";
RecordHealthError(pluginGuid, result.ErrorMessage);
LogWarningMsg(result.ErrorMessage);
onComplete?.Invoke(result);
Object.Destroy((Object)(object)((Component)this).gameObject);
yield break;
}
string value = match.Groups[1].Value;
result.LatestVersion = ExtractJsonString(value, "version");
result.ModName = ExtractJsonString(value, "name");
result.NexusUrl = ExtractJsonString(value, "nexus");
result.Changelog = ExtractJsonString(value, "changelog");
if (string.IsNullOrEmpty(result.LatestVersion))
{
result.Success = false;
result.ErrorMessage = "Could not parse version from response";
RecordHealthError(pluginGuid, result.ErrorMessage);
LogWarningMsg(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)
{
LogInfo("Update available for " + result.ModName + ": " + currentVersion + " -> " + result.LatestVersion);
}
else
{
LogInfo(result.ModName + " is up to date (v" + currentVersion + ")");
}
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = "Parse error: " + ex.Message;
RecordHealthError(pluginGuid, result.ErrorMessage);
LogErrorMsg(result.ErrorMessage);
}
}
finally
{
((IDisposable)www)?.Dispose();
}
onComplete?.Invoke(result);
Object.Destroy((Object)(object)((Component)this).gameObject);
}
private string ExtractJsonString(string json, string key)
{
Match match = ExtractFieldRegex.Match(json);
while (match.Success)
{
if (string.Equals(match.Groups["key"].Value, key, StringComparison.Ordinal))
{
return match.Groups["value"].Value;
}
match = match.NextMatch();
}
return null;
}
}
private const string VersionsUrl = "https://azraelgodking.github.io/SunhavenMod/versions.json";
private static readonly Dictionary<string, ModHealthSnapshot> HealthByPluginGuid = new Dictionary<string, ModHealthSnapshot>(StringComparer.OrdinalIgnoreCase);
private static readonly object HealthLock = new object();
private static readonly Dictionary<string, Regex> ModPatternCache = new Dictionary<string, Regex>(StringComparer.Ordinal);
private static readonly object ModPatternCacheLock = new object();
private static readonly Regex ExtractFieldRegex = new Regex("\"(?<key>[^\"]+)\"\\s*:\\s*(?:\"(?<value>[^\"]*)\"|null)", RegexOptions.Compiled);
public static void CheckForUpdate(string pluginGuid, string currentVersion, ManualLogSource logger = null, Action<VersionCheckResult> onComplete = null)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
TouchHealth(pluginGuid);
VersionCheckRunner versionCheckRunner = new GameObject("VersionChecker").AddComponent<VersionCheckRunner>();
Object.DontDestroyOnLoad((Object)(object)((Component)versionCheckRunner).gameObject);
SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(((Component)versionCheckRunner).gameObject);
versionCheckRunner.StartCheck(pluginGuid, currentVersion, logger, onComplete);
}
public static ModHealthSnapshot GetHealthSnapshot(string pluginGuid)
{
if (string.IsNullOrWhiteSpace(pluginGuid))
{
return null;
}
lock (HealthLock)
{
if (!HealthByPluginGuid.TryGetValue(pluginGuid, out ModHealthSnapshot value))
{
return null;
}
return new ModHealthSnapshot
{
PluginGuid = value.PluginGuid,
LastCheckUtc = value.LastCheckUtc,
ExceptionCount = value.ExceptionCount,
LastError = value.LastError
};
}
}
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');
int num = v1.IndexOfAny(new char[2] { '-', '+' });
if (num >= 0)
{
v1 = v1.Substring(0, num);
}
int num2 = v2.IndexOfAny(new char[2] { '-', '+' });
if (num2 >= 0)
{
v2 = v2.Substring(0, num2);
}
string[] array = v1.Split(new char[1] { '.' });
string[] array2 = v2.Split(new char[1] { '.' });
int num3 = Math.Max(array.Length, array2.Length);
for (int i = 0; i < num3; i++)
{
int result;
int num4 = ((i < array.Length && int.TryParse(array[i], out result)) ? result : 0);
int result2;
int num5 = ((i < array2.Length && int.TryParse(array2[i], out result2)) ? result2 : 0);
if (num4 < num5)
{
return -1;
}
if (num4 > num5)
{
return 1;
}
}
return 0;
}
private static void TouchHealth(string pluginGuid)
{
if (string.IsNullOrWhiteSpace(pluginGuid))
{
return;
}
lock (HealthLock)
{
if (!HealthByPluginGuid.TryGetValue(pluginGuid, out ModHealthSnapshot value))
{
value = new ModHealthSnapshot
{
PluginGuid = pluginGuid
};
HealthByPluginGuid[pluginGuid] = value;
}
value.LastCheckUtc = DateTime.UtcNow;
}
}
private static void RecordHealthError(string pluginGuid, string errorMessage)
{
if (string.IsNullOrWhiteSpace(pluginGuid))
{
return;
}
lock (HealthLock)
{
if (!HealthByPluginGuid.TryGetValue(pluginGuid, out ModHealthSnapshot value))
{
value = new ModHealthSnapshot
{
PluginGuid = pluginGuid
};
HealthByPluginGuid[pluginGuid] = value;
}
value.LastCheckUtc = DateTime.UtcNow;
value.ExceptionCount++;
value.LastError = errorMessage;
}
}
private static Regex GetModPattern(string pluginGuid)
{
lock (ModPatternCacheLock)
{
if (!ModPatternCache.TryGetValue(pluginGuid, out Regex value))
{
value = new Regex("\"" + Regex.Escape(pluginGuid) + "\"\\s*:\\s*\\{([^}]+)\\}", RegexOptions.Compiled | RegexOptions.Singleline);
ModPatternCache[pluginGuid] = value;
}
return value;
}
}
}
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)
{
object obj = type2.MakeGenericType(type).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_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Expected O, but got Unknown
//IL_00a3: 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)
{
string typeName2 = typeName;
Type type = AccessTools.TypeByName(typeName2);
if (type != null)
{
return type;
}
for (int i = 0; i < namespaces.Length; i++)
{
type = AccessTools.TypeByName(namespaces[i] + "." + typeName2);
if (type != null)
{
return type;
}
}
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
try
{
type = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == typeName2 || t.FullName == typeName2);
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;
}
try
{
PropertyInfo property = type.GetProperty(memberName, AllBindingFlags);
if (property != null && property.GetMethod != null && property.GetIndexParameters().Length == 0)
{
return property.GetValue(null);
}
}
catch (AmbiguousMatchException)
{
return 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" };
foreach (string memberName in array)
{
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;
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);
List<KeyValuePair<int, string>> list2 = new List<KeyValuePair<int, string>>();
List<KeyValuePair<int, string>> list3 = new List<KeyValuePair<int, string>>();
List<KeyValuePair<int, string>> list4 = new List<KeyValuePair<int, string>>();
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)
{
list2.Add(item);
}
else if (text3 == text)
{
list2.Add(item);
}
else if (text3.StartsWith(text))
{
list3.Add(item);
}
else if (text3.Contains(text))
{
list4.Add(item);
}
else if (flag && key.ToString().Contains(query.Trim()))
{
list4.Add(item);
}
}
}
list3.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => string.Compare(a.Value, b.Value, StringComparison.OrdinalIgnoreCase));
list4.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => string.Compare(a.Value, b.Value, StringComparison.OrdinalIgnoreCase));
list.AddRange(list2);
list.AddRange(list3);
list.AddRange(list4);
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;
}
public static List<KeyValuePair<int, string>> GetAllItems()
{
List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
try
{
Dictionary<int, ItemSellInfo> itemDictionary = GetItemDictionary();
if (itemDictionary == null)
{
return list;
}
foreach (KeyValuePair<int, ItemSellInfo> item in itemDictionary)
{
string value = item.Value?.name;
if (!string.IsNullOrEmpty(value))
{
list.Add(new KeyValuePair<int, string>(item.Key, value));
}
}
list.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => string.Compare(a.Value, b.Value, StringComparison.OrdinalIgnoreCase));
}
catch (Exception ex)
{
ManualLogSource log = _log;
if (log != null)
{
log.LogDebug((object)("[ItemSearch] GetAllItems: " + ex.Message));
}
}
return list;
}
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_005b;
}
}
_dbInstance = null;
_dictField = null;
_dbInstance = GetSingletonInstance("Wish.ItemInfoDatabase");
if (_dbInstance != null)
{
_dictField = _dbInstance.GetType().GetField("allItemSellInfos", BindingFlags.Instance | BindingFlags.Public);
}
goto IL_005b;
IL_005b:
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;
}
return type.MakeGenericType(type2).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(debugLog))
{
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(ManualLogSource debugLog)
{
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 (Exception ex)
{
if (debugLog != null)
{
debugLog.LogDebug((object)("[TextInputFocusGuard] Quantum Console focus check failed: " + ex.Message));
}
}
return false;
}
}
internal static class MinimalJsonParser
{
internal static void WriteJsonString(StringBuilder sb, string value)
{
sb.Append('"');
if (value != null)
{
foreach (char c in value)
{
switch (c)
{
case '"':
sb.Append("\\\"");
break;
case '\\':
sb.Append("\\\\");
break;
case '\n':
sb.Append("\\n");
break;
case '\r':
sb.Append("\\r");
break;
case '\t':
sb.Append("\\t");
break;
case '\b':
sb.Append("\\b");
break;
case '\f':
sb.Append("\\f");
break;
default:
sb.Append(c);
break;
}
}
}
sb.Append('"');
}
internal static void SkipWhitespace(string json, ref int pos)
{
while (pos < json.Length && char.IsWhiteSpace(json[pos]))
{
pos++;
}
}
internal static object ParseValue(string json, ref int pos)
{
SkipWhitespace(json, ref pos);
if (pos >= json.Length)
{
return null;
}
char c = json[pos];
switch (c)
{
case '"':
return ParseString(json, ref pos);
case '{':
return ParseObject(json, ref pos);
case '[':
return ParseArray(json, ref pos);
case 't':
return ParseLiteral(json, ref pos, "true", true);
case 'f':
return ParseLiteral(json, ref pos, "false", false);
case 'n':
return ParseLiteral(json, ref pos, "null", null);
default:
if (!char.IsDigit(c))
{
return null;
}
goto case '-';
case '-':
return ParseNumber(json, ref pos);
}
}
internal static Dictionary<string, object> ParseObject(string json, ref int pos)
{
SkipWhitespace(json, ref pos);
if (pos >= json.Length || json[pos] != '{')
{
return null;
}
pos++;
Dictionary<string, object> dictionary = new Dictionary<string, object>();
SkipWhitespace(json, ref pos);
if (pos < json.Length && json[pos] == '}')
{
pos++;
return dictionary;
}
while (pos < json.Length)
{
SkipWhitespace(json, ref pos);
string text = ParseString(json, ref pos);
if (text == null)
{
break;
}
SkipWhitespace(json, ref pos);
if (pos >= json.Length || json[pos] != ':')
{
break;
}
pos++;
SkipWhitespace(json, ref pos);
dictionary[text] = ParseValue(json, ref pos);
SkipWhitespace(json, ref pos);
if (pos >= json.Length || json[pos] != ',')
{
break;
}
pos++;
}
SkipWhitespace(json, ref pos);
if (pos < json.Length && json[pos] == '}')
{
pos++;
}
return dictionary;
}
internal static List<object> ParseArray(string json, ref int pos)
{
SkipWhitespace(json, ref pos);
if (pos >= json.Length || json[pos] != '[')
{
return null;
}
pos++;
List<object> list = new List<object>();
SkipWhitespace(json, ref pos);
if (pos < json.Length && json[pos] == ']')
{
pos++;
return list;
}
while (pos < json.Length)
{
SkipWhitespace(json, ref pos);
list.Add(ParseValue(json, ref pos));
SkipWhitespace(json, ref pos);
if (pos >= json.Length || json[pos] != ',')
{
break;
}
pos++;
}
SkipWhitespace(json, ref pos);
if (pos < json.Length && json[pos] == ']')
{
pos++;
}
return list;
}
internal static string ParseString(string json, ref int pos)
{
SkipWhitespace(json, ref pos);
if (pos >= json.Length || json[pos] != '"')
{
return null;
}
pos++;
StringBuilder stringBuilder = new StringBuilder();
while (pos < json.Length)
{
char c = json[pos];
if (c == '\\' && pos + 1 < json.Length)
{
pos++;
switch (json[pos])
{
case '"':
stringBuilder.Append('"');
break;
case '\\':
stringBuilder.Append('\\');
break;
case '/':
stringBuilder.Append('/');
break;
case 'n':
stringBuilder.Append('\n');
break;
case 'r':
stringBuilder.Append('\r');
break;
case 't':
stringBuilder.Append('\t');
break;
case 'b':
stringBuilder.Append('\b');
break;
case 'f':
stringBuilder.Append('\f');
break;
case 'u':
{
if (pos + 4 < json.Length && ushort.TryParse(json.Substring(pos + 1, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
{
pos += 4;
if (result >= 55296 && result <= 56319 && pos + 5 < json.Length && json[pos] == '\\' && json[pos + 1] == 'u' && ushort.TryParse(json.Substring(pos + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result2) && result2 >= 56320 && result2 <= 57343)
{
stringBuilder.Append(char.ConvertFromUtf32(char.ConvertToUtf32((char)result, (char)result2)));
pos += 6;
}
else
{
stringBuilder.Append((char)result);
}
}
else
{
stringBuilder.Append('u');
}
break;
}
default:
stringBuilder.Append(json[pos]);
break;
}
pos++;
}
else
{
if (c == '"')
{
pos++;
return stringBuilder.ToString();
}
stringBuilder.Append(c);
pos++;
}
}
return stringBuilder.ToString();
}
internal static object ParseNumber(string json, ref int pos)
{
int num = pos;
bool flag = false;
if (pos < json.Length && json[pos] == '-')
{
pos++;
}
while (pos < json.Length && char.IsDigit(json[pos]))
{
pos++;
}
if (pos < json.Length && json[pos] == '.')
{
flag = true;
pos++;
while (pos < json.Length && char.IsDigit(json[pos]))
{
pos++;
}
}
if (pos < json.Length && (json[pos] == 'e' || json[pos] == 'E'))
{
flag = true;
pos++;
if (pos < json.Length && (json[pos] == '+' || json[pos] == '-'))
{
pos++;
}
while (pos < json.Length && char.IsDigit(json[pos]))
{
pos++;
}
}
string s = json.Substring(num, pos - num);
if (flag && double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
{
return result;
}
if (!flag && long.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
{
return result2;
}
return 0L;
}
internal static object ParseLiteral(string json, ref int pos, string literal, object result)
{
if (pos + literal.Length <= json.Length && json.Substring(pos, literal.Length) == literal)
{
pos += literal.Length;
return result;
}
pos++;
return null;
}
internal static int ToInt(object val)
{
if (val is long num)
{
return (int)num;
}
if (val is double num2)
{
return (int)num2;
}
if (val is int)
{
return (int)val;
}
return 0;
}
}
}
namespace SenpaisChest
{
[BepInPlugin("com.azraelgodking.senpaischest", "Senpai's Chest", "2.7.0")]
[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_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Expected O, but got Unknown
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Expected O, but got Unknown
//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
ConfigFile = CreateNamedConfig();
ConfigFileHelper.ReplacePluginConfig((BaseUnityPlugin)(object)this, ConfigFile, (Action<string>)Log.LogWarning);
Log.LogInfo((object)"Loading Senpai's Chest v2.7.0");
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.7.0", 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_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: 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_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: 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)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
{
_museumTodoIntegration?.Dispose();
_museumTodoIntegration = null;
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_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Expected O, but got Unknown
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_0221: Expected O, but got Unknown
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Expected O, but got Unknown
//IL_0283: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Expected O, but got Unknown
//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0301: Expected O, but got Unknown
//IL_0371: Unknown result type (might be due to invalid IL or missing references)
//IL_037f: Expected O, but got Unknown
//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
//IL_03ff: 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_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Expected O, but got Unknown
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Expected O, but got Unknown
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: 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_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: 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
{
FieldInfo field = ((object)__instance).GetType().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_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: 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_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: 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_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: 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_014b: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Expected O, but got Unknown
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0204: Unknown result type (might be due to invalid IL or missing references)
//IL_0216: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_023d: Unknown result type (might be due to invalid IL or missing references)
//IL_0242: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: Unknown result type (might be due to invalid IL or missing references)
//IL_0257: Unknown result type (might be due to invalid IL or missing references)
//IL_02ca: 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;
}
if ((Object)(object)chestUiRoot.GetComponentInParent<Canvas>() == (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 obj = val2.AddComponent<CanvasGroup>();
obj.blocksRaycasts = false;
obj.interactable = false;
obj.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()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
SceneManager.activeSceneChanged -= OnActiveSceneChanged;
_museumTodoIntegration?.Dispose();
_museumTodoIntegration = null;
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;
CleanupDiscardSuppressionMap(realtimeSinceStartup);
if (_sceneDiscardSuppressByHandle.TryGetValue(((Scene)(ref scene)).handle, out var value))
{
return realtimeSinceStartup < value;
}
return false;
}
private static void CleanupDiscardSuppressionMap(float now)
{
int[] array = null;
int num = 0;
foreach (KeyValuePair<int, float> item in _sceneDiscardSuppressByHandle)
{
if (!(item.Value > now))
{
if (array == null)
{
array = new int[_sceneDiscardSuppressByHandle.Count];
}
array[num++] = item.Key;
}
}
for (int i = 0; i < num; i++)
{
_sceneDiscardSuppressByHandle.Remove(array[i]);
}
}
private static void OnActiveSceneChanged(Scene previous, Scene next)
{
if (((Scene)(ref previous)).IsValid())
{
CleanupDiscardSuppressionMap(Time.realtimeSinceStartup);
_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>();
foreach (Chest val in array)
{
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;
int num = (int)Math.Ceiling(scanInterval - _scanTimer);
if (num >= 1 && num <= 10 && num != _lastCountdownSecond)
{
_lastCountdownSecond = num;
if (SmartChestConfig.StaticEnableScanCountdownDebug)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)$"[Scan] Next scan in {num}...");
}
}
}
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_0012: 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()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
string text = (((Scene)(ref activeScene)).name ?? string.Empty).ToLowerInvariant();
if (!Application.isPlaying || text.Contains("menu") || text.Contains("title"))
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)"[PersistentRunner] OnDestroy during app quit/menu unload (expected).");
}
}
else
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogWarning((object)"[PersistentRunner] OnDestroy outside quit/menu (unexpected).");
}
}
}
}
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.7.0";
}
}
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 bool _confirmCopyRules;
private float _confirmCopyRulesUntil;
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 string _groupPatternInput = "";
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[6] { "By Item", "By Category", "By Item Type", "By Property", "By Group", "By wildcard name" };
private string _wildcardPatternInput = "";
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";
internal const string WildcardPatternControlName = "SmartChestWildcardPattern";
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 _stylesDirty = true;
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();
if (!(nameOfFocusedControl == "SmartChestItemSearch") && !(nameOfFocusedControl == "SmartChestGroupItemSearch"))
{
return nameOfFocusedControl == "SmartChestWildcardPattern";
}
return true;
}
public void Initialize(SmartChestManager manager)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
_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);
_stylesDirty = true;
_configWindowStyle = null;
((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;
_confirmCopyRules = 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;
_confirmCopyRules = 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_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: 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;
_wildcardPatternInput = "";
_confirmCopyRules = false;
_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_01d3: 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_01f4: Expected O, but got Unknown
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Expected O, but got Unknown
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Invalid comparison between Unknown and I4
//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_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
if (_stylesDirty || _configWindowStyle == null)
{
InitializeStyles();
}
if (_configWindowStyle == null)
{
return;
}
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_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: 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 obj = (((Object)(object)componentInParent != (Object)null) ? componentInParent.worldCamera : Camera.main);
val2 = RectTransformUtility.WorldToScreenPoint(obj, array[0]);
val3 = RectTransformUtility.WorldToScreenPoint(obj, 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;
return new Rect(x, num, num2, num3);
}
private static Rect ClampRectToScreen(Rect rect)
{
//IL_005c: 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_0021: 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_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0220: Unknown result type (might be due to invalid IL or missing references)
//IL_0325: Unknown result type (might be due to invalid IL or missing references)
//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
//IL_0627: Unknown result type (might be due to invalid IL or missing references)
//IL_08e0: Unknown result type (might be due to invalid IL or missing references)
//IL_0934: Unknown result type (might be due to invalid IL or missing references)
//IL_0b47: Unknown result type (might be due to invalid IL or missing references)
//IL_0c65: Unknown result type (might be due to invalid IL or missing references)
//IL_0c6b: Invalid comparison between Unknown and I4
//IL_0c12: Unknown result type (might be due to invalid IL or missing references)
//IL_0c18: Invalid comparison between Unknown and I4
//IL_0c72: Unknown result type (might be due to invalid IL or missing references)
//IL_0c78: Invalid comparison between Unknown and I4
//IL_0c56: Unknown result type (might be due to invalid IL or missing references)
//IL_0c1a: Unknown result type (might be due to invalid IL or missing references)
//IL_0c1f: Unknown result type (might be due to invalid IL or missing references)
if (