Decompiled source of Double Down in Lethal Casino v4.0.2

LethalCasinoDoubleDown.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("LethalCasinoDoubleDown")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LethalCasinoDoubleDown")]
[assembly: AssemblyTitle("LethalCasinoDoubleDown")]
[assembly: AssemblyVersion("1.0.0.0")]
public static class PluginInfo
{
	public const string PLUGIN_GUID = "Papkasse_Manden.Double_Down_In_Lethal_Casino";

	public const string PLUGIN_NAME = "Double_Down_In_Lethal_Casino";

	public const string PLUGIN_VERSION = "4.0.2";
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("Papkasse_Manden.Double_Down_In_Lethal_Casino", "Double_Down_In_Lethal_Casino", "4.0.2")]
public class BlackjackDoubleDownMod : BaseUnityPlugin
{
	private readonly Harmony harmony = new Harmony("Papkasse_Manden.Double_Down_In_Lethal_Casino");

	public static ManualLogSource Log { get; private set; }

	public static ConfigEntry<KeyboardShortcut> DoubleDownKey { get; private set; }

	private void Awake()
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"Plugin Papkasse_Manden.Double_Down_In_Lethal_Casino is loading...");
		DoubleDownKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "DoubleDownKey", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), "Key to perform Double Down action in Blackjack");
		ApplyAllPatches();
		Log.LogInfo((object)"Plugin Papkasse_Manden.Double_Down_In_Lethal_Casino v4.0.2 loaded successfully");
	}

	private void ApplyAllPatches()
	{
		if (!BlackjackReflectionCache.Initialize(Log))
		{
			Log.LogError((object)"Failed to initialize reflection cache. Aborting patches.");
			return;
		}
		CustomScrapControllerPatcher.ApplyPatches(harmony, Log);
		BlackjackDoubleDownPatcher.ApplyPatches(harmony, Log);
		BlackjackMultiplyScrapValuesPatcher.ApplyPatches(harmony, Log);
		BlackjackProcessResultsPatcher.ApplyPatches(harmony, Log);
		JoinGameServerRpcPatcher.ApplyPatches(harmony, Log);
	}
}
internal static class BlackjackReflectionCache
{
	public static Type BlackjackType { get; private set; }

	public static Type CustomScrapControllerType { get; private set; }

	public static FieldInfo GameInProgressField { get; private set; }

	public static FieldInfo GamblingPlayersField { get; private set; }

	public static FieldInfo GambledScrapField { get; private set; }

	public static FieldInfo PlayerCardsField { get; private set; }

	public static FieldInfo PlayerCompletedTurnField { get; private set; }

	public static FieldInfo OriginalScrapValueField { get; private set; }

	public static FieldInfo LockFromGamblingField { get; private set; }

	public static FieldInfo DelayedTasksField { get; private set; }

	public static FieldInfo DelayedTasksQueuedField { get; private set; }

	public static MethodInfo DestroyBetControlsClientRpcMethod { get; private set; }

	public static MethodInfo TakeTurnAsPlayerServerRpcMethod { get; private set; }

	public static MethodInfo ShowWarningMessageClientRpcMethod { get; private set; }

	public static MethodInfo MultiplyScrapValuesMethod { get; private set; }

	public static MethodInfo UpdateScrapValueClientRpcMethod { get; private set; }

	public static MethodInfo JoinGameServerRpcMethod { get; private set; }

	public static MethodInfo JoinGameSuccessfulClientRpcMethod { get; private set; }

	public static bool Initialize(ManualLogSource log)
	{
		try
		{
			BlackjackType = AccessTools.TypeByName("LethalCasino.Custom.Blackjack");
			CustomScrapControllerType = AccessTools.TypeByName("LethalCasino.Custom.CustomScrapController");
			if (BlackjackType == null || CustomScrapControllerType == null)
			{
				log.LogError((object)"Required LethalCasino types not found. Is LethalCasino installed?");
				return false;
			}
			GameInProgressField = GetField(BlackjackType, "gameInProgress");
			GamblingPlayersField = GetField(BlackjackType, "gamblingPlayers");
			GambledScrapField = GetField(BlackjackType, "gambledScrap");
			PlayerCardsField = GetField(BlackjackType, "playerCards");
			PlayerCompletedTurnField = GetField(BlackjackType, "playerCompletedTurn");
			DelayedTasksField = GetField(BlackjackType, "delayedTasks");
			DelayedTasksQueuedField = GetField(BlackjackType, "delayedTasksQueued");
			OriginalScrapValueField = GetField(CustomScrapControllerType, "originalScrapValue");
			LockFromGamblingField = GetField(CustomScrapControllerType, "lockFromGambling");
			TakeTurnAsPlayerServerRpcMethod = GetMethod(BlackjackType, "TakeTurnAsPlayerServerRpc", new Type[3]
			{
				typeof(NetworkBehaviourReference),
				typeof(int),
				typeof(string)
			});
			ShowWarningMessageClientRpcMethod = GetMethod(BlackjackType, "ShowWarningMessageClientRpc", new Type[4]
			{
				typeof(NetworkBehaviourReference),
				typeof(string),
				typeof(string),
				typeof(bool)
			});
			MultiplyScrapValuesMethod = GetMethod(BlackjackType, "MultiplyScrapValues", new Type[3]
			{
				typeof(List<GrabbableObject>),
				typeof(float),
				typeof(bool)
			});
			UpdateScrapValueClientRpcMethod = GetMethod(BlackjackType, "UpdateScrapValueClientRpc", new Type[3]
			{
				typeof(NetworkBehaviourReference),
				typeof(int),
				typeof(bool)
			});
			JoinGameServerRpcMethod = GetMethod(BlackjackType, "JoinGameServerRpc", new Type[2]
			{
				typeof(NetworkBehaviourReference),
				typeof(int)
			});
			DestroyBetControlsClientRpcMethod = GetMethod(BlackjackType, "DestroyBetControlsClientRpc", new Type[1] { typeof(int) });
			JoinGameSuccessfulClientRpcMethod = GetMethod(BlackjackType, "JoinGameSuccessfulClientRpc", new Type[3]
			{
				typeof(NetworkBehaviourReference),
				typeof(int),
				typeof(int)
			});
			return ValidateReflection(log);
		}
		catch (Exception arg)
		{
			log.LogError((object)$"Failed to initialize reflection cache: {arg}");
			return false;
		}
	}

	private static FieldInfo GetField(Type type, string fieldName)
	{
		FieldInfo fieldInfo = AccessTools.Field(type, fieldName);
		if (fieldInfo == null)
		{
			BlackjackDoubleDownMod.Log.LogWarning((object)("Field '" + fieldName + "' not found in " + type.Name));
		}
		return fieldInfo;
	}

	private static MethodInfo GetMethod(Type type, string methodName, Type[] parameters = null)
	{
		MethodInfo methodInfo = AccessTools.Method(type, methodName, parameters, (Type[])null);
		if (methodInfo == null)
		{
			BlackjackDoubleDownMod.Log.LogWarning((object)("Method '" + methodName + "' not found in " + type.Name));
		}
		return methodInfo;
	}

	private static bool ValidateReflection(ManualLogSource log)
	{
		(FieldInfo, string)[] array = new(FieldInfo, string)[7]
		{
			(GameInProgressField, "gameInProgress"),
			(GamblingPlayersField, "gamblingPlayers"),
			(GambledScrapField, "gambledScrap"),
			(PlayerCardsField, "playerCards"),
			(PlayerCompletedTurnField, "playerCompletedTurn"),
			(OriginalScrapValueField, "originalScrapValue"),
			(LockFromGamblingField, "lockFromGambling")
		};
		(MethodInfo, string)[] array2 = new(MethodInfo, string)[7]
		{
			(TakeTurnAsPlayerServerRpcMethod, "TakeTurnAsPlayerServerRpc"),
			(ShowWarningMessageClientRpcMethod, "ShowWarningMessageClientRpc"),
			(MultiplyScrapValuesMethod, "MultiplyScrapValues"),
			(UpdateScrapValueClientRpcMethod, "UpdateScrapValueClientRpc"),
			(JoinGameServerRpcMethod, "JoinGameServerRpc"),
			(JoinGameSuccessfulClientRpcMethod, "JoinGameSuccessfulClientRpc"),
			(DestroyBetControlsClientRpcMethod, "DestroyBetControlsClientRpc")
		};
		bool result = true;
		(FieldInfo, string)[] array3 = array;
		for (int i = 0; i < array3.Length; i++)
		{
			var (fieldInfo, text) = array3[i];
			if (fieldInfo == null)
			{
				log.LogError((object)("Required field '" + text + "' not found"));
				result = false;
			}
		}
		(MethodInfo, string)[] array4 = array2;
		for (int j = 0; j < array4.Length; j++)
		{
			var (methodInfo, text2) = array4[j];
			if (methodInfo == null)
			{
				log.LogError((object)("Required method '" + text2 + "' not found"));
				result = false;
			}
		}
		return result;
	}
}
internal static class CustomScrapControllerPatcher
{
	private static Dictionary<object, int> gambledValues = new Dictionary<object, int>();

	public static void ApplyPatches(Harmony harmony, ManualLogSource log)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method(BlackjackReflectionCache.CustomScrapControllerType, "__initializeVariables", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(CustomScrapControllerPatcher), "InitializeVariables_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				log.LogInfo((object)"CustomScrapController __initializeVariables method patched");
			}
			else
			{
				log.LogWarning((object)"Could not find __initializeVariables method in CustomScrapController");
			}
		}
		catch (Exception arg)
		{
			log.LogError((object)$"Failed to patch CustomScrapController: {arg}");
		}
	}

	[HarmonyPostfix]
	public static void InitializeVariables_Postfix(object __instance)
	{
		try
		{
			gambledValues[__instance] = 0;
			BlackjackDoubleDownMod.Log.LogDebug((object)"Initialized gambledValue to 0 for scrap");
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in InitializeVariables_Postfix: {arg}");
		}
	}

	public static int GetGambledValue(object customScrapController)
	{
		int value;
		return gambledValues.TryGetValue(customScrapController, out value) ? value : 0;
	}

	public static void SetGambledValue(object customScrapController, int value)
	{
		gambledValues[customScrapController] = value;
	}

	public static void ClearAllGambledValues()
	{
		gambledValues.Clear();
	}
}
internal static class BlackjackMultiplyScrapValuesPatcher
{
	public static void ApplyPatches(Harmony harmony, ManualLogSource log)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		try
		{
			MethodInfo multiplyScrapValuesMethod = BlackjackReflectionCache.MultiplyScrapValuesMethod;
			if (multiplyScrapValuesMethod != null)
			{
				harmony.Patch((MethodBase)multiplyScrapValuesMethod, new HarmonyMethod(typeof(BlackjackMultiplyScrapValuesPatcher), "MultiplyScrapValues_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				log.LogInfo((object)"Blackjack MultiplyScrapValues method patched successfully");
			}
			else
			{
				log.LogWarning((object)"Could not find MultiplyScrapValues method in Blackjack");
			}
		}
		catch (Exception arg)
		{
			log.LogError((object)$"Failed to patch MultiplyScrapValues: {arg}");
		}
	}

	[HarmonyPrefix]
	public static bool MultiplyScrapValues_Prefix(object __instance, List<GrabbableObject> scrapItems, float multiplier, bool disablePoofsOnZero, ref int __result)
	{
		//IL_0507: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			int playerIndexForScrap = GetPlayerIndexForScrap(__instance, scrapItems);
			BlackjackDoubleDownMod.Log.LogInfo((object)$"===== MultiplyScrapValues called for playerposition {playerIndexForScrap} =====");
			if (multiplier == 0f && playerIndexForScrap != -1 && BustTracking.IsPlayerAlreadyBusted(playerIndexForScrap))
			{
				BlackjackDoubleDownMod.Log.LogInfo((object)"SKIPPING duplicate bust processing caused by ProcessResults");
				__result = 0;
				return false;
			}
			if (multiplier == 0f && playerIndexForScrap != -1 && !BustTracking.IsPlayerAlreadyBusted(playerIndexForScrap))
			{
				BustTracking.MarkPlayerBusted(playerIndexForScrap);
				BlackjackDoubleDownMod.Log.LogInfo((object)$"MARKED player {playerIndexForScrap} as busted");
			}
			BlackjackDoubleDownMod.Log.LogInfo((object)$"Multiplier: {multiplier}, ScrapItems Count: {scrapItems?.Count}");
			List<GrabbableObject>[] array = (List<GrabbableObject>[])BlackjackReflectionCache.GambledScrapField.GetValue(__instance);
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] == null || array[i].Count <= 0)
				{
					continue;
				}
				BlackjackDoubleDownMod.Log.LogInfo((object)$"gambledScrapArray[{i}] has {array[i].Count} items");
				foreach (GrabbableObject item in array[i])
				{
					if ((Object)(object)item != (Object)null)
					{
						BlackjackDoubleDownMod.Log.LogInfo((object)$"  - {item.itemProperties.itemName} (Value: {item.scrapValue})");
					}
				}
			}
			int num = 0;
			foreach (GrabbableObject scrapItem in scrapItems)
			{
				if ((Object)(object)scrapItem == (Object)null)
				{
					continue;
				}
				BlackjackDoubleDownMod.Log.LogInfo((object)$"Processing scrap item: {scrapItem.itemProperties.itemName}, Current Value: {scrapItem.scrapValue}");
				Component component = ((Component)scrapItem).GetComponent(BlackjackReflectionCache.CustomScrapControllerType);
				if ((Object)(object)component == (Object)null)
				{
					BlackjackDoubleDownMod.Log.LogWarning((object)"No CustomScrapController found!");
					continue;
				}
				int num2 = CustomScrapControllerPatcher.GetGambledValue(component);
				int num3 = (int)BlackjackReflectionCache.OriginalScrapValueField.GetValue(component);
				if (num3 < num2)
				{
					num2 = num3;
				}
				BlackjackDoubleDownMod.Log.LogInfo((object)$"OriginalValue: {num3}, GambledValue: {num2}");
				int num4;
				if (num2 > 0)
				{
					if (multiplier == 0f)
					{
						num4 = Math.Max(0, num3 - num2);
						BlackjackDoubleDownMod.Log.LogInfo((object)$"DoubleDown LOSS Calculation: {num3} - {num2} = {num4}");
					}
					else if (multiplier == 2f)
					{
						num4 = num3 + num2;
						BlackjackDoubleDownMod.Log.LogInfo((object)$"DoubleDown WIN Calculation: {num3} + {num2}  = {num4}");
					}
					else if (multiplier == 2.5f)
					{
						num4 = num3 + (int)((float)num2 * 1.5f);
						BlackjackDoubleDownMod.Log.LogInfo((object)$"DoubleDown BLACKJACK Calculation: {num3} + ({num2} * 1.5) = {num4}");
					}
					else
					{
						num4 = num3;
						BlackjackDoubleDownMod.Log.LogInfo((object)$"DoubleDown TIE - Keeping original value: {num4}");
					}
				}
				else if (multiplier == 0f)
				{
					num4 = 0;
					BlackjackDoubleDownMod.Log.LogInfo((object)$"Normal LOSS Calculation: {num3} = {num4}");
				}
				else if (multiplier == 2f)
				{
					num4 = (int)((float)num3 * 2f);
					BlackjackDoubleDownMod.Log.LogInfo((object)$"Normal WIN Calculation: {num3} * 2 = {num4}");
				}
				else if (multiplier == 2.5f)
				{
					num4 = (int)((float)num3 * 2.5f);
					BlackjackDoubleDownMod.Log.LogInfo((object)$"Normal BLACKJACK Calculation: {num3} * 2.5 = {num4}");
				}
				else
				{
					num4 = num3;
					BlackjackDoubleDownMod.Log.LogInfo((object)$"Normal TIE - Keeping original value: {num4}");
				}
				int num5 = num4 - num3;
				num += num5;
				BlackjackDoubleDownMod.Log.LogInfo((object)$"Profit for this item: {num5}");
				if (num4 != scrapItem.scrapValue)
				{
					BlackjackDoubleDownMod.Log.LogInfo((object)$"Value changed! Updating from {scrapItem.scrapValue} to {num4}");
					BlackjackReflectionCache.UpdateScrapValueClientRpcMethod.Invoke(__instance, new object[3]
					{
						(object)new NetworkBehaviourReference((NetworkBehaviour)(object)scrapItem),
						num4,
						false
					});
				}
				else
				{
					BlackjackDoubleDownMod.Log.LogInfo((object)$"No value change needed. Current: {scrapItem.scrapValue}, New: {num4}");
				}
			}
			BlackjackDoubleDownMod.Log.LogInfo((object)$"Total Profit: {num}");
			__result = num;
			return false;
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in MultiplyScrapValues_Prefix: {arg}");
			return true;
		}
	}

	private static int GetPlayerIndexForScrap(object blackjackInstance, List<GrabbableObject> scrapItems)
	{
		List<GrabbableObject>[] array = (List<GrabbableObject>[])BlackjackReflectionCache.GambledScrapField.GetValue(blackjackInstance);
		for (int i = 0; i < array.Length; i++)
		{
			if (array[i] == scrapItems)
			{
				return i;
			}
		}
		return -1;
	}
}
internal static class BlackjackDoubleDownPatcher
{
	private static int lastItemSlot = -1;

	private static float lastHintTime = 0f;

	public static void ApplyPatches(Harmony harmony, ManualLogSource log)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method(BlackjackReflectionCache.BlackjackType, "Update", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(BlackjackDoubleDownPatcher), "Update_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo methodInfo2 = AccessTools.Method(BlackjackReflectionCache.BlackjackType, "CreateBetControlsClientRpc", new Type[2]
			{
				typeof(int),
				typeof(NetworkBehaviourReference)
			}, (Type[])null);
			harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(BlackjackDoubleDownPatcher), "CreateBetControls_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			log.LogInfo((object)"Double Down patches applied successfully");
		}
		catch (Exception arg)
		{
			log.LogError((object)$"Failed to apply patches: {arg}");
		}
	}

	[HarmonyPrefix]
	public static void Update_Prefix(object __instance)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null || !(bool)BlackjackReflectionCache.GameInProgressField.GetValue(__instance))
			{
				return;
			}
			int hoveredPlayerIndex = GetHoveredPlayerIndex();
			if (hoveredPlayerIndex != -1 && IsHoveringOverBetControls(localPlayerController) && !((Object)(object)localPlayerController.hoveringOverTrigger == (Object)null))
			{
				CheckForItemSwitchAndUpdateHint(__instance, localPlayerController, hoveredPlayerIndex);
				KeyboardShortcut value = BlackjackDoubleDownMod.DoubleDownKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && CanDoubleDown(__instance, localPlayerController, hoveredPlayerIndex))
				{
					PerformDoubleDown(__instance, localPlayerController, hoveredPlayerIndex);
				}
			}
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in Update_Prefix: {arg}");
		}
	}

	private static bool IsHoveringOverBetControls(PlayerControllerB player)
	{
		InteractTrigger hoveringOverTrigger = player.hoveringOverTrigger;
		int result;
		if (hoveringOverTrigger != null)
		{
			GameObject gameObject = ((Component)hoveringOverTrigger).gameObject;
			if (((gameObject == null) ? null : ((Object)gameObject).name?.Contains("Hit")).GetValueOrDefault())
			{
				result = 1;
				goto IL_009e;
			}
		}
		InteractTrigger hoveringOverTrigger2 = player.hoveringOverTrigger;
		if (hoveringOverTrigger2 == null)
		{
			result = 0;
		}
		else
		{
			GameObject gameObject2 = ((Component)hoveringOverTrigger2).gameObject;
			result = (((gameObject2 == null) ? null : ((Object)gameObject2).name?.Contains("Stand")).GetValueOrDefault() ? 1 : 0);
		}
		goto IL_009e;
		IL_009e:
		return (byte)result != 0;
	}

	[HarmonyPostfix]
	public static void CreateBetControls_Postfix(object __instance, int playerIdx, NetworkBehaviourReference playerRef)
	{
		//IL_005c: 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)
		try
		{
			if (ShouldShowDoubleDownHint())
			{
				PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
				PlayerControllerB val = default(PlayerControllerB);
				if (!((Object)(object)localPlayerController == (Object)null) && ((NetworkBehaviourReference)(ref playerRef)).TryGet<PlayerControllerB>(ref val, (NetworkManager)null) && !((Object)(object)val != (Object)(object)localPlayerController) && CanDoubleDown(__instance, localPlayerController, playerIdx))
				{
					KeyboardShortcut value = BlackjackDoubleDownMod.DoubleDownKey.Value;
					string text = ((object)(KeyboardShortcut)(ref value)).ToString();
					HUDManager.Instance.DisplayTip("Double Down Hint", "Press [" + text + "] to double your bet and receive one card.", false, false, "LC_Tip1");
				}
			}
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in CreateBetControls_Postfix: {arg}");
		}
	}

	private static void CheckForItemSwitchAndUpdateHint(object blackjackInstance, PlayerControllerB player, int playerIndex)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (player.currentItemSlot != lastItemSlot)
			{
				lastItemSlot = player.currentItemSlot;
				if (CanDoubleDown(blackjackInstance, player, playerIndex))
				{
					KeyboardShortcut value = BlackjackDoubleDownMod.DoubleDownKey.Value;
					string text = ((object)(KeyboardShortcut)(ref value)).ToString();
					HUDManager.Instance.DisplayTip("Double Down Hint", "Press [" + text + "] to double your bet and receive one card.", false, false, "LC_Tip1");
				}
			}
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in CheckForItemSwitchAndUpdateHint: {arg}");
		}
	}

	private static bool ShouldShowDoubleDownHint()
	{
		if (Time.time - lastHintTime > 20f)
		{
			lastHintTime = Time.time;
			return true;
		}
		return false;
	}

	private static int GetLocalPlayerIndex(object blackjackInstance, PlayerControllerB localPlayer)
	{
		PlayerControllerB[] array = (PlayerControllerB[])BlackjackReflectionCache.GamblingPlayersField.GetValue(blackjackInstance);
		for (int i = 0; i < array.Length; i++)
		{
			if ((Object)(object)array[i] == (Object)(object)localPlayer)
			{
				return i;
			}
		}
		return -1;
	}

	private static int GetHoveredPlayerIndex()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null || (Object)(object)val.hoveringOverTrigger == (Object)null)
		{
			return -1;
		}
		GameObject gameObject = ((Component)val.hoveringOverTrigger).gameObject;
		if ((Object)(object)gameObject == (Object)null)
		{
			return -1;
		}
		Transform val2 = gameObject.transform;
		while ((Object)(object)val2 != (Object)null)
		{
			if (((Object)val2).name.StartsWith("Player") && ((Object)val2).name.EndsWith("HandPosition"))
			{
				string s = ((Object)val2).name.Substring(6, 1);
				if (int.TryParse(s, out var result))
				{
					return result - 1;
				}
			}
			val2 = val2.parent;
		}
		return -1;
	}

	private static bool CanDoubleDown(object blackjackInstance, PlayerControllerB player, int playerIndex)
	{
		bool[] array = (bool[])BlackjackReflectionCache.PlayerCompletedTurnField.GetValue(blackjackInstance);
		if (array[playerIndex])
		{
			return false;
		}
		IList list = (IList)BlackjackReflectionCache.PlayerCardsField.GetValue(blackjackInstance);
		if (!(list[playerIndex] is IList list2) || list2.Count != 2)
		{
			return false;
		}
		GrabbableObject val = player.ItemSlots[player.currentItemSlot];
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		Component component = ((Component)val).GetComponent(BlackjackReflectionCache.CustomScrapControllerType);
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		if (val.scrapValue <= 0)
		{
			return false;
		}
		return true;
	}

	private static void PerformDoubleDown(object blackjackInstance, PlayerControllerB player, int playerIndex)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			BlackjackDoubleDownMod.Log.LogInfo((object)$"Starting double down locally, for {player.playerUsername} at position {playerIndex}");
			GrabbableObject val = player.ItemSlots[player.currentItemSlot];
			NetworkBehaviourReference val2 = default(NetworkBehaviourReference);
			((NetworkBehaviourReference)(ref val2))..ctor((NetworkBehaviour)(object)player);
			int num = playerIndex - 1000;
			BlackjackReflectionCache.JoinGameServerRpcMethod.Invoke(blackjackInstance, new object[2] { val2, num });
			BlackjackDoubleDownMod.Log.LogInfo((object)"Double down request sent");
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in PerformDoubleDown: {arg}");
		}
	}
}
internal static class BustTracking
{
	private static HashSet<int> alreadyBustedPlayers = new HashSet<int>();

	public static void MarkPlayerBusted(int playerIdx)
	{
		alreadyBustedPlayers.Add(playerIdx);
	}

	public static bool IsPlayerAlreadyBusted(int playerIdx)
	{
		return alreadyBustedPlayers.Contains(playerIdx);
	}

	public static void Clear()
	{
		alreadyBustedPlayers.Clear();
	}
}
internal static class BlackjackProcessResultsPatcher
{
	public static void ApplyPatches(Harmony harmony, ManualLogSource log)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		//IL_0054: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method(BlackjackReflectionCache.BlackjackType, "ProcessResults", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(BlackjackProcessResultsPatcher), "ProcessResults_Prefix", (Type[])null), new HarmonyMethod(typeof(BlackjackProcessResultsPatcher), "ProcessResults_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				log.LogInfo((object)"ProcessResults patched for bust tracking cleanup");
			}
		}
		catch (Exception arg)
		{
			log.LogError((object)$"Failed to patch ProcessResults: {arg}");
		}
	}

	[HarmonyPrefix]
	public static void ProcessResults_Prefix(object __instance)
	{
		try
		{
			PlayerControllerB[] array = (PlayerControllerB[])BlackjackReflectionCache.GamblingPlayersField.GetValue(__instance);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null && BustTracking.IsPlayerAlreadyBusted(i))
				{
					BlackjackDoubleDownMod.Log.LogInfo((object)$"Removing player {i} from ProcessResults - double down bust");
					array[i] = null;
				}
			}
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in ProcessResults_Prefix: {arg}");
		}
	}

	[HarmonyPostfix]
	public static void ProcessResults_Postfix()
	{
		BustTracking.Clear();
		CustomScrapControllerPatcher.ClearAllGambledValues();
		BlackjackDoubleDownMod.Log.LogInfo((object)"Cleared bust tracking AFTER ProcessResults");
	}
}
internal static class JoinGameServerRpcPatcher
{
	public static void ApplyPatches(Harmony harmony, ManualLogSource log)
	{
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method(BlackjackReflectionCache.BlackjackType, "JoinGameServerRpc", new Type[2]
			{
				typeof(NetworkBehaviourReference),
				typeof(int)
			}, (Type[])null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(JoinGameServerRpcPatcher), "JoinGameServerRpc_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				log.LogInfo((object)"JoinGameServerRpc patched for double down support");
			}
			else
			{
				log.LogError((object)"Could not find JoinGameServerRpc method to patch!");
			}
		}
		catch (Exception arg)
		{
			log.LogError((object)$"Failed to patch JoinGameServerRpc: {arg}");
		}
	}

	[HarmonyPrefix]
	public static bool JoinGameServerRpc_Prefix(object __instance, NetworkBehaviourReference playerRef, int playerIdx)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			BlackjackDoubleDownMod.Log.LogInfo((object)$"Running JoinGameServerRPC {playerIdx}");
			if (playerIdx >= -100)
			{
				return true;
			}
			object obj = ((__instance is NetworkBehaviour) ? __instance : null);
			if (obj != null && ((NetworkBehaviour)obj).IsServer)
			{
				BlackjackDoubleDownMod.Log.LogInfo((object)"SERVER: Handling double down logic");
				int playerIdx2 = playerIdx + 1000;
				HandleDoubleDownOnServer(__instance, playerRef, playerIdx2);
				return false;
			}
			BlackjackDoubleDownMod.Log.LogInfo((object)"CLIENT: sending joinGameServerRPC double down to host");
			return true;
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in JoinGameServerRpc_Prefix: {arg}");
			return true;
		}
	}

	private static void HandleDoubleDownOnServer(object __instance, NetworkBehaviourReference playerRef, int playerIdx)
	{
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_032b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			BlackjackDoubleDownMod.Log.LogInfo((object)$"SERVER: Handling double down for player {playerIdx}");
			PlayerControllerB val = default(PlayerControllerB);
			if (!((NetworkBehaviourReference)(ref playerRef)).TryGet<PlayerControllerB>(ref val, (NetworkManager)null))
			{
				BlackjackDoubleDownMod.Log.LogError((object)"Failed to get player controller from NetworkBehaviourReference");
				return;
			}
			GrabbableObject val2 = val.ItemSlots[val.currentItemSlot];
			if ((Object)(object)val2 == (Object)null)
			{
				BlackjackDoubleDownMod.Log.LogError((object)"No held item found for double down");
				return;
			}
			Component component = ((Component)val2).GetComponent(BlackjackReflectionCache.CustomScrapControllerType);
			if ((Object)(object)component == (Object)null)
			{
				BlackjackDoubleDownMod.Log.LogError((object)"No CustomScrapController found on held item");
				return;
			}
			if ((bool)BlackjackReflectionCache.LockFromGamblingField.GetValue(component))
			{
				BlackjackReflectionCache.ShowWarningMessageClientRpcMethod.Invoke(__instance, new object[4] { val, "Cannot bet", "Scrap is already being gambled", true });
				return;
			}
			BlackjackReflectionCache.LockFromGamblingField.SetValue(component, true);
			List<GrabbableObject>[] array = (List<GrabbableObject>[])BlackjackReflectionCache.GambledScrapField.GetValue(__instance);
			if (array == null || playerIdx < 0 || playerIdx >= array.Length)
			{
				BlackjackDoubleDownMod.Log.LogError((object)"Invalid gambledScrap array or player index");
				return;
			}
			int scrapValue = val2.scrapValue;
			BlackjackReflectionCache.OriginalScrapValueField.SetValue(component, val2.scrapValue);
			BlackjackDoubleDownMod.Log.LogInfo((object)"Updated originalScrapValue field");
			int num = 0;
			foreach (GrabbableObject item in array[playerIdx])
			{
				if ((Object)(object)item != (Object)null)
				{
					Component component2 = ((Component)item).GetComponent(BlackjackReflectionCache.CustomScrapControllerType);
					if ((Object)(object)component2 != (Object)null)
					{
						int num2 = (int)BlackjackReflectionCache.OriginalScrapValueField.GetValue(component2);
						num += num2;
					}
				}
			}
			int num3 = ((num <= scrapValue) ? num : scrapValue);
			CustomScrapControllerPatcher.SetGambledValue(component, num3);
			array[playerIdx].Add(val2);
			int num4 = num + num3;
			BlackjackDoubleDownMod.Log.LogInfo((object)$"Double down total bet amount: {num4}");
			PlayerControllerB[] array2 = (PlayerControllerB[])BlackjackReflectionCache.GamblingPlayersField.GetValue(__instance);
			if (array2 == null || playerIdx >= array2.Length)
			{
				BlackjackDoubleDownMod.Log.LogError((object)"Invalid gamblingPlayers array");
				return;
			}
			BlackjackReflectionCache.JoinGameSuccessfulClientRpcMethod?.Invoke(__instance, new object[3]
			{
				(object)new NetworkBehaviourReference((NetworkBehaviour)(object)val),
				playerIdx,
				num4
			});
			BlackjackReflectionCache.DestroyBetControlsClientRpcMethod?.Invoke(__instance, new object[1] { playerIdx });
			BlackjackReflectionCache.TakeTurnAsPlayerServerRpcMethod?.Invoke(__instance, new object[3]
			{
				(object)new NetworkBehaviourReference((NetworkBehaviour)(object)val),
				playerIdx,
				"hit"
			});
			BlackjackReflectionCache.TakeTurnAsPlayerServerRpcMethod?.Invoke(__instance, new object[3]
			{
				(object)new NetworkBehaviourReference((NetworkBehaviour)(object)val),
				playerIdx,
				"stand"
			});
			BlackjackDoubleDownMod.Log.LogInfo((object)$"Double down completed successfully for player {playerIdx}");
		}
		catch (Exception arg)
		{
			BlackjackDoubleDownMod.Log.LogError((object)$"Error in HandleDoubleDownOnServer: {arg}");
		}
	}
}