Decompiled source of ScratchCash v1.0.0

Games/Cash/Cash.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using FMODUnity;
using Microsoft.CodeAnalysis;
using Mirror;
using MoreMountains.Feedbacks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;

[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("Cash")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Cash")]
[assembly: AssemblyTitle("Cash")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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]
	[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 CashMod
{
	[BepInPlugin("com.kit2soin.cash", "Cash", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class CashPlugin : BaseUnityPlugin
	{
		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Cash Assembly loaded by BepInEx! Waiting for Base Loader...");
		}
	}
}
namespace MoreGameBase
{
	public class Cash : GameBase
	{
		private class ResultData
		{
			public int multiplicator;

			public double probability;

			public int[] splitPossibilities;
		}

		private class BaseNumberData
		{
			public int number;

			public int multiplicator;
		}

		public InteractableEventTrigger playButton;

		private int numberRowCount = 4;

		private int numberColCount = 5;

		private int baseNumberCount = 20;

		private int winNumberCount = 5;

		private float waitBeforeResetTimeWin = 2f;

		private float waitBeforeResetTimeLoose = 1f;

		private bool enablePlay = true;

		private static readonly ManualLogSource LOGGER = Logger.CreateLogSource("CASH");

		private ResultData[] resultData = new ResultData[10]
		{
			new ResultData
			{
				multiplicator = 100000,
				probability = 6.360306598579585E-07,
				splitPossibilities = new int[1] { 1 }
			},
			new ResultData
			{
				multiplicator = 20000,
				probability = 3.1801532992897924E-07,
				splitPossibilities = new int[1] { 1 }
			},
			new ResultData
			{
				multiplicator = 2000,
				probability = 7.95038324822448E-07,
				splitPossibilities = new int[2] { 1, 2 }
			},
			new ResultData
			{
				multiplicator = 1000,
				probability = 1.590076649644896E-06,
				splitPossibilities = new int[1] { 1 }
			},
			new ResultData
			{
				multiplicator = 100,
				probability = 0.00047702299489346884,
				splitPossibilities = new int[1] { 1 }
			},
			new ResultData
			{
				multiplicator = 20,
				probability = 0.02830336436367915,
				splitPossibilities = new int[2] { 1, 2 }
			},
			new ResultData
			{
				multiplicator = 10,
				probability = 0.02830336436367915,
				splitPossibilities = new int[2] { 1, 2 }
			},
			new ResultData
			{
				multiplicator = 4,
				probability = 0.10176490557727336,
				splitPossibilities = new int[4] { 1, 2, 3, 4 }
			},
			new ResultData
			{
				multiplicator = 2,
				probability = 0.45317438927143483,
				splitPossibilities = new int[2] { 1, 2 }
			},
			new ResultData
			{
				multiplicator = 1,
				probability = 0.3879736142680758,
				splitPossibilities = new int[1] { 1 }
			}
		};

		private static Random RNG = new Random();

		private Coroutine? drawingCoroutine = null;

		public GameObject ticketPrefab;

		public Transform ticketPoint;

		public Camera resultCam;

		public BoxCollider hitTarget;

		public int hitTargetLayerMask;

		public SpriteMask mask;

		public int spriteWidth = 828;

		public int spriteHeight = 552;

		public int spritePixelPerUnit = 100;

		public int brushSize = 45;

		public float finishedThreshold = 0.98f;

		private Transform? ticket;

		private Vector2 extents;

		private int halfBrushSize;

		private Color32[] brushPixels;

		private Texture2D texture;

		private HashSet<Vector2> drawPosToShare = new HashSet<Vector2>();

		private int totalVisiblePixels;

		private bool enableScratch;

		private bool textureNeedRedraw;

		private Color32 transparent = Color32.op_Implicit(new Color(0f, 0f, 0f, 0f));

		private Color32 nonTransparent = Color32.op_Implicit(new Color(1f, 1f, 1f, 1f));

		private Action? onCardFullyRevealed;

		private InteractableEventTrigger iet;

		public Color goldenColor = new Color(1f, 0.68f, 0f, 1f);

		public EventReference winSFX;

		public EventReference loseSFX;

		public EventReference tieSFX;

		private ParticleSystem winVFX;

		private ParticleSystem loseVFX;

		private ParticleSystem tieVFX;

		private void Timeout(float duration, Action callback)
		{
			((MonoBehaviour)this).StartCoroutine(RunTimeout(duration, callback));
		}

		private IEnumerator RunTimeout(float duration, Action callback)
		{
			yield return (object)new WaitForSeconds(duration);
			callback();
			yield return null;
		}

		private void Start()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00bc: 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)
			playButton.onInteractEvent.AddListener((UnityAction<PlayerInteract>)delegate
			{
				((MMFeedbacks)((Component)((Component)playButton).transform.Find("Feedbacks/PressFB")).gameObject.GetComponent<MMF_Player>()).PlayFeedbacks();
			});
			playButton.serverOnInteractEvent.AddListener((UnityAction<PlayerInteract>)((GameBase)this).TryStartGame);
			extents = new Vector2((float)spriteWidth / (float)spritePixelPerUnit / 2f, (float)spriteHeight / (float)spritePixelPerUnit / 2f);
			texture = new Texture2D(spriteWidth, spriteHeight, (TextureFormat)4, false);
			halfBrushSize = brushSize / 2;
			brushPixels = (Color32[])(object)new Color32[brushSize * brushSize];
			for (int num = 0; num < brushPixels.Length; num++)
			{
				brushPixels[num] = nonTransparent;
			}
			ticketPoint = ((Component)this).transform.Find("Model/TicketPoint");
			winVFX = ((Component)((Component)this).transform.Find("Feedbacks/GameWinVFX")).gameObject.GetComponent<ParticleSystem>();
			loseVFX = ((Component)((Component)this).transform.Find("Feedbacks/GameLoseVFX")).gameObject.GetComponent<ParticleSystem>();
			tieVFX = ((Component)((Component)this).transform.Find("Feedbacks/GameTieVFX")).gameObject.GetComponent<ParticleSystem>();
			base.gameFeedbacks = ((Component)this).GetComponent<CasinoGameFeedbacks>();
			if (NetworkServer.active)
			{
				NetworkServer.RegisterHandler<ScratchMessage>((Action<NetworkConnectionToClient, ScratchMessage>)HandleScratchMessage, true);
				NetworkServer.RegisterHandler<CardFinishedMessage>((Action<NetworkConnectionToClient, CardFinishedMessage>)HandleCardFinishedMessage, true);
			}
			CustomReadWriteFunctions.Register();
		}

		public override void OnStartServer()
		{
			((GameBase)this).OnStartServer();
		}

		public override void TryStartGame(PlayerInteract playerInteract)
		{
			if (!base.isPlaying && enablePlay)
			{
				((GameBase)this).TryStartGame(playerInteract);
			}
		}

		protected override void StartGame()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			((GameBase)this).StartGame();
			ResultData result = GetRandomWin();
			bool win = result != null;
			int[] randomisedNumbers = GetRandomisedNumbers();
			int[] array = new int[winNumberCount];
			int[] matchingWinNumbers = null;
			BaseNumberData[] array2 = new BaseNumberData[baseNumberCount];
			int num = 0;
			if (win)
			{
				int[] randomWinSplit = GetRandomWinSplit(result);
				matchingWinNumbers = new int[randomWinSplit.Length];
				num = randomWinSplit.Length;
				for (int i = 0; i < randomWinSplit.Length; i++)
				{
					array[i] = randomisedNumbers[i];
					matchingWinNumbers[i] = array[i];
					array2[i] = new BaseNumberData
					{
						number = randomisedNumbers[i],
						multiplicator = randomWinSplit[i]
					};
				}
			}
			for (int j = num; j < winNumberCount; j++)
			{
				array[j] = randomisedNumbers[j];
			}
			for (int k = 0; k < baseNumberCount - num; k++)
			{
				ResultData resultData = this.resultData[Random.Range(0, this.resultData.Length)];
				array2[num + k] = new BaseNumberData
				{
					number = randomisedNumbers[winNumberCount + k],
					multiplicator = resultData.multiplicator
				};
			}
			array2 = ShuffleList(array2);
			array = ShuffleList(array);
			enableScratch = true;
			enablePlay = false;
			onCardFullyRevealed = delegate
			{
				LOGGER.LogInfo((object)$"CardFullyRevealed - enableScratch={enableScratch}  || ticket={ticket} || onCardFullyRevealed={onCardFullyRevealed}");
				double multiplicator = (win ? ((double)result.multiplicator) : 0.0);
				BroadcastMatchingWinNumbersFeedback(matchingWinNumbers);
				Timeout(win ? waitBeforeResetTimeWin : waitBeforeResetTimeLoose, delegate
				{
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					((GameBase)this).Payout(multiplicator, (ChangeType)1, (Dictionary<string, object>)null, (BigNumber?)((GameBase)this).currentBet);
					BroadcastPlayGameResultFeedback(multiplicator);
					Timeout(0.5f, delegate
					{
						BroadcastResetGame();
						((GameBase)this).ResetGame();
						Timeout(0.5f, delegate
						{
							enablePlay = true;
						});
					});
				});
			};
			BroadcastNewTicket(array2, array);
		}

		private T[] ShuffleList<T>(T[] list)
		{
			return list.OrderBy((T _) => RNG.Next()).ToArray();
		}

		private ResultData? GetRandomWin()
		{
			if (RNG.NextDouble() > 0.262041875)
			{
				return null;
			}
			double num = RNG.NextDouble();
			int num2 = Random.Range(0, resultData.Length);
			while (true)
			{
				num -= resultData[num2].probability;
				if (num <= 0.0)
				{
					break;
				}
				num2 = (num2 + 1) % resultData.Length;
			}
			return resultData[num2];
		}

		private int[] GetRandomisedNumbers()
		{
			int[] list = new int[40]
			{
				1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
				11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
				21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
				31, 32, 33, 34, 35, 36, 37, 38, 39, 40
			};
			return ShuffleList(list);
		}

		private int[] GetRandomWinSplit(ResultData result)
		{
			int num = result.splitPossibilities[Random.Range(0, result.splitPossibilities.Length)];
			int[] array = new int[num];
			int num2 = result.multiplicator;
			for (int num3 = num; num3 > 0; num3--)
			{
				array[num3 - 1] = num2 / num3;
				num2 -= array[num3 - 1];
			}
			return array;
		}

		public void CardFullyRevealed()
		{
			LOGGER.LogInfo((object)$"CardFullyRevealed - enableScratch={enableScratch}  || ticket={ticket} || onCardFullyRevealed={onCardFullyRevealed}");
			if (enableScratch && !((Object)(object)ticket == (Object)null) && onCardFullyRevealed != null)
			{
				enableScratch = false;
				onCardFullyRevealed?.Invoke();
			}
		}

		private void NewTicket()
		{
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			ticket = Object.Instantiate<GameObject>(ticketPrefab).transform;
			ticket.SetParent(ticketPoint, false);
			resultCam = ((Component)ticket.Find("ResultCam")).gameObject.GetComponent<Camera>();
			totalVisiblePixels = CountVisiblePixels(ScreenAsSprite(resultCam));
			hitTarget = ((Component)ticket).GetComponent<BoxCollider>();
			hitTargetLayerMask = LayerMask.GetMask(new string[1] { "Default" });
			iet = (InteractableEventTrigger)(object)((Component)ticket).gameObject.AddComponent<CustomInteractableHold>();
			iet.onHoldEvent.AddListener((UnityAction<PlayerInteract>)OnHoldToScratch);
			iet.onHoldExitEvent.AddListener((UnityAction<PlayerInteract>)OnExitHoldToScratch);
			mask = ((Component)ticket.Find("SpriteMask")).gameObject.GetComponent<SpriteMask>();
			mask.sprite = Sprite.Create(texture, new Rect(0f, 0f, (float)spriteWidth, (float)spriteHeight), new Vector2(0.5f, 0.5f), (float)spritePixelPerUnit);
		}

		private void OnHoldToScratch(PlayerInteract pi)
		{
			Camera[] componentsInChildren = ((Component)pi).GetComponentsInChildren<Camera>();
			foreach (Camera val in componentsInChildren)
			{
				if (((Object)val).name == "Camera(Clone)")
				{
					StartScratch(val);
					break;
				}
			}
		}

		private void OnExitHoldToScratch(PlayerInteract _)
		{
			StopScratch();
		}

		private unsafe void InitTicket(BaseNumberData[] baseNumbers, int[] winNumbers)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			ResetScratchTexture();
			Transform val = ((Component)this).transform.Find("Model/TicketPoint/TicketPrefab(Clone)");
			BigNumber val2 = ((GameBase)this).currentBet;
			if (((GameBase)this).currentBet == ((GameBase)this).MinBet || ((GameBase)this).currentBet < BigNumber.op_Implicit(1))
			{
				val2 = BigNumber.Parse(((object)(*(BigNumber*)(&val2))/*cast due to .constrained prefix*/).ToString());
			}
			for (int i = 0; i < numberRowCount; i++)
			{
				Transform val3 = val.Find($"Numbers/BaseNumbers/Row{i}");
				for (int j = 0; j < numberColCount; j++)
				{
					Transform val4 = val3.Find($"{j}");
					BaseNumberData baseNumberData = baseNumbers[i * numberColCount + j];
					BigNumber val5 = baseNumberData.multiplicator * val2;
					((TMP_Text)((Component)val4.Find("Number")).gameObject.GetComponent<TextMeshPro>()).text = baseNumberData.number.ToString();
					((TMP_Text)((Component)val4.Find("Multiplicator")).gameObject.GetComponent<TextMeshPro>()).text = "x" + NumberToSpacedString(baseNumberData.multiplicator);
					((TMP_Text)((Component)val4.Find("Gain")).gameObject.GetComponent<TextMeshPro>()).text = $"${val5}";
				}
			}
			Transform val6 = val.Find("Numbers/WinNumbers");
			for (int k = 0; k < winNumberCount; k++)
			{
				((TMP_Text)((Component)val6.Find($"{k}")).gameObject.GetComponent<TextMeshPro>()).text = winNumbers[k].ToString();
			}
		}

		private string NumberToSpacedString(int n)
		{
			string text = n.ToString();
			if (text.Length > 3)
			{
				text = text.Insert(text.Length - 3, " ");
			}
			return text;
		}

		private void RemoveTicket()
		{
			Transform? obj = ticket;
			if (obj != null)
			{
				obj.SetParent((Transform)null);
			}
			Transform? obj2 = ticket;
			Object.Destroy((Object)(object)((obj2 != null) ? ((Component)obj2).gameObject : null));
			ticket = null;
			onCardFullyRevealed = null;
		}

		private void StartScratch(Camera playerCamera)
		{
			StopScratch();
			drawingCoroutine = ((MonoBehaviour)this).StartCoroutine(ScratchRayCast(playerCamera));
		}

		private void StopScratch()
		{
			if (drawingCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(drawingCoroutine);
				drawingCoroutine = null;
				if (GetTotalScratched() >= (double)finishedThreshold)
				{
					CmdCardFinished();
				}
			}
		}

		private IEnumerator ScratchRayCast(Camera playerCamera)
		{
			while (true)
			{
				Ray ray = new Ray(((Component)playerCamera).transform.position, ((Component)playerCamera).transform.forward);
				RaycastHit[] hits = (from val in Physics.RaycastAll(ray, float.PositiveInfinity, hitTargetLayerMask)
					where (Object)(object)((RaycastHit)(ref val)).collider == (Object)(object)hitTarget
					select val).ToArray();
				if (hits.Length != 0)
				{
					Vector3 localHit = ((Component)hitTarget).transform.InverseTransformPoint(((RaycastHit)(ref hits[0])).point);
					int x = (int)((localHit.x * -1f + extents.x) * (float)spritePixelPerUnit);
					int y = (int)((localHit.y + extents.y) * (float)spritePixelPerUnit);
					drawPosToShare.Add(new Vector2((float)x, (float)y));
				}
				yield return null;
			}
		}

		private void Scratch(int x, int y)
		{
			int num = Math.Max(x - halfBrushSize, 0);
			int num2 = Math.Max(y - halfBrushSize, 0);
			int num3 = ((num + brushSize >= spriteWidth) ? (spriteWidth - num) : brushSize);
			int num4 = ((num2 + brushSize >= spriteHeight) ? (spriteHeight - num2) : brushSize);
			texture.SetPixels32(num, num2, num3, num4, brushPixels);
			textureNeedRedraw = true;
		}

		private void Update()
		{
			if (drawPosToShare.Count > 0)
			{
				CmdSratch(drawPosToShare.ToArray());
				drawPosToShare.Clear();
			}
			if (textureNeedRedraw)
			{
				textureNeedRedraw = false;
				texture.Apply(false);
			}
		}

		private void ResetScratchTexture()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Color32[] array = (Color32[])(object)new Color32[spriteWidth * spriteHeight];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = transparent;
			}
			texture.SetPixels32(array);
			texture.Apply(false);
		}

		private Sprite ScreenAsSprite(Camera cam)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture val = new RenderTexture(Screen.width, Screen.height, 24);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(0f, 0f, (float)Screen.width, (float)Screen.height);
			Texture2D val3 = new Texture2D(Screen.width, Screen.height, (TextureFormat)4, false);
			cam.targetTexture = val;
			cam.Render();
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = val;
			val3.ReadPixels(val2, 0, 0);
			val3.Apply();
			cam.targetTexture = null;
			RenderTexture.active = active;
			Object.Destroy((Object)(object)val);
			return Sprite.Create(val3, val2, new Vector2(0.5f, 0.5f), (float)spritePixelPerUnit);
		}

		private int CountVisiblePixels(Sprite sprite)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			Color32[] pixels = sprite.texture.GetPixels32();
			foreach (Color32 val in pixels)
			{
				if (val.a > 0)
				{
					num++;
				}
			}
			return num;
		}

		private double GetTotalScratched()
		{
			int num = CountVisiblePixels(ScreenAsSprite(resultCam));
			return 1.0 - (double)num / (double)totalVisiblePixels;
		}

		private void PlayMatchingWinNumbersFeedback(string[]? matchingWinNumbers)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			if (matchingWinNumbers == null)
			{
				return;
			}
			Transform val = ((Component)this).transform.Find("Model/TicketPoint/TicketPrefab(Clone)");
			for (int i = 0; i < numberRowCount; i++)
			{
				Transform val2 = val.Find($"Numbers/BaseNumbers/Row{i}");
				for (int j = 0; j < numberColCount; j++)
				{
					Transform val3 = val2.Find($"{j}");
					TextMeshPro component = ((Component)val3.Find("Number")).gameObject.GetComponent<TextMeshPro>();
					if (matchingWinNumbers.Contains(((TMP_Text)component).text))
					{
						((TMP_Text)component).color = goldenColor;
						((TMP_Text)((Component)val3.Find("Multiplicator")).gameObject.GetComponent<TextMeshPro>()).color = goldenColor;
						((TMP_Text)((Component)val3.Find("Gain")).gameObject.GetComponent<TextMeshPro>()).color = goldenColor;
					}
				}
			}
			Transform val4 = val.Find("Numbers/WinNumbers");
			for (int k = 0; k < winNumberCount; k++)
			{
				TextMeshPro component2 = ((Component)val4.Find($"{k}")).gameObject.GetComponent<TextMeshPro>();
				if (matchingWinNumbers.Contains(((TMP_Text)component2).text))
				{
					((TMP_Text)component2).color = goldenColor;
				}
			}
		}

		private void PlayGameResultFeedback(double multiplier)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			if (multiplier < 1.0)
			{
				loseVFX.Play(true);
				SFXManager.SFXOneShot(winSFX, ((Component)this).transform.position);
			}
			else if (multiplier > 1.0)
			{
				winVFX.Play(true);
				SFXManager.SFXOneShot(loseSFX, ((Component)this).transform.position);
			}
			else
			{
				tieVFX.Play(true);
				SFXManager.SFXOneShot(tieSFX, ((Component)this).transform.position);
			}
		}

		private void Broadcast(string methodName, string param)
		{
			if (NetworkServer.active)
			{
				string text = "System.Void MoreGameBase.Cash::" + methodName + "(System.String)";
				int stableHashCode = Extensions.GetStableHashCode(text);
				NetworkWriterPooled val = NetworkWriterPool.Get();
				NetworkWriterExtensions.WriteString((NetworkWriter)(object)val, param);
				((NetworkBehaviour)this).SendRPCInternal(text, stableHashCode, (NetworkWriter)(object)val, 0, true);
				NetworkWriterPool.Return(val);
			}
		}

		private void BroadcastNewTicket(BaseNumberData[] baseNumbers, int[] winNumbers)
		{
			string param = string.Join(':', baseNumbers.Select((BaseNumberData x) => $"{x.number}/{x.multiplicator}").ToArray()) + ";" + string.Join(':', winNumbers);
			Broadcast("UserRpcNewTicket", param);
		}

		public void UserRpcNewTicket(string message)
		{
			if (NetworkClient.active)
			{
				string[] array = message.Split(';');
				BaseNumberData[] baseNumbers = (from x in array[0].Split(':')
					select x.Split('/') into x
					select new BaseNumberData
					{
						number = int.Parse(x[0]),
						multiplicator = int.Parse(x[1])
					}).ToArray();
				int[] winNumbers = (from x in array[1].Split(':')
					select int.Parse(x)).ToArray();
				NewTicket();
				InitTicket(baseNumbers, winNumbers);
			}
		}

		private void BroadcastResetGame()
		{
			Broadcast("UserRpcResetGame", "");
		}

		public void UserRpcResetGame(string _)
		{
			if (NetworkClient.active)
			{
				RemoveTicket();
			}
		}

		private void CmdSratch(Vector2[] drawPosList)
		{
			if (NetworkClient.active)
			{
				NetworkClient.Send<ScratchMessage>(new ScratchMessage
				{
					netId = ((NetworkBehaviour)this).netId,
					componentIndex = ((NetworkBehaviour)this).ComponentIndex,
					drawPosList = drawPosList
				}, 0);
			}
		}

		private void HandleScratchMessage(NetworkConnectionToClient _, ScratchMessage msg)
		{
			if (NetworkServer.active && NetworkServer.spawned.TryGetValue(msg.netId, out var value))
			{
				((Component)value.NetworkBehaviours[msg.componentIndex]).GetComponent<Cash>()?.BroadcastScratch(msg.drawPosList);
			}
		}

		public void BroadcastScratch(Vector2[] drawPosList)
		{
			if (enableScratch)
			{
				string text = $"{drawPosList[0].x}:{drawPosList[0].y}";
				for (int i = 1; i < drawPosList.Length; i++)
				{
					text += $";{drawPosList[i].x}:{drawPosList[i].y}";
				}
				Broadcast("UserRpcScratch", text);
			}
		}

		public void UserRpcScratch(string message)
		{
			if (NetworkClient.active)
			{
				string[] array = message.Split(';');
				string[] array2 = array;
				foreach (string text in array2)
				{
					string[] array3 = text.Split(':');
					Scratch(int.Parse(array3[0]), int.Parse(array3[1]));
				}
			}
		}

		private void CmdCardFinished()
		{
			LOGGER.LogInfo((object)"CmdCardFinished");
			if (NetworkClient.active)
			{
				NetworkClient.Send<CardFinishedMessage>(new CardFinishedMessage
				{
					netId = ((NetworkBehaviour)this).netId,
					componentIndex = ((NetworkBehaviour)this).ComponentIndex
				}, 0);
			}
		}

		private void HandleCardFinishedMessage(NetworkConnectionToClient _, CardFinishedMessage msg)
		{
			if (NetworkServer.active && NetworkServer.spawned.TryGetValue(msg.netId, out var value))
			{
				LOGGER.LogInfo((object)$"HandleCardFinishedMessage - enableScratch={enableScratch}  || ticket={ticket} || onCardFullyRevealed={onCardFullyRevealed}");
				((Component)value.NetworkBehaviours[msg.componentIndex]).GetComponent<Cash>()?.CardFullyRevealed();
			}
		}

		private void BroadcastMatchingWinNumbersFeedback(int[]? matchingWinNumbers)
		{
			Broadcast("UserRpcMatchingWinNumbersFeedback", (matchingWinNumbers != null) ? string.Join(':', matchingWinNumbers) : "null");
		}

		public void UserRpcMatchingWinNumbersFeedback(string message)
		{
			if (NetworkClient.active)
			{
				string[] matchingWinNumbers = (message.Equals("null") ? null : message.Split(':'));
				PlayMatchingWinNumbersFeedback(matchingWinNumbers);
			}
		}

		private void BroadcastPlayGameResultFeedback(double multiplier)
		{
			Broadcast("UserRpcPlayGameResultFeedback", multiplier.ToString());
		}

		public void UserRpcPlayGameResultFeedback(string message)
		{
			if (NetworkClient.active)
			{
				PlayGameResultFeedback(double.Parse(message));
			}
		}
	}
	public class CustomInteractableHold : InteractableEventTrigger
	{
		protected override void OnAwake()
		{
			((InteractableBase)this).OnAwake();
			base.onHoldEvent = new UnityEvent<PlayerInteract>();
			base.onHoldExitEvent = new UnityEvent<PlayerInteract>();
			((InteractableBase)this).HoldInteract = true;
			((InteractableBase)this).HoldDuration = 999999f;
			((InteractableBase)this).TooltipMessage = "Hold to scratch";
			((InteractableBase)this).InteractableName = "Ticket";
			((InteractableBase)this).CursorType = (CursorType)0;
		}

		public override void OnInteract(PlayerInteract playerInteract)
		{
		}

		public override void ServerOnInteract(PlayerInteract playerInteract)
		{
		}

		public override void RpcOnInteract(PlayerInteract playerInteract)
		{
		}

		public override void OnHover(PlayerInteract playerInteract)
		{
		}

		public override void OnHoverExit(PlayerInteract playerInteract)
		{
			((InteractableBase)this).OnHoldExit(playerInteract);
		}

		public override void OnHold(PlayerInteract playerInteract)
		{
			if (!((InteractableBase)this).IsBeingHold)
			{
				((InteractableBase)this).IsBeingHold = true;
				base.onHoldEvent?.Invoke(playerInteract);
			}
		}

		public override void OnHoldExit(PlayerInteract playerInteract)
		{
			if (((InteractableBase)this).IsBeingHold)
			{
				((InteractableBase)this).IsBeingHold = false;
				base.onHoldExitEvent?.Invoke(playerInteract);
			}
		}
	}
	public struct ScratchMessage : NetworkMessage
	{
		public uint netId;

		public byte componentIndex;

		public Vector2[] drawPosList;
	}
	public struct CardFinishedMessage : NetworkMessage
	{
		public uint netId;

		public byte componentIndex;
	}
	public static class CustomReadWriteFunctions
	{
		public static void Register()
		{
			Writer<ScratchMessage>.write = WriteScratch;
			Reader<ScratchMessage>.read = ReadScratch;
			Writer<CardFinishedMessage>.write = WriteCardFinished;
			Reader<CardFinishedMessage>.read = ReadCardFinished;
		}

		public static void WriteScratch(this NetworkWriter writer, ScratchMessage value)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			writer.Write<uint>(value.netId);
			writer.Write<byte>(value.componentIndex);
			writer.Write<int>(value.drawPosList.Length);
			Vector2[] drawPosList = value.drawPosList;
			foreach (Vector2 val in drawPosList)
			{
				writer.Write<Vector2>(val);
			}
		}

		public static ScratchMessage ReadScratch(this NetworkReader reader)
		{
			//IL_0043: 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)
			ScratchMessage result = new ScratchMessage
			{
				netId = reader.Read<uint>(),
				componentIndex = reader.Read<byte>(),
				drawPosList = (Vector2[])(object)new Vector2[reader.Read<int>()]
			};
			for (int i = 0; i < result.drawPosList.Length; i++)
			{
				result.drawPosList[i] = reader.Read<Vector2>();
			}
			return result;
		}

		public static void WriteCardFinished(this NetworkWriter writer, CardFinishedMessage value)
		{
			writer.Write<uint>(value.netId);
			writer.Write<byte>(value.componentIndex);
		}

		public static CardFinishedMessage ReadCardFinished(this NetworkReader reader)
		{
			return new CardFinishedMessage
			{
				netId = reader.Read<uint>(),
				componentIndex = reader.Read<byte>()
			};
		}
	}
}