using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using AzuExtendedPlayerInventory;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("WisplightSlot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WisplightSlot")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("0e9e18a0-13d4-46cb-828a-bece083ab26b")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace WisplightSlot;
public class CustomSlotData : MonoBehaviour
{
public string slotName;
}
[BepInPlugin("thebrutalskull.Brutal_WisplightSlot", "Brutal_WisplightSlot", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class WisplightSlot : BaseUnityPlugin
{
public class HumanoidPatch
{
[CompilerGenerated]
private sealed class <UpdateEquipmentStatusEffectsTranspiler>d__8 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
{
private int <>1__state;
private CodeInstruction <>2__current;
private int <>l__initialThreadId;
private IEnumerable<CodeInstruction> instructionsIn;
public IEnumerable<CodeInstruction> <>3__instructionsIn;
private List<CodeInstruction> <instructions>5__1;
private int <index>5__2;
CodeInstruction IEnumerator<CodeInstruction>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <UpdateEquipmentStatusEffectsTranspiler>d__8(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<instructions>5__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Expected O, but got Unknown
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<instructions>5__1 = instructionsIn.ToList();
if (<instructions>5__1[0].opcode != OpCodes.Newobj || <instructions>5__1[1].opcode != OpCodes.Stloc_0)
{
throw new Exception("CustomSlotItemLib transpiler injection point not found!");
}
<>2__current = <instructions>5__1[0];
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<>2__current = <instructions>5__1[1];
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
<>2__current = new CodeInstruction(OpCodes.Ldloc_0, (object)null);
<>1__state = 3;
return true;
case 3:
<>1__state = -1;
<>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
<>1__state = 4;
return true;
case 4:
<>1__state = -1;
<>2__current = CodeInstruction.Call(typeof(HumanoidPatch), "GetStatusEffectsFromCustomSlotItems", (Type[])null, (Type[])null);
<>1__state = 5;
return true;
case 5:
<>1__state = -1;
<>2__current = CodeInstruction.Call(typeof(HashSet<StatusEffect>), "UnionWith", (Type[])null, (Type[])null);
<>1__state = 6;
return true;
case 6:
<>1__state = -1;
<index>5__2 = 2;
break;
case 7:
<>1__state = -1;
<index>5__2++;
break;
}
if (<index>5__2 < <instructions>5__1.Count)
{
<>2__current = <instructions>5__1[<index>5__2];
<>1__state = 7;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
{
<UpdateEquipmentStatusEffectsTranspiler>d__8 <UpdateEquipmentStatusEffectsTranspiler>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<UpdateEquipmentStatusEffectsTranspiler>d__ = this;
}
else
{
<UpdateEquipmentStatusEffectsTranspiler>d__ = new <UpdateEquipmentStatusEffectsTranspiler>d__8(0);
}
<UpdateEquipmentStatusEffectsTranspiler>d__.instructionsIn = <>3__instructionsIn;
return <UpdateEquipmentStatusEffectsTranspiler>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
}
}
public static HashSet<StatusEffect> GetStatusEffectsFromCustomSlotItems(Humanoid __instance)
{
HashSet<StatusEffect> hashSet = new HashSet<StatusEffect>();
foreach (ItemData item in CustomSlotManager.AllSlotItems(__instance))
{
if (Object.op_Implicit((Object)(object)item.m_shared.m_equipStatusEffect))
{
hashSet.Add(item.m_shared.m_equipStatusEffect);
}
if (Traverse.Create((object)__instance).Method("HaveSetEffect", new Type[1] { typeof(ItemData) }, (object[])null).GetValue<bool>(new object[1] { item }))
{
hashSet.Add(item.m_shared.m_setStatusEffect);
}
}
return hashSet;
}
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref Humanoid __instance)
{
CustomSlotManager.Register(__instance);
}
[HarmonyPatch("EquipItem")]
[HarmonyPostfix]
private static void EquipItemPostfix(ref bool __result, ref Humanoid __instance, ItemData item, bool triggerEquipEffects = true)
{
if (__result && CustomSlotManager.IsCustomSlotItem(item))
{
string customSlotName = CustomSlotManager.GetCustomSlotName(item);
ItemData slotItem = CustomSlotManager.GetSlotItem(__instance, customSlotName);
if (slotItem != null)
{
__instance.UnequipItem(slotItem, triggerEquipEffects);
}
CustomSlotManager.SetSlotItem(__instance, customSlotName, item);
item.m_equipped = __instance.IsItemEquiped(item);
Traverse.Create((object)__instance).Method("SetupEquipment", Array.Empty<object>()).GetValue();
if (item.m_equipped && triggerEquipEffects)
{
Traverse.Create((object)__instance).Method("TriggerEquipEffect", new Type[1] { typeof(ItemData) }, (object[])null).GetValue(new object[1] { item });
}
__result = true;
}
}
[HarmonyPatch("GetEquipmentWeight")]
[HarmonyPostfix]
private static void GetEquipmentWeightPostfix(ref float __result, ref Humanoid __instance)
{
foreach (ItemData item in CustomSlotManager.AllSlotItems(__instance))
{
__result += item.m_shared.m_weight;
}
}
[HarmonyPatch("GetSetCount")]
[HarmonyPostfix]
private static void GetSetCountPostfix(ref int __result, ref Humanoid __instance, string setName)
{
foreach (ItemData item in CustomSlotManager.AllSlotItems(__instance))
{
if (item.m_shared.m_setName == setName)
{
__result++;
}
}
}
[HarmonyPatch("IsItemEquiped")]
[HarmonyPostfix]
private static void IsItemEquipedPostfix(ref bool __result, ref Humanoid __instance, ItemData item)
{
if (CustomSlotManager.IsCustomSlotItem(item))
{
string customSlotName = CustomSlotManager.GetCustomSlotName(item);
__result |= CustomSlotManager.GetSlotItem(__instance, customSlotName) == item;
}
}
[HarmonyPatch("UnequipAllItems")]
[HarmonyPostfix]
private static void UnequipAllItemsPostfix(ref Humanoid __instance)
{
foreach (ItemData item in CustomSlotManager.AllSlotItems(__instance))
{
__instance.UnequipItem(item, false);
}
}
[HarmonyPatch("UnequipItem")]
[HarmonyPostfix]
private static void UnequipItemPostfix(ref Humanoid __instance, ItemData item, bool triggerEquipEffects = true)
{
if (item != null)
{
string customSlotName = CustomSlotManager.GetCustomSlotName(item);
if (item == CustomSlotManager.GetSlotItem(__instance, customSlotName))
{
CustomSlotManager.SetSlotItem(__instance, customSlotName, null);
item.m_equipped = __instance.IsItemEquiped(item);
Traverse.Create((object)__instance).Method("UpdateEquipmentStatusEffects", Array.Empty<object>()).GetValue();
}
}
}
[IteratorStateMachine(typeof(<UpdateEquipmentStatusEffectsTranspiler>d__8))]
[HarmonyPatch("UpdateEquipmentStatusEffects")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> UpdateEquipmentStatusEffectsTranspiler(IEnumerable<CodeInstruction> instructionsIn)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <UpdateEquipmentStatusEffectsTranspiler>d__8(-2)
{
<>3__instructionsIn = instructionsIn
};
}
}
private readonly Harmony harmony = new Harmony("thebrutalskull.Brutal_WisplightSlot");
public static readonly ManualLogSource WisplightSlotLogger = Logger.CreateLogSource("Brutal_WisplightSlot");
private void Awake()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
if ((int)SystemInfo.graphicsDeviceType == 4)
{
WisplightSlotLogger.LogWarning((object)"This mod is client-side only and is not needed on a dedicated server. Plugin patches will not be applied.");
return;
}
if (API.IsLoaded())
{
API.AddSlot("Wisplight", (Func<Player, ItemData>)GetItem, (Func<ItemData, bool>)IsWisplight, -1);
}
harmony.PatchAll();
}
private ItemData GetItem(Humanoid player)
{
return ((IEnumerable<ItemData>)player.GetInventory().GetEquippedItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i != null && Object.op_Implicit((Object)(object)i.m_dropPrefab) && ((Object)i.m_dropPrefab).name == "Demister"));
}
private bool IsWisplight(ItemData item)
{
return item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab) && ((Object)item.m_dropPrefab).name == "Demister";
}
}
public static class CustomSlotManager
{
private static readonly Dictionary<Humanoid, Dictionary<string, ItemData>> customSlotItemData = new Dictionary<Humanoid, Dictionary<string, ItemData>>();
public static void Register(Humanoid humanoid)
{
customSlotItemData[humanoid] = new Dictionary<string, ItemData>();
}
public static void Unregister(Humanoid humanoid)
{
customSlotItemData.Remove(humanoid);
}
public static bool IsCustomSlotItem(ItemData item)
{
return GetCustomSlotName(item) != null;
}
public static string GetCustomSlotName(ItemData item)
{
if (item == null)
{
return null;
}
GameObject dropPrefab = item.m_dropPrefab;
if ((Object)(object)dropPrefab == (Object)null)
{
return null;
}
return dropPrefab.GetComponent<CustomSlotData>()?.slotName;
}
private static Dictionary<string, ItemData> GetCustomSlots(Humanoid humanoid)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
if (!((Object)humanoid != (Object)null) || !customSlotItemData.ContainsKey(humanoid))
{
return null;
}
return customSlotItemData[humanoid];
}
public static bool DoesSlotExist(Humanoid humanoid, string slotName)
{
return GetCustomSlots(humanoid)?.ContainsKey(slotName) ?? false;
}
public static bool IsSlotOccupied(Humanoid humanoid, string slotName)
{
return GetSlotItem(humanoid, slotName) != null;
}
public static ItemData GetSlotItem(Humanoid humanoid, string slotName)
{
Dictionary<string, ItemData> dictionary = ((slotName != null) ? GetCustomSlots(humanoid) : null);
if (dictionary == null || !dictionary.ContainsKey(slotName))
{
return null;
}
return dictionary[slotName];
}
public static void SetSlotItem(Humanoid humanoid, string slotName, ItemData item)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
if (!((Object)humanoid == (Object)null) && slotName != null)
{
customSlotItemData[humanoid][slotName] = item;
}
}
public static IEnumerable<ItemData> AllSlotItems(Humanoid humanoid)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
if ((Object)humanoid == (Object)null || !customSlotItemData.ContainsKey(humanoid))
{
return Enumerable.Empty<ItemData>();
}
return customSlotItemData[humanoid].Values.Where((ItemData x) => x != null).ToList();
}
public static void ApplyCustomSlotItem(GameObject gameObject, string slotName)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Expected O, but got Unknown
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
if ((Object)gameObject == (Object)null)
{
throw new ArgumentNullException("gameObject");
}
if (slotName == null)
{
throw new ArgumentNullException("slotName");
}
CustomSlotData component = gameObject.GetComponent<CustomSlotData>();
if ((Object)component != (Object)null)
{
if (component.slotName != slotName)
{
throw new InvalidOperationException("GameObject \"" + ((Object)gameObject).name + "\" already has component CustomSlotData! (\"" + component.slotName + "\" != \"" + slotName + "\")");
}
}
else
{
if ((Object)gameObject.GetComponent<ItemDrop>() == (Object)null)
{
throw new InvalidOperationException("GameObject \"" + ((Object)gameObject).name + "\" does not have component ItemDrop!");
}
gameObject.AddComponent<CustomSlotData>().slotName = slotName;
gameObject.GetComponent<ItemDrop>().m_itemData.m_shared.m_itemType = (ItemType)0;
}
}
}