Decompiled source of AtlyssCasino v1.0.1

AtlyssCasino.dll

Decompiled 10 minutes ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using AtlyssCasino.Blackjack;
using AtlyssCasino.Blackjack.Netcode;
using AtlyssCasino.Roulette;
using AtlyssCasino.Roulette.Netcode;
using BepInEx;
using BepInEx.Logging;
using CodeTalker;
using CodeTalker.Networking;
using CodeTalker.Packets;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AtlyssCasino")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AtlyssCasino")]
[assembly: AssemblyTitle("AtlyssCasino")]
[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 AtlyssCasino
{
	[HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")]
	public static class BlackjackDebugCommands
	{
		private static readonly List<GameObject> _spawnedCards = new List<GameObject>();

		private static readonly FieldInfo MaxOnscreenField = typeof(ChatBehaviour).GetField("maxOnscreenMessages", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(ChatBehaviour).GetField("_maxOnscreenMessages", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPrefix]
		public static bool Prefix(ChatBehaviour __instance, string _message)
		{
			try
			{
				if (string.IsNullOrEmpty(_message))
				{
					return true;
				}
				if (!_message.StartsWith("/"))
				{
					return true;
				}
				string text = _message.Trim();
				string[] array = text.Split(new char[1] { ' ' }, 2);
				string text2 = array[0].ToLower();
				string args = ((array.Length > 1) ? array[1] : "");
				switch (text2)
				{
				case "/spawncard":
					HandleSpawnCard(__instance, args);
					SetChatFocusFalse(__instance);
					return false;
				case "/clearcards":
					HandleClearCards(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/deckdebug":
					HandleDeckDebug(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/cleartable":
					HandleClearTable(__instance);
					SetChatFocusFalse(__instance);
					return false;
				default:
					return true;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[BJ-Debug] Command error: " + ex.Message));
				return true;
			}
		}

		private static void HandleSpawnCard(ChatBehaviour chat, string args)
		{
			//IL_00b6: 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_00cb: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0103: 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)
			if ((Object)(object)Plugin.AssetsBundle == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[BJ-Debug]</color> Assets bundle not loaded.");
				return;
			}
			if (string.IsNullOrWhiteSpace(args))
			{
				SendLocalMessage(chat, "<color=#FFD700>[BJ-Debug]</color> Usage: /spawncard {suit}_{rank}");
				return;
			}
			string text = NormalizeCardName(args.Trim());
			string text2 = "Deck06_" + text;
			GameObject val = Plugin.AssetsBundle.LoadAsset<GameObject>(text2);
			if ((Object)(object)val == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[BJ-Debug]</color> Card prefab not found: " + text2);
				return;
			}
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[BJ-Debug]</color> Player not found.");
				return;
			}
			Vector3 val2 = ((Component)mainPlayer).transform.position + ((Component)mainPlayer).transform.forward * 2f + Vector3.up * 1.2f;
			Quaternion val3 = Quaternion.LookRotation(-((Component)mainPlayer).transform.forward);
			GameObject val4 = Object.Instantiate<GameObject>(val, val2, val3);
			((Object)val4).name = "DebugCard_" + text;
			CardVisual cardVisual = val4.AddComponent<CardVisual>();
			cardVisual.Init(null, faceUp: true);
			_spawnedCards.Add(val4);
			SendLocalMessage(chat, "<color=#FFD700>[BJ-Debug]</color> Spawned: " + text2);
		}

		private static void HandleClearCards(ChatBehaviour chat)
		{
			int num = 0;
			foreach (GameObject spawnedCard in _spawnedCards)
			{
				if ((Object)(object)spawnedCard != (Object)null)
				{
					Object.Destroy((Object)(object)spawnedCard);
					num++;
				}
			}
			_spawnedCards.Clear();
			SendLocalMessage(chat, $"<color=#FFD700>[BJ-Debug]</color> Cleared {num} loose card(s).");
		}

		private static void HandleDeckDebug(ChatBehaviour chat)
		{
			try
			{
				Deck deck = new Deck();
				int count = deck.Count;
				if (count != 52)
				{
					SendLocalMessage(chat, "<color=#FF6666>[BJ-Debug]</color> [FAIL] " + $"Fresh deck has {count} cards, expected 52.");
					return;
				}
				deck.Shuffle();
				List<Card> list = new List<Card>(52);
				HashSet<string> hashSet = new HashSet<string>();
				List<string> list2 = new List<string>();
				while (!deck.IsEmpty)
				{
					Card card = deck.Draw();
					list.Add(card);
					string item = $"{card.Suit}_{card.Rank}";
					if (!hashSet.Add(item))
					{
						list2.Add(item);
					}
				}
				SendLocalMessage(chat, $"<color=#FFD700>[BJ-Debug]</color> Drew {list.Count}, unique {hashSet.Count}, dupes {list2.Count}.");
				bool flag = list.Count == 52 && hashSet.Count == 52 && list2.Count == 0;
				SendLocalMessage(chat, flag ? "<color=#66FF66>[BJ-Debug]</color> [PASS] 52 unique cards." : "<color=#FF6666>[BJ-Debug]</color> [FAIL] deck invariants broken.");
				bool flag2 = false;
				try
				{
					deck.Draw();
				}
				catch (InvalidOperationException)
				{
					flag2 = true;
				}
				SendLocalMessage(chat, "<color=#FFD700>[BJ-Debug]</color> Empty-draw: " + (flag2 ? "PASS" : "FAIL"));
				deck.ReshuffleAll();
				SendLocalMessage(chat, $"<color=#FFD700>[BJ-Debug]</color> ReshuffleAll count: {deck.Count}");
			}
			catch (Exception ex2)
			{
				SendLocalMessage(chat, "<color=#FF6666>[BJ-Debug]</color> Deck test crashed: " + ex2.Message);
			}
		}

		private static void HandleClearTable(ChatBehaviour chat)
		{
			BlackjackTable blackjackTable = FindLocalPlayerTable();
			if ((Object)(object)blackjackTable == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[BJ-Debug]</color> You must be seated.");
				return;
			}
			blackjackTable.ClearAllHands();
			SendLocalMessage(chat, "<color=#FFD700>[BJ-Debug]</color> Table cleared.");
		}

		private static BlackjackTable? FindLocalPlayerTable()
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return null;
			}
			BlackjackTable[] array = Object.FindObjectsOfType<BlackjackTable>();
			BlackjackTable[] array2 = array;
			foreach (BlackjackTable blackjackTable in array2)
			{
				if (blackjackTable.GetSeatForPlayer(mainPlayer) >= 0)
				{
					return blackjackTable;
				}
			}
			return null;
		}

		private static string NormalizeCardName(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return input;
			}
			string[] array = input.Split('_');
			if (array.Length != 2)
			{
				return input;
			}
			string text = array[0];
			string text2 = array[1];
			if (text.Length >= 1)
			{
				text = char.ToUpper(text[0]) + text.Substring(1).ToLower();
			}
			text2 = text2.ToUpper();
			return text + "_" + text2;
		}

		private static void SendLocalMessage(ChatBehaviour chat, string message)
		{
			try
			{
				if (MaxOnscreenField != null)
				{
					try
					{
						MaxOnscreenField.SetValue(chat, 50);
					}
					catch
					{
					}
				}
				chat.Init_GameLogicMessage(message);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[BJ-Debug] Chat failed: " + ex.Message));
			}
		}

		private static void SetChatFocusFalse(ChatBehaviour chat)
		{
			try
			{
				typeof(ChatBehaviour).GetField("_focusedInChat", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(chat, false);
			}
			catch
			{
			}
		}
	}
	public static class BlackjackSceneWatcher
	{
		private const string CASINO_SCENE_NAME = "AtlyssCasino";

		private static bool _wasInCasino;

		public static void Init()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
			SceneManager.sceneUnloaded += OnSceneUnloaded;
			SceneManager.activeSceneChanged += OnActiveSceneChanged;
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "AtlyssCasino")
			{
				_wasInCasino = true;
				Plugin.Log.LogInfo((object)"[SceneWatcher] Entered casino scene.");
			}
		}

		private static void OnSceneUnloaded(Scene scene)
		{
			if (((Scene)(ref scene)).name == "AtlyssCasino" && _wasInCasino)
			{
				Plugin.Log.LogInfo((object)"[SceneWatcher] Casino scene unloaded — running cleanup.");
				CleanupOnLeave();
				_wasInCasino = false;
			}
		}

		private static void OnActiveSceneChanged(Scene oldScene, Scene newScene)
		{
			if (_wasInCasino && ((Scene)(ref oldScene)).name == "AtlyssCasino" && ((Scene)(ref newScene)).name != "AtlyssCasino")
			{
				Plugin.Log.LogInfo((object)("[SceneWatcher] Active scene changed away from casino (" + ((Scene)(ref oldScene)).name + " -> " + ((Scene)(ref newScene)).name + ") — running cleanup."));
				CleanupOnLeave();
				_wasInCasino = false;
			}
		}

		private static void CleanupOnLeave()
		{
			try
			{
				ReleaseAnySeatedTable();
				DestroyStrayCards();
				Plugin.HasSetBlackjackBet = false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[SceneWatcher] Cleanup failed: " + ex.Message));
			}
		}

		private static void ReleaseAnySeatedTable()
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				Plugin.Log.LogInfo((object)"[SceneWatcher] No local player — skipping seat release.");
				return;
			}
			BlackjackTable[] array = Object.FindObjectsOfType<BlackjackTable>();
			BlackjackTable[] array2 = array;
			foreach (BlackjackTable blackjackTable in array2)
			{
				int seatForPlayer = blackjackTable.GetSeatForPlayer(mainPlayer);
				if (seatForPlayer >= 0)
				{
					string name = ((Object)blackjackTable).name;
					if (BJNetcode.AmHost())
					{
						blackjackTable.ReleaseSeat(seatForPlayer);
						int hostSeatIndex = blackjackTable.HostSeatIndex;
						BJNetcode.BroadcastSeatReleased(name, seatForPlayer, hostSeatIndex);
						Plugin.Log.LogInfo((object)$"[SceneWatcher] Auto-released host seat {seatForPlayer} at '{name}'.");
					}
					else
					{
						BJNetcode.SendReleaseSeatRequest(name);
						blackjackTable.ApplySeatReleased(seatForPlayer, blackjackTable.HostSeatIndex);
						Plugin.Log.LogInfo((object)($"[SceneWatcher] Auto-released client seat {seatForPlayer} at '{name}' " + "(request sent + local mirror)."));
					}
				}
			}
		}

		private static void DestroyStrayCards()
		{
			CardVisual[] array = Object.FindObjectsOfType<CardVisual>();
			int num = 0;
			CardVisual[] array2 = array;
			foreach (CardVisual cardVisual in array2)
			{
				if (!((Object)(object)cardVisual == (Object)null) && !((Object)(object)((Component)cardVisual).gameObject == (Object)null))
				{
					Object.Destroy((Object)(object)((Component)cardVisual).gameObject);
					num++;
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"[SceneWatcher] Destroyed {num} stray card object(s).");
			}
		}
	}
	public class CasinoEntryFee : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <BootPlayerToSanctum>d__16 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Player player;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <BootPlayerToSanctum>d__16(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = ((MonoBehaviour)Plugin.Instance).StartCoroutine(CasinoExitTrigger.ForceReturnToSanctum(player, "[EntryFee]"));
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					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();
			}
		}

		[CompilerGenerated]
		private sealed class <ShowBrokeMessageDelayed>d__17 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private int <i>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ShowBrokeMessageDelayed>d__17(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Expected O, but got Unknown
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(3.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<i>5__1 = 0;
					break;
				case 2:
					<>1__state = -1;
					<i>5__1++;
					break;
				}
				if (<i>5__1 < 3)
				{
					try
					{
						ErrorPromptTextManager.current.Init_ErrorPrompt("Come back when you're a little... mmm... richer!");
					}
					catch
					{
					}
					<>2__current = (object)new WaitForSeconds(3.8f);
					<>1__state = 2;
					return true;
				}
				Plugin.Log.LogInfo((object)"[EntryFee] Broke message shown.");
				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 const int ENTRY_FEE = 100;

		private const float MESSAGE_DELAY = 3.5f;

		private const float MESSAGE_REPEAT_INTERVAL = 3.8f;

		private const int MESSAGE_REPEAT_COUNT = 3;

		private const string BROKE_MESSAGE = "Come back when you're a little... mmm... richer!";

		private static readonly HashSet<ulong> _paidPlayers = new HashSet<ulong>();

		private static bool _pendingBrokeMessage = false;

		private static bool _isBooting = false;

		private BoxCollider? _collider;

		private bool _playerWasInside = false;

		private void Awake()
		{
			_collider = ((Component)this).GetComponent<BoxCollider>();
			_paidPlayers.Clear();
			_pendingBrokeMessage = false;
			_isBooting = false;
			SceneManager.sceneUnloaded += OnSceneUnloaded;
			SceneManager.sceneLoaded += OnSceneLoaded;
			Plugin.Log.LogInfo((object)$"[EntryFee] Entry fee trigger active. Fee: {100} Crowns.");
		}

		private void OnDestroy()
		{
			SceneManager.sceneUnloaded -= OnSceneUnloaded;
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private static void OnSceneUnloaded(Scene scene)
		{
			if (!(((Scene)(ref scene)).name != "AtlyssCasino"))
			{
				_paidPlayers.Clear();
				_pendingBrokeMessage = false;
				_isBooting = false;
				Plugin.Log.LogInfo((object)"[EntryFee] Casino unloaded — paid list cleared.");
			}
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (_pendingBrokeMessage && !(((Scene)(ref scene)).name == "AtlyssCasino"))
			{
				_pendingBrokeMessage = false;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(ShowBrokeMessageDelayed());
			}
		}

		private void Update()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_collider == (Object)null || _isBooting)
			{
				return;
			}
			Player mainPlayer = Player._mainPlayer;
			if (!((Object)(object)mainPlayer == (Object)null))
			{
				Bounds bounds = ((Collider)_collider).bounds;
				bool flag = ((Bounds)(ref bounds)).Contains(((Component)mainPlayer).transform.position);
				if (flag && !_playerWasInside)
				{
					HandlePlayerEntered(mainPlayer);
				}
				_playerWasInside = flag;
			}
		}

		private void HandlePlayerEntered(Player player)
		{
			ulong steam = GetSteam64(player);
			if (_paidPlayers.Contains(steam))
			{
				Plugin.Log.LogInfo((object)"[EntryFee] Player already paid — welcome back.");
				return;
			}
			PlayerInventory component = ((Component)player).GetComponent<PlayerInventory>();
			if (!((Object)(object)component == (Object)null))
			{
				if (component._heldCurrency < 100)
				{
					ErrorPromptTextManager.current.Init_ErrorPrompt($"You need at least {100} Crowns to enter!");
					Plugin.Log.LogInfo((object)($"[EntryFee] Player {steam} has {component._heldCurrency} Crowns " + "— insufficient. Sending back to Sanctum."));
					_isBooting = true;
					_pendingBrokeMessage = true;
					((MonoBehaviour)this).StartCoroutine(BootPlayerToSanctum(player));
				}
				else
				{
					component.Network_heldCurrency -= 100;
					_paidPlayers.Add(steam);
					ErrorPromptTextManager.current.Init_ErrorPrompt("Welcome to AtlyssCasino! " + $"{100} Crown entry fee charged. Good luck!");
					Plugin.Log.LogInfo((object)($"[EntryFee] Player {steam} paid {100} Crowns. " + $"Balance: {component.Network_heldCurrency}."));
				}
			}
		}

		[IteratorStateMachine(typeof(<BootPlayerToSanctum>d__16))]
		private static IEnumerator BootPlayerToSanctum(Player player)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BootPlayerToSanctum>d__16(0)
			{
				player = player
			};
		}

		[IteratorStateMachine(typeof(<ShowBrokeMessageDelayed>d__17))]
		private static IEnumerator ShowBrokeMessageDelayed()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ShowBrokeMessageDelayed>d__17(0);
		}

		private static void TeleportToStartPoint(Player player)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			GameObject[] array = GameObject.FindGameObjectsWithTag("spawnPoint");
			GameObject[] array2 = array;
			foreach (GameObject val in array2)
			{
				if (((Object)val).name.Contains("startPoint"))
				{
					((Component)player).transform.position = val.transform.position;
					break;
				}
			}
		}

		private static ulong GetSteam64(Player player)
		{
			if (ulong.TryParse(player.Network_steamID, out var result))
			{
				return result;
			}
			return BJNetcode.GetLocalSteam64();
		}
	}
	public static class CasinoPatch
	{
		[CompilerGenerated]
		private sealed class <SetupDelayed>d__3 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private GameObject[] <allObjects>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SetupDelayed>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<allObjects>5__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
				{
					<>1__state = -1;
					_overlayShader = Shader.Find("Unlit/Texture");
					if ((Object)(object)_overlayShader == (Object)null)
					{
						_overlayShader = Shader.Find("Standard");
					}
					ManualLogSource log = Plugin.Log;
					Shader? overlayShader = _overlayShader;
					log.LogInfo((object)("[Casino] Overlay shader: " + (((overlayShader != null) ? ((Object)overlayShader).name : null) ?? "NULL")));
					<allObjects>5__1 = Object.FindObjectsOfType<GameObject>();
					HookSlotMachines(<allObjects>5__1);
					HookBlackjackTables(<allObjects>5__1);
					HookRouletteTables(<allObjects>5__1);
					HookEntryFee();
					HookExitTrigger();
					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();
			}
		}

		private static Shader? _overlayShader;

		public static void Init()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (!(((Scene)(ref scene)).name != "AtlyssCasino"))
			{
				Plugin.Log.LogInfo((object)"[Casino] Casino scene loaded!");
				((MonoBehaviour)Plugin.Instance).StartCoroutine(SetupDelayed());
			}
		}

		[IteratorStateMachine(typeof(<SetupDelayed>d__3))]
		private static IEnumerator SetupDelayed()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SetupDelayed>d__3(0);
		}

		private static void HookSlotMachines(GameObject[] allObjects)
		{
			int num = 0;
			foreach (GameObject val in allObjects)
			{
				if (((Object)val).name != "SlotBet_Confirm")
				{
					continue;
				}
				Transform parent = val.transform.parent;
				GameObject val2 = ((parent != null) ? ((Component)parent).gameObject : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					((Object)val2).name = $"SlotMachine_{num}";
					num++;
					SlotMachine slotMachine = val2.GetComponent<SlotMachine>() ?? val2.AddComponent<SlotMachine>();
					slotMachine.MatIdle = MakeMat("idle");
					slotMachine.MatIdleBlank = MakeMat("idle_blank");
					slotMachine.MatWin = MakeMat("win");
					slotMachine.MatJackpot = MakeMat("jackpot");
					slotMachine.MatCherry = MakeMat("cherry");
					slotMachine.MatLemon = MakeMat("lemon");
					slotMachine.MatOrange = MakeMat("orange");
					slotMachine.MatStar = MakeMat("star");
					slotMachine.MatDiamond = MakeMat("diamond");
					slotMachine.MatSeven = MakeMat("seven");
					slotMachine.Init();
					SlotBetConfirm slotBetConfirm = val.GetComponent<SlotBetConfirm>() ?? val.AddComponent<SlotBetConfirm>();
					slotBetConfirm.Setup(slotMachine);
					Transform val3 = val2.transform.Find("SlotBet_Selector");
					if ((Object)(object)val3 != (Object)null)
					{
						Plugin.Log.LogInfo((object)"[Casino] Removing leftover SlotBet_Selector from old prefab instance.");
						Object.Destroy((Object)(object)((Component)val3).gameObject);
					}
				}
			}
			Plugin.Log.LogInfo((object)$"[Casino] Hooked {num} slot machine(s).");
		}

		private static void HookBlackjackTables(GameObject[] allObjects)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			foreach (GameObject val in allObjects)
			{
				if (!((Object)val).name.StartsWith("Blackjack Table") || !HasAnyBlackjackWiring(val.transform))
				{
					continue;
				}
				num++;
				BlackjackTable blackjackTable = val.GetComponent<BlackjackTable>() ?? val.AddComponent<BlackjackTable>();
				int num5 = 0;
				Dictionary<int, BlackjackSeatTrigger> dictionary = new Dictionary<int, BlackjackSeatTrigger>();
				Dictionary<int, Transform> dictionary2 = new Dictionary<int, Transform>();
				foreach (Transform item in val.transform)
				{
					Transform val2 = item;
					string text = ((Object)val2).name.Trim();
					if (text == "DealerAnchor")
					{
						blackjackTable.SetDealerAnchor(val2);
						num5++;
						continue;
					}
					int num6 = ParseIndexedName(text, "SeatAnchor");
					if (num6 >= 0)
					{
						if (num6 >= 5)
						{
							Plugin.Log.LogWarning((object)($"[Casino] '{text}' index {num6} " + ">= MAX_PLAYERS; skipping."));
							continue;
						}
						blackjackTable.SetSeatAnchor(num6, val2);
						num5++;
						continue;
					}
					int num7 = ParseIndexedName(text, "SeatTrigger");
					if (num7 >= 0)
					{
						if (num7 >= 5)
						{
							Plugin.Log.LogWarning((object)($"[Casino] '{text}' index {num7} " + ">= MAX_PLAYERS; skipping."));
							continue;
						}
						BlackjackSeatTrigger blackjackSeatTrigger = ((Component)val2).gameObject.GetComponent<BlackjackSeatTrigger>() ?? ((Component)val2).gameObject.AddComponent<BlackjackSeatTrigger>();
						blackjackSeatTrigger.Setup(blackjackTable, num7);
						dictionary[num7] = blackjackSeatTrigger;
						continue;
					}
					int num8 = ParseIndexedName(text, "Stool");
					if (num8 >= 0)
					{
						if (num8 >= 5)
						{
							Plugin.Log.LogWarning((object)($"[Casino] '{text}' index {num8} " + ">= MAX_PLAYERS; skipping."));
						}
						else
						{
							dictionary2[num8] = val2;
						}
					}
				}
				int count = dictionary.Count;
				int num9 = 0;
				foreach (KeyValuePair<int, BlackjackSeatTrigger> item2 in dictionary)
				{
					if (dictionary2.TryGetValue(item2.Key, out var value))
					{
						item2.Value.SetStool(value);
						num9++;
					}
					else
					{
						Plugin.Log.LogInfo((object)($"[Casino] No Stool with index {item2.Key} on " + "'" + ((Object)val).name + "' — seat color won't change."));
					}
				}
				Plugin.Log.LogInfo((object)("[Casino] Hooked Blackjack table '" + ((Object)val).name + "' — " + $"{count} trigger(s), " + $"{num5} anchor(s), " + $"{num9} stool(s)."));
				num2 += count;
				num3 += num5;
				num4 += num9;
			}
			Plugin.Log.LogInfo((object)($"[Casino] Hooked {num} blackjack table(s), " + $"{num2} trigger(s), {num3} anchor(s), " + $"{num4} stool(s)."));
		}

		private static bool HasAnyBlackjackWiring(Transform parent)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			foreach (Transform item in parent)
			{
				Transform val = item;
				string text = ((Object)val).name.Trim();
				if (text == "DealerAnchor")
				{
					return true;
				}
				if (ParseIndexedName(text, "SeatAnchor") >= 0)
				{
					return true;
				}
				if (ParseIndexedName(text, "SeatTrigger") >= 0)
				{
					return true;
				}
			}
			return false;
		}

		private static void HookRouletteTables(GameObject[] allObjects)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (GameObject val in allObjects)
			{
				if (((Object)val).name.StartsWith("Roulette Table") && (!((Object)(object)val.transform.parent != (Object)null) || !((Object)val.transform.parent).name.StartsWith("Roulette Table")))
				{
					num++;
					RouletteTable rouletteTable = val.GetComponent<RouletteTable>() ?? val.AddComponent<RouletteTable>();
					rouletteTable.Init();
					Transform val2 = val.transform.Find("RouletteTrigger");
					if ((Object)(object)val2 == (Object)null)
					{
						Plugin.Log.LogWarning((object)("[Casino] Roulette table '" + ((Object)val).name + "' has no 'RouletteTrigger' child — players won't be able to join. Add an empty child GameObject named 'RouletteTrigger' in Unity."));
						continue;
					}
					RouletteTrigger rouletteTrigger = ((Component)val2).gameObject.GetComponent<RouletteTrigger>() ?? ((Component)val2).gameObject.AddComponent<RouletteTrigger>();
					rouletteTrigger.Setup(rouletteTable);
					Plugin.Log.LogInfo((object)("[Casino] Hooked roulette table '" + ((Object)val).name + "' " + $"with trigger at {val2.position}."));
				}
			}
			Plugin.Log.LogInfo((object)$"[Casino] Hooked {num} roulette table(s).");
		}

		private static void HookEntryFee()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("EntryFeeTrigger");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[Casino] No 'EntryFeeTrigger' GameObject found in scene. Add an empty GameObject with that name and a Box Collider (Is Trigger checked) near the casino entrance.");
				return;
			}
			if ((Object)(object)val.GetComponent<CasinoEntryFee>() == (Object)null)
			{
				val.AddComponent<CasinoEntryFee>();
			}
			Plugin.Log.LogInfo((object)("[Casino] Entry fee trigger hooked at " + $"{val.transform.position}."));
		}

		private static void HookExitTrigger()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("ExitTrigger");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[Casino] No 'ExitTrigger' GameObject found in scene. Add an empty GameObject named 'ExitTrigger' with a Box Collider (Is Trigger checked) near the exit.");
				return;
			}
			if ((Object)(object)val.GetComponent<CasinoExitTrigger>() == (Object)null)
			{
				val.AddComponent<CasinoExitTrigger>();
			}
			Plugin.Log.LogInfo((object)("[Casino] Exit trigger hooked at " + $"{val.transform.position}."));
		}

		private static int ParseIndexedName(string name, string prefix)
		{
			if (name == prefix)
			{
				return 0;
			}
			string text = prefix + " (";
			if (!name.StartsWith(text))
			{
				return -1;
			}
			if (!name.EndsWith(")"))
			{
				return -1;
			}
			int length = text.Length;
			int num = name.Length - text.Length - ")".Length;
			if (num <= 0)
			{
				return -1;
			}
			string s = name.Substring(length, num);
			if (!int.TryParse(s, out var result))
			{
				return -1;
			}
			return result;
		}

		private static Material? MakeMat(string textureName)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00b7: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Plugin.AssetsBundle == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[Casino] AssetsBundle is null.");
				return null;
			}
			Texture2D val = Plugin.AssetsBundle.LoadAsset<Texture2D>(textureName);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("[Casino] Texture not found: " + textureName));
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			if ((Object)(object)_overlayShader == (Object)null)
			{
				Plugin.Log.LogError((object)"[Casino] No shader available for overlay!");
				return null;
			}
			Material val2 = new Material(_overlayShader)
			{
				name = "SlotMat_Runtime_" + textureName,
				mainTexture = (Texture)(object)val
			};
			val2.mainTextureScale = Vector2.one;
			val2.mainTextureOffset = Vector2.zero;
			return val2;
		}
	}
	[HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")]
	public static class CommandHandler
	{
		private static readonly FieldInfo? MaxOnscreenField = typeof(ChatBehaviour).GetField("maxOnscreenMessages", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(ChatBehaviour).GetField("_maxOnscreenMessages", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPrefix]
		public static bool Prefix(ChatBehaviour __instance, string _message)
		{
			try
			{
				if (string.IsNullOrEmpty(_message))
				{
					return true;
				}
				if (!_message.StartsWith("/"))
				{
					return true;
				}
				string text = _message.Trim();
				string[] array = text.Split(new char[1] { ' ' }, 2);
				string text2 = array[0].ToLower();
				string args = ((array.Length > 1) ? array[1] : "");
				switch (text2)
				{
				case "/slotbet":
					HandleSlotBet(__instance, args);
					SetChatFocusFalse(__instance);
					return false;
				case "/blackjackbet":
				case "/bjbet":
					HandleBlackjackBet(__instance, args);
					SetChatFocusFalse(__instance);
					return false;
				case "/ready":
					HandleReady(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/start":
					HandleStart(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/hit":
					HandleHit(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/stand":
					HandleStand(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/leave":
					HandleLeave(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/tbet":
					HandleRouletteBet(__instance, args);
					SetChatFocusFalse(__instance);
					return false;
				case "/rbet":
					HandleRBet(__instance, args);
					SetChatFocusFalse(__instance);
					return false;
				case "/rclearbets":
					HandleRClearBets(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/rstandby":
					HandleRReady(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/rspin":
					HandleRSpin(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/rleave":
					HandleRLeave(__instance);
					SetChatFocusFalse(__instance);
					return false;
				case "/casinohelp":
					HandleCasinoHelp(__instance);
					SetChatFocusFalse(__instance);
					return false;
				default:
					return true;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Casino] Chat command error: " + ex.Message));
				return true;
			}
		}

		private static void HandleSlotBet(ChatBehaviour chat, string args)
		{
			int result;
			if (string.IsNullOrWhiteSpace(args))
			{
				if (Plugin.HasSetBet)
				{
					SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Current slot bet: " + $"<color=#FFFFFF>{Plugin.CurrentBet}</color> Crowns. " + "Usage: /slotbet <amount>");
					return;
				}
				string text = string.Join(", ", Plugin.AllowedBets);
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> No slot bet set yet. Usage: /slotbet <amount> — allowed: " + text);
			}
			else if (!int.TryParse(args.Trim(), out result))
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Invalid amount '" + args + "'. Use a number.");
			}
			else if (!IsAllowedBet(result))
			{
				string arg = string.Join(", ", Plugin.AllowedBets);
				SendLocalMessage(chat, $"<color=#FF6666>[Casino]</color> Bet {result} not allowed. Choose: {arg}");
			}
			else
			{
				Plugin.CurrentBet = result;
				Plugin.HasSetBet = true;
				Plugin.Log.LogInfo((object)$"[Casino] Slot bet set to {result} via chat.");
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Slot bet set to " + $"<color=#FFFFFF>{result}</color> Crowns.");
			}
		}

		private static void HandleBlackjackBet(ChatBehaviour chat, string args)
		{
			int result;
			if (string.IsNullOrWhiteSpace(args))
			{
				if (Plugin.HasSetBlackjackBet)
				{
					SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Current blackjack bet: " + $"<color=#FFFFFF>{Plugin.BlackjackBet}</color> Crowns.");
					return;
				}
				string text = string.Join(", ", Plugin.AllowedBets);
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> No blackjack bet set. Usage: /blackjackbet <amount> — allowed: " + text + ". Required before claiming a seat.");
			}
			else if (IsLocalPlayerSeatedAtAnyBlackjackTable())
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Can't change bet while seated. Use /leave first.");
			}
			else if (!int.TryParse(args.Trim(), out result))
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Invalid amount '" + args + "'. Use a number.");
			}
			else if (!IsAllowedBet(result))
			{
				string arg = string.Join(", ", Plugin.AllowedBets);
				SendLocalMessage(chat, $"<color=#FF6666>[Casino]</color> Bet {result} not allowed. Choose: {arg}");
			}
			else
			{
				Plugin.BlackjackBet = result;
				Plugin.HasSetBlackjackBet = true;
				Plugin.Log.LogInfo((object)$"[Casino] Blackjack bet set to {result} via chat.");
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Blackjack bet set to " + $"<color=#FFFFFF>{result}</color> Crowns. " + "Press F at a seat trigger to claim your spot.");
			}
		}

		private static void HandleReady(ChatBehaviour chat)
		{
			var (blackjackTable, num) = FindLocalSeat();
			if ((Object)(object)blackjackTable == (Object)null || num < 0)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You must be seated at a blackjack table.");
				return;
			}
			if (blackjackTable.RoundInProgress)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Round in progress — can't change ready state.");
				return;
			}
			bool flag = blackjackTable.IsPlayerReady(num);
			bool flag2 = !flag;
			if (flag2)
			{
				int bet = blackjackTable.Hands[num].Bet;
				int localCrownBalance = GetLocalCrownBalance();
				if (localCrownBalance < bet)
				{
					SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You can't afford your bet " + $"({localCrownBalance} < {bet}). Use /leave and /blackjackbet to lower it.");
					return;
				}
			}
			if (BJNetcode.AmHost())
			{
				blackjackTable.SetPlayerReady(num, flag2);
				BJNetcode.BroadcastReadyChanged(((Object)blackjackTable).name, num, flag2);
				SendLocalMessage(chat, $"<color=#FFD700>[Casino]</color> Seat {num + 1}: " + (flag2 ? "<color=#66FF66>READY</color>" : "<color=#CCCCCC>not ready</color>") + ". " + ReadyCountSummary(blackjackTable));
			}
			else
			{
				BJNetcode.SendReadyToggleRequest(((Object)blackjackTable).name, flag2);
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Ready " + (flag2 ? "ON" : "OFF") + " request sent to host...");
			}
		}

		private static void HandleStart(ChatBehaviour chat)
		{
			var (blackjackTable, num) = FindLocalSeat();
			if ((Object)(object)blackjackTable == (Object)null || num < 0)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You must be seated to /start.");
				return;
			}
			if (!blackjackTable.IsHost(num))
			{
				Player hostPlayer = blackjackTable.GetHostPlayer();
				string text = (((Object)(object)hostPlayer == (Object)null) ? "(none)" : $"seat {blackjackTable.HostSeatIndex + 1}");
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Only the host (" + text + ") can /start.");
				return;
			}
			if (blackjackTable.RoundInProgress)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Round already in progress.");
				return;
			}
			if (!blackjackTable.AllSeatedPlayersReady)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Not all seated players are /ready.");
				return;
			}
			if (!BJNetcode.AmHost())
			{
				BJNetcode.SendStartRoundRequest(((Object)blackjackTable).name);
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> /start request sent to lobby host...");
				return;
			}
			BlackjackTable.StartRoundResult startRoundResult = blackjackTable.StartRound();
			if (startRoundResult.KickedSeats != null && startRoundResult.KickedSeats.Count > 0)
			{
				foreach (int kickedSeat in startRoundResult.KickedSeats)
				{
					SendLocalMessage(chat, $"<color=#FF6666>[Casino]</color> Seat {kickedSeat + 1} auto-left (couldn't afford bet).");
				}
			}
			if (!startRoundResult.Success)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Could not start: " + startRoundResult.Reason);
				return;
			}
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Round started. " + $"Seat {startRoundResult.FirstTurnSeat + 1}'s turn.");
			ShowLocalHandPrompt(blackjackTable, finalView: false);
			if (!blackjackTable.RoundInProgress)
			{
				ShowLocalHandPrompt(blackjackTable, finalView: true);
			}
		}

		private static void HandleHit(ChatBehaviour chat)
		{
			var (blackjackTable, num) = FindLocalSeat();
			if ((Object)(object)blackjackTable == (Object)null || num < 0)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You must be seated to /hit.");
				return;
			}
			if (!BJNetcode.AmHost())
			{
				BJNetcode.SendHitRequest(((Object)blackjackTable).name);
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> /hit request sent...");
				return;
			}
			BlackjackTable.HitResult hitResult = blackjackTable.PlayerHit(num);
			if (!hitResult.Success)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> " + hitResult.Reason);
				return;
			}
			BlackjackHand blackjackHand = blackjackTable.Hands[num];
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Hit: " + blackjackHand.Describe());
			ShowLocalHandPrompt(blackjackTable, hitResult.RoundResolved);
			if (hitResult.AutoStood && !hitResult.RoundResolved)
			{
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> " + (hitResult.Busted ? "Busted — turn ends." : "21 — turn ends.") + ((hitResult.NextTurnSeat >= 0) ? $" Seat {hitResult.NextTurnSeat + 1}'s turn." : ""));
			}
		}

		private static void HandleStand(ChatBehaviour chat)
		{
			var (blackjackTable, num) = FindLocalSeat();
			if ((Object)(object)blackjackTable == (Object)null || num < 0)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You must be seated to /stand.");
				return;
			}
			if (!BJNetcode.AmHost())
			{
				BJNetcode.SendStandRequest(((Object)blackjackTable).name);
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> /stand request sent...");
				return;
			}
			BlackjackTable.StandResult standResult = blackjackTable.PlayerStand(num);
			if (!standResult.Success)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> " + standResult.Reason);
				return;
			}
			SendLocalMessage(chat, $"<color=#FFD700>[Casino]</color> Stood on {blackjackTable.Hands[num].BestValue}.");
			ShowLocalHandPrompt(blackjackTable, standResult.RoundResolved);
			if (!standResult.RoundResolved && standResult.NextTurnSeat >= 0)
			{
				SendLocalMessage(chat, $"<color=#FFD700>[Casino]</color> Seat {standResult.NextTurnSeat + 1}'s turn.");
			}
		}

		private static void HandleLeave(ChatBehaviour chat)
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Player not found.");
				return;
			}
			BlackjackTable[] array = Object.FindObjectsOfType<BlackjackTable>();
			BlackjackTable[] array2 = array;
			foreach (BlackjackTable blackjackTable in array2)
			{
				int seatForPlayer = blackjackTable.GetSeatForPlayer(mainPlayer);
				if (seatForPlayer >= 0)
				{
					if (BJNetcode.AmHost())
					{
						blackjackTable.ReleaseSeat(seatForPlayer);
						int hostSeatIndex = blackjackTable.HostSeatIndex;
						BJNetcode.BroadcastSeatReleased(((Object)blackjackTable).name, seatForPlayer, hostSeatIndex);
						Plugin.HasSetBlackjackBet = false;
						SendLocalMessage(chat, $"<color=#FFD700>[Casino]</color> Left seat {seatForPlayer + 1}. " + "Bet cleared — /blackjackbet to set a new one.");
					}
					else
					{
						BJNetcode.SendReleaseSeatRequest(((Object)blackjackTable).name);
						Plugin.HasSetBlackjackBet = false;
						SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Leave request sent " + $"for seat {seatForPlayer + 1}. Bet cleared — /blackjackbet to set a new one.");
					}
					return;
				}
			}
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> You're not seated at any blackjack table.");
		}

		private static void HandleRouletteBet(ChatBehaviour chat, string args)
		{
			if (string.IsNullOrWhiteSpace(args))
			{
				if (Plugin.HasSetRouletteBet)
				{
					SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Current roulette bet amount: " + $"<color=#FFFFFF>{Plugin.RouletteBet}</color> Crowns per /rbet. " + "Usage: /tbet <amount>");
					return;
				}
				string text = string.Join(", ", Plugin.AllowedBets);
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> No roulette bet amount set. Usage: /tbet <amount> — allowed: " + text + ". Required before joining the table.");
				return;
			}
			if (!int.TryParse(args.Trim(), out var result))
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Invalid amount '" + args + "'. Use a number.");
				return;
			}
			if (!IsAllowedBet(result))
			{
				string arg = string.Join(", ", Plugin.AllowedBets);
				SendLocalMessage(chat, $"<color=#FF6666>[Casino]</color> Bet {result} not allowed. Choose: {arg}");
				return;
			}
			RouletteTable rouletteTable = FindLocalRouletteTable();
			if ((Object)(object)rouletteTable != (Object)null)
			{
				List<PlacedBet> betsForPlayer = rouletteTable.GetBetsForPlayer(Player._mainPlayer);
				if (betsForPlayer.Count > 0)
				{
					SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Clear your bets first with /rclearbets before changing your bet amount.");
					return;
				}
			}
			Plugin.RouletteBet = result;
			Plugin.HasSetRouletteBet = true;
			Plugin.Log.LogInfo((object)$"[Casino] Roulette bet set to {result} via chat.");
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Roulette bet amount set to " + $"<color=#FFFFFF>{result}</color> Crowns per /rbet. " + "Walk up to the table and press F to join.");
		}

		private static void HandleRBet(ChatBehaviour chat, string args)
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return;
			}
			RouletteTable rouletteTable = FindLocalRouletteTable();
			if ((Object)(object)rouletteTable == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You are not at a roulette table. Walk up and press F to join.");
				return;
			}
			if (!Plugin.HasSetRouletteBet)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Set a bet amount first: /tbet <amount>");
				return;
			}
			if (!RouletteLogic.TryParseBet(args, out BetType betType, out int betTarget, out string errorMsg))
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> " + errorMsg);
				return;
			}
			if (BJNetcode.AmHost())
			{
				if (!rouletteTable.TryPlaceBet(mainPlayer, betType, betTarget, Plugin.RouletteBet, out string errorMsg2))
				{
					SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> " + errorMsg2);
					return;
				}
				RNNetcode.BroadcastBetPlaced(((Object)rouletteTable).name, BJNetcode.GetLocalSteam64(), betType, betTarget, Plugin.RouletteBet);
			}
			else
			{
				RNNetcode.SendPlaceBetRequest(((Object)rouletteTable).name, betType, betTarget, Plugin.RouletteBet);
			}
			string text = RouletteLogic.DescribeBet(betType, betTarget);
			List<PlacedBet> betsForPlayer = rouletteTable.GetBetsForPlayer(mainPlayer);
			string text2 = RouletteLogic.FormatBetSummary(betsForPlayer);
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Bet placed: " + $"<color=#FFFFFF>{Plugin.RouletteBet}</color> on {text}. " + "All bets: " + text2);
			Plugin.Log.LogInfo((object)$"[Casino] /rbet {text} {Plugin.RouletteBet} crowns.");
		}

		private static void HandleRClearBets(ChatBehaviour chat)
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return;
			}
			RouletteTable rouletteTable = FindLocalRouletteTable();
			if ((Object)(object)rouletteTable == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You are not at a roulette table.");
				return;
			}
			if (BJNetcode.AmHost())
			{
				if (!rouletteTable.TryClearBets(mainPlayer, out string errorMsg))
				{
					SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> " + errorMsg);
					return;
				}
				RNNetcode.BroadcastBetsCleared(((Object)rouletteTable).name, BJNetcode.GetLocalSteam64());
			}
			else
			{
				RNNetcode.SendClearBetsRequest(((Object)rouletteTable).name);
			}
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> All bets cleared and refunded.");
		}

		private static void HandleRReady(ChatBehaviour chat)
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return;
			}
			RouletteTable rouletteTable = FindLocalRouletteTable();
			if ((Object)(object)rouletteTable == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You are not at a roulette table. Walk up and press F to join.");
				return;
			}
			bool flag = rouletteTable.IsPlayerReady(mainPlayer);
			bool flag2 = !flag;
			if (flag2 && rouletteTable.GetBetsForPlayer(mainPlayer).Count == 0)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> Place at least one bet first. Use /rbet <type> [number].");
				return;
			}
			if (BJNetcode.AmHost())
			{
				if (!rouletteTable.TrySetReady(mainPlayer, flag2, out string errorMsg))
				{
					SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> " + errorMsg);
					return;
				}
				RNNetcode.BroadcastReadyChanged(((Object)rouletteTable).name, BJNetcode.GetLocalSteam64(), flag2);
			}
			else
			{
				RNNetcode.SendReadyToggleRequest(((Object)rouletteTable).name, flag2);
			}
			string text = (flag2 ? "<color=#66FF66>READY</color>" : "<color=#CCCCCC>not ready</color>");
			string text2 = ((rouletteTable.IsTableHost(mainPlayer) && flag2 && rouletteTable.AllPlayersReady()) ? " All players ready — use /rspin to spin the wheel!" : ((rouletteTable.IsTableHost(mainPlayer) && flag2) ? " Waiting for other players to /rstandby." : (flag2 ? " Waiting for host to /rspin." : "")));
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> You are " + text + "." + text2);
		}

		private static void HandleRSpin(ChatBehaviour chat)
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return;
			}
			RouletteTable rouletteTable = FindLocalRouletteTable();
			if ((Object)(object)rouletteTable == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> You are not at a roulette table.");
			}
			else if (BJNetcode.AmHost())
			{
				if (!rouletteTable.TryStartSpin(mainPlayer, out string errorMsg))
				{
					SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> " + errorMsg);
				}
			}
			else
			{
				RNNetcode.SendSpinRequest(((Object)rouletteTable).name);
			}
		}

		private static void HandleRLeave(ChatBehaviour chat)
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return;
			}
			RouletteTable rouletteTable = FindLocalRouletteTable();
			if ((Object)(object)rouletteTable == (Object)null)
			{
				SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> You are not at a roulette table.");
				return;
			}
			if (rouletteTable.IsSpinning)
			{
				SendLocalMessage(chat, "<color=#FF6666>[Casino]</color> The wheel is spinning — wait for the round to finish before leaving.");
				return;
			}
			if (BJNetcode.AmHost())
			{
				ulong localSteam = BJNetcode.GetLocalSteam64();
				rouletteTable.Leave(mainPlayer);
				RNNetcode.BroadcastPlayerLeft(((Object)rouletteTable).name, localSteam, 0uL, rouletteTable.PlayerCount);
			}
			else
			{
				RNNetcode.SendLeaveTableRequest(((Object)rouletteTable).name);
				rouletteTable.Leave(mainPlayer);
			}
			Plugin.HasSetRouletteBet = false;
			SendLocalMessage(chat, "<color=#FFD700>[Casino]</color> Left the roulette table. Any unplaced bet amounts have been refunded. Use /tbet to set a new bet amount.");
			Plugin.Log.LogInfo((object)"[Casino] Local player left roulette table via /rleave.");
		}

		private static void HandleCasinoHelp(ChatBehaviour chat)
		{
			string text = string.Join(", ", Plugin.AllowedBets);
			SendLocalMessage(chat, "<color=#FFD700>[Casino Commands]</color>");
			SendLocalMessage(chat, "<color=#AAAAAA>-- SLOTS --</color>");
			SendLocalMessage(chat, "<color=#FFFFFF>/slotbet <amount></color> - Set slot bet (" + text + ")");
			SendLocalMessage(chat, "<color=#AAAAAA>-- BLACKJACK --</color>");
			SendLocalMessage(chat, "<color=#FFFFFF>/blackjackbet <amount></color> - Set blackjack bet");
			SendLocalMessage(chat, "<color=#FFFFFF>/ready</color>  - Toggle ready");
			SendLocalMessage(chat, "<color=#FFFFFF>/start</color>  - Begin round (host only)");
			SendLocalMessage(chat, "<color=#FFFFFF>/hit</color>    - Take a card");
			SendLocalMessage(chat, "<color=#FFFFFF>/stand</color>  - End your turn");
			SendLocalMessage(chat, "<color=#FFFFFF>/leave</color>  - Leave your seat");
			SendLocalMessage(chat, "<color=#AAAAAA>-- ROULETTE --</color>");
			SendLocalMessage(chat, "<color=#FFFFFF>/tbet <amount></color> - Set roulette stake per bet");
			SendLocalMessage(chat, "<color=#FFFFFF>/rbet <type> [num]</color>  - Place a bet");
			SendLocalMessage(chat, "  Types: number 0-36, red, black, even, odd, low, high, dozen 1-3, column 1-3");
			SendLocalMessage(chat, "<color=#FFFFFF>/rclearbets</color> - Clear and refund all your bets");
			SendLocalMessage(chat, "<color=#FFFFFF>/rstandby</color>     - Toggle ready at roulette");
			SendLocalMessage(chat, "<color=#FFFFFF>/rspin</color>      - Spin the wheel (host only)");
			SendLocalMessage(chat, "<color=#FFFFFF>/rleave</color>     - Leave the roulette table");
			SendLocalMessage(chat, "<color=#FFFFFF>/casinohelp</color> - This help");
		}

		private static bool IsAllowedBet(int amount)
		{
			int[] allowedBets = Plugin.AllowedBets;
			foreach (int num in allowedBets)
			{
				if (num == amount)
				{
					return true;
				}
			}
			return false;
		}

		private static (BlackjackTable?, int) FindLocalSeat()
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return (null, -1);
			}
			BlackjackTable[] array = Object.FindObjectsOfType<BlackjackTable>();
			BlackjackTable[] array2 = array;
			foreach (BlackjackTable blackjackTable in array2)
			{
				int seatForPlayer = blackjackTable.GetSeatForPlayer(mainPlayer);
				if (seatForPlayer >= 0)
				{
					return (blackjackTable, seatForPlayer);
				}
			}
			return (null, -1);
		}

		private static bool IsLocalPlayerSeatedAtAnyBlackjackTable()
		{
			var (blackjackTable, num) = FindLocalSeat();
			return (Object)(object)blackjackTable != (Object)null && num >= 0;
		}

		private static RouletteTable? FindLocalRouletteTable()
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return null;
			}
			RouletteTable[] array = Object.FindObjectsOfType<RouletteTable>();
			RouletteTable[] array2 = array;
			foreach (RouletteTable rouletteTable in array2)
			{
				if (rouletteTable.IsPlayerAtTable(mainPlayer))
				{
					return rouletteTable;
				}
			}
			return null;
		}

		private static int GetLocalCrownBalance()
		{
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return 0;
			}
			PlayerInventory component = ((Component)mainPlayer).GetComponent<PlayerInventory>();
			if ((Object)(object)component == (Object)null)
			{
				return 0;
			}
			return component._heldCurrency;
		}

		private static string ReadyCountSummary(BlackjackTable table)
		{
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < 5; i++)
			{
				if (!((Object)(object)table.GetSeatedPlayer(i) == (Object)null))
				{
					num2++;
					if (table.IsPlayerReady(i))
					{
						num++;
					}
				}
			}
			return $"({num}/{num2} ready)";
		}

		private static void ShowLocalHandPrompt(BlackjackTable table, bool finalView)
		{
			try
			{
				Player mainPlayer = Player._mainPlayer;
				if ((Object)(object)mainPlayer == (Object)null)
				{
					return;
				}
				int seatForPlayer = table.GetSeatForPlayer(mainPlayer);
				if (seatForPlayer >= 0)
				{
					string text = (finalView ? table.DescribePlayerHandFinal(seatForPlayer) : table.DescribePlayerHandStatus(seatForPlayer));
					if (!string.IsNullOrEmpty(text))
					{
						ErrorPromptTextManager.current.Init_ErrorPrompt(text);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Casino] ShowLocalHandPrompt failed: " + ex.Message));
			}
		}

		private static void SendLocalMessage(ChatBehaviour chat, string message)
		{
			try
			{
				if (MaxOnscreenField != null)
				{
					try
					{
						MaxOnscreenField.SetValue(chat, 50);
					}
					catch
					{
					}
				}
				chat.Init_GameLogicMessage(message);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Casino] Failed to send local chat message: " + ex.Message));
			}
		}

		private static void SetChatFocusFalse(ChatBehaviour chat)
		{
			try
			{
				typeof(ChatBehaviour).GetField("_focusedInChat", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(chat, false);
			}
			catch
			{
			}
		}
	}
	public class CasinoExitTrigger : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <ForceReturnToSanctum>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Player player;

			public string caller;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ForceReturnToSanctum>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					ErrorPromptTextManager.current.Init_ErrorPrompt("Returning to Sanctum...");
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					ConfigurePortal(caller);
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					Plugin.Log.LogInfo((object)(caller + " Strategy 1: InteractQueue_RecallPortal..."));
					if (TryInteractQueue(caller))
					{
						Plugin.Log.LogInfo((object)(caller + " InteractQueue_RecallPortal fired."));
						return false;
					}
					<>2__current = null;
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					Plugin.Log.LogInfo((object)(caller + " Strategy 2: Cmd_SceneTransport (full path)..."));
					if (TrySceneTransport(player, "Assets/Scenes/00_zone_forest/_zone00_sanctum.unity", "startPoint"))
					{
						Plugin.Log.LogInfo((object)(caller + " Cmd_SceneTransport fired."));
						return false;
					}
					Plugin.Log.LogInfo((object)(caller + " Strategy 3: Cmd_SceneTransport (short name)..."));
					if (TrySceneTransport(player, "Sanctum", "startPoint"))
					{
						Plugin.Log.LogInfo((object)(caller + " Cmd_SceneTransport (short) fired."));
						return false;
					}
					Plugin.Log.LogInfo((object)(caller + " Strategy 4: _requestedRecall..."));
					if (TrySetRecallFlag(player))
					{
						Plugin.Log.LogInfo((object)(caller + " _requestedRecall set."));
						return false;
					}
					Plugin.Log.LogWarning((object)(caller + " Strategy 5: SceneManager.LoadScene..."));
					SceneManager.LoadScene("Assets/Scenes/00_zone_forest/_zone00_sanctum.unity");
					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();
			}
		}

		private const string SANCTUM_PATH = "Assets/Scenes/00_zone_forest/_zone00_sanctum.unity";

		private const float INPUT_COOLDOWN = 0.5f;

		private BoxCollider? _collider;

		private bool _playerNearby = false;

		private bool _isTransitioning = false;

		private float _nextInputTime = 0f;

		private void Awake()
		{
			_collider = ((Component)this).GetComponent<BoxCollider>();
			Plugin.Log.LogInfo((object)"[ExitTrigger] Casino exit trigger active.");
		}

		private void Update()
		{
			if (_isTransitioning)
			{
				return;
			}
			Player mainPlayer = Player._mainPlayer;
			if (!((Object)(object)mainPlayer == (Object)null))
			{
				bool flag = IsPlayerInRange(mainPlayer);
				if (flag && !_playerNearby)
				{
					_playerNearby = true;
					ErrorPromptTextManager.current.Init_ErrorPrompt("Press F to return to Sanctum.");
				}
				else if (!flag && _playerNearby)
				{
					_playerNearby = false;
				}
				if (_playerNearby && Input.GetKeyDown((KeyCode)102) && !(Time.time < _nextInputTime))
				{
					_nextInputTime = Time.time + 0.5f;
					_isTransitioning = true;
					((MonoBehaviour)this).StartCoroutine(ForceReturnToSanctum(mainPlayer));
				}
			}
		}

		private bool IsPlayerInRange(Player player)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_collider != (Object)null)
			{
				Bounds bounds = ((Collider)_collider).bounds;
				return ((Bounds)(ref bounds)).Contains(((Component)player).transform.position);
			}
			return Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) < 3f;
		}

		[IteratorStateMachine(typeof(<ForceReturnToSanctum>d__9))]
		public static IEnumerator ForceReturnToSanctum(Player player, string caller = "[ExitTrigger]")
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ForceReturnToSanctum>d__9(0)
			{
				player = player,
				caller = caller
			};
		}

		private static void ConfigurePortal(string caller)
		{
			GameObject val = GameObject.Find("_entity_recallPortal");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			MonoBehaviour[] array = componentsInChildren;
			foreach (MonoBehaviour val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Type type = ((object)val2).GetType();
				FieldInfo field = type.GetField("_scenePortal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null))
				{
					object value = field.GetValue(val2);
					if (value != null)
					{
						Type type2 = value.GetType();
						type2.GetField("_subScene", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(value, "Assets/Scenes/00_zone_forest/_zone00_sanctum.unity");
						type2.GetField("_spawnPointTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(value, "startPoint");
						type.GetField("_isPortalOpen", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(val2, true);
						field.SetValue(val2, value);
						Plugin.Log.LogInfo((object)(caller + " RecallPortal configured → 'Assets/Scenes/00_zone_forest/_zone00_sanctum.unity'"));
						break;
					}
				}
			}
		}

		private static bool TryInteractQueue(string caller)
		{
			GameObject val = GameObject.Find("_entity_recallPortal");
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			string[] array = new string[5] { "InteractQueue_RecallPortal", "Init_RecallPortal", "Interact_RecallPortal", "Activate_RecallPortal", "Open_RecallPortal" };
			MonoBehaviour[] array2 = componentsInChildren;
			foreach (MonoBehaviour val2 in array2)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Type type = ((object)val2).GetType();
				string[] array3 = array;
				foreach (string text in array3)
				{
					MethodInfo method = type.GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method == null))
					{
						Plugin.Log.LogInfo((object)(caller + " Calling " + type.Name + "." + text + "()"));
						try
						{
							method.Invoke(val2, null);
							return true;
						}
						catch (Exception ex)
						{
							Plugin.Log.LogWarning((object)(caller + " " + text + " threw: " + ex.Message));
						}
					}
				}
			}
			MonoBehaviour[] array4 = componentsInChildren;
			foreach (MonoBehaviour val3 in array4)
			{
				if (!((Object)(object)val3 == (Object)null) && !(((object)val3).GetType().Name != "RecallPortal"))
				{
					MethodInfo[] methods = ((object)val3).GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					StringBuilder stringBuilder = new StringBuilder();
					MethodInfo[] array5 = methods;
					foreach (MethodInfo methodInfo in array5)
					{
						stringBuilder.Append(methodInfo.Name).Append(", ");
					}
					Plugin.Log.LogInfo((object)$"{caller} RecallPortal methods: {stringBuilder}");
				}
			}
			return false;
		}

		private static bool TrySceneTransport(Player player, string sceneName, string spawnTag)
		{
			MethodInfo method = ((object)player).GetType().GetMethod("Cmd_SceneTransport", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				Plugin.Log.LogWarning((object)"[ExitTrigger] Cmd_SceneTransport not found.");
				return false;
			}
			try
			{
				ParameterInfo[] parameters = method.GetParameters();
				Plugin.Log.LogInfo((object)($"[ExitTrigger] Cmd_SceneTransport params: {parameters.Length} " + "(" + ((parameters.Length != 0) ? parameters[0].ParameterType.Name : "") + ")"));
				object[] parameters2;
				if (parameters.Length < 3)
				{
					parameters2 = ((parameters.Length != 2) ? new object[1] { sceneName } : new object[2] { sceneName, spawnTag });
				}
				else
				{
					object obj = Enum.ToObject(parameters[2].ParameterType, 0);
					parameters2 = new object[3] { sceneName, spawnTag, obj };
				}
				method.Invoke(player, parameters2);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[ExitTrigger] Cmd_SceneTransport threw: " + ex.Message));
				return false;
			}
		}

		private static bool TrySetRecallFlag(Player player)
		{
			string[] array = new string[4] { "_requestedRecall", "_recallRequested", "_isRecalling", "_recall" };
			foreach (string text in array)
			{
				FieldInfo field = ((object)player).GetType().GetField(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null) && !(field.FieldType != typeof(bool)))
				{
					field.SetValue(player, true);
					Plugin.Log.LogInfo((object)("[ExitTrigger] Set " + text + "=true on Player."));
					return true;
				}
			}
			return false;
		}
	}
	[BepInPlugin("dev.seth.atlysscasino", "Atlyss Casino", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <ShowHUDCoroutine>d__15 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string message;

			public float duration;

			public float refreshInterval;

			private float <elapsed>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ShowHUDCoroutine>d__15(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<elapsed>5__1 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<elapsed>5__1 += refreshInterval;
					break;
				}
				if (<elapsed>5__1 < duration)
				{
					try
					{
						ErrorPromptTextManager.current.Init_ErrorPrompt(message);
					}
					catch
					{
						return false;
					}
					<>2__current = (object)new WaitForSeconds(refreshInterval);
					<>1__state = 1;
					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();
			}
		}

		public static ManualLogSource Log = null;

		public static AssetBundle? AssetsBundle = null;

		public static int CurrentBet = 100;

		public static bool HasSetBet = false;

		public static int BlackjackBet = 100;

		public static bool HasSetBlackjackBet = false;

		public static int RouletteBet = 100;

		public static bool HasSetRouletteBet = false;

		public static readonly int[] AllowedBets = new int[4] { 10, 50, 100, 500 };

		public static Plugin Instance { get; private set; } = null;


		private void Awake()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			LoadAssetBundle();
			CasinoPatch.Init();
			BlackjackSceneWatcher.Init();
			BJNetcode.Initialize();
			RNNetcode.Initialize();
			Harmony val = new Harmony("dev.seth.atlysscasino");
			val.PatchAll();
			Log.LogInfo((object)"Atlyss Casino loaded!");
			Log.LogInfo((object)"[Casino] Slots: /slotbet | Blackjack: /blackjackbet /ready /start /hit /stand /leave | Roulette: /tbet /rbet /rclearbets /rstandby /rspin /rleave | Help: /casinohelp");
		}

		public static void ShowHUD(string message, float duration = 8f, float refreshInterval = 2.8f)
		{
			((MonoBehaviour)Instance).StartCoroutine(ShowHUDCoroutine(message, duration, refreshInterval));
		}

		[IteratorStateMachine(typeof(<ShowHUDCoroutine>d__15))]
		private static IEnumerator ShowHUDCoroutine(string message, float duration, float refreshInterval)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ShowHUDCoroutine>d__15(0)
			{
				message = message,
				duration = duration,
				refreshInterval = refreshInterval
			};
		}

		private void LoadAssetBundle()
		{
			try
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				string text = Path.Combine(directoryName, "atlysscasino_assets");
				AssetsBundle = AssetBundle.LoadFromFile(text);
				if ((Object)(object)AssetsBundle == (Object)null)
				{
					Log.LogError((object)("[Casino] Failed to load asset bundle at '" + text + "'"));
				}
				else
				{
					Log.LogInfo((object)"[Casino] Assets bundle loaded.");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[Casino] Bundle load exception: " + ex.Message));
			}
		}
	}
	public class SlotBetConfirm : MonoBehaviour
	{
		private SlotMachine? _machine;

		private bool _playerNearby = false;

		public void Setup(SlotMachine machine)
		{
			_machine = machine;
		}

		private void Update()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return;
			}
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)mainPlayer).transform.position);
			bool flag = num < 2.5f;
			if (flag && !_playerNearby)
			{
				_playerNearby = true;
				if (Plugin.HasSetBet)
				{
					ErrorPromptTextManager.current.Init_ErrorPrompt($"Bet: {Plugin.CurrentBet} Crowns. " + "Press F to spin. Change bet with /slotbet <amount>.");
				}
				else
				{
					ErrorPromptTextManager.current.Init_ErrorPrompt("No bet set. Use /slotbet <amount> to set your bet.");
				}
				Plugin.Log.LogInfo((object)"[Casino] Player near slot trigger.");
			}
			else if (!flag && _playerNearby)
			{
				_playerNearby = false;
			}
			if (_playerNearby && Input.GetKeyDown((KeyCode)102))
			{
				if (!Plugin.HasSetBet)
				{
					ErrorPromptTextManager.current.Init_ErrorPrompt("Set a bet first with /slotbet <amount>!");
				}
				else
				{
					_machine?.TryPlay();
				}
			}
		}
	}
	public class SlotMachine : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <AnimateLever>d__45 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public SlotMachine <>4__this;

			private float <elapsed>5__1;

			private float <duration>5__2;

			private Quaternion <start>5__3;

			private Quaternion <pulled>5__4;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AnimateLever>d__45(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: 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_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: 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_00db: Unknown result type (might be due to invalid IL or missing references)
				//IL_0116: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: Expected O, but got Unknown
				//IL_015c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0162: Unknown result type (might be due to invalid IL or missing references)
				//IL_0174: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if ((Object)(object)<>4__this._lever == (Object)null)
					{
						return false;
					}
					<elapsed>5__1 = 0f;
					<duration>5__2 = 0.3f;
					<start>5__3 = <>4__this._lever.localRotation;
					<pulled>5__4 = <start>5__3 * Quaternion.Euler(-30f, 0f, 0f);
					goto IL_00fe;
				case 1:
					<>1__state = -1;
					goto IL_00fe;
				case 2:
					<>1__state = -1;
					<elapsed>5__1 = 0f;
					break;
				case 3:
					{
						<>1__state = -1;
						break;
					}
					IL_00fe:
					if (<elapsed>5__1 < <duration>5__2)
					{
						<elapsed>5__1 += Time.deltaTime;
						<>4__this._lever.localRotation = Quaternion.Lerp(<start>5__3, <pulled>5__4, <elapsed>5__1 / <duration>5__2);
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>2__current = (object)new WaitForSeconds(0.3f);
					<>1__state = 2;
					return true;
				}
				if (<elapsed>5__1 < <duration>5__2)
				{
					<elapsed>5__1 += Time.deltaTime;
					<>4__this._lever.localRotation = Quaternion.Lerp(<pulled>5__4, <start>5__3, <elapsed>5__1 / <duration>5__2);
					<>2__current = null;
					<>1__state = 3;
					return true;
				}
				<>4__this._lever.localRotation = <start>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();
			}
		}

		[CompilerGenerated]
		private sealed class <FlashAllReels>d__41 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Material flashMat;

			public int times;

			public float interval;

			public int[] results;

			public SlotMachine <>4__this;

			private int <t>5__1;

			private int <i>5__2;

			private int <i>5__3;

			private int <i>5__4;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FlashAllReels>d__41(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0115: Expected O, but got Unknown
				//IL_0097: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (<>4__this._symbolMaterials == null)
					{
						return false;
					}
					<t>5__1 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__3 = 0;
					while (<i>5__3 < 3)
					{
						<>4__this.SetReel(<i>5__3, <>4__this._symbolMaterials[results[<i>5__3]]);
						<i>5__3++;
					}
					<>2__current = (object)new WaitForSeconds(interval);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<t>5__1++;
					break;
				}
				if (<t>5__1 < times)
				{
					<i>5__2 = 0;
					while (<i>5__2 < 3)
					{
						<>4__this.SetReel(<i>5__2, flashMat);
						<i>5__2++;
					}
					<>2__current = (object)new WaitForSeconds(interval);
					<>1__state = 1;
					return true;
				}
				<i>5__4 = 0;
				while (<i>5__4 < 3)
				{
					<>4__this.SetReel(<i>5__4, flashMat);
					<i>5__4++;
				}
				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();
			}
		}

		[CompilerGenerated]
		private sealed class <PlaySlotsLocal>d__37 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public int wager;

			public PlayerInventory inventory;

			public int r1;

			public int r2;

			public int r3;

			public SlotMachine <>4__this;

			private float <multiplier>5__1;

			private string <tier>5__2;

			private bool <bigWin>5__3;

			private bool <isJackpot>5__4;

			private string <resultLine>5__5;

			private int <payout>5__6;

			private int <i>5__7;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlaySlotsLocal>d__37(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<tier>5__2 = null;
				<resultLine>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0281: Unknown result type (might be due to invalid IL or missing references)
				//IL_028b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					(float, string, bool) tuple = <>4__this.CalculatePayout(r1, r2, r3);
					<multiplier>5__1 = tuple.Item1;
					<tier>5__2 = tuple.Item2;
					<bigWin>5__3 = tuple.Item3;
					<isJackpot>5__4 = r1 == 4 && r2 == 4 && r3 == 4;
					<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.RunSpinVisuals(r1, r2, r3, <isJackpot>5__4, <bigWin>5__3, <multiplier>5__1 > 0f));
					<>1__state = 1;
					return true;
				}
				case 1:
					<>1__state = -1;
					<resultLine>5__5 = "[ " + <>4__this._symbols[r1] + " | " + <>4__this._symbols[r2] + " | " + <>4__this._symbols[r3] + " ]";
					if (<multiplier>5__1 > 0f)
					{
						<payout>5__6 = Mathf.FloorToInt((float)wager * <multiplier>5__1);
						if (<payout>5__6 < 1)
						{
							<payout>5__6 = 1;
						}
						PlayerInventory obj = inventory;
						obj.Network_heldCurrency += <payout>5__6;
						ErrorPromptTextManager.current.Init_ErrorPrompt($"{<resultLine>5__5}\n{<tier>5__2} Won {<payout>5__6} Crowns!");
						Plugin.Log.LogInfo((object)($"[Slots] {<tier>5__2} — bet {wager}, payout {<payout>5__6} " + $"({<multiplier>5__1:F2}x)."));
					}
					else
					{
						ErrorPromptTextManager.current.Init_ErrorPrompt($"{<resultLine>5__5}\nNo match. Lost {wager} Crowns.");
						Plugin.Log.LogInfo((object)$"[Slots] Loss — bet {wager}.");
					}
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<i>5__7 = 0;
					while (<i>5__7 < 3)
					{
						<>4__this.SetReel(<i>5__7, <>4__this.MatIdleBlank);
						<i>5__7++;
					}
					<>4__this.SetTopScreen(<>4__this.MatIdle);
					<>4__this.InUse = false;
					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();
			}
		}

		[CompilerGenerated]
		private sealed class <PlaySlotsRemote>d__38 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public int r1;

			public int r2;

			public int r3;

			public SlotMachine <>4__this;

			private float <multiplier>5__1;

			private string <tier>5__2;

			private bool <bigWin>5__3;

			private bool <isJackpot>5__4;

			private int <i>5__5;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlaySlotsRemote>d__38(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<tier>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fe: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					(float, string, bool) tuple = <>4__this.CalculatePayout(r1, r2, r3);
					<multiplier>5__1 = tuple.Item1;
					<tier>5__2 = tuple.Item2;
					<bigWin>5__3 = tuple.Item3;
					<isJackpot>5__4 = r1 == 4 && r2 == 4 && r3 == 4;
					<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.RunSpinVisuals(r1, r2, r3, <isJackpot>5__4, <bigWin>5__3, <multiplier>5__1 > 0f));
					<>1__state = 1;
					return true;
				}
				case 1:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<i>5__5 = 0;
					while (<i>5__5 < 3)
					{
						<>4__this.SetReel(<i>5__5, <>4__this.MatIdleBlank);
						<i>5__5++;
					}
					<>4__this.SetTopScreen(<>4__this.MatIdle);
					<>4__this.InUse = false;
					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();
			}
		}

		[CompilerGenerated]
		private sealed class <RunSpinVisuals>d__39 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public int r1;

			public int r2;

			public int r3;

			public bool isJackpot;

			public bool bigWin;

			public bool isWin;

			public SlotMachine <>4__this;

			private int[] <results>5__1;

			private float[] <reelDurations>5__2;

			private int <i>5__3;

			private Material <flashMat>5__4;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RunSpinVisuals>d__39(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<results>5__1 = null;
				<reelDurations>5__2 = null;
				<flashMat>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0274: Unknown result type (might be due to invalid IL or missing references)
				//IL_027e: Expected O, but got Unknown
				//IL_0139: Unknown result type (might be due to invalid IL or missing references)
				//IL_0143: Expected O, but got Unknown
				//IL_0248: Unknown result type (might be due to invalid IL or missing references)
				//IL_0252: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if ((Object)(object)<>4__this._lever != (Object)null)
					{
						((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.AnimateLever());
					}
					<>4__this.SetTopScreen(<>4__this.MatIdleBlank);
					<results>5__1 = new int[3] { r1, r2, r3 };
					<reelDurations>5__2 = new float[3] { 1.5f, 2f, 2.5f };
					<i>5__3 = 0;
					while (<i>5__3 < 3)
					{
						((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.SpinReel(<i>5__3, <reelDurations>5__2[<i>5__3], <results>5__1[<i>5__3]));
						<i>5__3++;
					}
					<>2__current = (object)new WaitForSeconds(<reelDurations>5__2[2] + 0.3f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (isWin)
					{
						<flashMat>5__4 = (isJackpot ? <>4__this.MatJackpot : <>4__this.MatWin);
						<>4__this.SetTopScreen(<flashMat>5__4);
						if (isJackpot)
						{
							<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FlashAllReels(<>4__this.MatJackpot, 6, 0.15f, <results>5__1));
							<>1__state = 2;
							return true;
						}
						if (bigWin)
						{
							<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FlashAllReels(<>4__this.MatWin, 4, 0.2f, <results>5__1));
							<>1__state = 3;
							return true;
						}
						<>2__current = (object)new WaitForSeconds(1.5f);
						<>1__state = 4;
						return true;
					}
					<>2__current = (object)new WaitForSeconds(1.5f);
					<>1__state = 5;
					return true;
				case 2:
					<>1__state = -1;
					goto IL_0263;
				case 3:
					<>1__state = -1;
					goto IL_0263;
				case 4:
					<>1__state = -1;
					goto IL_0263;
				case 5:
					{
						<>1__state = -1;
						break;
					}
					IL_0263:
					<flashMat>5__4 = null;
					break;
				}
				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();
			}
		}

		[CompilerGenerated]
		private sealed class <SpinReel>d__40 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public int reelIndex;

			public float duration;

			public int finalResult;

			public SlotMachine <>4__this;

			private float <elapsed>5__1;

			private float <nextFlicker>5__2;

			private float <flickerSpeed>5__3;

			private float <progress>5__4;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SpinReel>d__40(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (<>4__this._symbolMaterials == null)
					{
						return false;
					}
					<elapsed>5__1 = 0f;
					<nextFlicker>5__2 = 0f;
					<flickerSpeed>5__3 = 0.08f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsed>5__1 < duration)
				{
					if (<elapsed>5__1 >= <nextFlicker>5__2)
					{
						<>4__this.SetReel(reelIndex, <>4__this._symbolMaterials[Random.Range(0, <>4__this._symbolMaterials.Length)]);
						<progress>5__4 = <elapsed>5__1 / duration;
						<flickerSpeed>5__3 = Mathf.Lerp(0.05f, 0.35f, <progress>5__4);
						<nextFlicker>5__2 = <elapsed>5__1 + <flickerSpeed>5__3;
					}
					<elapsed>5__1 += Time.deltaTime;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				<>4__this.SetReel(reelIndex, <>4__this._symbolMaterials[finalResult]);
				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 bool InUse = false;

		public float NextInputTime = 0f;

		private Transform? _lever;

		private GameObject? _backdrop;

		private MeshRenderer? _backdropRenderer;

		private GameObject[] _reels = (GameObject[])(object)new GameObject[3];

		private MeshRenderer?[] _reelRenderers = (MeshRenderer?[])(object)new MeshRenderer[3];

		private GameObject? _topScreen;

		private MeshRenderer? _topScreenRenderer;

		public Material? MatIdle;

		public Material? MatIdleBlank;

		public Material? MatWin;

		public Material? MatJackpot;

		public Material? MatCherry;

		public Material? MatLemon;

		public Material? MatOrange;

		public Material? MatStar;

		public Material? MatDiamond;

		public Material? MatSeven;

		private Material?[]? _symbolMaterials;

		private const int CherryIdx = 0;

		private const int LemonIdx = 1;

		private const int OrangeIdx = 2;

		private const int StarIdx = 3;

		private const int DiamondIdx = 4;

		private const int SevenIdx = 5;

		private readonly string[] _symbols = new string[6] { "Cherry", "Lemon", "Orange", "Star", "Diamond", "Seven" };

		public void Init()
		{
			_lever = ((Component)this).transform.Find("Lever");
			Transform val = ((Component)this).transform.Find("ScreenAnchor");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"[Slots] ScreenAnchor child not found!");
			}
			else
			{
				BuildBackdrop(val);
				BuildThreeReels(val);
			}
			Transform val2 = ((Component)this).transform.Find("TopScreenAnchor");
			if ((Object)(object)val2 != (Object)null)
			{
				BuildTopScreen(val2);
			}
			_symbolMaterials = (Material?[]?)(object)new Material[6] { MatCherry, MatLemon, MatOrange, MatStar, MatDiamond, MatSeven };
			SetBackdrop(MatIdleBlank);
			for (int i = 0; i < 3; i++)
			{
				SetReel(i, MatIdleBlank);
			}
			SetTopScreen(MatIdle);
		}

		private void BuildBackdrop(Transform anchor)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)val).name = "SlotScreenBackdrop";
			Collider component = val.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			val.transform.SetParent(anchor, false);
			val.transform.localPosition = new Vector3(0f, 0f, 0.001f);
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			_backdrop = val;
			_backdropRenderer = val.GetComponent<MeshRenderer>();
		}

		private void BuildThreeReels(Transform anchor)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f / 3f;
			float[] array = new float[3]
			{
				-1f / 3f,
				0f,
				1f / 3f
			};
			for (int i = 0; i < 3; i++)
			{
				GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
				((Object)val).name = $"SlotReel_{i}";
				Collider component = val.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				val.transform.SetParent(anchor, false);
				val.transform.localPosition = new Vector3(array[i], 0f, -0.001f);
				val.transform.localRotation = Quaternion.identity;
				val.transform.localScale = new Vector3(num, 1f, 1f);
				_reels[i] = val;
				_reelRenderers[i] = val.GetComponent<MeshRenderer>();
			}
		}

		private void BuildTopScreen(Transform anchor)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)val).name = "SlotTopScreen";
			Collider component = val.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			val.transform.SetParent(anchor, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			_topScreen = val;
			_topScreenRenderer = val.GetComponent<MeshRenderer>();
		}

		public void TryPlay()
		{
			if (Time.time < NextInputTime)
			{
				return;
			}
			NextInputTime = Time.time + 0.5f;
			if (InUse)
			{
				ErrorPromptTextManager.current.Init_ErrorPrompt("Machine is in use!");
				return;
			}
			Player mainPlayer = Player._mainPlayer;
			if ((Object)(object)mainPlayer == (Object)null)
			{
				return;
			}
			PlayerInventory component = ((Component)mainPlayer).GetComponent<PlayerInventory>();
			if (!((Object)(object)component == (Object)null))
			{
				int currentBet = Plugin.CurrentBet;
				if (component._heldCurrency < currentBet)
				{
					ErrorPromptTextManager.current.Init_ErrorPrompt($"Not enough Crowns! Need {currentBet}, " + $"you have {component._heldCurrency}.");
					return;
				}
				int num = Random.Range(0, _symbols.Length);
				int num2 = Random.Range(0, _symbols.Length);
				int num3 = Random.Range(0, _symbols.Length);
				InUse = true;
				component.Network_heldCurrency -= currentBet;
				Plugin.Log.LogInfo((object)$"[Slots] Playing '{((Object)this).name}' with bet {currentBet} -> [{num}, {num2}, {num3}].");
				BJNetcode.BroadcastSlotSpinResult(((Object)this).name, num, num2, num3);
				((MonoBehaviour)this).StartCoroutine(PlaySlotsLocal(currentBet, component, num, num2, num3));
			}
		}

		public void ApplyRemoteSpin(int r1, int r2, int r3)
		{
			if (InUse)
			{
				Plugin.Log.LogWarning((object)("[Slots] ApplyRemoteSpin on '" + ((Object)this).name + "' but machine is already in use — dropping remote spin to avoid visual clash."));
				return;
			}
			if (r1 < 0 || r1 >= _symbols.Length || r2 < 0 || r2 >= _symbols.Length || r3 < 0 || r3 >= _symbols.Length)
			{
				Plugin.Log.LogError((object)("[Slots] ApplyRemoteSpin on '" + ((Object)this).name + "': invalid symbol indices " + $"[{r1}, {r2}, {r3}]. Spin not played."));
				return;
			}
			InUse = true;
			Plugin.Log.LogInfo((object)$"[Slots] Mirroring remote spin on '{((Object)this).name}' -> [{r1}, {r2}, {r3}].");
			((MonoBehaviour)this).StartCoroutine(PlaySlotsRemote(r1, r2, r3));
		}

		private static bool IsFruit(int idx)
		{
			return idx == 0 || idx == 1 || idx == 2;
		}

		private static bool IsStarOrSeven(int idx)
		{
			return idx == 3 || idx == 5;
		}

		private (float multiplier, string tier, bool bigWin) CalculatePayout(int r1, int r2, int r3)
		{
			if (r1 == r2 && r2 == r3)
			{
				if (r1 == 4)
				{
					return (100f, "JACKPOT!", true);
				}
				if (IsStarOrSeven(r1))
				{
					return (2f, "Triple Match!", false);
				}
				return (1f, "Triple Fruit!", false);
			}
			int num = 0;
			int[] array = new int[3] { r1, r2, r3 };
			foreach (int num2 in array)
			{
				if (num2 == 4)
				{
					num++;
				}
			}
			if (num == 2)
			{
				return (2f, "Two Diamonds!", false);
			}
			if (HasExactlyTwoOfSame(r1, r2, r3, out var matchedIdx))
			{
				if (IsStarOrSeven(matchedIdx))
				{
					return (0.5f, "Near Miss!", false);
				}
				if (IsFruit(matchedIdx))
				{
					return (0.25f, "Fruit Pair", false);
				}
			}
			return (0f, "No match", false);
		}

		private static bool HasExactlyTwoOfSame(int r1, int r2, int r3, out int matchedIdx)
		{
			if (r1 == r2 && r2 == r3)
			{
				matchedIdx = -1;
				return false;
			}
			if (r1 == r2)
			{
				matchedIdx = r1;
				return true;
			}
			if (r2 == r3)
			{
				matchedIdx = r2;
				return true;
			}
			if (r1 == r3)
			{
				matchedIdx = r1;
				return true;
			}
			matchedIdx = -1;
			return false;
		}

		[IteratorStateMachine(typeof(<PlaySlotsLocal>d__37))]
		private IEnumerator PlaySlotsLocal(int wager, PlayerInventory inventory, int r1, int r2, int r3)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlaySlotsLocal>d__37(0)
			{
				<>4__this = this,
				wager = wager,
				inventory = inventory,
				r1 = r1,
				r2 = r2,
				r3 = r3
			};
		}

		[IteratorStateMachine(typeof(<PlaySlotsRemote>d__38))]
		private IEnumerator PlaySlotsRemote(int r1, int r2, int r3)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlaySlotsRemote>d__38(0)
			{
				<>4__this = this,
				r1 = r1,
				r2 = r2,
				r3 = r3
			};
		}

		[IteratorStateMachine(typeof(<RunSpinVisuals>d__39))]
		private IEnumerator RunSpinVisuals(int r1, int r2, int r3, bool isJackpot, bool bigWin, bool isWin)
		{
			/