Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HousePersistentDeck v1.1.0
HousePersistentDeck.dll
Decompiled 11 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("HousePersistentDeck")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+fa6bc2bd0384d671c71712b67fafdeea462fc7c9")] [assembly: AssemblyProduct("HousePersistentDeck")] [assembly: AssemblyTitle("HousePersistentDeck")] [assembly: AssemblyVersion("1.0.0.0")] [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 HousePersistentDeck { internal sealed class CardFeedUI : MonoBehaviour { [CompilerGenerated] private sealed class <AnimateNewest>d__32 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CardFeedUI <>4__this; private int <slotIdx>5__2; private Color <orig>5__3; private Color <flash>5__4; private float <t>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AnimateNewest>d__32(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; CardFeedUI cardFeedUI = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <slotIdx>5__2 = Mathf.Min(cardFeedUI._history.Count - 1, 5); if (<slotIdx>5__2 < 0) { return false; } <orig>5__3 = ((Graphic)cardFeedUI._slotBg[<slotIdx>5__2]).color; <flash>5__4 = Color.Lerp(<orig>5__3, Color.white, 0.45f); <t>5__5 = 0f; goto IL_00e5; case 1: <>1__state = -1; goto IL_00e5; case 2: { <>1__state = -1; break; } IL_00e5: if (<t>5__5 < 0.12f) { ((Graphic)cardFeedUI._slotBg[<slotIdx>5__2]).color = Color.Lerp(<orig>5__3, <flash>5__4, <t>5__5 / 0.12f); <t>5__5 += Time.deltaTime; <>2__current = null; <>1__state = 1; return true; } <t>5__5 = 0f; break; } if (<t>5__5 < 0.18f) { ((Graphic)cardFeedUI._slotBg[<slotIdx>5__2]).color = Color.Lerp(<flash>5__4, <orig>5__3, <t>5__5 / 0.18f); <t>5__5 += Time.deltaTime; <>2__current = null; <>1__state = 2; return true; } ((Graphic)cardFeedUI._slotBg[<slotIdx>5__2]).color = <orig>5__3; 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(); } } public static bool Enabled = true; public static string Position = "bottom-left"; public static float Opacity = 0.82f; public static float Scale = 1f; public static readonly Dictionary<int, Sprite> CardSprites = new Dictionary<int, Sprite>(); public static readonly Dictionary<int, (string shortName, Color color)> CardColors = new Dictionary<int, (string, Color)>(); private const int FeedSize = 6; private const float SlotW = 54f; private const float SlotH = 72f; private const float SlotGap = 5f; private const float PanelPad = 8f; private readonly List<(int id, string name)> _history = new List<(int, string)>(6); private Canvas? _canvas; private RectTransform? _panelRect; private readonly Image[] _slotBg = (Image[])(object)new Image[6]; private readonly Image[] _slotIcon = (Image[])(object)new Image[6]; private readonly Text[] _slotText = (Text[])(object)new Text[6]; private readonly CanvasGroup[] _slotGroup = (CanvasGroup[])(object)new CanvasGroup[6]; public static CardFeedUI? Instance { get; private set; } public static void AddCard(int cardId, string displayName) { if (!((Object)(object)Instance == (Object)null)) { Instance.PushCard(cardId, displayName); } } public static void ClearFeed() { if (!((Object)(object)Instance == (Object)null)) { Instance._history.Clear(); Instance.RefreshSlots(); } } public static void SetVisible(bool visible) { if (!((Object)(object)Instance == (Object)null) && (Object)(object)Instance._panelRect != (Object)null) { ((Component)Instance._panelRect).gameObject.SetActive(visible); } } private void Awake() { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); BuildCanvas(); } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void BuildCanvas() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0190: 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) _canvas = ((Component)this).gameObject.AddComponent<Canvas>(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 55; _canvas.pixelPerfect = true; CanvasScaler obj = ((Component)this).gameObject.AddComponent<CanvasScaler>(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); obj.screenMatchMode = (ScreenMatchMode)0; obj.matchWidthOrHeight = 0.5f; ((Component)this).gameObject.AddComponent<GraphicRaycaster>(); GameObject val = new GameObject("CardFeedPanel"); val.transform.SetParent(((Component)this).transform, false); _panelRect = val.AddComponent<RectTransform>(); ApplyAnchorPosition(_panelRect); ((Graphic)val.AddComponent<Image>()).color = new Color(0.04f, 0.06f, 0.1f, 0.88f); CanvasGroup obj2 = val.AddComponent<CanvasGroup>(); obj2.alpha = Opacity; obj2.interactable = false; obj2.blocksRaycasts = false; float num = 365f; float num2 = 88f; _panelRect.sizeDelta = new Vector2(num, num2); GameObject val2 = new GameObject("Accent"); val2.transform.SetParent(val.transform, false); RectTransform obj3 = val2.AddComponent<RectTransform>(); obj3.anchorMin = new Vector2(0f, 1f); obj3.anchorMax = new Vector2(1f, 1f); obj3.pivot = new Vector2(0.5f, 1f); obj3.offsetMin = Vector2.zero; obj3.offsetMax = Vector2.zero; obj3.sizeDelta = new Vector2(0f, 2f); ((Graphic)val2.AddComponent<Image>()).color = new Color(0.39f, 0.71f, 0.85f, 0.7f); for (int i = 0; i < 6; i++) { float cx = 8f + (float)i * 59f + 27f; BuildSlot(val.transform, i, cx, 0f); } RefreshSlots(); ((Component)_panelRect).gameObject.SetActive(false); } private void BuildSlot(Transform parent, int index, float cx, float cy) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0034: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: 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_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"Slot{index}"); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent<RectTransform>(); obj.anchorMin = new Vector2(0f, 0.5f); obj.anchorMax = new Vector2(0f, 0.5f); obj.pivot = new Vector2(0.5f, 0.5f); obj.anchoredPosition = new Vector2(cx, cy); obj.sizeDelta = new Vector2(54f, 72f); CanvasGroup val2 = val.AddComponent<CanvasGroup>(); val2.alpha = 0f; _slotGroup[index] = val2; Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = new Color(0.15f, 0.18f, 0.22f, 1f); _slotBg[index] = val3; GameObject val4 = new GameObject("Icon"); val4.transform.SetParent(val.transform, false); RectTransform obj2 = val4.AddComponent<RectTransform>(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.offsetMin = new Vector2(2f, 2f); obj2.offsetMax = new Vector2(-2f, -2f); Image val5 = val4.AddComponent<Image>(); val5.preserveAspect = true; ((Behaviour)val5).enabled = false; _slotIcon[index] = val5; GameObject val6 = new GameObject("Text"); val6.transform.SetParent(val.transform, false); RectTransform obj3 = val6.AddComponent<RectTransform>(); obj3.anchorMin = Vector2.zero; obj3.anchorMax = Vector2.one; obj3.offsetMin = new Vector2(3f, 4f); obj3.offsetMax = new Vector2(-3f, -4f); Text val7 = val6.AddComponent<Text>(); val7.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val7.fontSize = 9; val7.fontStyle = (FontStyle)1; val7.alignment = (TextAnchor)4; ((Graphic)val7).color = Color.white; val7.horizontalOverflow = (HorizontalWrapMode)0; val7.verticalOverflow = (VerticalWrapMode)1; val7.lineSpacing = 1.1f; _slotText[index] = val7; GameObject val8 = new GameObject("Border"); val8.transform.SetParent(val.transform, false); RectTransform obj4 = val8.AddComponent<RectTransform>(); obj4.anchorMin = Vector2.zero; obj4.anchorMax = Vector2.one; obj4.offsetMin = Vector2.zero; obj4.offsetMax = Vector2.zero; Image obj5 = val8.AddComponent<Image>(); ((Graphic)obj5).color = new Color(1f, 1f, 1f, 0.18f); obj5.fillCenter = false; } private void ApplyAnchorPosition(RectTransform rt) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_01d2: 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) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) float num = 365f; float num2 = 88f; Vector2 val = default(Vector2); switch (Position) { case "top-right": ((Vector2)(ref val))..ctor(1f, 1f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(1f, 1f); rt.anchoredPosition = new Vector2(-12f, -12f); break; case "top-left": ((Vector2)(ref val))..ctor(0f, 1f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(0f, 1f); rt.anchoredPosition = new Vector2(12f, -12f); break; case "bottom-right": ((Vector2)(ref val))..ctor(1f, 0f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(1f, 0f); rt.anchoredPosition = new Vector2(-12f, 12f); break; case "bottom-center": ((Vector2)(ref val))..ctor(0.5f, 0f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(0.5f, 0f); rt.anchoredPosition = new Vector2(0f, 2f); break; default: ((Vector2)(ref val))..ctor(0f, 0f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(0f, 0f); rt.anchoredPosition = new Vector2(12f, 12f); break; } rt.sizeDelta = new Vector2(num, num2); } private void PushCard(int cardId, string displayName) { _history.Add((cardId, displayName)); if (_history.Count > 6) { _history.RemoveAt(0); } RefreshSlots(); ((MonoBehaviour)this).StartCoroutine(AnimateNewest()); } private void RefreshSlots() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 6; i++) { int num = _history.Count - (6 - i); if (num < 0) { _slotGroup[i].alpha = 0f; continue; } (int id, string name) tuple = _history[num]; int item = tuple.id; string item2 = tuple.name; int num2 = 5 - i; ((Graphic)_slotBg[i]).color = GetSlotColor(item); if (CardSprites.TryGetValue(item, out Sprite value) && (Object)(object)value != (Object)null) { _slotIcon[i].sprite = value; ((Behaviour)_slotIcon[i]).enabled = true; ((Behaviour)_slotText[i]).enabled = false; } else { ((Behaviour)_slotIcon[i]).enabled = false; _slotText[i].text = FormatName(item2); ((Behaviour)_slotText[i]).enabled = true; } _slotGroup[i].alpha = Mathf.Lerp(1f, 0.38f, (float)num2 / 5f); } } [IteratorStateMachine(typeof(<AnimateNewest>d__32))] private IEnumerator AnimateNewest() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AnimateNewest>d__32(0) { <>4__this = this }; } private static Color GetSlotColor(int cardId) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (CardColors.TryGetValue(cardId, out (string, Color) value)) { return value.Item2; } return Color.HSVToRGB(((float)cardId * 0.618034f % 1f + 1f) % 1f, 0.45f, 0.55f); } private static string FormatName(string rawName) { if (string.IsNullOrEmpty(rawName) || rawName == "?") { return "?"; } string text = rawName.Replace("The ", "").Replace(" of ", "\n").Trim(); string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return rawName; } if (array.Length <= 2) { return text; } return array[0] + "\n" + array[1]; } } internal sealed class DeckDisplayUI : MonoBehaviour { private const int MaxSlots = 60; private const float SlotW = 28f; private const float SlotH = 37f; private const float SlotGap = 3f; private const float ColGap = 4f; private const float PanelPad = 6f; private const int NumCols = 2; private static readonly Color BgHand = new Color(0.28f, 0.22f, 0.06f, 1f); private static readonly Color BgNormal = new Color(0.12f, 0.14f, 0.18f, 1f); private Canvas? _canvas; private RectTransform? _panelRect; private CanvasGroup? _panelGroup; private bool _refreshPending; private readonly RectTransform[] _slotRt = (RectTransform[])(object)new RectTransform[60]; private readonly Image[] _slotBg = (Image[])(object)new Image[60]; private readonly Image[] _slotIcon = (Image[])(object)new Image[60]; public static DeckDisplayUI? Instance { get; private set; } public static void RequestRefresh() { if ((Object)(object)Instance != (Object)null) { Instance._refreshPending = true; } } public static void Refresh(int[] hand, List<int> drawPile, List<int> discard) { if (!((Object)(object)Instance == (Object)null)) { Instance.DoRefresh(hand, drawPile, discard); } } public static void SetVisible(bool v) { if (!((Object)(object)Instance == (Object)null) && (Object)(object)Instance._panelRect != (Object)null) { ((Component)Instance._panelRect).gameObject.SetActive(v); } } private void Awake() { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); BuildCanvas(); } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void LateUpdate() { if (_refreshPending) { _refreshPending = false; DoRefresh(Plugin.GetCurrentHand(), Plugin.GetCurrentDeck(), Plugin.GetCurrentDiscard()); } } private void BuildCanvas() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) _canvas = ((Component)this).gameObject.AddComponent<Canvas>(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 54; _canvas.pixelPerfect = true; CanvasScaler obj = ((Component)this).gameObject.AddComponent<CanvasScaler>(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); obj.screenMatchMode = (ScreenMatchMode)0; obj.matchWidthOrHeight = 0.5f; ((Component)this).gameObject.AddComponent<GraphicRaycaster>(); GameObject val = new GameObject("DeckDisplayPanel"); val.transform.SetParent(((Component)this).transform, false); _panelRect = val.AddComponent<RectTransform>(); _panelRect.anchorMin = new Vector2(0f, 0.5f); _panelRect.anchorMax = new Vector2(0f, 0.5f); _panelRect.pivot = new Vector2(0f, 0.5f); ((Graphic)val.AddComponent<Image>()).color = new Color(0.04f, 0.06f, 0.1f, 0.88f); _panelGroup = val.AddComponent<CanvasGroup>(); _panelGroup.alpha = CardFeedUI.Opacity; _panelGroup.interactable = false; _panelGroup.blocksRaycasts = false; GameObject val2 = new GameObject("Accent"); val2.transform.SetParent(val.transform, false); RectTransform obj2 = val2.AddComponent<RectTransform>(); obj2.anchorMin = new Vector2(1f, 0f); obj2.anchorMax = new Vector2(1f, 1f); obj2.pivot = new Vector2(1f, 0.5f); obj2.offsetMin = Vector2.zero; obj2.offsetMax = Vector2.zero; obj2.sizeDelta = new Vector2(2f, 0f); ((Graphic)val2.AddComponent<Image>()).color = new Color(0.39f, 0.71f, 0.85f, 0.5f); for (int i = 0; i < 60; i++) { BuildSlot(val.transform, i); } ((Component)_panelRect).gameObject.SetActive(false); } private void BuildSlot(Transform parent, int index) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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) //IL_0100: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"DeckSlot{index}"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0f, 0.5f); val2.anchorMax = new Vector2(0f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = new Vector2(28f, 37f); _slotRt[index] = val2; val.SetActive(false); Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = BgNormal; _slotBg[index] = val3; GameObject val4 = new GameObject("Icon"); val4.transform.SetParent(val.transform, false); RectTransform obj = val4.AddComponent<RectTransform>(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = new Vector2(2f, 2f); obj.offsetMax = new Vector2(-2f, -2f); Image val5 = val4.AddComponent<Image>(); val5.preserveAspect = true; ((Behaviour)val5).enabled = false; _slotIcon[index] = val5; } private void DoRefresh(int[] hand, List<int> drawPile, List<int> discard) { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: 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_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panelRect == (Object)null) { return; } if ((Object)(object)_panelGroup != (Object)null) { _panelGroup.alpha = CardFeedUI.Opacity; } List<int> list = new List<int>(); if (hand != null) { list.AddRange(hand); } if (drawPile != null) { list.AddRange(drawPile); } if (discard != null) { list.AddRange(discard); } list.Sort(); int num = Math.Min(list.Count, 60); for (int i = num; i < 60; i++) { ((Component)_slotRt[i]).gameObject.SetActive(false); } if (num == 0) { ((Component)_panelRect).gameObject.SetActive(false); return; } int num2 = (num + 2 - 1) / 2; float num3 = 72f; float num4 = (float)num2 * 40f - 3f + 12f; _panelRect.sizeDelta = new Vector2(num3, num4); _panelRect.anchoredPosition = new Vector2(2f, 0f); List<int> list2 = ((hand != null) ? new List<int>(hand) : new List<int>()); for (int j = 0; j < num; j++) { int num5 = list[j]; int num6 = list2.IndexOf(num5); bool flag = num6 >= 0; if (flag) { list2.RemoveAt(num6); } int num7 = j % 2; int num8 = j / 2; float num9 = 6f + (float)num7 * 32f + 14f; float num10 = num4 * 0.5f - 6f - (float)num8 * 40f - 18.5f; _slotRt[j].anchoredPosition = new Vector2(num9, num10); ((Component)_slotRt[j]).gameObject.SetActive(true); if (CardFeedUI.CardSprites.TryGetValue(num5, out Sprite value) && (Object)(object)value != (Object)null) { _slotIcon[j].sprite = value; ((Graphic)_slotIcon[j]).color = Color.white; ((Behaviour)_slotIcon[j]).enabled = true; ((Graphic)_slotBg[j]).color = (flag ? BgHand : BgNormal); } else { ((Behaviour)_slotIcon[j]).enabled = false; (string, Color) value2; Color val = ((!CardFeedUI.CardColors.TryGetValue(num5, out value2)) ? Color.HSVToRGB(((float)num5 * 0.618034f % 1f + 1f) % 1f, 0.45f, 0.55f) : value2.Item2); ((Graphic)_slotBg[j]).color = (flag ? Color.Lerp(val, new Color(0.6f, 0.45f, 0.1f), 0.5f) : val); } } ((Component)_panelRect).gameObject.SetActive(true); } } [BepInPlugin("com.fae.housepersistentdeck", "House Persistent Deck", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { private sealed class DeckState { public int[] GameDeck { get; } public int[] DiscardPile { get; } public int[] HandCards { get; } public DeckState(int[] gameDeck, int[] discardPile, int[] handCards) { GameDeck = gameDeck; DiscardPile = discardPile; HandCards = handCards; } } public const string PluginGuid = "com.fae.housepersistentdeck"; public const string PluginName = "House Persistent Deck"; public const string PluginVersion = "1.1.0"; private static readonly Dictionary<object, DeckState> SavedDecks = new Dictionary<object, DeckState>(); private static readonly HashSet<object> InitialisingManagers = new HashSet<object>(); private static readonly HashSet<object> RestoringManagers = new HashSet<object>(); private static Type? _managerType; private static Type? _hudType; private static FieldInfo? _characterBodyField; private static FieldInfo? _gameDeckField; private static FieldInfo? _discardPileField; private static FieldInfo? _handCardsField; private static FieldInfo? _initialisedField; private static FieldInfo? _isAuthorityField; private static FieldInfo? _hudPassiveManagerField; private static FieldInfo? _hudInstanceField; private static FieldInfo? _hudCardArtsField; private static MethodInfo? _hudNewHandMethod; private static MethodInfo? _hudUpdateCardDisplayMethod; private static int[]? _handSnapshot; private static List<int>? _discardSnapshot; private static object? _activeManager; private static bool _cardPushedViaButton; private static int _nextHandDepth; private static bool _inNextHand; private static bool _debugDumped; private static ManualLogSource? _log; private static MethodInfo? _directCardPlayMethod; private static ConfigEntry<bool>? _feedEnabled; private static ConfigEntry<string>? _feedPosition; private static ConfigEntry<float>? _feedOpacity; private static ConfigEntry<float>? _feedScale; private Harmony? _harmony; private static Dictionary<string, (string abbr, Color color)>? _knownCardStyles; private void Awake() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; _managerType = AccessTools.TypeByName("HouseMod.SkillStates.House.HousePassiveManager"); _hudType = AccessTools.TypeByName("HouseMod.SkillStates.House.HouseHUDManager"); if (_managerType == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find HousePassiveManager. Is TheHouse 2.3.2 loaded?"); return; } InitConfig(); CacheReflection(); DiscoverCardNames(); _harmony = new Harmony("com.fae.housepersistentdeck"); TryPatchDirectCardPlay(); Patch(_managerType, "Initialise", "InitialisePrefix", "InitialisePostfix"); Patch(_managerType, "NextHand", "NextHandPrefix", "NextHandPostfix"); Patch(_managerType, "HandleScepterCard", null, "SavePostfix"); Patch(_managerType, "OnDestroy", "SavePrefix"); if (_hudNewHandMethod != null) { try { _harmony.Patch((MethodBase)_hudNewHandMethod, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "HudNewHandPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch HouseHUDManager.NewHand: " + ex.Message)); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"House deck persistence + card feed patches installed."); } private void InitConfig() { _feedEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("CardFeed", "Enabled", true, "Show the card play history feed on the HUD."); _feedPosition = ((BaseUnityPlugin)this).Config.Bind<string>("CardFeed", "Position", "bottom-center", "Feed position. Values: bottom-left | bottom-right | top-left | top-right | bottom-center"); _feedOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("CardFeed", "Opacity", 0.82f, "Background opacity of the feed panel (0 = transparent, 1 = opaque)."); _feedScale = ((BaseUnityPlugin)this).Config.Bind<float>("CardFeed", "Scale", 1f, "UI scale multiplier for the card feed."); ApplyFeedConfig(); _feedEnabled.SettingChanged += delegate { ApplyFeedConfig(); }; _feedPosition.SettingChanged += delegate { ApplyFeedConfig(); }; _feedOpacity.SettingChanged += delegate { ApplyFeedConfig(); }; _feedScale.SettingChanged += delegate { ApplyFeedConfig(); }; } private static void ApplyFeedConfig() { CardFeedUI.Enabled = _feedEnabled?.Value ?? true; CardFeedUI.Position = _feedPosition?.Value ?? "bottom-center"; CardFeedUI.Opacity = _feedOpacity?.Value ?? 0.82f; CardFeedUI.Scale = _feedScale?.Value ?? 1f; } private void CacheReflection() { _characterBodyField = AccessTools.Field(_managerType, "characterBody"); _gameDeckField = AccessTools.Field(_managerType, "gameDeck"); _discardPileField = AccessTools.Field(_managerType, "gameDeckDiscardPile"); _handCardsField = AccessTools.Field(_managerType, "handCards"); _initialisedField = AccessTools.Field(_managerType, "Initialised"); _isAuthorityField = AccessTools.Field(_managerType, "isAuthority"); if (!(_hudType == null)) { _hudPassiveManagerField = AccessTools.Field(_hudType, "passiveManager"); _hudInstanceField = AccessTools.Field(_hudType, "instance"); _hudCardArtsField = AccessTools.Field(_hudType, "CardArts"); _hudNewHandMethod = AccessTools.Method(_hudType, "NewHand", new Type[2] { typeof(int[]), typeof(string) }, (Type[])null); _hudUpdateCardDisplayMethod = AccessTools.Method(_hudType, "UpdateCardDisplay", (Type[])null, (Type[])null); } } private static void DiscoverCardNames() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) _knownCardStyles = new Dictionary<string, (string, Color)>(StringComparer.OrdinalIgnoreCase) { ["king"] = ("King\n♠Wands", new Color(0.94f, 0.67f, 0.13f)), ["queen"] = ("Queen\n♣Cups", new Color(0.26f, 0.52f, 0.95f)), ["knight"] = ("Knight\n♦Swords", new Color(0.63f, 0.75f, 0.8f)), ["page"] = ("Page\n♦Pents", new Color(0.25f, 0.72f, 0.45f)), ["jack"] = ("Jack\n♦Diams", new Color(0.25f, 0.82f, 0.91f)), ["ace"] = ("Ace\n♠Spades", new Color(0.25f, 0.35f, 0.55f)), ["three"] = ("3 of\nKind", new Color(0.6f, 0.22f, 0.8f)), ["ante"] = ("Up the\nAnte!", new Color(0.25f, 0.78f, 0.3f)), ["bust"] = ("Bust", new Color(0.83f, 0.18f, 0.18f)), ["snake"] = ("Snake\nEyes", new Color(0.83f, 0.4f, 0.14f)), ["pick"] = ("Pick-Up\n52", new Color(0.25f, 0.65f, 0.9f)), ["sun"] = ("The Sun", new Color(0.97f, 0.91f, 0.14f)), ["moon"] = ("The Moon", new Color(0.44f, 0.55f, 0.82f)), ["star"] = ("The Star", new Color(0.14f, 0.84f, 0.8f)), ["world"] = ("The World", new Color(0.92f, 0.92f, 0.95f)), ["judgement"] = ("Judge-\nment", new Color(0.82f, 0.35f, 0.1f)), ["judgment"] = ("Judge-\nment", new Color(0.82f, 0.35f, 0.1f)) }; } private static void PopulateCardColorsFromDeck(object manager) { //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) if (CardFeedUI.CardColors.Count > 0) { return; } List<int> list = ReadList(_gameDeckField, manager); if (list == null || _knownCardStyles == null) { return; } MethodInfo methodInfo = null; if (_hudType != null) { methodInfo = AccessTools.Method(_hudType, "GetCardName", new Type[1] { typeof(int) }, (Type[])null) ?? AccessTools.Method(_hudType, "GetName", new Type[1] { typeof(int) }, (Type[])null) ?? AccessTools.Method(_hudType, "CardName", new Type[1] { typeof(int) }, (Type[])null); } if (methodInfo == null && _managerType != null) { methodInfo = AccessTools.Method(_managerType, "GetCardName", new Type[1] { typeof(int) }, (Type[])null) ?? AccessTools.Method(_managerType, "CardName", new Type[1] { typeof(int) }, (Type[])null); } foreach (int item in list.Distinct()) { string text = null; if (methodInfo != null) { try { text = methodInfo.Invoke(null, new object[1] { item }) as string; } catch { } } if (text == null) { continue; } foreach (var (value, tuple2) in _knownCardStyles) { if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { CardFeedUI.CardColors[item] = (tuple2.Item1, tuple2.Item2); break; } } if (!CardFeedUI.CardColors.ContainsKey(item)) { float num = ((float)item * 0.618034f % 1f + 1f) % 1f; CardFeedUI.CardColors[item] = (text, Color.HSVToRGB(num, 0.55f, 0.72f)); } } } private void TryPatchDirectCardPlay() { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown if (_managerType == null) { return; } string[] array = new string[6] { "UseCard", "SelectCard", "PlayCard", "HandleCard", "ActivateCard", "OnCardSelected" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.Method(_managerType, text, (Type[])null, (Type[])null); if (!(methodInfo == null)) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && !(parameters[0].ParameterType != typeof(int))) { _directCardPlayMethod = methodInfo; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[CardFeed] Found direct card play method: " + text + "(int)")); _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "DirectPlayPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return; } } } if (_hudType != null) { array = new string[5] { "OnCardClick", "CardButtonPressed", "HandleCardButton", "OnCardSelected", "CardClicked" }; foreach (string text2 in array) { MethodInfo methodInfo2 = AccessTools.Method(_hudType, text2, (Type[])null, (Type[])null); if (!(methodInfo2 == null)) { ParameterInfo[] parameters2 = methodInfo2.GetParameters(); if (parameters2.Length == 1 && !(parameters2[0].ParameterType != typeof(int))) { _directCardPlayMethod = methodInfo2; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[CardFeed] Found HUD card click method: " + text2 + "(int)")); _harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "DirectPlayPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return; } } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[CardFeed] No direct play method found; will use discard-diff fallback."); } private static void ClearRunState() { SavedDecks.Clear(); InitialisingManagers.Clear(); RestoringManagers.Clear(); CardFeedUI.ClearFeed(); } private static void EnsureFeedUIExists() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<bool>? feedEnabled = _feedEnabled; if ((feedEnabled == null || feedEnabled.Value) && !((Object)(object)CardFeedUI.Instance != (Object)null)) { new GameObject("[HousePersistentDeck] CardFeed").AddComponent<CardFeedUI>(); EnsureDeckDisplayExists(); } } private static void EnsureDeckDisplayExists() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)DeckDisplayUI.Instance != (Object)null)) { new GameObject("[HousePersistentDeck] DeckDisplay").AddComponent<DeckDisplayUI>(); } } private static void HudNewHandPostfix(object __instance, int[] __0) { if (_inNextHand || __0 == null || __0.Length == 0 || !(_hudCardArtsField?.GetValue(null) is Image[] array)) { return; } for (int i = 0; i < __0.Length && i < array.Length; i++) { Image obj = array[i]; if ((Object)(object)((obj != null) ? obj.sprite : null) != (Object)null) { CardFeedUI.CardSprites[__0[i]] = array[i].sprite; } } } private static void InitialisePrefix(object __instance) { if (!GetBool(_initialisedField, __instance)) { InitialisingManagers.Add(__instance); } } private static void InitialisePostfix(object __instance) { if (!InitialisingManagers.Remove(__instance) || !GetBool(_initialisedField, __instance)) { return; } _activeManager = __instance; PopulateCardColorsFromDeck(__instance); EnsureFeedUIExists(); EnsureDeckDisplayExists(); CardFeedUI.SetVisible(visible: true); DeckDisplayUI.SetVisible(v: true); object deckKey = GetDeckKey(__instance); if (deckKey != null) { if (SavedDecks.TryGetValue(deckKey, out DeckState value)) { RestoreState(__instance, value); UpdateHud(__instance); } else { CardFeedUI.ClearFeed(); SaveState(__instance); } RefreshDeckDisplay(__instance); if (!_debugDumped) { _debugDumped = true; DumpDebugInfo(__instance); } } } private static void SavePrefix(object __instance) { SaveState(__instance); _activeManager = null; _inNextHand = false; _nextHandDepth = 0; CardFeedUI.SetVisible(visible: false); DeckDisplayUI.SetVisible(v: false); } private static void SavePostfix(object __instance) { if (!InitialisingManagers.Contains(__instance) && !RestoringManagers.Contains(__instance)) { SaveState(__instance); } } private static void NextHandPrefix(object __instance, string __0) { ConfigEntry<bool>? feedEnabled = _feedEnabled; if (feedEnabled == null || !feedEnabled.Value || _directCardPlayMethod != null) { return; } _nextHandDepth++; _inNextHand = true; int[] array = ReadArray(_handCardsField, __instance); Image[] array2 = _hudCardArtsField?.GetValue(null) as Image[]; if (_nextHandDepth == 1 && array != null && array2 != null) { for (int i = 0; i < array.Length && i < array2.Length; i++) { Image obj = array2[i]; if ((Object)(object)((obj != null) ? obj.sprite : null) != (Object)null) { CardFeedUI.CardSprites[array[i]] = array2[i].sprite; } } } if (_nextHandDepth == 1 && int.TryParse(__0, out var result) && array != null && result >= 0 && result < array.Length) { _cardPushedViaButton = true; PushCardToFeed(array[result]); } } private static void NextHandPostfix(object __instance) { _nextHandDepth = Math.Max(0, _nextHandDepth - 1); _inNextHand = _nextHandDepth > 0; if (!InitialisingManagers.Contains(__instance) && !RestoringManagers.Contains(__instance)) { SaveState(__instance); } if (_nextHandDepth == 0) { _cardPushedViaButton = false; _handSnapshot = null; _discardSnapshot = null; RefreshDeckDisplay(__instance); } } private static void DirectPlayPrefix(object __instance, int __0) { ConfigEntry<bool>? feedEnabled = _feedEnabled; if (feedEnabled != null && feedEnabled.Value) { int[] array = ReadArray(_handCardsField, __instance); if (array != null && array.Contains(__0)) { PushCardToFeed(__0); } else if (array != null && __0 >= 0 && __0 < array.Length) { PushCardToFeed(array[__0]); } } } internal static int[] GetCurrentHand() { return ReadArray(_handCardsField, _activeManager) ?? Array.Empty<int>(); } internal static List<int> GetCurrentDeck() { return ReadList(_gameDeckField, _activeManager) ?? new List<int>(); } internal static List<int> GetCurrentDiscard() { return ReadList(_discardPileField, _activeManager) ?? new List<int>(); } private static void RefreshDeckDisplay(object _) { DeckDisplayUI.RequestRefresh(); } private static void DumpDebugInfo(object manager) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== HousePersistentDeck DEBUG DUMP ==="); stringBuilder.AppendLine("\n[HousePassiveManager fields] (" + _managerType?.FullName + ")"); if (_managerType != null) { FieldInfo[] fields = _managerType.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { string text = "?"; try { text = fieldInfo.GetValue(manager)?.ToString() ?? "null"; } catch { } stringBuilder.AppendLine(" " + (fieldInfo.IsStatic ? "static " : "") + fieldInfo.FieldType.Name + " " + fieldInfo.Name + " = " + text); } } stringBuilder.AppendLine("\n[HousePassiveManager methods]"); if (_managerType != null) { foreach (MethodInfo item in from m in _managerType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) orderby m.Name select m) { stringBuilder.AppendLine(" " + (item.IsStatic ? "static " : "") + item.ReturnType.Name + " " + item.Name + "(" + string.Join(", ", from p in item.GetParameters() select p.ParameterType.Name + " " + p.Name) + ")"); } } stringBuilder.AppendLine("\n[HouseHUDManager fields] (" + _hudType?.FullName + ")"); if (_hudType != null) { FieldInfo[] fields = _hudType.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { stringBuilder.AppendLine(" " + (fieldInfo2.IsStatic ? "static " : "") + fieldInfo2.FieldType.Name + " " + fieldInfo2.Name); } } stringBuilder.AppendLine("\n[HouseHUDManager methods]"); if (_hudType != null) { foreach (MethodInfo item2 in from m in _hudType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) orderby m.Name select m) { stringBuilder.AppendLine(" " + (item2.IsStatic ? "static " : "") + item2.ReturnType.Name + " " + item2.Name + "(" + string.Join(", ", from p in item2.GetParameters() select p.ParameterType.Name + " " + p.Name) + ")"); } } int[] array = ReadArray(_handCardsField, manager); List<int> list = ReadList(_gameDeckField, manager); List<int> list2 = ReadList(_discardPileField, manager); stringBuilder.AppendLine("\n[Deck state] hand=[" + ((array != null) ? string.Join(",", array) : "NULL") + "]"); stringBuilder.AppendLine(string.Format(" drawPile (count={0}): [{1}]", list?.Count ?? (-1), (list != null) ? string.Join(",", list) : "NULL")); stringBuilder.AppendLine(string.Format(" discard (count={0}): [{1}]", list2?.Count ?? (-1), (list2 != null) ? string.Join(",", list2) : "NULL")); stringBuilder.AppendLine("\n[Patch status]"); stringBuilder.AppendLine($" _gameDeckField found: {_gameDeckField != null}"); stringBuilder.AppendLine($" _discardPileField found: {_discardPileField != null}"); stringBuilder.AppendLine($" _handCardsField found: {_handCardsField != null}"); stringBuilder.AppendLine($" _hudNewHandMethod found: {_hudNewHandMethod != null}"); stringBuilder.AppendLine(" _directCardPlayMethod: " + (_directCardPlayMethod?.Name ?? "none")); stringBuilder.AppendLine($" _inNextHand: {_inNextHand}"); stringBuilder.AppendLine($" CardSprites cached: {CardFeedUI.CardSprites.Count}"); stringBuilder.AppendLine($" CardColors cached: {CardFeedUI.CardColors.Count}"); stringBuilder.AppendLine("=== END DEBUG DUMP ==="); ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)stringBuilder.ToString()); } } private static void PushCardToFeed(int cardId) { EnsureFeedUIExists(); string cardDisplayName = GetCardDisplayName(cardId); CardFeedUI.AddCard(cardId, cardDisplayName); } private static string GetCardDisplayName(int cardId) { if (CardFeedUI.CardColors.TryGetValue(cardId, out (string, Color) value)) { return value.Item1; } return $"#{cardId}"; } private static int FindRemovedCard(int[] before, int[] after) { Dictionary<int, int> dictionary = new Dictionary<int, int>(); int[] array = after; foreach (int key in array) { dictionary[key] = dictionary.GetValueOrDefault(key, 0) + 1; } int result = -1; int num = 0; array = before; foreach (int num2 in array) { int num4 = (dictionary[num2] = dictionary.GetValueOrDefault(num2, 0) - 1); if (num4 < 0) { result = num2; num++; } } if (num != 1) { return -1; } return result; } private static bool HandsEquivalent(int[] a, int[] b) { if (a.Length != b.Length) { return false; } return a.OrderBy((int x) => x).SequenceEqual(b.OrderBy((int x) => x)); } private static int FindAddedCard(List<int> before, List<int> after) { Dictionary<int, int> dictionary = new Dictionary<int, int>(); foreach (int item in before) { dictionary[item] = dictionary.GetValueOrDefault(item, 0) + 1; } int result = -1; int num = 0; foreach (int item2 in after) { dictionary[item2] = dictionary.GetValueOrDefault(item2, 0) - 1; } foreach (var (num4, num5) in dictionary) { if (num5 < 0) { result = num4; num++; } } if (num != 1) { return -1; } return result; } private static void SaveState(object manager) { object deckKey = GetDeckKey(manager); if (deckKey != null) { List<int> list = ReadList(_gameDeckField, manager); List<int> list2 = ReadList(_discardPileField, manager); int[] array = ReadArray(_handCardsField, manager); if (list != null && list2 != null && array != null) { SavedDecks[deckKey] = new DeckState(list.ToArray(), list2.ToArray(), array.ToArray()); } } } private static void RestoreState(object manager, DeckState state) { RestoringManagers.Add(manager); try { _gameDeckField?.SetValue(manager, state.GameDeck.ToList()); _discardPileField?.SetValue(manager, state.DiscardPile.ToList()); _handCardsField?.SetValue(manager, state.HandCards.ToArray()); } finally { RestoringManagers.Remove(manager); } } private static void UpdateHud(object manager) { if (!GetBool(_isAuthorityField, manager)) { return; } int[] array = ReadArray(_handCardsField, manager); if (array != null) { _hudPassiveManagerField?.SetValue(null, manager); object obj = _hudInstanceField?.GetValue(null); if (obj != null) { _hudNewHandMethod?.Invoke(obj, new object[2] { array.ToArray(), "Default" }); _hudUpdateCardDisplayMethod?.Invoke(obj, null); } } } private static object? GetDeckKey(object manager) { object obj = _characterBodyField?.GetValue(manager); if (obj == null) { return null; } return (AccessTools.Property(obj.GetType(), "master")?.GetValue(obj) ?? AccessTools.Field(obj.GetType(), "master")?.GetValue(obj)) ?? obj; } private void Patch(Type type, string methodName, string? prefix = null, string? postfix = null) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not patch " + type.FullName + "." + methodName + ": method not found.")); return; } Type typeFromHandle = typeof(Plugin); try { _harmony.Patch((MethodBase)methodInfo, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeFromHandle, prefix, (Type[])null, (Type[])null)), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeFromHandle, postfix, (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch " + type.FullName + "." + methodName + ": " + ex.Message)); } } private static bool GetBool(FieldInfo? field, object instance) { object obj = field?.GetValue(instance); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static List<int>? ReadList(FieldInfo? field, object instance) { return field?.GetValue(instance) as List<int>; } private static int[]? ReadArray(FieldInfo? field, object instance) { return field?.GetValue(instance) as int[]; } } }