using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[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.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BeehiveInventory")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BeehiveInventory")]
[assembly: AssemblyTitle("BeehiveInventory")]
[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 BeehiveInventory
{
[BepInPlugin("haruhi.peak.beehiveinventory", "Beehive Inventory", "1.0.0")]
public sealed class BeehiveInventoryPlugin : BaseUnityPlugin
{
public const string ModGuid = "haruhi.peak.beehiveinventory";
public const string ModName = "Beehive Inventory";
public const string ModVersion = "1.0.0";
internal static ManualLogSource Log;
internal static ushort? BeehiveItemId;
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
try
{
Harmony.CreateAndPatchAll(typeof(BeehiveInventoryPlugin).Assembly, "haruhi.peak.beehiveinventory");
Log.LogInfo((object)"[Beehive Inventory] loaded.");
}
catch (Exception arg)
{
Log.LogError((object)string.Format("[{0}] Harmony patching failed: {1}", "Beehive Inventory", arg));
}
TryWarmupBeehivePrefab();
}
private void Update()
{
if (!BeehiveItemId.HasValue)
{
TryWarmupBeehivePrefab();
}
}
private static void TryWarmupBeehivePrefab()
{
try
{
ushort itemId;
Item val = TryFindBeehivePrefab(out itemId);
if (!((Object)(object)val == (Object)null))
{
BeehiveItemId = itemId;
if (EnsureBeehiveIsStorable(val))
{
Log.LogInfo((object)string.Format("[{0}] Beehive unlocked for inventory/backpack. itemID={1}", "Beehive Inventory", itemId));
}
}
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogDebug((object)("[Beehive Inventory] warmup failed (will retry): " + ex.Message));
}
}
}
internal static bool IsBeehiveItemId(ushort itemId)
{
if (BeehiveItemId.HasValue && itemId == BeehiveItemId.Value)
{
return true;
}
try
{
Item val = default(Item);
if (ItemDatabase.TryGetItem(itemId, ref val) && (Object)(object)val != (Object)null)
{
return IsBeehivePrefab(val);
}
}
catch
{
}
return false;
}
internal static bool IsBeehivePrefab(Item item)
{
try
{
string text = ((Object)item).name ?? string.Empty;
if (text.IndexOf("Beehive", StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
ItemUIData uIData = item.UIData;
if (uIData != null)
{
FieldInfo fieldInfo = AccessTools.Field(((object)uIData).GetType(), "itemName");
if (fieldInfo != null)
{
string text2 = fieldInfo.GetValue(uIData) as string;
if (!string.IsNullOrWhiteSpace(text2) && text2.IndexOf("Beehive", StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
}
}
}
catch
{
}
return false;
}
internal static Item? TryFindBeehivePrefab(out ushort itemId)
{
itemId = 0;
if (BeehiveItemId.HasValue)
{
try
{
Item val = default(Item);
if (ItemDatabase.TryGetItem(BeehiveItemId.Value, ref val) && (Object)(object)val != (Object)null)
{
itemId = val.itemID;
return val;
}
}
catch
{
}
}
ItemDatabase val2 = Resources.FindObjectsOfTypeAll<ItemDatabase>().FirstOrDefault();
if ((Object)(object)val2 == (Object)null)
{
return null;
}
Type type = ((object)val2).GetType();
FieldInfo fieldInfo = AccessTools.Field(type, "itemLookup");
if (fieldInfo != null && fieldInfo.GetValue(val2) is IDictionary dictionary)
{
foreach (DictionaryEntry item in dictionary)
{
object? value = item.Value;
Item val3 = (Item)((value is Item) ? value : null);
if (val3 != null && (Object)(object)val3 != (Object)null && IsBeehivePrefab(val3))
{
itemId = val3.itemID;
return val3;
}
}
}
PropertyInfo propertyInfo = AccessTools.Property(type, "Objects");
if (propertyInfo != null && propertyInfo.GetValue(val2) is IEnumerable enumerable)
{
foreach (object item2 in enumerable)
{
Item val4 = (Item)((item2 is Item) ? item2 : null);
if (val4 != null && (Object)(object)val4 != (Object)null && IsBeehivePrefab(val4))
{
itemId = val4.itemID;
return val4;
}
}
}
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo2 in fields)
{
try
{
object value2 = fieldInfo2.GetValue(val2);
if (!(value2 is IEnumerable enumerable2))
{
continue;
}
foreach (object item3 in enumerable2)
{
Item val5 = (Item)((item3 is Item) ? item3 : null);
if (val5 != null && (Object)(object)val5 != (Object)null && IsBeehivePrefab(val5))
{
itemId = val5.itemID;
return val5;
}
}
}
catch
{
}
}
return null;
}
internal static bool EnsureBeehiveIsStorable(Item beehivePrefab)
{
bool flag = false;
try
{
ItemUIData uIData = beehivePrefab.UIData;
if (uIData != null)
{
flag |= TrySetBoolMember(uIData, "canDrop", value: true);
flag |= TrySetBoolMember(uIData, "canThrow", value: true);
flag |= EnableBoolMembersByKeywords(uIData, new string[8] { "inventory", "backpack", "store", "stow", "pocket", "slot", "stash", "carry" });
}
}
catch
{
}
try
{
flag |= EnableBoolMembersByKeywords(beehivePrefab, new string[7] { "inventory", "backpack", "store", "stow", "pocket", "slot", "stash" });
}
catch
{
}
try
{
flag |= ClearRestrictiveItemTags(beehivePrefab);
}
catch
{
}
return flag;
}
private static bool TrySetBoolMember(object target, string memberName, bool value)
{
Type type = target.GetType();
FieldInfo fieldInfo = AccessTools.Field(type, memberName);
if (fieldInfo != null && fieldInfo.FieldType == typeof(bool))
{
bool flag = (bool)fieldInfo.GetValue(target);
if (flag != value)
{
fieldInfo.SetValue(target, value);
return true;
}
return false;
}
PropertyInfo propertyInfo = AccessTools.Property(type, memberName);
if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool) && propertyInfo.CanWrite)
{
bool flag2 = (bool)propertyInfo.GetValue(target, null);
if (flag2 != value)
{
propertyInfo.SetValue(target, value, null);
return true;
}
return false;
}
return false;
}
private static bool EnableBoolMembersByKeywords(object target, string[] keywords)
{
bool result = false;
Type type = target.GetType();
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType != typeof(bool) || !HasKeyword(fieldInfo.Name, keywords))
{
continue;
}
try
{
if (!(bool)fieldInfo.GetValue(target))
{
fieldInfo.SetValue(target, true);
result = true;
}
}
catch
{
}
}
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (PropertyInfo propertyInfo in properties)
{
if (propertyInfo.PropertyType != typeof(bool) || !propertyInfo.CanRead || !propertyInfo.CanWrite || !HasKeyword(propertyInfo.Name, keywords))
{
continue;
}
try
{
if (!(bool)propertyInfo.GetValue(target, null))
{
propertyInfo.SetValue(target, true, null);
result = true;
}
}
catch
{
}
}
return result;
static bool HasKeyword(string name, string[] kws)
{
string name2 = name;
return kws.Any((string k) => name2.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0);
}
}
private static bool ClearRestrictiveItemTags(Item item)
{
Type type = ((object)item).GetType();
FieldInfo fieldInfo = AccessTools.Field(type, "itemTags");
if (fieldInfo == null)
{
return false;
}
object value = fieldInfo.GetValue(item);
if (value == null)
{
return false;
}
Type fieldType = fieldInfo.FieldType;
if (!fieldType.IsEnum)
{
return false;
}
ulong num = Convert.ToUInt64(value);
ulong num2 = num;
foreach (object value2 in Enum.GetValues(fieldType))
{
string text = Enum.GetName(fieldType, value2) ?? string.Empty;
if (!string.IsNullOrWhiteSpace(text))
{
bool flag = text.IndexOf("No", StringComparison.OrdinalIgnoreCase) >= 0 && (text.IndexOf("Inventory", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Backpack", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Store", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Stow", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Pocket", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Slot", StringComparison.OrdinalIgnoreCase) >= 0);
flag |= text.IndexOf("Cannot", StringComparison.OrdinalIgnoreCase) >= 0 && (text.IndexOf("Store", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Stow", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Inventory", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Backpack", StringComparison.OrdinalIgnoreCase) >= 0);
flag |= text.IndexOf("Unstorable", StringComparison.OrdinalIgnoreCase) >= 0;
if (flag | (text.IndexOf("NotStorable", StringComparison.OrdinalIgnoreCase) >= 0))
{
ulong num3 = Convert.ToUInt64(value2);
num2 &= ~num3;
}
}
}
if (num2 == num)
{
return false;
}
fieldInfo.SetValue(item, Enum.ToObject(fieldType, num2));
return true;
}
}
[HarmonyPatch(typeof(Player), "AddItem")]
internal static class Player_AddItem_BeehiveRetryPatch
{
[ThreadStatic]
private static bool _reentry;
private static void Postfix(Player __instance, ushort itemID, ItemInstanceData instanceData, ref ItemSlot slot, ref bool __result)
{
if (__result || _reentry || !BeehiveInventoryPlugin.IsBeehiveItemId(itemID))
{
return;
}
try
{
_reentry = true;
ushort itemId;
Item val = BeehiveInventoryPlugin.TryFindBeehivePrefab(out itemId);
if ((Object)(object)val != (Object)null)
{
BeehiveInventoryPlugin.BeehiveItemId = itemId;
BeehiveInventoryPlugin.EnsureBeehiveIsStorable(val);
}
ItemSlot val2 = default(ItemSlot);
if (__instance.AddItem(itemID, instanceData, ref val2))
{
slot = val2;
__result = true;
BeehiveInventoryPlugin.Log.LogInfo((object)$"[Beehive Inventory] Retry succeeded: Beehive stored (slot {slot.itemSlotID}).");
}
else
{
BeehiveInventoryPlugin.Log.LogWarning((object)"[Beehive Inventory] Retry failed: still cannot store Beehive. Game update might have changed checks.");
}
}
catch (Exception arg)
{
BeehiveInventoryPlugin.Log.LogError((object)$"[Beehive Inventory] Error while retrying AddItem for Beehive: {arg}");
}
finally
{
_reentry = false;
}
}
}
}