Decompiled source of DoubleOrNothing v0.1.5

plugins/HowToFish.CoinFlip.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Managing.Client;
using FishNet.Managing.Object;
using FishNet.Managing.Server;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Localization.Components;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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 = "")]
[assembly: AssemblyCompany("HowToFish.CoinFlip")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.5.0")]
[assembly: AssemblyInformationalVersion("0.1.5")]
[assembly: AssemblyProduct("HowToFish.CoinFlip")]
[assembly: AssemblyTitle("HowToFish.CoinFlip")]
[assembly: AssemblyVersion("0.1.5.0")]
namespace HowToFish.CoinFlip;

internal static class CoinAnim
{
	private static readonly FieldInfo AnimField = typeof(Tool).GetField("_anim", BindingFlags.Instance | BindingFlags.NonPublic);

	internal static AnimationClip FlipClip;

	internal static AnimationClip HoldClip;

	private static readonly List<float[]> _flipCoin = new List<float[]>();

	private static readonly List<float[]> _holdCoin = new List<float[]>();

	private static float _fps = 30f;

	private static bool _loadFailed;

	private static GameObject _coin;

	private static Transform _wrist;

	private static Animation _anim;

	private static Item _heldCoin;

	private static bool _tails;

	private const float TailsSwitchFrame = 42f;

	private const float SnatchClosedFrame = 114f;

	private const float RevealFrame = 80f;

	private static bool _revealFired;

	private static readonly List<float[]> _flipWrist = new List<float[]>();

	private static readonly List<float[]> _holdWrist = new List<float[]>();

	private static Mesh _cachedMesh;

	private static Material _cachedMat;

	private static bool _outcomeKnown;

	private static int _outcomeBetId = -1;

	private const float OutcomeDeadlineFrame = 40f;

	internal static int FlipKeyCount => _flipCoin.Count;

	internal static event Action<bool> OnFlipRevealed;

	internal static float[] SampleFlipCoin(float frames)
	{
		return Sample(_flipCoin, frames, clamp: true);
	}

	internal static float[] SampleHoldCoin(float frames)
	{
		return Sample(_holdCoin, frames, clamp: false);
	}

	internal static float[] SampleFlipWrist(float frames)
	{
		return Sample(_flipWrist, frames, clamp: true);
	}

	internal static float[] SampleHoldWrist(float frames)
	{
		return Sample(_holdWrist, frames, clamp: false);
	}

	internal static Material SharedCoinMaterial()
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_cachedMat != (Object)null)
		{
			return _cachedMat;
		}
		Shader val = Shader.Find("Universal Render Pipeline/Lit");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Sprites/Default");
		}
		_cachedMat = new Material(val);
		Texture2D val2 = LoadCoinTexture();
		if ((Object)(object)val2 != (Object)null)
		{
			if (_cachedMat.HasProperty("_BaseMap"))
			{
				_cachedMat.SetTexture("_BaseMap", (Texture)(object)val2);
			}
			_cachedMat.mainTexture = (Texture)(object)val2;
		}
		if (_cachedMat.HasProperty("_BaseColor"))
		{
			_cachedMat.SetColor("_BaseColor", Color.white);
		}
		if (_cachedMat.HasProperty("_Metallic"))
		{
			_cachedMat.SetFloat("_Metallic", 0f);
		}
		if (_cachedMat.HasProperty("_Smoothness"))
		{
			_cachedMat.SetFloat("_Smoothness", 0.05f);
		}
		return _cachedMat;
	}

	internal static void Tick()
	{
		Player localPlayer = Player.LocalPlayer;
		Item val = (((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.Holding != (Object)null) ? localPlayer.Holding.HeldItem : null);
		if (!((Object)(object)val != (Object)null) || val.ID != 201)
		{
			if ((Object)(object)_heldCoin != (Object)null)
			{
				Detach();
			}
			return;
		}
		if ((Object)(object)_heldCoin != (Object)(object)val)
		{
			Attach(val);
		}
		if (!((Object)(object)_anim == (Object)null))
		{
			AnimationState val2 = _anim["Flip"];
			if ((TrackedReference)(object)val2 != (TrackedReference)null && _anim.IsPlaying("Flip") && val2.time >= FlipClip.length - 0.001f)
			{
				_anim.Play("Idle");
			}
		}
	}

	private static void Attach(Item held)
	{
		_heldCoin = held;
		Tool val = (Tool)(object)((held is Tool) ? held : null);
		_anim = (Animation)(((Object)(object)val != (Object)null && AnimField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if ((Object)(object)_anim == (Object)null)
		{
			_anim = ((Component)held).GetComponentInChildren<Animation>(true);
		}
		EnsureCoinProp();
		if ((Object)(object)_coin != (Object)null)
		{
			_coin.SetActive(true);
		}
	}

	private static void Detach()
	{
		_heldCoin = null;
		_anim = null;
		_wrist = null;
		if ((Object)(object)_coin != (Object)null)
		{
			_coin.SetActive(false);
		}
		CoinHintPatch.Hide();
	}

	internal static void TriggerFlip(Item held)
	{
		if ((Object)(object)_heldCoin != (Object)(object)held)
		{
			Attach(held);
		}
		if (!((Object)(object)_anim == (Object)null) && !((Object)(object)_anim.GetClip("Flip") == (Object)null) && !_anim.IsPlaying("Flip"))
		{
			_anim.CrossFade("Flip", 0.08f);
			_anim["Flip"].time = 0f;
			_revealFired = false;
			CoinGamble.LockBet();
			_tails = false;
			_outcomeKnown = false;
			CoinGamble.ArmResolve(_tails, 80f / _fps);
			_outcomeBetId = CoinGamble.LastArmedBetId;
			CoinAudio.OnFlipStarted();
			CoinNet.SendFlipStarted();
			if (_outcomeBetId < 0)
			{
				_tails = Random.value < 0.5f;
				_outcomeKnown = true;
			}
			Plugin.Log.Info("Coin flip started" + ((_outcomeBetId >= 0) ? (" (bet " + _outcomeBetId + ", waiting for the host's roll)") : ""));
		}
	}

	internal static void SetOutcome(int betItemId, bool tails)
	{
		if (!_outcomeKnown && betItemId == _outcomeBetId)
		{
			_tails = tails;
			_outcomeKnown = true;
			CoinGamble.SetPendingOutcome(betItemId, tails);
			Plugin.Log.Info("Coin flip -> " + (tails ? "TAILS" : "HEADS") + " (host's roll)");
		}
	}

	internal static void LateTick()
	{
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_coin == (Object)null || !_coin.activeSelf || (Object)(object)_wrist == (Object)null || (Object)(object)_anim == (Object)null)
		{
			return;
		}
		bool flag = _anim.IsPlaying("Flip");
		float num = 0f;
		float[] array;
		if (flag)
		{
			num = _anim["Flip"].time * _fps;
			array = Sample(_flipCoin, num, clamp: true);
			CoinAudio.Tick(num);
			if (!_outcomeKnown && num >= 40f)
			{
				_tails = Random.value < 0.5f;
				_outcomeKnown = true;
				CoinGamble.SetPendingOutcome(_outcomeBetId, _tails);
				Plugin.Log.Warn("Coin flip -> " + (_tails ? "TAILS" : "HEADS") + " (no roll from the host in time, local fallback)");
			}
			if (!_revealFired && num >= 80f)
			{
				_revealFired = true;
				CoinAnim.OnFlipRevealed?.Invoke(_tails);
			}
		}
		else
		{
			AnimationState val = _anim["Idle"];
			float num2 = (((TrackedReference)(object)val != (TrackedReference)null) ? val.time : Time.time);
			array = Sample(_holdCoin, num2 * _fps, clamp: false);
		}
		_coin.transform.position = _wrist.position + _wrist.rotation * new Vector3(array[0], array[1], array[2]);
		Quaternion val2 = _wrist.rotation * new Quaternion(array[3], array[4], array[5], array[6]);
		if (_tails && flag && num >= 42f && num < 114f)
		{
			val2 *= Quaternion.AngleAxis(180f, Vector3.forward);
		}
		_coin.transform.rotation = val2;
		_coin.transform.localScale = new Vector3(array[7], array[8], array[9]);
	}

	private static float[] Sample(List<float[]> keys, float fi, bool clamp)
	{
		//IL_007c: 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)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		if (keys.Count == 0)
		{
			return new float[10];
		}
		fi = (clamp ? Mathf.Clamp(fi, 0f, (float)keys.Count - 1.001f) : Mathf.Repeat(fi, (float)(keys.Count - 1)));
		int num = (int)fi;
		float num2 = fi - (float)num;
		float[] array = keys[num];
		float[] array2 = keys[Mathf.Min(num + 1, keys.Count - 1)];
		Vector3 val = Vector3.Lerp(new Vector3(array[0], array[1], array[2]), new Vector3(array2[0], array2[1], array2[2]), num2);
		Quaternion val2 = Quaternion.Slerp(new Quaternion(array[3], array[4], array[5], array[6]), new Quaternion(array2[3], array2[4], array2[5], array2[6]), num2);
		if (array.Length < 10)
		{
			return new float[7] { val.x, val.y, val.z, val2.x, val2.y, val2.z, val2.w };
		}
		Vector3 val3 = Vector3.Lerp(new Vector3(array[7], array[8], array[9]), new Vector3(array2[7], array2[8], array2[9]), num2);
		return new float[10] { val.x, val.y, val.z, val2.x, val2.y, val2.z, val2.w, val3.x, val3.y, val3.z };
	}

	private static void EnsureCoinProp()
	{
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Expected O, but got Unknown
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Expected O, but got Unknown
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Expected O, but got Unknown
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_anim == (Object)null)
		{
			_wrist = null;
			return;
		}
		Transform transform = ((Component)_anim).transform;
		_wrist = transform.Find("Hands/r_IK");
		if ((Object)(object)_wrist == (Object)null)
		{
			Plugin.Log.Warn("Coin: no Hands/r_IK under anim root");
		}
		else
		{
			if ((Object)(object)_coin != (Object)null && (Object)(object)_coin.transform.parent == (Object)(object)transform)
			{
				return;
			}
			if ((Object)(object)_coin != (Object)null)
			{
				Object.Destroy((Object)(object)_coin);
			}
			_coin = new GameObject("CoinProp");
			_coin.transform.SetParent(transform, false);
			GameObject val = new GameObject("CoinMesh");
			val.transform.SetParent(_coin.transform, false);
			val.AddComponent<MeshFilter>().sharedMesh = LoadCoinMesh();
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			Shader val3 = Shader.Find("Universal Render Pipeline/Lit");
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = Shader.Find("Sprites/Default");
			}
			Material val4 = new Material(val3);
			Texture2D val5 = LoadCoinTexture();
			if ((Object)(object)val5 != (Object)null)
			{
				if (val4.HasProperty("_BaseMap"))
				{
					val4.SetTexture("_BaseMap", (Texture)(object)val5);
				}
				val4.mainTexture = (Texture)(object)val5;
			}
			if (val4.HasProperty("_BaseColor"))
			{
				val4.SetColor("_BaseColor", Color.white);
			}
			if (val4.HasProperty("_Metallic"))
			{
				val4.SetFloat("_Metallic", 0f);
			}
			if (val4.HasProperty("_Smoothness"))
			{
				val4.SetFloat("_Smoothness", 0.05f);
			}
			((Renderer)val2).material = val4;
			int layer = ((Component)transform).gameObject.layer;
			_coin.layer = layer;
			val.layer = layer;
		}
	}

	internal static bool EnsureLoaded()
	{
		if (_loadFailed)
		{
			return false;
		}
		if ((Object)(object)FlipClip != (Object)null && (Object)(object)HoldClip != (Object)null)
		{
			return true;
		}
		FlipClip = LoadFile("CoinFlip_game.txt", (WrapMode)8, _flipCoin, _flipWrist);
		HoldClip = LoadFile("CoinHold_game.txt", (WrapMode)2, _holdCoin, _holdWrist);
		if ((Object)(object)FlipClip == (Object)null || (Object)(object)HoldClip == (Object)null)
		{
			_loadFailed = true;
			return false;
		}
		return true;
	}

	private static string Strip(string p)
	{
		return p.StartsWith("KnifeAnimated/") ? p.Substring("KnifeAnimated/".Length) : p;
	}

	private static AnimationClip LoadFile(string file, WrapMode wrap, List<float[]> coinKeys, List<float[]> wristKeys)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		wristKeys.Clear();
		string path = CoinItem.AssetPath(file);
		if (!File.Exists(path))
		{
			Plugin.Log.Warn("Coin: missing " + file);
			return null;
		}
		CultureInfo invariantCulture = CultureInfo.InvariantCulture;
		AnimationClip clip = new AnimationClip
		{
			legacy = true,
			wrapMode = wrap
		};
		string curPath = null;
		int num = 7;
		int num2 = 0;
		List<float> times = new List<float>();
		List<float>[] comps = new List<float>[7];
		for (int i = 0; i < 7; i++)
		{
			comps[i] = new List<float>();
		}
		coinKeys.Clear();
		string[] array = File.ReadAllLines(path);
		foreach (string text in array)
		{
			string text2 = text.Trim();
			if (text2.Length == 0)
			{
				continue;
			}
			if (text2.StartsWith("fps "))
			{
				_fps = float.Parse(text2.Substring(4), invariantCulture);
			}
			else
			{
				if (text2.StartsWith("frames "))
				{
					continue;
				}
				if (text2.StartsWith("hide "))
				{
					Flush();
					curPath = null;
					string text3 = Strip(text2.Substring(5));
					AnimationCurve val = AnimationCurve.Constant(0f, 0.1f, 0.0001f);
					clip.SetCurve(text3, typeof(Transform), "localScale.x", val);
					clip.SetCurve(text3, typeof(Transform), "localScale.y", val);
					clip.SetCurve(text3, typeof(Transform), "localScale.z", val);
					clip.SetCurve(text3, typeof(Transform), "localPosition.y", AnimationCurve.Constant(0f, 0.1f, -5f));
					continue;
				}
				if (text2.StartsWith("node "))
				{
					Flush();
					curPath = Strip(text2.Substring(5));
					num = 7;
					num2 = 0;
					continue;
				}
				if (text2 == "coin")
				{
					Flush();
					curPath = null;
					num = 10;
					continue;
				}
				string[] array2 = text2.Split(' ');
				if (array2.Length < num)
				{
					continue;
				}
				if (num == 10)
				{
					float[] array3 = new float[10];
					for (int k = 0; k < 10; k++)
					{
						array3[k] = float.Parse(array2[k], invariantCulture);
					}
					coinKeys.Add(array3);
				}
				else
				{
					if (curPath == null)
					{
						continue;
					}
					times.Add((float)num2 / _fps);
					for (int l = 0; l < 7; l++)
					{
						comps[l].Add(float.Parse(array2[l], invariantCulture));
					}
					if (curPath == "Hands/r_IK")
					{
						float[] array4 = new float[7];
						for (int m = 0; m < 7; m++)
						{
							array4[m] = comps[m][comps[m].Count - 1];
						}
						wristKeys.Add(array4);
					}
					num2++;
				}
			}
		}
		Flush();
		clip.EnsureQuaternionContinuity();
		Plugin.Log.Info("Coin: " + file + " -> " + clip.length.ToString("0.##") + "s, " + coinKeys.Count + " coin keys");
		return clip;
		void Flush()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			if (curPath != null && times.Count != 0)
			{
				string[] array5 = new string[7] { "localPosition.x", "localPosition.y", "localPosition.z", "localRotation.x", "localRotation.y", "localRotation.z", "localRotation.w" };
				for (int n = 0; n < 7; n++)
				{
					Keyframe[] array6 = (Keyframe[])(object)new Keyframe[times.Count];
					for (int num3 = 0; num3 < times.Count; num3++)
					{
						array6[num3] = new Keyframe(times[num3], comps[n][num3]);
					}
					AnimationCurve val2 = new AnimationCurve(array6);
					for (int num4 = 0; num4 < array6.Length; num4++)
					{
						val2.SmoothTangents(num4, 0f);
					}
					clip.SetCurve(curPath, typeof(Transform), array5[n], val2);
				}
				times.Clear();
				for (int num5 = 0; num5 < 7; num5++)
				{
					comps[num5].Clear();
				}
			}
		}
	}

	internal static Mesh LoadCoinMesh()
	{
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Expected O, but got Unknown
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_cachedMesh != (Object)null)
		{
			return _cachedMesh;
		}
		string path = CoinItem.AssetPath("CoinMesh.txt");
		CultureInfo invariantCulture = CultureInfo.InvariantCulture;
		List<Vector3> list = new List<Vector3>();
		List<Vector2> list2 = new List<Vector2>();
		string[] array = File.ReadAllLines(path);
		foreach (string text in array)
		{
			string[] array2 = text.Trim().Split(' ');
			if (array2.Length == 5)
			{
				list.Add(new Vector3(0f - float.Parse(array2[0], invariantCulture), float.Parse(array2[1], invariantCulture), 0f - float.Parse(array2[2], invariantCulture)));
				list2.Add(new Vector2(float.Parse(array2[3], invariantCulture), float.Parse(array2[4], invariantCulture)));
			}
		}
		Mesh val = new Mesh
		{
			name = "CoinMesh"
		};
		val.SetVertices(list);
		val.SetUVs(0, list2);
		int[] array3 = new int[list.Count];
		for (int j = 0; j < array3.Length; j++)
		{
			array3[j] = j;
		}
		val.SetTriangles(array3, 0);
		val.RecalculateNormals();
		val.RecalculateBounds();
		_cachedMesh = val;
		return val;
	}

	internal static Texture2D LoadCoinTexture()
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		string path = CoinItem.AssetPath("CoinTexture.png");
		if (!File.Exists(path))
		{
			Plugin.Log.Warn("Coin: no CoinTexture.png");
			return null;
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		ImageConversion.LoadImage(val, File.ReadAllBytes(path));
		((Texture)val).filterMode = (FilterMode)0;
		return val;
	}

	internal static void Cleanup()
	{
		Detach();
		if ((Object)(object)_coin != (Object)null)
		{
			Object.Destroy((Object)(object)_coin);
			_coin = null;
		}
		_loadFailed = false;
	}
}
internal static class CoinAudio
{
	private struct Cue
	{
		public float Frame;

		public string Clip;

		public float Vol;

		public bool Fired;
	}

	private static Cue[] _cues;

	internal static void OnFlipStarted()
	{
		_cues = new Cue[6]
		{
			new Cue
			{
				Frame = 31f,
				Clip = "MetallicItemImpact_V1",
				Vol = 0.9f
			},
			new Cue
			{
				Frame = 33f,
				Clip = "PickupWhoosh",
				Vol = 0.8f
			},
			new Cue
			{
				Frame = 56f,
				Clip = "Click",
				Vol = 0.7f
			},
			new Cue
			{
				Frame = 104f,
				Clip = "PickupWhoosh",
				Vol = 0.55f
			},
			new Cue
			{
				Frame = 111f,
				Clip = "PunchSwoosh",
				Vol = 0.8f
			},
			new Cue
			{
				Frame = 116f,
				Clip = "MetallicItemImpact_V2",
				Vol = 0.6f
			}
		};
	}

	internal static void Tick(float frame)
	{
		if (_cues == null)
		{
			return;
		}
		for (int i = 0; i < _cues.Length; i++)
		{
			if (!_cues[i].Fired && frame >= _cues[i].Frame)
			{
				_cues[i].Fired = true;
				Play(_cues[i].Clip, _cues[i].Vol);
			}
		}
	}

	private static void Play(string clip, float vol)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.LocalPlayer;
		if (!((Object)(object)localPlayer == (Object)null))
		{
			AudioManager.PlayClipAt(clip, ((Component)localPlayer).transform.position, true, (AudioDistance)1, vol, 0.02f);
		}
	}

	internal static void Cleanup()
	{
		_cues = null;
	}
}
internal static class CoinGamble
{
	private struct LabelTweak
	{
		public float TowardHead;

		public float Height;
	}

	private class PendingBet
	{
		public Item Bet;

		public bool Tails;

		public float At;
	}

	private const float Range = 4f;

	private const float Radius = 0.35f;

	private static readonly Collider[] Buf = (Collider[])(object)new Collider[64];

	private static readonly FieldInfo HasOutlineF = typeof(Item).GetField("_hasOutline", BindingFlags.Instance | BindingFlags.NonPublic);

	private static Item _target;

	private static float _nextScan;

	private static Item _bet;

	private static WorldText _label;

	private static readonly List<Material> _outlineMats = new List<Material>();

	private static readonly List<Color> _origColors = new List<Color>();

	private static readonly int OutlineColorID = Shader.PropertyToID("_Outline_Color");

	private static bool _matsSearched;

	private static bool _tinted;

	private static readonly Dictionary<string, LabelTweak> _labelTweaks = new Dictionary<string, LabelTweak>
	{
		{
			"Bowhead Whale",
			new LabelTweak
			{
				TowardHead = 0.35f,
				Height = 0.45f
			}
		},
		{
			"Goblin Shark",
			new LabelTweak
			{
				TowardHead = 0.5f,
				Height = 1f
			}
		}
	};

	private static readonly List<GameObject> _holoParts = new List<GameObject>();

	private static Material _holoMat;

	private static int _labelWorth = -1;

	private static readonly List<PendingBet> _pending = new List<PendingBet>();

	internal static int LastArmedBetId = -1;

	internal static readonly float[] HeadsChanceByDepth = new float[5] { 0.55f, 0.5f, 0.42f, 0.33f, 0.25f };

	private const float WinStepPct = 0.05f;

	private const float WinTickDelay = 0.3f;

	private const float WinPopScale = 0.35f;

	internal static int CountingItemId = -1;

	internal static int CountingWorth = -1;

	private static readonly List<WorldText> _counters = new List<WorldText>();

	internal const float DrainDuration = 0.5f;

	private const float LossStepPct = 0.1f;

	private const float LossTickDelay = 0.15f;

	internal static bool CountingDown;

	internal static void Tick()
	{
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		for (int num = _pending.Count - 1; num >= 0; num--)
		{
			PendingBet pendingBet = _pending[num];
			if ((Object)(object)pendingBet.Bet != (Object)null && Object.op_Implicit((Object)(object)pendingBet.Bet.BirdHolder))
			{
				_pending.RemoveAt(num);
				CoinLock.Release(((NetworkBehaviour)pendingBet.Bet).ObjectId);
				OnBetStolen(pendingBet.Bet);
			}
			else if (Time.unscaledTime >= pendingBet.At)
			{
				_pending.RemoveAt(num);
				ResolveBet(pendingBet.Bet, pendingBet.Tails);
			}
		}
		Player localPlayer = Player.LocalPlayer;
		bool flag = (Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.Holding != (Object)null && (Object)(object)localPlayer.Holding.HeldItem != (Object)null && localPlayer.Holding.HeldItem.ID == 201;
		if (flag && Time.unscaledTime < _nextScan)
		{
			if ((Object)(object)_target != (Object)null && (_target.IsDestroying || ((NetworkBehaviour)_target).IsDeinitializing))
			{
				ClearTargetVisuals();
				_target = null;
			}
		}
		else
		{
			Item val = (flag ? FindLookTarget(localPlayer) : null);
			if (flag)
			{
				_nextScan = Time.unscaledTime + 0.1f;
			}
			if ((Object)(object)val != (Object)(object)_target)
			{
				if ((Object)(object)_target != (Object)null)
				{
					ClearTargetVisuals();
				}
				_target = val;
				if ((Object)(object)_target != (Object)null)
				{
					ApplyTargetVisuals();
					AudioManager.PlayClipAt("Click", ((Component)_target).transform.position, false, (AudioDistance)1, 0.6f, 0.05f);
				}
			}
		}
		UpdateLabel();
		if ((Object)(object)_holoMat != (Object)null && _holoParts.Count > 0)
		{
			Color rainbow = CoinVfx.Rainbow;
			rainbow.a = 0.32f + 0.14f * Mathf.Sin(Time.unscaledTime * (3.2f + 1.6f * (float)Depth(_target)));
			_holoMat.color = rainbow;
		}
	}

	private static Item FindLookTarget(Player p)
	{
		//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_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		Transform val = (((Object)(object)p.Camera != (Object)null) ? p.Camera.CamTransform : null);
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		int num = Physics.OverlapCapsuleNonAlloc(val.position, val.position + val.forward * 4f, 0.35f, Buf, LayerMask.op_Implicit(GameInfo.ItemLayer));
		Item result = null;
		float num2 = 0.94f;
		for (int i = 0; i < num; i++)
		{
			Collider val2 = Buf[i];
			if ((Object)(object)val2 == (Object)null || !((Component)val2).CompareTag("Item"))
			{
				continue;
			}
			Item val3 = ItemManager.Get(((Component)val2).transform);
			if (!((Object)(object)val3 == (Object)null) && !val3.IsDestroying && !((NetworkBehaviour)val3).IsDeinitializing && val3.IsInteractable && !Object.op_Implicit((Object)(object)val3.SyncedHolder) && !Object.op_Implicit((Object)(object)val3.BirdHolder) && (!Object.op_Implicit((Object)(object)val3.Creature) || val3.Creature.IsDead) && val3.ID != 201 && val3.TotalWorth > 0)
			{
				Bounds bounds = val2.bounds;
				Vector3 val4 = ((Bounds)(ref bounds)).center - val.position;
				float num3 = Vector3.Dot(((Vector3)(ref val4)).normalized, val.forward);
				if (num3 > num2)
				{
					num2 = num3;
					result = val3;
				}
			}
		}
		return result;
	}

	internal static Vector3 LabelAnchor(Item item)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		bool flag = false;
		Bounds val = default(Bounds);
		Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>();
		foreach (Renderer val2 in componentsInChildren)
		{
			if (val2.enabled && !val2.forceRenderingOff && !(((Object)val2).name == "CoinHolo"))
			{
				if (!flag)
				{
					val = val2.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref val)).Encapsulate(val2.bounds);
				}
			}
		}
		if (!flag)
		{
			return ((Component)item).transform.position + Vector3.up * 0.35f;
		}
		if (_labelTweaks.TryGetValue(CleanName(item), out var value))
		{
			Vector3 position = ((Component)item).transform.position;
			float num = Mathf.Lerp(((Bounds)(ref val)).center.x, position.x, value.TowardHead);
			float num2 = Mathf.Lerp(((Bounds)(ref val)).center.z, position.z, value.TowardHead);
			float num3 = Mathf.Lerp(((Bounds)(ref val)).center.y, ((Bounds)(ref val)).max.y, value.Height) + 0.26f;
			return new Vector3(num, num3, num2);
		}
		return new Vector3(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).max.y + 0.26f, ((Bounds)(ref val)).center.z);
	}

	private static string CleanName(Item item)
	{
		string name = ((Object)item).name;
		int num = name.IndexOf("(Clone)", StringComparison.Ordinal);
		return ((num >= 0) ? name.Substring(0, num) : name).Trim();
	}

	private static void ApplyTargetVisuals()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		BuildHologram(_target);
		if ((Object)(object)GameInfo.CurCamera != (Object)null && (Object)(object)GameInfo.WorldTextPrefab != (Object)null)
		{
			_label = Object.Instantiate<WorldText>(GameInfo.WorldTextPrefab, LabelAnchor(_target), Quaternion.identity);
			_label.SetText("<color=#FFD700>$" + _target.TotalWorth + "</color>\n<size=60%>double or nothing?</size>", 0.2f);
			_label.ScaleAnimation(true);
		}
	}

	private static void ClearTargetVisuals()
	{
		DestroyHologram();
		if ((Object)(object)_label != (Object)null)
		{
			LeanTween.cancel(((Component)_label).gameObject);
			Object.Destroy((Object)(object)((Component)_label).gameObject);
			_label = null;
		}
		_labelWorth = -1;
		CountingItemId = -1;
		CountingWorth = -1;
		CountingDown = false;
	}

	private static void BuildHologram(Item item)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Expected O, but got Unknown
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_holoMat == (Object)null)
		{
			_holoMat = new Material(Shader.Find("Sprites/Default"));
			_holoMat.renderQueue = 3100;
		}
		Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>();
		foreach (Renderer val in componentsInChildren)
		{
			if (!val.enabled || val.forceRenderingOff)
			{
				continue;
			}
			SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
			MeshRenderer val3 = (MeshRenderer)(object)((val is MeshRenderer) ? val : null);
			if ((Object)(object)val2 == (Object)null && (Object)(object)val3 == (Object)null)
			{
				continue;
			}
			GameObject val4 = new GameObject("CoinHolo");
			val4.transform.SetParent(((Component)val).transform, false);
			val4.layer = ((Component)val).gameObject.layer;
			if ((Object)(object)val2 != (Object)null)
			{
				SkinnedMeshRenderer val5 = val4.AddComponent<SkinnedMeshRenderer>();
				val5.sharedMesh = val2.sharedMesh;
				val5.bones = val2.bones;
				val5.rootBone = val2.rootBone;
				((Renderer)val5).localBounds = ((Renderer)val2).localBounds;
				((Renderer)val5).sharedMaterial = _holoMat;
				((Renderer)val5).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val5).receiveShadows = false;
			}
			else
			{
				MeshFilter component = ((Component)val3).GetComponent<MeshFilter>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
				{
					Object.Destroy((Object)(object)val4);
					continue;
				}
				val4.transform.localScale = Vector3.one * 1.02f;
				val4.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
				MeshRenderer val6 = val4.AddComponent<MeshRenderer>();
				((Renderer)val6).sharedMaterial = _holoMat;
				((Renderer)val6).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val6).receiveShadows = false;
			}
			_holoParts.Add(val4);
		}
	}

	private static void DestroyHologram()
	{
		foreach (GameObject holoPart in _holoParts)
		{
			if ((Object)(object)holoPart != (Object)null)
			{
				Object.Destroy((Object)(object)holoPart);
			}
		}
		_holoParts.Clear();
	}

	private static void UpdateLabel()
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_label == (Object)null) && !((Object)(object)_target == (Object)null))
		{
			((Component)_label).transform.position = LabelAnchor(_target);
			int num = ((CountingItemId == ((NetworkBehaviour)_target).ObjectId && CountingWorth >= 0) ? CountingWorth : _target.TotalWorth);
			if (num != _labelWorth)
			{
				_labelWorth = num;
				string text = ((CountingDown && CountingItemId == ((NetworkBehaviour)_target).ObjectId) ? "#FFFFFF" : HeatColor(Depth(_target)));
				_label.SetText("<color=" + text + ">$" + _labelWorth + "</color>\n<size=60%>double or nothing?</size>", 0.2f);
			}
		}
	}

	private static void TintOutline(bool gold)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		if (!_matsSearched)
		{
			FindOutlineMats();
		}
		if (gold != _tinted)
		{
			_tinted = gold;
			for (int i = 0; i < _outlineMats.Count; i++)
			{
				_outlineMats[i].SetColor(OutlineColorID, gold ? (CoinVfx.Rainbow * 2f) : _origColors[i]);
			}
		}
	}

	private static void FindOutlineMats()
	{
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		_matsSearched = true;
		try
		{
			int num = (1 << LayerMask.NameToLayer("OutlinedObject")) | (1 << LayerMask.NameToLayer("OutlinedObjectNoPlayerCol"));
			foreach (ScriptableRendererFeature rendererFeature in GameInfo.UrpAsset.rendererDataList[0].rendererFeatures)
			{
				RenderObjects val = (RenderObjects)(object)((rendererFeature is RenderObjects) ? rendererFeature : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.settings.overrideMaterial == (Object)null) && (((LayerMask)(ref val.settings.filterSettings.LayerMask)).value & num) != 0)
				{
					Material overrideMaterial = val.settings.overrideMaterial;
					if (overrideMaterial.HasProperty(OutlineColorID) && !_outlineMats.Contains(overrideMaterial))
					{
						_outlineMats.Add(overrideMaterial);
						_origColors.Add(overrideMaterial.GetColor(OutlineColorID));
						Plugin.Log.Info("Gamble: outline material '" + ((Object)overrideMaterial).name + "' (" + ((Object)overrideMaterial.shader).name + ")");
					}
				}
			}
			if (_outlineMats.Count == 0)
			{
				Plugin.Log.Warn("Gamble: no outline material found - no gold tint.");
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.Warn("Gamble: outline search failed: " + ex.Message);
		}
	}

	internal static void LockBet()
	{
		_bet = _target;
		if ((Object)(object)_bet != (Object)null)
		{
			Plugin.Log.Info("Gamble ON: " + _bet.GetName() + " worth $" + _bet.TotalWorth + " (" + (_pending.Count + 1) + " in the air)");
		}
	}

	internal static void ArmResolve(bool tails, float secondsUntilReveal)
	{
		if ((Object)(object)_bet == (Object)null)
		{
			LastArmedBetId = -1;
			return;
		}
		_pending.Add(new PendingBet
		{
			Bet = _bet,
			Tails = tails,
			At = Time.unscaledTime + secondsUntilReveal
		});
		LastArmedBetId = ((NetworkBehaviour)_bet).ObjectId;
		_bet = null;
	}

	internal static void SetPendingOutcome(int betItemId, bool tails)
	{
		for (int num = _pending.Count - 1; num >= 0; num--)
		{
			if ((Object)(object)_pending[num].Bet != (Object)null && ((NetworkBehaviour)_pending[num].Bet).ObjectId == betItemId)
			{
				_pending[num].Tails = tails;
				break;
			}
		}
	}

	internal static int Depth(Item item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return 0;
		}
		float bettingMultiplier = item.BettingMultiplier;
		if (bettingMultiplier <= 1f)
		{
			return 0;
		}
		return Mathf.Max(0, Mathf.RoundToInt(Mathf.Log(bettingMultiplier, 2f)));
	}

	internal static float HeadsChance(int depth)
	{
		return HeadsChanceByDepth[Mathf.Clamp(depth, 0, HeadsChanceByDepth.Length - 1)];
	}

	internal static string HeatColor(int depth)
	{
		return depth switch
		{
			0 => "#FFD700", 
			1 => "#FFB000", 
			2 => "#FF7A00", 
			3 => "#FF4A1A", 
			_ => "#FF2A2A", 
		};
	}

	internal static Item FindItem(int objectId)
	{
		if (objectId < 0 || (Object)(object)InstanceFinder.ClientManager == (Object)null)
		{
			return null;
		}
		if (((ManagedObjects)InstanceFinder.ClientManager.Objects).Spawned.TryGetValue(objectId, out var value) && (Object)(object)value != (Object)null)
		{
			return ((Component)value).GetComponent<Item>();
		}
		return null;
	}

	private static void OnBetStolen(Item bet)
	{
		//IL_0024: 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_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: 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)
		Bird birdHolder = bet.BirdHolder;
		Vector3 val = (((Object)(object)birdHolder != (Object)null) ? ((Component)birdHolder).transform.position : ((Component)bet).transform.position);
		AudioManager.PlayRandomClipAt("Seagull_V", 1, 11, val, true, (AudioDistance)2, 1f, 0.1f);
		if ((Object)(object)GameInfo.CurCamera != (Object)null && (Object)(object)GameInfo.WorldTextPrefab != (Object)null)
		{
			WorldText val2 = Object.Instantiate<WorldText>(GameInfo.WorldTextPrefab, val + Vector3.up * 0.3f, Quaternion.identity);
			val2.SetText("<color=#FF4444>STOLEN</color>", 0.22f);
			val2.FloatAndRemoveAnimation();
		}
		Plugin.Log.Info("Gamble OFF: a bird took the pot.");
	}

	private static void ResolveBet(Item bet, bool tails)
	{
		if (!((Object)(object)bet == (Object)null) && !bet.IsDestroying && !((NetworkBehaviour)bet).IsDeinitializing && !Object.op_Implicit((Object)(object)bet.SyncedHolder) && !Object.op_Implicit((Object)(object)bet.BirdHolder))
		{
			CoinNet.ResolveGamble(bet, tails);
			CoinTutorial.CompleteOnce();
		}
	}

	internal static void PlayOutcomeFx(Vector3 pos, bool win, int newWorth, int itemObjectId = -1)
	{
		//IL_0026: 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_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: 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)
		if (win)
		{
			string text = ((Depth(FindItem(itemObjectId)) >= 2) ? "GreenConfetti" : "RedConfetti");
			ParticleManager.Play(text, pos, Vector3.up);
			AudioManager.PlayClipAt("Confetti", pos, false, (AudioDistance)2, 1f, 0.1f);
			AudioManager.PlayClipAt("Win", pos, false, (AudioDistance)2, 1f, 0.1f);
			if (!((Object)(object)Plugin.Instance == (Object)null))
			{
				if ((Object)(object)_label != (Object)null && (Object)(object)_target != (Object)null && ((NetworkBehaviour)_target).ObjectId == itemObjectId)
				{
					((MonoBehaviour)Plugin.Instance).StartCoroutine(CountUp(_label, newWorth / 2, newWorth, itemObjectId, isLabel: true));
				}
				else if ((Object)(object)GameInfo.CurCamera != (Object)null && (Object)(object)GameInfo.WorldTextPrefab != (Object)null)
				{
					WorldText val = Object.Instantiate<WorldText>(GameInfo.WorldTextPrefab, pos + Vector3.up * 0.25f, Quaternion.identity);
					_counters.Add(val);
					((MonoBehaviour)Plugin.Instance).StartCoroutine(CountUp(val, newWorth / 2, newWorth, itemObjectId, isLabel: false));
				}
			}
			return;
		}
		bool flag = (Object)(object)_label != (Object)null && (Object)(object)_target != (Object)null && ((NetworkBehaviour)_target).ObjectId == itemObjectId;
		if (newWorth > 0 && (Object)(object)Plugin.Instance != (Object)null)
		{
			if (flag)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(CountDown(_label, newWorth, itemObjectId, isLabel: true, pos));
			}
			else if ((Object)(object)GameInfo.CurCamera != (Object)null && (Object)(object)GameInfo.WorldTextPrefab != (Object)null)
			{
				WorldText val2 = Object.Instantiate<WorldText>(GameInfo.WorldTextPrefab, pos + Vector3.up * 0.25f, Quaternion.identity);
				_counters.Add(val2);
				((MonoBehaviour)Plugin.Instance).StartCoroutine(CountDown(val2, newWorth, itemObjectId, isLabel: false, pos));
			}
		}
		else
		{
			LossLanding(pos);
		}
	}

	private static IEnumerator CountDown(WorldText wt, int from, int itemObjectId, bool isLabel, Vector3 pos)
	{
		//IL_0023: 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)
		GameObject go = ((Component)wt).gameObject;
		CountingItemId = itemObjectId;
		CountingWorth = from;
		CountingDown = true;
		if (!isLabel)
		{
			wt.SetText(White(from), 0.25f);
			wt.ScaleAnimation(true);
		}
		else
		{
			LeanTween.cancel(go);
			LeanTween.scale(go, Vector3.one, 0.25f).setEase((LeanTweenType)2);
		}
		float t0 = Time.unscaledTime;
		while ((Object)(object)wt != (Object)null)
		{
			float t1 = Mathf.Clamp01((Time.unscaledTime - t0) / 0.5f);
			float left = (1f - t1) * (1f - t1);
			CountingWorth = Mathf.RoundToInt((float)from * left);
			if (!isLabel)
			{
				wt.SetText(White(CountingWorth), 0.25f);
			}
			if (t1 >= 1f)
			{
				break;
			}
			yield return null;
		}
		LossLanding(pos);
		if (isLabel)
		{
			ClearTargetVisuals();
		}
		else if ((Object)(object)wt != (Object)null)
		{
			_counters.Remove(wt);
			LeanTween.cancel(go);
			Object.Destroy((Object)(object)go);
			CountingItemId = -1;
			CountingWorth = -1;
			CountingDown = false;
		}
	}

	private static void LossLanding(Vector3 pos)
	{
		//IL_0006: 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_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		AudioManager.PlayClipAt("Error", pos, false, (AudioDistance)1, 1f, 0.5f);
		if ((Object)(object)GameInfo.CurCamera != (Object)null && (Object)(object)GameInfo.WorldTextPrefab != (Object)null)
		{
			WorldText val = Object.Instantiate<WorldText>(GameInfo.WorldTextPrefab, pos + Vector3.up * 0.25f, Quaternion.identity);
			val.SetText("You lost", 0.2f);
			val.FloatAndRemoveAnimation();
		}
	}

	private static string White(int worth)
	{
		return "<color=#FFFFFF>$" + worth + "</color>";
	}

	private static IEnumerator CountUp(WorldText wt, int from, int to, int itemObjectId, bool isLabel)
	{
		GameObject go = ((Component)wt).gameObject;
		int cur = from;
		CountingItemId = itemObjectId;
		CountingWorth = cur;
		if (!isLabel)
		{
			wt.SetText(Gold(cur), 0.25f);
			wt.ScaleAnimation(true);
		}
		while (cur != to && (Object)(object)wt != (Object)null)
		{
			long num = (long)to - (long)cur;
			long step = Math.Max(1L, (long)Math.Ceiling(Math.Abs((double)num) * 0.05000000074505806));
			cur = (int)((step >= Math.Abs(num)) ? to : (cur + Math.Sign(num) * step));
			long remaining = Math.Abs((long)to - (long)cur);
			CountingWorth = cur;
			if (!isLabel)
			{
				wt.SetText(Gold(cur), 0.25f);
			}
			AudioManager.PlayClipAt("UIHover", ((Component)wt).transform.position, true, (AudioDistance)0, 1f, 0.02f);
			if (remaining == 0)
			{
				break;
			}
			yield return (object)new WaitForSeconds(0.3f / (float)remaining);
			if ((Object)(object)wt == (Object)null)
			{
				yield break;
			}
			LeanTween.cancel(go);
			go.transform.localScale = Vector3.one * 1.35f;
			LeanTween.scale(go, Vector3.one, 0.4f).setEase((LeanTweenType)2);
		}
		if ((Object)(object)wt == (Object)null)
		{
			CountingItemId = -1;
			CountingWorth = -1;
			yield break;
		}
		LeanTween.cancel(go);
		go.transform.localScale = Vector3.one * 1.35f;
		LeanTween.scale(go, Vector3.one, 0.4f).setEase((LeanTweenType)2);
		if (isLabel)
		{
			yield return (object)new WaitForSeconds(0.4f);
			CountingItemId = -1;
			CountingWorth = -1;
			yield break;
		}
		wt.SetText(Gold(to) + "!", 0.25f);
		yield return (object)new WaitForSeconds(1.2f);
		CountingItemId = -1;
		CountingWorth = -1;
		if (!((Object)(object)wt == (Object)null))
		{
			LeanTween.cancel(go);
			LeanTween.scale(go, Vector3.zero, 0.3f).setEase((LeanTweenType)26);
			LeanTween.move(go, go.transform.position + Vector3.up * 0.4f, 0.3f).setDestroyOnComplete(true);
			_counters.Remove(wt);
		}
	}

	private static string Gold(int worth)
	{
		return "<color=#FFD700>$" + worth + "</color>";
	}

	internal static void Cleanup()
	{
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		foreach (WorldText counter in _counters)
		{
			if ((Object)(object)counter != (Object)null)
			{
				LeanTween.cancel(((Component)counter).gameObject);
				Object.Destroy((Object)(object)((Component)counter).gameObject);
			}
		}
		_counters.Clear();
		CountingItemId = -1;
		CountingWorth = -1;
		ClearTargetVisuals();
		_target = null;
		_bet = null;
		_pending.Clear();
		for (int i = 0; i < _outlineMats.Count; i++)
		{
			_outlineMats[i].SetColor(OutlineColorID, _origColors[i]);
		}
		if ((Object)(object)_holoMat != (Object)null)
		{
			Object.Destroy((Object)(object)_holoMat);
			_holoMat = null;
		}
	}
}
internal class CoinWorldVisibility : MonoBehaviour
{
	private Item _item;

	private MeshRenderer _mr;

	private void Awake()
	{
		_item = ((Component)this).GetComponentInParent<Item>();
		_mr = ((Component)this).GetComponent<MeshRenderer>();
	}

	private void LateUpdate()
	{
		if (!((Object)(object)_item == (Object)null) && !((Object)(object)_mr == (Object)null))
		{
			bool flag = (Object)(object)_item.SyncedHolder == (Object)null;
			if (((Renderer)_mr).enabled != flag)
			{
				((Renderer)_mr).enabled = flag;
			}
		}
	}
}
internal static class CoinItem
{
	internal const byte Id = 201;

	internal const string ItemName = "Lucky Coin";

	internal static Item Prefab;

	internal static bool Built;

	private const float CounterOut = 0.7f;

	private const float CounterSide = 0.35f;

	private const float TentSide = 0.47f;

	private const float TentUp = -0.03f;

	private const float TentRoll = 270f;

	private static Vector3 _tentNormal;

	private static Mesh _coinMesh;

	private static Material _coinMat;

	private static float _nextShopCheck;

	private static bool _cleanedOldStands;

	private static readonly Dictionary<string, GameObject> _stands = new Dictionary<string, GameObject>();

	private static readonly HashSet<string> _failedOn = new HashSet<string>();

	private static readonly string[] ShopIslands = new string[3] { "Island3", "Island4", "Island5" };

	internal static string AssetPath(string file)
	{
		try
		{
			string location = Assembly.GetExecutingAssembly().Location;
			if (!string.IsNullOrEmpty(location))
			{
				string directoryName = Path.GetDirectoryName(location);
				string text = Path.Combine(directoryName, "CoinFlip", file);
				if (File.Exists(text))
				{
					return text;
				}
				text = Path.Combine(directoryName, file);
				if (File.Exists(text))
				{
					return text;
				}
			}
		}
		catch
		{
		}
		return Path.Combine(Paths.PluginPath, "CoinFlip", file);
	}

	internal static IEnumerator Build()
	{
		Item knife = null;
		while ((Object)(object)knife == (Object)null || (Object)(object)InstanceFinder.NetworkManager == (Object)null)
		{
			knife = GameInfo.GetSpawnable("knife");
			if ((Object)(object)knife == (Object)null || (Object)(object)InstanceFinder.NetworkManager == (Object)null)
			{
				yield return (object)new WaitForSecondsRealtime(0.5f);
			}
		}
		Item existing = GameInfo.IDToItem((byte)201);
		if ((Object)(object)existing != (Object)null)
		{
			if (((Object)existing).name == "Lucky Coin")
			{
				Prefab = existing;
				SetPrivate(Prefab, "_cost", 1);
				ApplyCoinLook(Prefab);
				Built = true;
				Plugin.Log.Info("Adopted the Coin registered before this hot reload (ID=" + (byte)201 + ").");
			}
			else
			{
				Plugin.Log.Warn("Item ID " + (byte)201 + " is taken by '" + ((Object)existing).name + "'. Aborting.");
			}
		}
		else
		{
			GameObject holder = new GameObject("CoinPrefabHolder");
			holder.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)holder);
			Prefab = Object.Instantiate<Item>(knife, holder.transform);
			((Object)Prefab).name = "Lucky Coin";
			Prefab.SetID((byte)201);
			SetPrivate(Prefab, "_cost", 1);
			SetPrivate(Prefab, "_worth", 0);
			ApplyCoinLook(Prefab);
			RegisterWithGameInfo(Prefab);
			RegisterWithFishNet(Prefab);
			Built = true;
			Plugin.Log.Info("Coin built: ID=" + (byte)201 + " cost=$1 (knife clone, clips swapped).");
		}
	}

	private static void ApplyCoinLook(Item item)
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Expected O, but got Unknown
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: 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_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Expected O, but got Unknown
		//IL_0365: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_039a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0510: Unknown result type (might be due to invalid IL or missing references)
		//IL_0526: Unknown result type (might be due to invalid IL or missing references)
		SetPrivate(item, "_hasInspectAnim", false);
		if ((Object)(object)_coinMesh == (Object)null)
		{
			_coinMesh = CoinAnim.LoadCoinMesh();
		}
		if ((Object)(object)_coinMat == (Object)null)
		{
			Shader val = Shader.Find("Universal Render Pipeline/Lit");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Sprites/Default");
			}
			_coinMat = new Material(val);
			Texture2D val2 = CoinAnim.LoadCoinTexture();
			if ((Object)(object)val2 != (Object)null)
			{
				if (_coinMat.HasProperty("_BaseMap"))
				{
					_coinMat.SetTexture("_BaseMap", (Texture)(object)val2);
				}
				_coinMat.mainTexture = (Texture)(object)val2;
			}
			if (_coinMat.HasProperty("_BaseColor"))
			{
				_coinMat.SetColor("_BaseColor", Color.white);
			}
			if (_coinMat.HasProperty("_Metallic"))
			{
				_coinMat.SetFloat("_Metallic", 0f);
			}
			if (_coinMat.HasProperty("_Smoothness"))
			{
				_coinMat.SetFloat("_Smoothness", 0.05f);
			}
		}
		int num = 0;
		SkinnedMeshRenderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<SkinnedMeshRenderer>(true);
		foreach (SkinnedMeshRenderer val3 in componentsInChildren)
		{
			if (((Object)val3).name.ToLower().Contains("knife") || ((Object)(object)val3.sharedMesh != (Object)null && ((Object)val3.sharedMesh).name.ToLower().Contains("knife")))
			{
				((Renderer)val3).forceRenderingOff = true;
				num++;
			}
		}
		Transform val4 = ((Component)item).transform.Find("CoinWorldModel");
		GameObject val5;
		if ((Object)(object)val4 == (Object)null)
		{
			val5 = new GameObject("CoinWorldModel");
			val5.transform.SetParent(((Component)item).transform, false);
			val5.transform.localScale = Vector3.one * 2.2f;
			val5.AddComponent<MeshFilter>().sharedMesh = _coinMesh;
			((Renderer)val5.AddComponent<MeshRenderer>()).sharedMaterial = _coinMat;
			val5.layer = ((Component)item).gameObject.layer;
		}
		else
		{
			val5 = ((Component)val4).gameObject;
		}
		val5.transform.localScale = Vector3.one * 2.2f;
		if ((Object)(object)val5.GetComponent<CoinWorldVisibility>() == (Object)null)
		{
			val5.AddComponent<CoinWorldVisibility>();
		}
		Collider[] array = GetPrivate<Collider[]>(item, "_worldColliders");
		if (array != null)
		{
			Collider[] array2 = array;
			foreach (Collider val6 in array2)
			{
				if ((Object)(object)val6 != (Object)null && ((Object)val6).name != "CoinCollider")
				{
					val6.enabled = false;
				}
			}
		}
		Transform val7 = ((Component)item).transform.Find("CoinCollider");
		BoxCollider val9;
		if ((Object)(object)val7 == (Object)null)
		{
			GameObject val8 = new GameObject("CoinCollider");
			val8.transform.SetParent(((Component)item).transform, false);
			val8.layer = 9;
			val8.tag = ((Component)item).gameObject.tag;
			val9 = val8.AddComponent<BoxCollider>();
			val9.size = new Vector3(0.095f, 0.028f, 0.095f);
			val9.center = Vector3.zero;
		}
		else
		{
			val9 = ((Component)val7).GetComponent<BoxCollider>();
		}
		val9.size = new Vector3(0.095f, 0.028f, 0.095f);
		SetPrivate(item, "_worldColliders", new Collider[1] { (Collider)val9 });
		AudioClip clip = AudioManager.GetClip("MetallicItemImpact_V1");
		if ((Object)(object)clip != (Object)null)
		{
			ImpactSoundType val10 = ScriptableObject.CreateInstance<ImpactSoundType>();
			SetPrivate(val10, "_clips", new AudioClip[3]
			{
				clip,
				AudioManager.GetClip("MetallicItemImpact_V2"),
				AudioManager.GetClip("MetallicItemImpact_V3")
			});
			SetPrivate(val10, "_minVelToPlayClips", new float[3] { 0.5f, 2f, 4f });
			SetPrivate(val10, "_velForMaxVol", 6f);
			SetPrivate(val10, "_maxVol", 0.8f);
			SetPrivate(val10, "_minVol", 0.15f);
			SetPrivate(val10, "_minDelay", 0.15f);
			SetPrivate(item, "_impactSoundType", val10);
		}
		Item spawnable = GameInfo.GetSpawnable("knife");
		if ((Object)(object)spawnable != (Object)null)
		{
			RestoreHandTransforms(item, spawnable, "_handTransformsRight");
			RestoreHandTransforms(item, spawnable, "_handTransformsLeft");
		}
		SetPrivate(item, "_mesh", _coinMesh);
		SetPrivate(item, "_inventoryMeshScale", 14f);
		SetPrivate(item, "_inventoryMeshRot", (object)new Vector3(90f, 0f, 0f));
		SetPrivate(item, "_inventoryMeshPos", Vector3.zero);
		Animation componentInChildren = ((Component)item).GetComponentInChildren<Animation>(true);
		if ((Object)(object)componentInChildren == (Object)null)
		{
			Plugin.Log.Warn("Coin clone has no Animation component!");
			return;
		}
		if (!CoinAnim.EnsureLoaded())
		{
			Plugin.Log.Warn("Coin clips missing - animations disabled.");
			return;
		}
		if ((Object)(object)componentInChildren.GetClip("Idle") != (Object)null)
		{
			componentInChildren.RemoveClip("Idle");
		}
		if ((Object)(object)componentInChildren.GetClip("Inspect") != (Object)null)
		{
			componentInChildren.RemoveClip("Inspect");
		}
		componentInChildren.AddClip(CoinAnim.HoldClip, "Idle");
		if ((Object)(object)componentInChildren.GetClip("Flip") != (Object)null)
		{
			componentInChildren.RemoveClip("Flip");
		}
		componentInChildren.AddClip(CoinAnim.FlipClip, "Flip");
		Plugin.Log.Info("Coin look applied: " + num + " knife renderers hidden, world coin added, clips Idle=hold, Flip=flip.");
	}

	private static void RestoreHandTransforms(Item coin, Item knife, string field)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		HandTransforms val = GetPrivate<HandTransforms>(knife, field);
		if (val == null)
		{
			SetPrivate(coin, field, (object)new HandTransforms(false));
			return;
		}
		HandTransforms val2 = new HandTransforms(val.Exists);
		SetPrivate(val2, "_handPos", val.HandPos);
		SetPrivate(val2, "_handRot", val.HandRot);
		SetPrivate(val2, "_fingerRots", val.FingerRots);
		Transform val3 = null;
		if ((Object)(object)val.Parent != (Object)null)
		{
			List<string> list = new List<string>();
			Transform parent = val.Parent;
			while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)((Component)knife).transform)
			{
				list.Insert(0, ((Object)parent).name);
				parent = parent.parent;
			}
			val3 = ((Component)coin).transform;
			foreach (string item in list)
			{
				val3 = val3.Find(item);
				if ((Object)(object)val3 == (Object)null)
				{
					break;
				}
			}
		}
		SetPrivate(val2, "_parent", val3);
		SetPrivate(coin, field, val2);
	}

	private static void RegisterWithGameInfo(Item item)
	{
		AddToStaticDict("_allItems", item.ID, item);
		AddToStaticDict("_idToSpawnable", item.ID, item);
		AddToStaticDict("_nameToSpawnable", ((Object)item).name.Replace(" ", "").ToLower(), item);
	}

	private static void AddToStaticDict(string field, object key, Item value)
	{
		FieldInfo field2 = typeof(GameInfo).GetField(field, BindingFlags.Static | BindingFlags.NonPublic);
		if (field2 == null)
		{
			Plugin.Log.Warn("GameInfo." + field + " not found.");
		}
		else if (field2.GetValue(null) is IDictionary dictionary)
		{
			dictionary[key] = value;
		}
	}

	private static void RegisterWithFishNet(Item item)
	{
		NetworkObject component = ((Component)item).GetComponent<NetworkObject>();
		if ((Object)(object)component == (Object)null)
		{
			Plugin.Log.Warn("Coin has no NetworkObject - cannot spawn.");
			return;
		}
		PrefabObjects spawnablePrefabs = InstanceFinder.NetworkManager.SpawnablePrefabs;
		if ((Object)(object)spawnablePrefabs == (Object)null)
		{
			Plugin.Log.Warn("SpawnablePrefabs is null.");
			return;
		}
		int objectCount = spawnablePrefabs.GetObjectCount();
		spawnablePrefabs.AddObject(component, true, true);
		Plugin.Log.Info("Coin registered with FishNet: " + objectCount + " -> " + spawnablePrefabs.GetObjectCount());
	}

	internal static void SetPrivate(object target, string field, object value)
	{
		Type type = target.GetType();
		while (type != null)
		{
			FieldInfo field2 = type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);
			if (field2 != null)
			{
				field2.SetValue(target, value);
				return;
			}
			type = type.BaseType;
		}
		Plugin.Log.Warn("Field '" + field + "' not found on " + target.GetType().Name);
	}

	internal static T GetPrivate<T>(object target, string field) where T : class
	{
		Type type = target.GetType();
		while (type != null)
		{
			FieldInfo field2 = type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);
			if (field2 != null)
			{
				return field2.GetValue(target) as T;
			}
			type = type.BaseType;
		}
		return null;
	}

	internal static void TickShop()
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		if (!Built || Time.unscaledTime < _nextShopCheck)
		{
			return;
		}
		_nextShopCheck = Time.unscaledTime + 2f;
		if (!_cleanedOldStands)
		{
			_cleanedOldStands = true;
			ItemPurchasable[] array = Object.FindObjectsByType<ItemPurchasable>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (ItemPurchasable val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == "Coin (Purchasable)")
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
				}
			}
		}
		for (int j = 0; j < SceneManager.sceneCount; j++)
		{
			Scene sceneAt = SceneManager.GetSceneAt(j);
			if (!((Scene)(ref sceneAt)).isLoaded || _failedOn.Contains(((Scene)(ref sceneAt)).name) || (_stands.TryGetValue(((Scene)(ref sceneAt)).name, out var value) && (Object)(object)value != (Object)null))
			{
				continue;
			}
			string[] shopIslands = ShopIslands;
			foreach (string text in shopIslands)
			{
				if (text.Equals(((Scene)(ref sceneAt)).name, StringComparison.OrdinalIgnoreCase))
				{
					PlaceOnIsland(sceneAt);
					break;
				}
			}
		}
	}

	private static void PlaceOnIsland(Scene scene)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: 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_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_036c: Unknown result type (might be due to invalid IL or missing references)
		//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0401: Unknown result type (might be due to invalid IL or missing references)
		//IL_0408: Unknown result type (might be due to invalid IL or missing references)
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		//IL_0417: Unknown result type (might be due to invalid IL or missing references)
		//IL_041c: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0420: Unknown result type (might be due to invalid IL or missing references)
		//IL_042a: Unknown result type (might be due to invalid IL or missing references)
		//IL_042f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0434: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02af: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_046f: Unknown result type (might be due to invalid IL or missing references)
		//IL_044e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0453: Unknown result type (might be due to invalid IL or missing references)
		//IL_045d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0462: Unknown result type (might be due to invalid IL or missing references)
		//IL_0467: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_0329: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_0644: Unknown result type (might be due to invalid IL or missing references)
		//IL_0649: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05da: Unknown result type (might be due to invalid IL or missing references)
		//IL_05df: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0603: Unknown result type (might be due to invalid IL or missing references)
		//IL_0608: Unknown result type (might be due to invalid IL or missing references)
		//IL_0612: Unknown result type (might be due to invalid IL or missing references)
		//IL_0617: Unknown result type (might be due to invalid IL or missing references)
		//IL_0629: Unknown result type (might be due to invalid IL or missing references)
		//IL_0633: Unknown result type (might be due to invalid IL or missing references)
		//IL_0710: Unknown result type (might be due to invalid IL or missing references)
		//IL_0715: Unknown result type (might be due to invalid IL or missing references)
		//IL_072d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0732: Unknown result type (might be due to invalid IL or missing references)
		//IL_073c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0741: Unknown result type (might be due to invalid IL or missing references)
		//IL_0753: Unknown result type (might be due to invalid IL or missing references)
		//IL_075d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0669: Unknown result type (might be due to invalid IL or missing references)
		//IL_066e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0673: Unknown result type (might be due to invalid IL or missing references)
		//IL_0678: Unknown result type (might be due to invalid IL or missing references)
		//IL_067d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0682: Unknown result type (might be due to invalid IL or missing references)
		//IL_068d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0692: Unknown result type (might be due to invalid IL or missing references)
		//IL_0697: Unknown result type (might be due to invalid IL or missing references)
		//IL_069c: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_06cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f5: Unknown result type (might be due to invalid IL or missing references)
		_tentNormal = Vector3.zero;
		bool flag = ((Scene)(ref scene)).name.Equals("Island3", StringComparison.OrdinalIgnoreCase);
		string text = (flag ? "Dynamite" : "Beer");
		ItemPurchasable val = null;
		ItemPurchasable[] array = Object.FindObjectsByType<ItemPurchasable>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		foreach (ItemPurchasable val2 in array)
		{
			if (!((Object)(object)val2 == (Object)null) && !(((Component)val2).gameObject.scene != scene))
			{
				Item val3 = GetPrivate<Item>(val2, "_itemToPurchase");
				if ((Object)(object)val3 != (Object)null && ((Object)val3).name == text)
				{
					val = val2;
					break;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.Warn("Coin shop: no " + text + " stand on " + ((Scene)(ref scene)).name);
			_failedOn.Add(((Scene)(ref scene)).name);
			return;
		}
		GameObject val4 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent);
		((Object)val4).name = "Coin (Purchasable)";
		SetPrivate(val4.GetComponent<ItemPurchasable>(), "_itemToPurchase", Prefab);
		Vector3 val9;
		if (flag)
		{
			val4.transform.position = ((Component)val).transform.TransformPoint(new Vector3(-0.237f, 0.183f, 0.15f));
			val4.transform.rotation = ((Component)val).transform.rotation;
		}
		else
		{
			Transform transform = ((Component)val).transform;
			if (((Scene)(ref scene)).name.Equals("Island5", StringComparison.OrdinalIgnoreCase))
			{
				Vector3 val5 = Vector3.zero;
				Vector3 val6 = transform.position;
				float num = float.MaxValue;
				RaycastHit val8 = default(RaycastHit);
				for (int j = 0; j < 8; j++)
				{
					Vector3 val7 = Quaternion.AngleAxis((float)j * 45f, Vector3.up) * Vector3.forward;
					if (Physics.Raycast(transform.position, val7, ref val8, 0.8f) && ((RaycastHit)(ref val8)).distance < num)
					{
						num = ((RaycastHit)(ref val8)).distance;
						val5 = ((RaycastHit)(ref val8)).normal;
						val6 = ((RaycastHit)(ref val8)).point;
					}
				}
				if (val5 == Vector3.zero)
				{
					val5 = -transform.forward;
					Plugin.Log.Warn("Coin shop: no tent wall behind the beer, guessing its facing.");
				}
				val9 = Vector3.Cross(val5, Vector3.up);
				Vector3 normalized = ((Vector3)(ref val9)).normalized;
				Vector3 val10 = val6 + normalized * 0.47f + Vector3.up * -0.03f;
				RaycastHit val11 = default(RaycastHit);
				if (Physics.Raycast(val10 + val5 * 0.5f, -val5, ref val11, 1f))
				{
					val6 = ((RaycastHit)(ref val11)).point;
					val5 = ((RaycastHit)(ref val11)).normal;
					val10 = val6;
				}
				val4.transform.position = val10 + val5 * 0.03f;
				val4.transform.rotation = transform.rotation;
				_tentNormal = val5;
			}
			else
			{
				NPC val12 = null;
				float num2 = float.MaxValue;
				NPC[] array2 = Object.FindObjectsByType<NPC>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				foreach (NPC val13 in array2)
				{
					if (!((Object)(object)val13 == (Object)null) && !(((Component)val13).gameObject.scene != scene))
					{
						val9 = ((Component)val13).transform.position - transform.position;
						float sqrMagnitude = ((Vector3)(ref val9)).sqrMagnitude;
						if (sqrMagnitude < num2)
						{
							num2 = sqrMagnitude;
							val12 = val13;
						}
					}
				}
				Vector3 position = transform.position;
				if ((Object)(object)val12 != (Object)null)
				{
					Transform transform2 = ((Component)val12).transform;
					Vector3 val14 = transform2.position + transform2.forward * 0.7f + transform2.right * 0.35f;
					RaycastHit val15 = default(RaycastHit);
					if (Physics.Raycast(val14 + Vector3.up * 1.5f, Vector3.down, ref val15, 2f))
					{
						position = ((RaycastHit)(ref val15)).point + Vector3.up * 0.02f;
					}
					else
					{
						position = val14;
						Plugin.Log.Warn("Coin shop: no counter found under the seller on " + ((Scene)(ref scene)).name + ", placing in the air.");
					}
				}
				else
				{
					Plugin.Log.Warn("Coin shop: no NPC found on " + ((Scene)(ref scene)).name);
				}
				val4.transform.position = position;
				val4.transform.rotation = transform.rotation;
			}
		}
		Mesh val16 = null;
		Item spawnable = GameInfo.GetSpawnable(flag ? "dynamite" : "beer");
		if ((Object)(object)spawnable != (Object)null)
		{
			MeshFilter[] componentsInChildren = ((Component)spawnable).GetComponentsInChildren<MeshFilter>(true);
			int num3 = 0;
			if (num3 < componentsInChildren.Length)
			{
				MeshFilter val17 = componentsInChildren[num3];
				val16 = val17.sharedMesh;
			}
		}
		int num4 = 0;
		MeshFilter[] componentsInChildren2 = val4.GetComponentsInChildren<MeshFilter>(true);
		foreach (MeshFilter val18 in componentsInChildren2)
		{
			if (!((Object)(object)val16 != (Object)null) || !((Object)(object)val18.sharedMesh != (Object)(object)val16))
			{
				val18.sharedMesh = _coinMesh;
				MeshRenderer component = ((Component)val18).GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).sharedMaterial = _coinMat;
				}
				if (flag)
				{
					Vector3 val19 = ((Component)val).transform.rotation * new Vector3(-0.61f, -0.79f, 0f);
					((Component)val18).transform.rotation = Quaternion.AngleAxis(35f, val19) * Quaternion.FromToRotation(Vector3.up, -val19);
					Transform transform3 = ((Component)val18).transform;
					transform3.position += Vector3.up * 0.07f;
					((Component)val18).transform.localScale = Vector3.one * 2.5f;
				}
				else if (_tentNormal != Vector3.zero)
				{
					((Component)val18).transform.rotation = Quaternion.AngleAxis(270f, _tentNormal) * Quaternion.FromToRotation(Vector3.up, _tentNormal);
					val9 = Vector3.Cross(_tentNormal, Vector3.up);
					Vector3 normalized2 = ((Vector3)(ref val9)).normalized;
					((Component)val18).transform.position = val4.transform.position + Vector3.up * 0.03f + normalized2 * 0.05f;
					((Component)val18).transform.localScale = Vector3.one * 2.5f;
				}
				else
				{
					((Component)val18).transform.rotation = Quaternion.AngleAxis(180f, Vector3.right);
					((Component)val18).transform.position = val4.transform.position + Vector3.up * 0.012f;
					((Component)val18).transform.localScale = Vector3.one * 2f;
				}
				num4++;
				if ((Object)(object)val16 == (Object)null)
				{
					break;
				}
			}
		}
		_stands[((Scene)(ref scene)).name] = val4;
		Plugin.Log.Info("Coin on sale on " + ((Scene)(ref scene)).name + " (display meshes swapped: " + num4 + ").");
	}
}
internal struct GambleRequestMsg : IBroadcast
{
	public byte Version;

	public int ItemObjectId;

	public bool Tails;
}
internal struct FlipStartedMsg : IBroadcast
{
	public byte Version;

	public int PlayerObjectId;

	public int BetItemObjectId;
}
internal struct FlipOutcomeMsg : IBroadcast
{
	public byte Version;

	public int ItemObjectId;

	public bool Tails;

	public byte Depth;
}
internal struct GambleResultMsg : IBroadcast
{
	public byte Version;

	public int ItemObjectId;

	public Vector3 Pos;

	public bool Win;

	public int NewWorth;
}
internal static class CoinLock
{
	private static readonly Dictionary<int, float> _locked = new Dictionary<int, float>();

	private static readonly List<int> _expired = new List<int>();

	internal static void Add(int itemObjectId)
	{
		if (itemObjectId >= 0)
		{
			_locked[itemObjectId] = Time.unscaledTime + 9f;
		}
	}

	internal static void Release(int itemObjectId)
	{
		_locked.Remove(itemObjectId);
	}

	internal static bool IsLocked(Item item)
	{
		return (Object)(object)item != (Object)null && _locked.ContainsKey(((NetworkBehaviour)item).ObjectId);
	}

	internal static void Tick()
	{
		if (_locked.Count == 0)
		{
			return;
		}
		_expired.Clear();
		foreach (KeyValuePair<int, float> item in _locked)
		{
			if (Time.unscaledTime > item.Value)
			{
				_expired.Add(item.Key);
			}
		}
		foreach (int item2 in _expired)
		{
			_locked.Remove(item2);
		}
	}

	internal static void Clear()
	{
		_locked.Clear();
	}
}
internal static class CoinNet
{
	private const byte ProtocolVersion = 3;

	private static bool _registered;

	private const float DrainSeconds = 0.6f;

	private static readonly Dictionary<int, bool> _serverRolls = new Dictionary<int, bool>();

	internal static void Register()
	{
		if (!_registered && !((Object)(object)InstanceFinder.NetworkManager == (Object)null) && !((Object)(object)InstanceFinder.ServerManager == (Object)null) && !((Object)(object)InstanceFinder.ClientManager == (Object)null))
		{
			PurgeStaleHandlers(InstanceFinder.ServerManager);
			PurgeStaleHandlers(InstanceFinder.ClientManager);
			GenericWriter<GambleRequestMsg>.SetWrite((Action<Writer, GambleRequestMsg>)WriteRequest);
			GenericReader<GambleRequestMsg>.SetRead((Func<Reader, GambleRequestMsg>)ReadRequest);
			GenericWriter<GambleResultMsg>.SetWrite((Action<Writer, GambleResultMsg>)WriteResult);
			GenericReader<GambleResultMsg>.SetRead((Func<Reader, GambleResultMsg>)ReadResult);
			GenericWriter<FlipStartedMsg>.SetWrite((Action<Writer, FlipStartedMsg>)WriteFlip);
			GenericReader<FlipStartedMsg>.SetRead((Func<Reader, FlipStartedMsg>)ReadFlip);
			GenericWriter<FlipOutcomeMsg>.SetWrite((Action<Writer, FlipOutcomeMsg>)WriteOutcome);
			GenericReader<FlipOutcomeMsg>.SetRead((Func<Reader, FlipOutcomeMsg>)ReadOutcome);
			InstanceFinder.ServerManager.RegisterBroadcast<GambleRequestMsg>((Action<NetworkConnection, GambleRequestMsg, Channel>)OnServerRequest, true);
			InstanceFinder.ClientManager.RegisterBroadcast<GambleResultMsg>((Action<GambleResultMsg, Channel>)OnClientResult);
			InstanceFinder.ServerManager.RegisterBroadcast<FlipStartedMsg>((Action<NetworkConnection, FlipStartedMsg, Channel>)OnServerFlip, true);
			InstanceFinder.ClientManager.RegisterBroadcast<FlipStartedMsg>((Action<FlipStartedMsg, Channel>)OnClientFlip);
			InstanceFinder.ClientManager.RegisterBroadcast<FlipOutcomeMsg>((Action<FlipOutcomeMsg, Channel>)OnClientOutcome);
			_registered = true;
			Plugin.Log.Info("CoinNet registered (protocol v" + (byte)3 + ").");
		}
	}

	internal static void Unregister()
	{
		if (!_registered)
		{
			return;
		}
		_registered = false;
		try
		{
			ServerManager serverManager = InstanceFinder.ServerManager;
			if (serverManager != null)
			{
				serverManager.UnregisterBroadcast<GambleRequestMsg>((Action<NetworkConnection, GambleRequestMsg, Channel>)OnServerRequest);
			}
			ClientManager clientManager = InstanceFinder.ClientManager;
			if (clientManager != null)
			{
				clientManager.UnregisterBroadcast<GambleResultMsg>((Action<GambleResultMsg, Channel>)OnClientResult);
			}
			ServerManager serverManager2 = InstanceFinder.ServerManager;
			if (serverManager2 != null)
			{
				serverManager2.UnregisterBroadcast<FlipStartedMsg>((Action<NetworkConnection, FlipStartedMsg, Channel>)OnServerFlip);
			}
			ClientManager clientManager2 = InstanceFinder.ClientManager;
			if (clientManager2 != null)
			{
				clientManager2.UnregisterBroadcast<FlipStartedMsg>((Action<FlipStartedMsg, Channel>)OnClientFlip);
			}
			ClientManager clientManager3 = InstanceFinder.ClientManager;
			if (clientManager3 != null)
			{
				clientManager3.UnregisterBroadcast<FlipOutcomeMsg>((Action<FlipOutcomeMsg, Channel>)OnClientOutcome);
			}
			PurgeStaleHandlers(InstanceFinder.ServerManager);
			PurgeStaleHandlers(InstanceFinder.ClientManager);
		}
		catch (Exception ex)
		{
			Plugin.Log.Warn("CoinNet unregister: " + ex.Message);
		}
	}

	internal static void ResolveGamble(Item bet, bool tails)
	{
		if ((Object)(object)Server.Instance != (Object)null && ((NetworkBehaviour)Server.Instance).IsServerInitialized)
		{
			ServerApply(bet, tails);
			return;
		}
		if (!_registered)
		{
			Plugin.Log.Warn("Gamble: no relay registered - outcome dropped.");
			return;
		}
		InstanceFinder.ClientManager.Broadcast<GambleRequestMsg>(new GambleRequestMsg
		{
			Version = 3,
			ItemObjectId = ((NetworkBehaviour)bet).ObjectId,
			Tails = tails
		}, (Channel)0);
	}

	private static void ServerApply(Item bet, bool tails)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)bet == (Object)null || bet.IsDestroying || ((NetworkBehaviour)bet).IsDeinitializing || Object.op_Implicit((Object)(object)bet.SyncedHolder))
		{
			return;
		}
		tails = TakeServerRoll(((NetworkBehaviour)bet).ObjectId, tails);
		Vector3 pos = CoinGamble.LabelAnchor(bet);
		GambleResultMsg gambleResultMsg = new GambleResultMsg
		{
			Version = 3,
			ItemObjectId = ((NetworkBehaviour)bet).ObjectId,
			Pos = pos,
			Win = !tails
		};
		if (!tails)
		{
			bet.AddBetMultiplier(2f);
			gambleResultMsg.NewWorth = bet.TotalWorth;
			Plugin.Log.Info("Gamble WON: worth doubled to $" + gambleResultMsg.NewWorth);
		}
		else
		{
			gambleResultMsg.NewWorth = bet.TotalWorth;
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(DestroyAfterDrain(bet));
			}
			else
			{
				bet.DestroyItem((byte)0, byte.MaxValue);
			}
			Plugin.Log.Info("Gamble LOST: draining $" + gambleResultMsg.NewWorth + " then destroying.");
		}
		InstanceFinder.ServerManager.Broadcast<GambleResultMsg>(gambleResultMsg, true, (Channel)0);
	}

	private static IEnumerator DestroyAfterDrain(Item bet)
	{
		yield return (object)new WaitForSeconds(0.6f);
		if (!((Object)(object)bet == (Object)null) && !bet.IsDestroying && !((NetworkBehaviour)bet).IsDeinitializing && !Object.op_Implicit((Object)(object)bet.BirdHolder))
		{
			bet.DestroyItem((byte)0, byte.MaxValue);
		}
	}

	private static void OnServerRequest(NetworkConnection conn, GambleRequestMsg m, Channel channel)
	{
		if (m.Version == 3 && ((ManagedObjects)InstanceFinder.ServerManager.Objects).Spawned.TryGetValue(m.ItemObjectId, out var value) && !((Object)(object)value == (Object)null))
		{
			Item component = ((Component)value).GetComponent<Item>();
			if (!((Object)(object)component == (Object)null) && component.TotalWorth > 0)
			{
				ServerApply(component, m.Tails);
			}
		}
	}

	private static void OnClientResult(GambleResultMsg m, Channel channel)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (m.Version == 3)
		{
			if (m.Win)
			{
				CoinLock.Release(m.ItemObjectId);
			}
			CoinGamble.PlayOutcomeFx(m.Pos, m.Win, m.NewWorth, m.ItemObjectId);
		}
	}

	internal static void SendFlipStarted()
	{
		if (_registered && !((Object)(object)Player.LocalPlayer == (Object)null))
		{
			CoinLock.Add(CoinGamble.LastArmedBetId);
			Plugin.Log.Info("CoinNet: flip sent (me=" + ((NetworkBehaviour)Player.LocalPlayer).ObjectId + " bet=" + CoinGamble.LastArmedBetId + ")");
			InstanceFinder.ClientManager.Broadcast<FlipStartedMsg>(new FlipStartedMsg
			{
				Version = 3,
				PlayerObjectId = ((NetworkBehaviour)Player.LocalPlayer).ObjectId,
				BetItemObjectId = CoinGamble.LastArmedBetId
			}, (Channel)0);
		}
	}

	private static void OnServerFlip(NetworkConnection conn, FlipStartedMsg m, Channel channel)
	{
		if (m.Version == 3)
		{
			InstanceFinder.ServerManager.BroadcastExcept<FlipStartedMsg>(conn, m, true, (Channel)0);
			Plugin.Log.Info("CoinNet: server relayed flip of " + m.PlayerObjectId);
			if (m.BetItemObjectId >= 0)
			{
				RollForFlip(conn, m.BetItemObjectId);
			}
		}
	}

	private static void RollForFlip(NetworkConnection gambler, int itemObjectId)
	{
		if (!((ManagedObjects)InstanceFinder.ServerManager.Objects).Spawned.TryGetValue(itemObjectId, out var value) || (Object)(object)value == (Object)null)
		{
			return;
		}
		Item component = ((Component)value).GetComponent<Item>();
		if (!((Object)(object)component == (Object)null))
		{
			int num = CoinGamble.Depth(component);
			float num2 = CoinGamble.HeadsChance(num);
			bool flag = Random.value >= num2;
			_serverRolls[itemObjectId] = flag;
			Plugin.Log.Info("Coin roll: " + component.GetName() + " depth " + num + " (heads " + Mathf.RoundToInt(num2 * 100f) + "%) -> " + (flag ? "TAILS" : "HEADS"));
			FlipOutcomeMsg flipOutcomeMsg = new FlipOutcomeMsg
			{
				Version = 3,
				ItemObjectId = itemObjectId,
				Tails = flag,
				Depth = (byte)num
			};
			if (gambler.IsLocalClient)
			{
				OnClientOutcome(flipOutcomeMsg, (Channel)0);
			}
			else
			{
				InstanceFinder.ServerManager.Broadcast<FlipOutcomeMsg>(gambler, flipOutcomeMsg, true, (Channel)0);
			}
		}
	}

	private static bool TakeServerRoll(int itemObjectId, bool claimed)
	{
		if (_serverRolls.TryGetValue(itemObjectId, out var value))
		{
			_serverRolls.Remove(itemObjectId);
			return value;
		}
		return claimed;
	}

	private static void OnClientOutcome(FlipOutcomeMsg m, Channel channel)
	{
		if (m.Version == 3)
		{
			CoinAnim.SetOutcome(m.ItemObjectId, m.Tails);
		}
	}

	private static void OnClientFlip(FlipStartedMsg m, Channel channel)
	{
		if (m.Version == 3)
		{
			Plugin.Log.Info("CoinNet: flip msg received from " + m.PlayerObjectId);
			if (!((Object)(object)Player.LocalPlayer != (Object)null) || m.PlayerObjectId != ((NetworkBehaviour)Player.LocalPlayer).ObjectId)
			{
				CoinLock.Add(m.BetItemObjectId);
				CoinRemote.OnRemoteFlip(m.PlayerObjectId);
			}
		}
	}

	private static void WriteOutcome(Writer w, FlipOutcomeMsg m)
	{
		w.WriteByte(m.Version);
		w.WriteInt32(m.ItemObjectId);
		w.WriteBoolean(m.Tails);
		w.WriteByte(m.Depth);
	}

	private static FlipOutcomeMsg ReadOutcome(Reader r)
	{
		return new FlipOutcomeMsg
		{
			Version = r.ReadByte(),
			ItemObjectId = r.ReadInt32(),
			Tails = r.ReadBoolean(),
			Depth = r.ReadByte()
		};
	}

	private static void WriteRequest(Writer w, GambleRequestMsg m)
	{
		w.WriteByte(m.Version);
		w.WriteInt32(m.ItemObjectId);
		w.WriteBoolean(m.Tails);
	}

	private static void WriteFlip(Writer w, FlipStartedMsg m)
	{
		w.WriteByte(m.Version);
		w.WriteInt32(m.PlayerObjectId);
		w.WriteInt32(m.BetItemObjectId);
	}

	private static FlipStartedMsg ReadFlip(Reader r)
	{
		return new FlipStartedMsg
		{
			Version = r.ReadByte(),
			PlayerObjectId = r.ReadInt32(),
			BetItemObjectId = r.ReadInt32()
		};
	}

	private static GambleRequestMsg ReadRequest(Reader r)
	{
		return new GambleRequestMsg
		{
			Version = r.ReadByte(),
			ItemObjectId = r.ReadInt32(),
			Tails = r.ReadBoolean()
		};
	}

	private static void WriteResult(Writer w, GambleResultMsg m)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		w.WriteByte(m.Version);
		w.WriteInt32(m.ItemObjectId);
		w.WriteVector3(m.Pos);
		w.WriteBoolean(m.Win);
		w.WriteInt32(m.NewWorth);
	}

	private static GambleResultMsg ReadResult(Reader r)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		return new GambleResultMsg
		{
			Version = r.ReadByte(),
			ItemObjectId = r.ReadInt32(),
			Pos = r.ReadVector3(),
			Win = r.ReadBoolean(),
			NewWorth = r.ReadInt32()
		};
	}

	private static void PurgeStaleHandlers(object manager)
	{
		if (manager == null || !(manager.GetType().GetField("_broadcastHandlers", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(manager) is IDictionary dictionary))
		{
			return;
		}
		List<object> list = new List<object>();
		foreach (DictionaryEntry item in dictionary)
		{
			Type type = item.Value?.GetType();
			if (type == null || !type.IsGenericType)
			{
				continue;
			}
			Type[] genericArguments = type.GetGenericArguments();
			if (genericArguments.Length == 1)
			{
				string fullName = genericArguments[0].FullName;
				if (fullName == typeof(GambleRequestMsg).FullName || fullName == typeof(GambleResultMsg).FullName || fullName == typeof(FlipStartedMsg).FullName || fullName == typeof(FlipOutcomeMsg).FullName)
				{
					list.Add(item.Key);
				}
			}
		}
		foreach (object item2 in list)
		{
			dictionary.Remove(item2);
		}
		if (list.Count > 0)
		{
			Plugin.Log.Info("CoinNet purged " + list.Count + " stale handler(s) (hot reload).");
		}
	}
}
internal static class CoinRemote
{
	private class RemoteCoin
	{
		public Player Holder;

		public Item Item;

		public Animation Anim;

		public Transform Wrist;

		public GameObject Coin;

		public bool Flipping;
	}

	private static readonly FieldInfo AnimField = typeof(Tool).GetField("_anim", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo HandsMeshField = typeof(Tool).GetField("_handsMesh", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly Dictionary<Player, RemoteCoin> _coins = new Dictionary<Player, RemoteCoin>();

	private static readonly HashSet<Player> _holdersNow = new HashSet<Player>();

	private static readonly List<Player> _tmp = new List<Player>();

	private static float _nextScan;

	internal static void Tick()
	{
		if (Time.unscaledTime < _nextScan)
		{
			TickFlips();
			return;
		}
		_nextScan = Time.unscaledTime + 0.5f;
		_holdersNow.Clear();
		foreach (KeyValuePair<Transform, Item> item in ItemManager.Items)
		{
			Item value = item.Value;
			if (!((Object)(object)value == (Object)null) && value.ID == 201 && !value.IsInInventory && ((Component)value).gameObject.activeInHierarchy)
			{
				Player syncedHolder = value.SyncedHolder;
				if ((Object)(object)syncedHolder != (Object)null && (Object)(object)syncedHolder != (Object)(object)Player.LocalPlayer)
				{
					_holdersNow.Add(syncedHolder);
				}
			}
		}
		foreach (Player item2 in _holdersNow)
		{
			if (!_coins.ContainsKey(item2))
			{
				Create(item2);
			}
		}
		_tmp.Clear();
		foreach (KeyValuePair<Player, RemoteCoin> coin in _coins)
		{
			if ((Object)(object)coin.Key == (Object)null || !_holdersNow.Contains(coin.Key))
			{
				_tmp.Add(coin.Key);
			}
		}
		foreach (Player item3 in _tmp)
		{
			Remove(item3);
		}
		TickFlips();
	}

	private static void TickFlips()
	{
		foreach (KeyValuePair<Player, RemoteCoin> coin in _coins)
		{
			RemoteCoin value = coin.Value;
			if (value.Flipping && !((Object)(object)value.Anim == (Object)null))
			{
				AnimationState val = value.Anim["Flip"];
				if ((TrackedReference)(object)val == (TrackedReference)null || !value.Anim.IsPlaying("Flip") || val.time >= CoinAnim.FlipClip.length - 0.001f)
				{
					value.Flipping = false;
					value.Anim.Play("Idle");
					SetHandsVisible(value, on: false);
				}
			}
		}
	}

	internal static void EndOfFrame()
	{
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		foreach (KeyValuePair<Player, RemoteCoin> coin in _coins)
		{
			RemoteCoin value = coin.Value;
			if ((Object)(object)value.Wrist == (Object)null || (Object)(object)value.Coin == (O