Decompiled source of ScorchedVoxels v0.20.72

ScorchedVoxels.dll

Decompiled a month ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using R2API.Networking;
using R2API.Networking.Interfaces;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Navigation;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Stats;
using RoR2.UI;
using TMPro;
using Unity.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ScorchedVoxels")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.20.72.0")]
[assembly: AssemblyInformationalVersion("0.20.72+a4d65434dd33f229551efc8d9b06c8cae4d20476")]
[assembly: AssemblyProduct("ScorchedVoxels")]
[assembly: AssemblyTitle("ScorchedVoxels")]
[assembly: AssemblyVersion("0.20.72.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ScorchedVoxels
{
	internal class ArcadeColorGrid
	{
		private class Tile
		{
			public int idx;

			public UiTile ui;

			public Image sprite;

			public Image swatch;

			public UiKit.Label badge;
		}

		public const float TileW = 96f;

		public const float TileH = 112f;

		public const float Gap = 8f;

		private const float SpriteScale = 6f;

		private readonly List<Tile> tiles = new List<Tile>();

		private string profileKey;

		public Action onChanged;

		public int PickedCount => UserLifetimeStats.ArcadeColors(profileKey).Count;

		public float Build(RectTransform content, float contentW, string userProfileKey)
		{
			profileKey = userProfileKey;
			tiles.Clear();
			int num = Mathf.Max(2, Mathf.FloorToInt((contentW + 8f) / 104f));
			float num2 = (0f - ((float)num * 96f + (float)(num - 1) * 8f)) * 0.5f;
			for (int i = 0; i < 16; i++)
			{
				int num3 = i % num;
				int num4 = i / num;
				float x = num2 + (float)num3 * 104f + 48f;
				float y = 0f - ((float)num4 * 120f + 56f);
				tiles.Add(BuildTile(content, i, x, y));
			}
			Refresh();
			return (float)((16 + num - 1) / num) * 120f;
		}

		private Tile BuildTile(RectTransform content, int idx, float x, float y)
		{
			//IL_0047: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00bf: 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_00e9: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: 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_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: 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_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			Tile tile = new Tile
			{
				idx = idx
			};
			tile.ui = new UiTile($"color_{idx}", content, new Vector2(96f, 112f), new Vector2(x, y), (UnityAction)delegate
			{
				OnTileClicked(idx);
			});
			GameObject val = new GameObject("commando");
			val.transform.SetParent(((Component)tile.ui.Face).transform, false);
			tile.sprite = val.AddComponent<Image>();
			((Graphic)tile.sprite).raycastTarget = false;
			RectTransform rectTransform = ((Graphic)tile.sprite).rectTransform;
			rectTransform.pivot = new Vector2(0.5f, 0f);
			rectTransform.anchorMin = new Vector2(0.5f, 0f);
			rectTransform.anchorMax = new Vector2(0.5f, 0f);
			rectTransform.sizeDelta = new Vector2(36f, 66f);
			rectTransform.anchoredPosition = new Vector2(0f, 26f);
			if (CommandoSprites.Ready)
			{
				tile.sprite.sprite = CommandoSprites.CommandoFrame(idx, 0f);
			}
			else
			{
				((Behaviour)tile.sprite).enabled = false;
				tile.swatch = UiKit.CreateImage("swatch", ((Component)tile.ui.Face).transform, CommandoSprites.Tint(idx));
				((Graphic)tile.swatch).raycastTarget = false;
				RectTransform rectTransform2 = ((Graphic)tile.swatch).rectTransform;
				rectTransform2.pivot = new Vector2(0.5f, 0f);
				rectTransform2.anchorMin = new Vector2(0.5f, 0f);
				rectTransform2.anchorMax = new Vector2(0.5f, 0f);
				rectTransform2.sizeDelta = new Vector2(36f, 66f);
				rectTransform2.anchoredPosition = new Vector2(0f, 26f);
			}
			UiKit.Label label = UiKit.CreateLabel($"label_{idx}", ((Component)tile.ui.Face).transform, 11f, UiKit.TextPale, (TextAnchor)4);
			label.Rect.anchorMin = new Vector2(0f, 0f);
			label.Rect.anchorMax = new Vector2(1f, 0f);
			label.Rect.pivot = new Vector2(0.5f, 0f);
			label.Rect.sizeDelta = new Vector2(-6f, 20f);
			label.Rect.anchoredPosition = new Vector2(0f, 3f);
			label.ClipSingleLine();
			label.Text = CommandoSprites.ColorwayNames[idx];
			tile.badge = UiKit.CreateLabel($"badge_{idx}", ((Component)tile.ui.Face).transform, 16f, UiKit.Gold, (TextAnchor)4);
			tile.badge.Rect.anchorMin = new Vector2(1f, 1f);
			tile.badge.Rect.anchorMax = new Vector2(1f, 1f);
			tile.badge.Rect.sizeDelta = new Vector2(22f, 22f);
			tile.badge.Rect.anchoredPosition = new Vector2(-14f, -14f);
			tile.badge.Bold();
			tile.badge.Text = "";
			return tile;
		}

		private void OnTileClicked(int idx)
		{
			List<int> list = new List<int>(UserLifetimeStats.ArcadeColors(profileKey));
			if (list.Contains(idx))
			{
				list.Remove(idx);
			}
			else if (list.Count < 3)
			{
				list.Add(idx);
			}
			else
			{
				list[2] = idx;
			}
			UserLifetimeStats.SetArcadeColors(profileKey, list);
			Refresh();
			onChanged?.Invoke();
		}

		public void Refresh()
		{
			IReadOnlyList<int> readOnlyList = UserLifetimeStats.ArcadeColors(profileKey);
			foreach (Tile tile in tiles)
			{
				int num = -1;
				for (int i = 0; i < readOnlyList.Count; i++)
				{
					if (readOnlyList[i] == tile.idx)
					{
						num = i;
						break;
					}
				}
				tile.ui.Selected = num == 0;
				tile.badge.Text = ((num >= 0) ? (num + 1).ToString() : "");
			}
		}

		public void Tick()
		{
			if (!CommandoSprites.Ready)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			foreach (Tile tile in tiles)
			{
				tile.sprite.sprite = CommandoSprites.CommandoFrame(tile.idx, unscaledTime);
				if (!((Behaviour)tile.sprite).enabled)
				{
					((Behaviour)tile.sprite).enabled = true;
				}
				if ((Object)(object)tile.swatch != (Object)null && ((Behaviour)tile.swatch).enabled)
				{
					((Behaviour)tile.swatch).enabled = false;
				}
			}
		}
	}
	internal static class ArcadeTheming
	{
		public static string DestinationScene;
	}
	internal static class ArcadeLocal
	{
		public static NetworkUser User()
		{
			foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
			{
				if ((Object)(object)readOnlyInstances != (Object)null && ((NetworkBehaviour)readOnlyInstances).isLocalPlayer)
				{
					return readOnlyInstances;
				}
			}
			return null;
		}

		public static string ProfileKey()
		{
			NetworkUser val = User();
			if (!((Object)(object)val == (Object)null))
			{
				return UserLifetimeStats.ProfileKey(val);
			}
			return null;
		}

		public static uint NetId()
		{
			//IL_0010: 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)
			NetworkUser val = User();
			if (!((Object)(object)val == (Object)null))
			{
				NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
				return ((NetworkInstanceId)(ref netId)).Value;
			}
			return 0u;
		}

		public static int PreferredColorway()
		{
			//IL_002d: 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)
			NetworkUser val = User();
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			IReadOnlyList<int> readOnlyList = UserLifetimeStats.ArcadeColors(val);
			if (readOnlyList != null && readOnlyList.Count > 0)
			{
				return readOnlyList[0];
			}
			NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
			return CommandoSprites.ColorwayFor(((NetworkInstanceId)(ref netId)).Value);
		}
	}
	internal static class ArcadeRng
	{
		public static uint Step(ref uint state)
		{
			uint num = state;
			num ^= num << 13;
			num ^= num >> 17;
			num ^= num << 5;
			return state = num;
		}

		public static int Next(ref uint state, int maxExclusive)
		{
			return (int)(Step(ref state) % (uint)maxExclusive);
		}
	}
	internal class ArcadeContext
	{
		public uint seed;

		public RectTransform panel;

		public float width;

		public float height;

		public WormsGame.MatchConfig wormsMatch;

		public RaceGame.MatchConfig raceMatch;
	}
	internal interface IMiniGame
	{
		void Start(ArcadeContext ctx);

		void Tick(float dt);

		void End();
	}
	internal static class ArcadeInput
	{
		public static bool Blocked;

		public static bool ActionDown;

		public static bool ActionHeld;

		public static bool RopeDown;

		public static bool RopeHeld;

		public static bool DuckHeld;

		public static bool ToggleDown;

		public static void Poll(RectTransform clickArea)
		{
			//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)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if (Blocked)
			{
				ActionDown = (ActionHeld = (RopeDown = (RopeHeld = (DuckHeld = (ToggleDown = false)))));
				return;
			}
			ActionDown = Input.GetKeyDown((KeyCode)32) || Input.GetKeyDown((KeyCode)119) || Input.GetKeyDown((KeyCode)273) || (Input.GetMouseButtonDown(0) && inArea(Vector2.op_Implicit(Input.mousePosition)));
			ActionHeld = Input.GetKey((KeyCode)32) || Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)273) || Input.GetMouseButton(0);
			RopeDown = Input.GetKeyDown((KeyCode)115) || Input.GetKeyDown((KeyCode)274) || Input.GetKeyDown((KeyCode)306) || (Input.GetMouseButtonDown(1) && inArea(Vector2.op_Implicit(Input.mousePosition)));
			RopeHeld = Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)274) || Input.GetKey((KeyCode)306) || Input.GetMouseButton(1);
			DuckHeld = Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)274) || Input.GetKey((KeyCode)306);
			ToggleDown = Input.GetKeyDown((KeyCode)103);
			bool inArea(Vector2 p)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)clickArea != (Object)null)
				{
					return RectTransformUtility.RectangleContainsScreenPoint(clickArea, p);
				}
				return false;
			}
		}
	}
	internal static class ArcadeHost
	{
		internal enum GameKind
		{
			Runner,
			Worms,
			Race,
			Terrarium
		}

		private abstract class MatchChannel
		{
			protected const float ResendSeconds = 2f;

			protected const float HostSilenceFoldSeconds = 8f;

			protected readonly bool hostLive;

			protected float nextResendAt;

			protected float lastHostMsgAt;

			protected abstract uint HostMatchId { get; }

			protected abstract uint RunningMatchId { get; }

			protected abstract bool JoinPending { get; }

			protected MatchChannel(bool hostLive)
			{
				this.hostLive = hostLive;
				lastHostMsgAt = Time.unscaledTime;
			}

			protected abstract void StartPendingGame();

			protected abstract void SendAnnounce();

			protected abstract void SendTeardown();

			protected abstract void HostTickCanon();

			protected abstract void Close();

			public void StampHostMsg()
			{
				lastHostMsgAt = Time.unscaledTime;
			}

			public void Tick()
			{
				if (JoinPending)
				{
					if (!uiBuilt)
					{
						return;
					}
					StartPendingGame();
				}
				if (!NetworkServer.active)
				{
					if (RunningMatchId != 0 && Time.unscaledTime - lastHostMsgAt > 8f)
					{
						Close();
						FoldLocalMatch();
					}
				}
				else
				{
					if (!hostLive)
					{
						return;
					}
					if (RunningMatchId != HostMatchId)
					{
						SendTeardown();
						Close();
						return;
					}
					HostTickCanon();
					if (Time.unscaledTime >= nextResendAt)
					{
						nextResendAt = Time.unscaledTime + 2f;
						SendAnnounce();
					}
				}
			}
		}

		private sealed class WormsChannel : MatchChannel
		{
			private readonly WormsGame.MatchConfig hostCfg;

			private WormsGame.MatchConfig pendingCfg;

			private WormsShot[] pendingShots;

			private readonly List<WormsShot> shotLog = new List<WormsShot>();

			private WormsShot[] shotLogCache = Array.Empty<WormsShot>();

			private readonly List<WormsShot> requestQueue = new List<WormsShot>();

			private readonly HashSet<uint> forfeited = new HashSet<uint>();

			private int timedShotCount = -1;

			private float turnDeadlineAt;

			protected override uint HostMatchId => hostCfg.matchId;

			protected override uint RunningMatchId
			{
				get
				{
					if (!(game is WormsGame wormsGame))
					{
						return 0u;
					}
					return wormsGame.MatchId;
				}
			}

			protected override bool JoinPending => pendingCfg != null;

			private WormsChannel(bool hostLive, WormsGame.MatchConfig hostCfg)
				: base(hostLive)
			{
				this.hostCfg = hostCfg;
			}

			public static WormsChannel Host(WormsGame.MatchConfig cfg)
			{
				return new WormsChannel(hostLive: true, cfg);
			}

			public static WormsChannel Join(WormsGame.MatchConfig cfg, WormsShot[] shots)
			{
				WormsChannel wormsChannel = new WormsChannel(hostLive: false, null);
				if (uiBuilt)
				{
					StartGame(GameKind.Worms, cfg, null);
					if (game is WormsGame wormsGame)
					{
						wormsGame.CatchUp(shots);
					}
				}
				else
				{
					wormsChannel.pendingCfg = cfg;
					wormsChannel.pendingShots = shots;
				}
				return wormsChannel;
			}

			public bool OwnsMatch(uint matchId)
			{
				if (hostLive)
				{
					return hostCfg.matchId == matchId;
				}
				return false;
			}

			protected override void StartPendingGame()
			{
				WormsGame.MatchConfig matchCfg = pendingCfg;
				WormsShot[] array = pendingShots;
				pendingCfg = null;
				pendingShots = null;
				StartGame(GameKind.Worms, matchCfg, null);
				if (game is WormsGame wormsGame && array != null)
				{
					wormsGame.CatchUp(array);
				}
			}

			protected override void SendAnnounce()
			{
				if (shotLogCache.Length != shotLog.Count)
				{
					shotLogCache = shotLog.ToArray();
				}
				NetMessageExtensions.Send((INetMessage)(object)new WormsMatchMessage(hostCfg.matchId, hostCfg.seed, hostCfg.ids, hostCfg.colorways, shotLogCache), (NetworkDestination)1);
			}

			protected override void SendTeardown()
			{
				NetMessageExtensions.Send((INetMessage)(object)new WormsMatchMessage(0u, 0u, Array.Empty<uint>(), Array.Empty<byte>(), Array.Empty<WormsShot>()), (NetworkDestination)1);
			}

			protected override void HostTickCanon()
			{
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				WormsGame wormsGame = (WormsGame)game;
				if (wormsGame.MatchOver)
				{
					requestQueue.Clear();
					return;
				}
				while (!wormsGame.InFlight && !wormsGame.MatchOver && requestQueue.Count > 0)
				{
					WormsShot shot = requestQueue[0];
					requestQueue.RemoveAt(0);
					HostApplyShot(shot);
				}
				if (wormsGame.MatchOver)
				{
					return;
				}
				uint currentTurnOwner = wormsGame.CurrentTurnOwner;
				if (currentTurnOwner != 0)
				{
					bool flag = false;
					foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
					{
						if ((Object)(object)readOnlyInstances != (Object)null)
						{
							NetworkInstanceId netId = ((NetworkBehaviour)readOnlyInstances).netId;
							if (((NetworkInstanceId)(ref netId)).Value == currentTurnOwner)
							{
								flag = true;
								break;
							}
						}
					}
					if (!flag && forfeited.Add(currentTurnOwner))
					{
						HostApplyShot(new WormsShot
						{
							shooterNetId = currentTurnOwner,
							weapon = 254
						});
					}
				}
				if (wormsGame.InFlight || wormsGame.KnownShotCount != timedShotCount)
				{
					timedShotCount = wormsGame.KnownShotCount;
					turnDeadlineAt = Time.unscaledTime + 45f;
				}
				else if (currentTurnOwner != 0 && Time.unscaledTime >= turnDeadlineAt)
				{
					HostApplyShot(new WormsShot
					{
						shooterNetId = currentTurnOwner,
						weapon = byte.MaxValue
					});
				}
			}

			protected override void Close()
			{
				wormsChannel = null;
			}

			public void HostApplyClientRequest(WormsShot shot)
			{
				//IL_0024: 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)
				if (!WormsGame.ValidWeaponByte(shot.weapon))
				{
					return;
				}
				NetworkUser val = ArcadeLocal.User();
				if ((Object)(object)val != (Object)null)
				{
					uint shooterNetId = shot.shooterNetId;
					NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
					if (shooterNetId == ((NetworkInstanceId)(ref netId)).Value)
					{
						return;
					}
				}
				HostApplyShot(shot);
			}

			public void HostApplyShot(WormsShot shot)
			{
				if (!hostLive || !(game is WormsGame wormsGame) || wormsGame.MatchId != hostCfg.matchId || wormsGame.MatchOver || (shot.weapon != byte.MaxValue && shot.weapon != 254 && !WormsGame.ValidWeaponByte(shot.weapon)))
				{
					return;
				}
				if (wormsGame.InFlight)
				{
					for (int num = requestQueue.Count - 1; num >= 0; num--)
					{
						if (requestQueue[num].shooterNetId == shot.shooterNetId && requestQueue[num].weapon != 254)
						{
							requestQueue.RemoveAt(num);
						}
					}
					requestQueue.Add(shot);
				}
				else if (shot.weapon == 254 || shot.shooterNetId == wormsGame.CurrentTurnOwner)
				{
					int count = shotLog.Count;
					shotLog.Add(shot);
					wormsGame.ApplyShot(shot, animate: true);
					NetMessageExtensions.Send((INetMessage)(object)new WormsShotMessage(hostCfg.matchId, (ushort)count, shot), (NetworkDestination)1);
				}
			}
		}

		private sealed class RaceChannel : MatchChannel
		{
			private readonly RaceGame.MatchConfig hostCfg;

			private RaceGame.MatchConfig pendingCfg;

			private float roundBumpAt;

			protected override uint HostMatchId => hostCfg.matchId;

			protected override uint RunningMatchId
			{
				get
				{
					if (!(game is RaceGame raceGame))
					{
						return 0u;
					}
					return raceGame.MatchId;
				}
			}

			protected override bool JoinPending => pendingCfg != null;

			private RaceChannel(bool hostLive, RaceGame.MatchConfig hostCfg)
				: base(hostLive)
			{
				this.hostCfg = hostCfg;
			}

			public static RaceChannel Host(RaceGame.MatchConfig cfg)
			{
				return new RaceChannel(hostLive: true, cfg);
			}

			public static RaceChannel Join(RaceGame.MatchConfig cfg)
			{
				RaceChannel raceChannel = new RaceChannel(hostLive: false, null);
				if (uiBuilt)
				{
					StartGame(GameKind.Race, null, cfg);
				}
				else
				{
					raceChannel.pendingCfg = cfg;
				}
				return raceChannel;
			}

			protected override void StartPendingGame()
			{
				RaceGame.MatchConfig raceCfg = pendingCfg;
				pendingCfg = null;
				StartGame(GameKind.Race, null, raceCfg);
			}

			protected override void SendAnnounce()
			{
				NetMessageExtensions.Send((INetMessage)(object)new RaceMatchMessage(hostCfg.matchId, hostCfg.seed, hostCfg.round, hostCfg.ids, hostCfg.colorways, hostCfg.wins), (NetworkDestination)1);
			}

			protected override void SendTeardown()
			{
				NetMessageExtensions.Send((INetMessage)(object)new RaceMatchMessage(0u, 0u, 0, Array.Empty<uint>(), Array.Empty<byte>(), Array.Empty<byte>()), (NetworkDestination)1);
			}

			protected override void HostTickCanon()
			{
				RaceGame raceGame = (RaceGame)game;
				if (raceGame.TryTakeRoundWinner(out var winner))
				{
					for (int i = 0; i < hostCfg.ids.Length; i++)
					{
						if (hostCfg.ids[i] == winner && hostCfg.wins[i] < byte.MaxValue)
						{
							hostCfg.wins[i]++;
						}
					}
					raceGame.ApplyMatchState(hostCfg.round, hostCfg.wins);
					roundBumpAt = Time.unscaledTime + 3f;
					nextResendAt = 0f;
				}
				if (roundBumpAt > 0f && Time.unscaledTime >= roundBumpAt)
				{
					roundBumpAt = 0f;
					hostCfg.round++;
					raceGame.ApplyMatchState(hostCfg.round, hostCfg.wins);
					nextResendAt = 0f;
				}
			}

			protected override void Close()
			{
				raceChannel = null;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__ToggleColorPanel;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Action <>9__50_0;

			public static UnityAction <>9__51_0;

			public static UnityAction <>9__51_1;

			public static UnityAction <>9__51_2;

			public static UnityAction <>9__51_3;

			public static UnityAction <>9__51_4;

			internal void <ToggleColorPanel>b__50_0()
			{
				if (colorCount != null)
				{
					colorCount.Text = $"{colorGrid.PickedCount} / 3 picked";
				}
			}

			internal void <BuildUi>b__51_0()
			{
				StartOrStop(GameKind.Runner);
			}

			internal void <BuildUi>b__51_1()
			{
				StartOrStop(GameKind.Race);
			}

			internal void <BuildUi>b__51_2()
			{
				StartOrStop(GameKind.Worms);
			}

			internal void <BuildUi>b__51_3()
			{
				StartOrStop(GameKind.Terrarium);
			}

			internal void <BuildUi>b__51_4()
			{
				holdEngaged = !holdEngaged;
				holdBtn.Text = (holdEngaged ? "UNLOCK LOADING" : "LOCK LOADING");
			}
		}

		private const float ButtonH = 30f;

		internal const float RunnerStripH = 150f;

		internal const float RunnerSoloW = 480f;

		private const float WormsStripW = 1100f;

		private const float WormsStripH = 185f;

		private const float RaceStripW = 1100f;

		private const float RaceStripH = 208f;

		private const float TankStripW = 700f;

		private const float TankStripH = 185f;

		private const float StripBottomLimit = -408f;

		internal const float CeremonyGraceSeconds = 3f;

		private const float ReelArrivalGrace = 1.5f;

		private static float lastLotteryAt = -1f;

		private static bool holdEngaged;

		private static UiKit.Btn holdBtn;

		private static GameKind activeKind;

		private static GameKind lastKind = GameKind.Runner;

		private static float stripH = 150f;

		private static float btnNoteUntil;

		private static UiKit.Btn btnNoteOn;

		private static string btnNotePrior;

		private static GameObject root;

		private static float attachedAt;

		private static bool uiBuilt;

		private static UiKit.Btn playBtn;

		private static UiKit.Btn raceBtn;

		private static UiKit.Btn wormsBtn;

		private static UiKit.Btn tankBtn;

		private static UiKit.Btn colorsBtn;

		private static GameObject colorPanel;

		private static ArcadeColorGrid colorGrid;

		private static UiKit.Label colorCount;

		private static GameObject strip;

		private static RectTransform stripRect;

		private static RectTransform stripContent;

		private static IMiniGame game;

		private static float matchStartedAt;

		private const float StopArmSeconds = 0.75f;

		private static WormsChannel wormsChannel;

		private static RaceChannel raceChannel;

		public static bool CeremonyClosed { get; private set; }

		public static bool HoldingLoadingScreen
		{
			get
			{
				if ((Object)(object)root != (Object)null && uiBuilt)
				{
					return holdEngaged;
				}
				return false;
			}
		}

		public static bool StripOpen => (Object)(object)strip != (Object)null;

		public static float StripReserve
		{
			get
			{
				if (!((Object)(object)strip != (Object)null))
				{
					return 0f;
				}
				return stripH + 44f;
			}
		}

		public static void Attach(GameObject overlayRoot)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			CeremonyClosed = false;
			lastLotteryAt = -1f;
			uiBuilt = false;
			holdEngaged = false;
			attachedAt = Time.unscaledTime;
			root = new GameObject("arcade");
			root.transform.SetParent(overlayRoot.transform, false);
			UiKit.Stretch(root.AddComponent<RectTransform>());
			if (ModOptions.ArcadeEnabled.Value)
			{
				CommandoSprites.EnsureLoading();
				WeaponIcons.EnsureLoading();
			}
		}

		public static void Detach()
		{
			EndGame();
			SpectateStrips.Clear();
			TerrariumStrips.Clear();
			ArcadeSpectate.Clear();
			RaceSpectate.Clear();
			TerrariumNet.Clear();
			DropMatchChannels();
			RaceSpectate.ActiveMatchId = 0u;
			btnNoteUntil = 0f;
			btnNoteOn = null;
			btnNotePrior = null;
			matchStartedAt = 0f;
			root = null;
			playBtn = null;
			raceBtn = null;
			wormsBtn = null;
			tankBtn = null;
			colorsBtn = null;
			colorPanel = null;
			colorGrid = null;
			colorCount = null;
			holdBtn = null;
			strip = null;
			stripRect = null;
			stripContent = null;
			uiBuilt = false;
			holdEngaged = false;
			CeremonyClosed = false;
			lastLotteryAt = -1f;
		}

		public static void Tick()
		{
			if ((Object)(object)root == (Object)null || !ModOptions.ArcadeEnabled.Value)
			{
				return;
			}
			int num;
			if (!CeremonyClosed)
			{
				if (!LoadingOverlay.AnyReelAwaitingShow)
				{
					num = (LoadingOverlay.AnyReelLive ? 1 : 0);
					if (num == 0)
					{
						goto IL_003d;
					}
				}
				else
				{
					num = 1;
				}
				lastLotteryAt = Time.unscaledTime;
				goto IL_003d;
			}
			goto IL_0098;
			IL_003d:
			float num2 = ((num != 0) ? float.MaxValue : ((!(lastLotteryAt >= 0f)) ? ((NetworkUser.readOnlyInstancesList.Count > 1) ? (attachedAt + 1.5f) : attachedAt) : lastLotteryAt));
			if (Time.unscaledTime < num2)
			{
				return;
			}
			CeremonyClosed = true;
			CommandoSprites.EnsureLoading();
			WeaponIcons.EnsureLoading();
			goto IL_0098;
			IL_0098:
			if (CommandoSprites.Failed)
			{
				return;
			}
			if (!uiBuilt)
			{
				if (!CommandoSprites.Ready)
				{
					return;
				}
				BuildUi();
			}
			PositionUi();
			if (holdBtn != null)
			{
				bool flag = NetworkUser.readOnlyInstancesList.Count <= 1 || NetworkServer.active;
				if (holdBtn.Go.activeSelf != flag)
				{
					holdBtn.Go.SetActive(flag);
				}
			}
			ArcadeInput.Blocked = (Object)(object)colorPanel != (Object)null;
			ArcadeInput.Poll(stripContent);
			bool flag2 = game is WormsGame { MatchId: not 0u } || (game is RaceGame raceGame && raceGame.MatchId != 0);
			bool flag3 = (lastKind == GameKind.Worms || lastKind == GameKind.Race) && NetworkUser.readOnlyInstancesList.Count > 1;
			if (ArcadeInput.ToggleDown && !flag2 && !flag3)
			{
				StartOrStop(lastKind);
			}
			colorGrid?.Tick();
			SpectateStrips.Tick();
			TerrariumStrips.Tick();
			if (game != null && ((Object)(object)colorPanel == (Object)null || flag2))
			{
				game.Tick(Mathf.Min(Time.unscaledDeltaTime, 0.05f));
			}
			TickButtonNote();
			TickMatchChannels();
		}

		private static void ToggleColorPanel()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00dc: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: 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_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: 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)
			if ((Object)(object)colorPanel != (Object)null)
			{
				Object.Destroy((Object)(object)colorPanel);
				colorPanel = null;
				colorGrid = null;
				colorCount = null;
				return;
			}
			string text = ArcadeLocal.ProfileKey() ?? UserLifetimeStats.ProfileKey(LocalUserManager.GetFirstLocalUser());
			if (text == null)
			{
				return;
			}
			colorPanel = new GameObject("arcadeColorModal");
			colorPanel.transform.SetParent(root.transform, false);
			UiKit.Stretch(colorPanel.AddComponent<RectTransform>());
			Image obj = UiKit.CreateImage("dim", colorPanel.transform, new Color(0f, 0f, 0f, 0.55f));
			UiKit.Stretch(((Graphic)obj).rectTransform);
			ButtonClickedEvent onClick = ((Component)obj).gameObject.AddComponent<Button>().onClick;
			object obj2 = <>O.<0>__ToggleColorPanel;
			if (obj2 == null)
			{
				UnityAction val = ToggleColorPanel;
				<>O.<0>__ToggleColorPanel = val;
				obj2 = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj2);
			UiWindow uiWindow = new UiWindow("panel", colorPanel.transform, UiKit.PanelSolid, UiKit.OutlineBright);
			GameObject go = uiWindow.Go;
			RectTransform rect = uiWindow.Rect;
			Transform transform = go.transform;
			Vector2 size = new Vector2(26f, 26f);
			object obj3 = <>O.<0>__ToggleColorPanel;
			if (obj3 == null)
			{
				UnityAction val2 = ToggleColorPanel;
				<>O.<0>__ToggleColorPanel = val2;
				obj3 = (object)val2;
			}
			UiKit.Btn btn = UiKit.CreateButton("close", transform, size, 14f, "X", (UnityAction)obj3);
			btn.Rect.anchorMin = new Vector2(1f, 1f);
			btn.Rect.anchorMax = new Vector2(1f, 1f);
			btn.Rect.pivot = new Vector2(1f, 1f);
			btn.Rect.anchoredPosition = new Vector2(-6f, -6f);
			UiKit.Label label = UiKit.CreateLabel("header", go.transform, 17f, UiKit.HeaderTan, (TextAnchor)3);
			label.Rect.anchorMin = new Vector2(0f, 1f);
			label.Rect.anchorMax = new Vector2(1f, 1f);
			label.Rect.pivot = new Vector2(0.5f, 1f);
			label.Rect.sizeDelta = new Vector2(-28f, 36f);
			label.Rect.anchoredPosition = new Vector2(0f, -2f);
			label.Bold();
			label.Text = "ARCADE COLORS";
			colorCount = UiKit.CreateLabel("count", go.transform, 12f, UiKit.TextDim, (TextAnchor)5);
			colorCount.Rect.anchorMin = new Vector2(0f, 1f);
			colorCount.Rect.anchorMax = new Vector2(1f, 1f);
			colorCount.Rect.pivot = new Vector2(0.5f, 1f);
			colorCount.Rect.sizeDelta = new Vector2(-88f, 36f);
			colorCount.Rect.anchoredPosition = new Vector2(-30f, -2f);
			GameObject val3 = new GameObject("content");
			val3.transform.SetParent(go.transform, false);
			RectTransform val4 = val3.AddComponent<RectTransform>();
			val4.anchorMin = new Vector2(0.5f, 1f);
			val4.anchorMax = new Vector2(0.5f, 1f);
			val4.pivot = new Vector2(0.5f, 1f);
			val4.anchoredPosition = new Vector2(0f, -40f);
			colorGrid = new ArcadeColorGrid();
			colorGrid.onChanged = delegate
			{
				if (colorCount != null)
				{
					colorCount.Text = $"{colorGrid.PickedCount} / 3 picked";
				}
			};
			float num = colorGrid.Build(val4, 408f, text);
			val4.sizeDelta = new Vector2(408f, num);
			colorCount.Text = $"{colorGrid.PickedCount} / 3 picked";
			rect.sizeDelta = new Vector2(436f, 40f + num + 14f);
			rect.anchoredPosition = new Vector2(0f, 40f);
		}

		private static void BuildUi()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_010e: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_01b0: 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_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Expected O, but got Unknown
			//IL_01fd: 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_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Expected O, but got Unknown
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: 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_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Expected O, but got Unknown
			uiBuilt = true;
			GameObject gameObject = ((Component)root.transform.parent).gameObject;
			if ((Object)(object)gameObject.GetComponent<GraphicRaycaster>() == (Object)null)
			{
				gameObject.AddComponent<GraphicRaycaster>();
			}
			if ((Object)(object)gameObject.GetComponent<CursorOpener>() == (Object)null)
			{
				gameObject.AddComponent<MPEventSystemProvider>();
				gameObject.AddComponent<MPEventSystemLocator>();
				gameObject.AddComponent<CursorOpener>();
			}
			Transform transform = root.transform;
			Vector2 size = new Vector2(110f, 30f);
			object obj = <>c.<>9__51_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					StartOrStop(GameKind.Runner);
				};
				<>c.<>9__51_0 = val;
				obj = (object)val;
			}
			playBtn = UiKit.CreateButton("arcadeRunner", transform, size, 11f, "RUNNER", (UnityAction)obj);
			Transform transform2 = root.transform;
			Vector2 size2 = new Vector2(110f, 30f);
			object obj2 = <>c.<>9__51_1;
			if (obj2 == null)
			{
				UnityAction val2 = delegate
				{
					StartOrStop(GameKind.Race);
				};
				<>c.<>9__51_1 = val2;
				obj2 = (object)val2;
			}
			raceBtn = UiKit.CreateButton("arcadeRace", transform2, size2, 11f, "RACE", (UnityAction)obj2);
			Transform transform3 = root.transform;
			Vector2 size3 = new Vector2(110f, 30f);
			object obj3 = <>c.<>9__51_2;
			if (obj3 == null)
			{
				UnityAction val3 = delegate
				{
					StartOrStop(GameKind.Worms);
				};
				<>c.<>9__51_2 = val3;
				obj3 = (object)val3;
			}
			wormsBtn = UiKit.CreateButton("arcadeWorms", transform3, size3, 11f, "WORMS", (UnityAction)obj3);
			Transform transform4 = root.transform;
			Vector2 size4 = new Vector2(110f, 30f);
			object obj4 = <>c.<>9__51_3;
			if (obj4 == null)
			{
				UnityAction val4 = delegate
				{
					StartOrStop(GameKind.Terrarium);
				};
				<>c.<>9__51_3 = val4;
				obj4 = (object)val4;
			}
			tankBtn = UiKit.CreateButton("arcadeTank", transform4, size4, 11f, "TANK", (UnityAction)obj4);
			Transform transform5 = root.transform;
			Vector2 size5 = new Vector2(110f, 30f);
			object obj5 = <>O.<0>__ToggleColorPanel;
			if (obj5 == null)
			{
				UnityAction val5 = ToggleColorPanel;
				<>O.<0>__ToggleColorPanel = val5;
				obj5 = (object)val5;
			}
			colorsBtn = UiKit.CreateButton("arcadeColors", transform5, size5, 11f, "COLORS", (UnityAction)obj5);
			Transform transform6 = root.transform;
			Vector2 size6 = new Vector2(150f, 26f);
			object obj6 = <>c.<>9__51_4;
			if (obj6 == null)
			{
				UnityAction val6 = delegate
				{
					holdEngaged = !holdEngaged;
					holdBtn.Text = (holdEngaged ? "UNLOCK LOADING" : "LOCK LOADING");
				};
				<>c.<>9__51_4 = val6;
				obj6 = (object)val6;
			}
			holdBtn = UiKit.CreateButton("arcadeLock", transform6, size6, 13f, "LOCK LOADING", (UnityAction)obj6);
			holdBtn.Rect.anchorMin = Vector2.zero;
			holdBtn.Rect.anchorMax = Vector2.zero;
			holdBtn.Rect.pivot = Vector2.zero;
			holdBtn.Rect.anchoredPosition = new Vector2(14f, 12f);
			holdBtn.Go.SetActive(false);
		}

		private static void PositionUi()
		{
			//IL_013a: 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_016e: 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_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			if (!LoadingOverlay.TryGetLocalCardSlot(out var x, out var width, out var cardBottom))
			{
				if (playBtn.Go.activeSelf)
				{
					playBtn.Go.SetActive(false);
				}
				raceBtn.Go.SetActive(false);
				wormsBtn.Go.SetActive(false);
				tankBtn.Go.SetActive(false);
				colorsBtn.Go.SetActive(false);
				if ((Object)(object)strip != (Object)null)
				{
					strip.SetActive(false);
				}
				return;
			}
			if (!playBtn.Go.activeSelf)
			{
				playBtn.Go.SetActive(true);
				raceBtn.Go.SetActive(true);
				wormsBtn.Go.SetActive(true);
				tankBtn.Go.SetActive(true);
				colorsBtn.Go.SetActive(true);
				if ((Object)(object)strip != (Object)null)
				{
					strip.SetActive(true);
				}
			}
			float num = Mathf.Min(110f, (width - 22f) / 5f);
			float num2 = num + 4f;
			float num3 = cardBottom - 22f;
			playBtn.Rect.sizeDelta = new Vector2(num, 30f);
			raceBtn.Rect.sizeDelta = new Vector2(num, 30f);
			wormsBtn.Rect.sizeDelta = new Vector2(num, 30f);
			tankBtn.Rect.sizeDelta = new Vector2(num, 30f);
			colorsBtn.Rect.sizeDelta = new Vector2(num, 30f);
			playBtn.Rect.anchoredPosition = new Vector2(x - 2f * num2, num3);
			raceBtn.Rect.anchoredPosition = new Vector2(x - 1f * num2, num3);
			wormsBtn.Rect.anchoredPosition = new Vector2(x, num3);
			tankBtn.Rect.anchoredPosition = new Vector2(x + 1f * num2, num3);
			colorsBtn.Rect.anchoredPosition = new Vector2(x + 2f * num2, num3);
			bool interactable = NetworkUser.readOnlyInstancesList.Count <= 1 || NetworkServer.active;
			wormsBtn.Interactable = interactable;
			raceBtn.Interactable = interactable;
			if ((Object)(object)stripRect != (Object)null)
			{
				float x2 = stripRect.sizeDelta.x;
				float num4 = (LoadingOverlay.MultiRowWall ? (LoadingOverlay.WallBottom - 44f) : (cardBottom - 44f));
				num4 = Mathf.Max(num4, -408f + stripH);
				Rect rect = ((RectTransform)root.transform).rect;
				float num5 = ((Rect)(ref rect)).width * 0.5f;
				if (num5 < 1f)
				{
					num5 = 960f;
				}
				float num6 = Mathf.Max(num5 - 10f - x2 * 0.5f, 0f);
				float num7 = Mathf.Clamp(x, 0f - num6, num6);
				stripRect.anchoredPosition = new Vector2(num7, num4 - stripH * 0.5f);
			}
		}

		private static float StripWidthFor(GameKind kind, float cardW)
		{
			switch (kind)
			{
			case GameKind.Worms:
				return 1100f;
			case GameKind.Race:
				return 1100f;
			case GameKind.Terrarium:
				if (NetworkUser.readOnlyInstancesList.Count > 1 && !LoadingOverlay.MultiRowWall)
				{
					return cardW;
				}
				return 700f;
			default:
				if (NetworkUser.readOnlyInstancesList.Count > 1 && !LoadingOverlay.MultiRowWall)
				{
					return cardW;
				}
				return 480f;
			}
		}

		internal static float RunnerFieldWidthFor(float cardW)
		{
			return StripWidthFor(GameKind.Runner, (cardW <= 0f) ? 480f : cardW) - 4f;
		}

		private static void ResetGameButtons()
		{
			playBtn.Text = "RUNNER";
			raceBtn.Text = "RACE";
			wormsBtn.Text = "WORMS";
			tankBtn.Text = "TANK";
			btnNoteUntil = 0f;
			btnNoteOn = null;
			btnNotePrior = null;
		}

		private static void FlashButtonNote(UiKit.Btn btn, string note)
		{
			if (btnNoteOn != btn)
			{
				if (btnNoteOn != null && btnNotePrior != null)
				{
					btnNoteOn.Text = btnNotePrior;
				}
				btnNotePrior = btn.Text;
			}
			btn.Text = note;
			btnNoteOn = btn;
			btnNoteUntil = Time.unscaledTime + 2.5f;
		}

		private static void TickButtonNote()
		{
			if (!(btnNoteUntil <= 0f) && !(Time.unscaledTime < btnNoteUntil))
			{
				btnNoteUntil = 0f;
				if (btnNoteOn != null && btnNotePrior != null)
				{
					btnNoteOn.Text = btnNotePrior;
				}
				btnNoteOn = null;
				btnNotePrior = null;
			}
		}

		private static void StartOrStop(GameKind kind)
		{
			if ((game is WormsGame { MatchId: not 0u } || game is RaceGame { MatchId: not 0u }) && !NetworkServer.active)
			{
				return;
			}
			if (kind == GameKind.Worms && NetworkUser.readOnlyInstancesList.Count > 1)
			{
				if (NetworkServer.active && (!(game is WormsGame wormsGame2) || !StopHostedMatch(wormsGame2.MatchId)))
				{
					StartWormsMultiplayer();
				}
				return;
			}
			if (kind == GameKind.Race && NetworkUser.readOnlyInstancesList.Count > 1)
			{
				if (NetworkServer.active && (!(game is RaceGame raceGame2) || !StopHostedMatch(raceGame2.MatchId)))
				{
					StartRaceMultiplayer();
				}
				return;
			}
			bool flag = game != null && activeKind == kind;
			if (game != null)
			{
				EndGame();
				ResetGameButtons();
				LoadingOverlay.InvalidateCards();
				if (flag)
				{
					return;
				}
			}
			StartGame(kind, null, null);
		}

		private static void StartGame(GameKind kind, WormsGame.MatchConfig matchCfg, RaceGame.MatchConfig raceCfg)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if (game != null)
			{
				EndGame();
			}
			ResetGameButtons();
			activeKind = kind;
			lastKind = kind;
			stripH = kind switch
			{
				GameKind.Terrarium => 185f, 
				GameKind.Race => 208f, 
				GameKind.Worms => 185f, 
				_ => 150f, 
			};
			LoadingOverlay.TryGetLocalCardSlot(out var _, out var width, out var _);
			float num = StripWidthFor(kind, (width <= 0f) ? 480f : width);
			UiWindow uiWindow = new UiWindow("arcadeStrip", root.transform, new Color(0.03f, 0.035f, 0.05f, 0.97f), UiKit.Outline);
			strip = uiWindow.Go;
			stripRect = uiWindow.Rect;
			stripRect.sizeDelta = new Vector2(num, stripH);
			LoadingOverlay.InvalidateCards();
			stripContent = uiWindow.AddMaskedContent();
			ArcadeContext ctx = new ArcadeContext
			{
				seed = VoxelTerrainManager.StageSeed,
				panel = stripContent,
				width = num - 4f,
				height = stripH - 4f,
				wormsMatch = matchCfg,
				raceMatch = raceCfg
			};
			IMiniGame miniGame2;
			switch (kind)
			{
			default:
			{
				IMiniGame miniGame = new RunnerGame();
				miniGame2 = miniGame;
				break;
			}
			case GameKind.Terrarium:
			{
				IMiniGame miniGame = new TerrariumGame();
				miniGame2 = miniGame;
				break;
			}
			case GameKind.Race:
			{
				IMiniGame miniGame = new RaceGame();
				miniGame2 = miniGame;
				break;
			}
			case GameKind.Worms:
			{
				IMiniGame miniGame = new WormsGame();
				miniGame2 = miniGame;
				break;
			}
			}
			game = miniGame2;
			game.Start(ctx);
			(kind switch
			{
				GameKind.Terrarium => tankBtn, 
				GameKind.Race => raceBtn, 
				GameKind.Worms => wormsBtn, 
				_ => playBtn, 
			}).Text = ((matchCfg != null || raceCfg != null) ? "MATCH ON" : "STOP");
		}

		private static void EndGame()
		{
			if (game != null)
			{
				if (game is WormsGame { MatchId: not 0u } || game is RaceGame { MatchId: not 0u })
				{
					lastKind = GameKind.Runner;
				}
				try
				{
					game.End();
				}
				catch (Exception ex)
				{
					ScorchedVoxelsPlugin.Log.LogWarning((object)("[ScorchedVoxels] arcade game teardown: " + ex.Message));
				}
				game = null;
			}
			if ((Object)(object)strip != (Object)null)
			{
				Object.Destroy((Object)(object)strip);
				strip = null;
				stripRect = null;
				stripContent = null;
			}
		}

		private static void FoldLocalMatch()
		{
			EndGame();
			ResetGameButtons();
			LoadingOverlay.InvalidateCards();
		}

		private static void DropMatchChannels()
		{
			wormsChannel = null;
			raceChannel = null;
		}

		private static void TickMatchChannels()
		{
			wormsChannel?.Tick();
			raceChannel?.Tick();
		}

		private static bool StopHostedMatch(uint runningMatchId)
		{
			if (runningMatchId == 0)
			{
				return false;
			}
			if (Time.unscaledTime - matchStartedAt >= 0.75f)
			{
				EndGame();
				ResetGameButtons();
				LoadingOverlay.InvalidateCards();
			}
			return true;
		}

		private static uint[] DraftModdedPlayers(string gameName, UiKit.Btn button)
		{
			//IL_0024: 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)
			List<uint> list = new List<uint>();
			foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
			{
				if (!((Object)(object)readOnlyInstances == (Object)null))
				{
					NetworkInstanceId netId = ((NetworkBehaviour)readOnlyInstances).netId;
					uint value = ((NetworkInstanceId)(ref netId)).Value;
					if ((((NetworkBehaviour)readOnlyInstances).isLocalPlayer || VoxelTerrainManager.IsModdedUser(value)) && !list.Contains(value))
					{
						list.Add(value);
					}
					if (list.Count == 8)
					{
						break;
					}
				}
			}
			if (list.Count < 2)
			{
				ScorchedVoxelsPlugin.Log.LogWarning((object)("[ScorchedVoxels] " + gameName + ": no other modded players to draft"));
				FlashButtonNote(button, "WAITING FOR PLAYERS");
				return null;
			}
			matchStartedAt = Time.unscaledTime;
			return list.ToArray();
		}

		private static uint NewMatchId()
		{
			return (uint)((Environment.TickCount * -1640531535) | 1);
		}

		private static byte[] ResolveColorways(uint[] ids)
		{
			int num = ids.Length;
			int[] array = new int[num];
			bool[] array2 = new bool[16];
			for (int i = 0; i < num; i++)
			{
				array[i] = -1;
			}
			int[] array3 = new int[num];
			for (int j = 0; j < num; j++)
			{
				array3[j] = j;
			}
			Array.Sort(array3, (int a, int b) => ids[a].CompareTo(ids[b]));
			int[] array4;
			for (int num2 = 0; num2 < 3; num2++)
			{
				array4 = array3;
				foreach (int num4 in array4)
				{
					if (array[num4] < 0)
					{
						RosterEntry rosterEntry = LoadingRoster.Find(ids[num4]);
						int num5 = ((rosterEntry == null) ? (-1) : (num2 switch
						{
							1 => rosterEntry.prefB, 
							0 => rosterEntry.prefA, 
							_ => rosterEntry.prefC, 
						}));
						if (num5 >= 0 && num5 < array2.Length && !array2[num5])
						{
							array[num4] = num5;
							array2[num5] = true;
						}
					}
				}
			}
			array4 = array3;
			foreach (int num6 in array4)
			{
				if (array[num6] < 0)
				{
					int num7 = CommandoSprites.ColorwayFor(ids[num6]);
					while (array2[num7])
					{
						num7 = (num7 + 1) % array2.Length;
					}
					array[num6] = num7;
					array2[num7] = true;
				}
			}
			byte[] array5 = new byte[num];
			for (int num8 = 0; num8 < num; num8++)
			{
				array5[num8] = (byte)array[num8];
			}
			return array5;
		}

		private static void StartWormsMultiplayer()
		{
			uint[] array = DraftModdedPlayers("worms", wormsBtn);
			if (array != null)
			{
				uint num = NewMatchId();
				uint seed = VoxelTerrainManager.StageSeed ^ num;
				Random random = new Random((int)seed);
				for (int num2 = array.Length - 1; num2 > 0; num2--)
				{
					int num3 = random.Next(num2 + 1);
					ref uint reference = ref array[num2];
					ref uint reference2 = ref array[num3];
					uint num4 = array[num3];
					uint num5 = array[num2];
					reference = num4;
					reference2 = num5;
				}
				WormsGame.MatchConfig matchConfig = new WormsGame.MatchConfig
				{
					matchId = num,
					seed = seed,
					ids = array,
					colorways = ResolveColorways(array)
				};
				wormsChannel = WormsChannel.Host(matchConfig);
				StartGame(GameKind.Worms, matchConfig, null);
			}
		}

		internal static void HostApplyWormsShot(WormsShot shot)
		{
			wormsChannel?.HostApplyShot(shot);
		}

		internal static void OnWormsShotRequest(uint matchId, WormsShot shot)
		{
			if (wormsChannel != null && wormsChannel.OwnsMatch(matchId))
			{
				wormsChannel.HostApplyClientRequest(shot);
			}
		}

		internal static void OnWormsShot(uint matchId, int index, WormsShot shot)
		{
			if (game is WormsGame wormsGame && wormsGame.MatchId == matchId && index == wormsGame.KnownShotCount)
			{
				wormsGame.QueueCanonShot(shot);
			}
		}

		internal static void OnWormsMatchMessage(uint matchId, uint seed, uint[] ids, byte[] colorways, WormsShot[] shots)
		{
			if ((Object)(object)root == (Object)null || !ModOptions.ArcadeEnabled.Value)
			{
				return;
			}
			if (matchId == 0 || ids.Length == 0)
			{
				if (game is WormsGame { MatchId: not 0u })
				{
					FoldLocalMatch();
				}
				wormsChannel = null;
			}
			else if (game is WormsGame wormsGame2 && wormsGame2.MatchId == matchId)
			{
				wormsChannel?.StampHostMsg();
				wormsGame2.CatchUp(shots);
			}
			else
			{
				wormsChannel = WormsChannel.Join(new WormsGame.MatchConfig
				{
					matchId = matchId,
					seed = seed,
					ids = ids,
					colorways = colorways
				}, shots);
			}
		}

		private static void StartRaceMultiplayer()
		{
			uint[] array = DraftModdedPlayers("race", raceBtn);
			if (array != null)
			{
				uint num = NewMatchId();
				RaceGame.MatchConfig matchConfig = new RaceGame.MatchConfig
				{
					matchId = num,
					seed = (VoxelTerrainManager.StageSeed ^ num),
					ids = array,
					colorways = ResolveColorways(array),
					round = 0,
					wins = new byte[array.Length]
				};
				raceChannel = RaceChannel.Host(matchConfig);
				StartGame(GameKind.Race, null, matchConfig);
			}
		}

		internal static void OnRaceMatchMessage(uint matchId, uint seed, byte round, uint[] ids, byte[] colorways, byte[] wins)
		{
			if ((Object)(object)root == (Object)null || !ModOptions.ArcadeEnabled.Value)
			{
				return;
			}
			if (matchId == 0 || ids.Length == 0)
			{
				if (game is RaceGame { MatchId: not 0u })
				{
					FoldLocalMatch();
				}
				raceChannel = null;
			}
			else if (game is RaceGame raceGame2 && raceGame2.MatchId == matchId)
			{
				raceChannel?.StampHostMsg();
				raceGame2.ApplyMatchState(round, wins);
			}
			else
			{
				raceChannel = RaceChannel.Join(new RaceGame.MatchConfig
				{
					matchId = matchId,
					seed = seed,
					ids = ids,
					colorways = colorways,
					round = round,
					wins = wins
				});
			}
		}
	}
	internal class ArcadeSnapshotMessage : INetMessage, ISerializableObject
	{
		public const int MaxObstacles = 8;

		private uint ownerNetId;

		private byte colorway;

		private ushort score;

		private byte state;

		private byte playerY;

		private byte speed;

		private byte[] obKind = new byte[8];

		private byte[] obX = new byte[8];

		private int obCount;

		public void Set(uint ownerNetId, byte colorway, ushort score, byte state, byte playerY, byte speed, byte[] obKind, byte[] obX, int obCount)
		{
			this.ownerNetId = ownerNetId;
			this.colorway = colorway;
			this.score = score;
			this.state = state;
			this.playerY = playerY;
			this.speed = speed;
			this.obKind = obKind;
			this.obX = obX;
			this.obCount = obCount;
		}

		public void Serialize(NetworkWriter writer)
		{
			writer.WritePackedUInt32(ownerNetId);
			writer.Write(colorway);
			writer.Write(score);
			writer.Write(state);
			writer.Write(playerY);
			writer.Write(speed);
			int num = Mathf.Min(obCount, 8);
			writer.Write((byte)num);
			for (int i = 0; i < num; i++)
			{
				writer.Write(obKind[i]);
				writer.Write(obX[i]);
			}
		}

		public void Deserialize(NetworkReader reader)
		{
			ownerNetId = reader.ReadPackedUInt32();
			colorway = reader.ReadByte();
			score = reader.ReadUInt16();
			state = reader.ReadByte();
			playerY = reader.ReadByte();
			speed = reader.ReadByte();
			int num = reader.ReadByte();
			if (obKind.Length < 8)
			{
				obKind = new byte[8];
				obX = new byte[8];
			}
			obCount = 0;
			for (int i = 0; i < num; i++)
			{
				byte b = reader.ReadByte();
				byte b2 = reader.ReadByte();
				if (obCount < 8)
				{
					obKind[obCount] = b;
					obX[obCount] = b2;
					obCount++;
				}
			}
		}

		public void OnReceived()
		{
			if (NetworkServer.active)
			{
				if (!HostRelay.Relaying)
				{
					ArcadeSpectate.Store(ownerNetId, colorway, score, state, playerY, speed, obKind, obX, obCount);
					HostRelay.FanOut((INetMessage)(object)this, ownerNetId);
				}
			}
			else
			{
				ArcadeSpectate.Store(ownerNetId, colorway, score, state, playerY, speed, obKind, obX, obCount);
			}
		}
	}
	internal static class HostRelay
	{
		private static bool relaying;

		public static bool Relaying => relaying;

		public static void FanOut(INetMessage msg, uint ownerNetId)
		{
			if (ArcadeSpectate.IsLocalPlayer(ownerNetId))
			{
				return;
			}
			relaying = true;
			try
			{
				NetMessageExtensions.Send(msg, (NetworkDestination)1);
			}
			finally
			{
				relaying = false;
			}
		}
	}
	internal struct WormsShot
	{
		public const byte WeaponPass = byte.MaxValue;

		public const byte WeaponForfeit = 254;

		public uint shooterNetId;

		public byte weapon;

		public byte angle;

		public byte power;

		public ushort tx;

		public ushort ty;

		public void Write(NetworkWriter w)
		{
			w.WritePackedUInt32(shooterNetId);
			w.Write(weapon);
			w.Write(angle);
			w.Write(power);
			w.Write(tx);
			w.Write(ty);
		}

		public static WormsShot Read(NetworkReader r)
		{
			return new WormsShot
			{
				shooterNetId = r.ReadPackedUInt32(),
				weapon = r.ReadByte(),
				angle = r.ReadByte(),
				power = r.ReadByte(),
				tx = r.ReadUInt16(),
				ty = r.ReadUInt16()
			};
		}
	}
	internal class WormsMatchMessage : INetMessage, ISerializableObject
	{
		private uint matchId;

		private uint seed;

		private uint[] ids = Array.Empty<uint>();

		private byte[] colorways = Array.Empty<byte>();

		private WormsShot[] shots = Array.Empty<WormsShot>();

		public WormsMatchMessage()
		{
		}

		public WormsMatchMessage(uint matchId, uint seed, uint[] ids, byte[] colorways, WormsShot[] shots)
		{
			this.matchId = matchId;
			this.seed = seed;
			this.ids = ids;
			this.colorways = colorways;
			this.shots = shots;
		}

		public void Serialize(NetworkWriter writer)
		{
			writer.WritePackedUInt32(matchId);
			writer.WritePackedUInt32(seed);
			writer.Write((byte)ids.Length);
			for (int i = 0; i < ids.Length; i++)
			{
				writer.WritePackedUInt32(ids[i]);
				writer.Write(colorways[i]);
			}
			writer.Write((ushort)shots.Length);
			WormsShot[] array = shots;
			foreach (WormsShot wormsShot in array)
			{
				wormsShot.Write(writer);
			}
		}

		public void Deserialize(NetworkReader reader)
		{
			matchId = reader.ReadPackedUInt32();
			seed = reader.ReadPackedUInt32();
			int num = reader.ReadByte();
			ids = new uint[num];
			colorways = new byte[num];
			for (int i = 0; i < num; i++)
			{
				ids[i] = reader.ReadPackedUInt32();
				colorways[i] = reader.ReadByte();
			}
			int num2 = reader.ReadUInt16();
			shots = new WormsShot[num2];
			for (int j = 0; j < num2; j++)
			{
				shots[j] = WormsShot.Read(reader);
			}
		}

		public void OnReceived()
		{
			if (!NetworkServer.active)
			{
				ArcadeHost.OnWormsMatchMessage(matchId, seed, ids, colorways, shots);
			}
		}
	}
	internal class WormsShotRequestMessage : INetMessage, ISerializableObject
	{
		private uint matchId;

		private WormsShot shot;

		public WormsShotRequestMessage()
		{
		}

		public WormsShotRequestMessage(uint matchId, WormsShot shot)
		{
			this.matchId = matchId;
			this.shot = shot;
		}

		public void Serialize(NetworkWriter writer)
		{
			writer.WritePackedUInt32(matchId);
			shot.Write(writer);
		}

		public void Deserialize(NetworkReader reader)
		{
			matchId = reader.ReadPackedUInt32();
			shot = WormsShot.Read(reader);
		}

		public void OnReceived()
		{
			if (NetworkServer.active)
			{
				ArcadeHost.OnWormsShotRequest(matchId, shot);
			}
		}
	}
	internal class WormsShotMessage : INetMessage, ISerializableObject
	{
		private uint matchId;

		private ushort index;

		private WormsShot shot;

		public WormsShotMessage()
		{
		}

		public WormsShotMessage(uint matchId, ushort index, WormsShot shot)
		{
			this.matchId = matchId;
			this.index = index;
			this.shot = shot;
		}

		public void Serialize(NetworkWriter writer)
		{
			writer.WritePackedUInt32(matchId);
			writer.Write(index);
			shot.Write(writer);
		}

		public void Deserialize(NetworkReader reader)
		{
			matchId = reader.ReadPackedUInt32();
			index = reader.ReadUInt16();
			shot = WormsShot.Read(reader);
		}

		public void OnReceived()
		{
			if (!NetworkServer.active)
			{
				ArcadeHost.OnWormsShot(matchId, index, shot);
			}
		}
	}
	internal class RaceMatchMessage : INetMessage, ISerializableObject
	{
		private uint matchId;

		private uint seed;

		private byte round;

		private uint[] ids = Array.Empty<uint>();

		private byte[] colorways = Array.Empty<byte>();

		private byte[] wins = Array.Empty<byte>();

		public RaceMatchMessage()
		{
		}

		public RaceMatchMessage(uint matchId, uint seed, byte round, uint[] ids, byte[] colorways, byte[] wins)
		{
			this.matchId = matchId;
			this.seed = seed;
			this.round = round;
			this.ids = ids;
			this.colorways = colorways;
			this.wins = wins;
		}

		public void Serialize(NetworkWriter writer)
		{
			writer.WritePackedUInt32(matchId);
			writer.WritePackedUInt32(seed);
			writer.Write(round);
			writer.Write((byte)ids.Length);
			for (int i = 0; i < ids.Length; i++)
			{
				writer.WritePackedUInt32(ids[i]);
				writer.Write(colorways[i]);
				writer.Write(wins[i]);
			}
		}

		public void Deserialize(NetworkReader reader)
		{
			matchId = reader.ReadPackedUInt32();
			seed = reader.ReadPackedUInt32();
			round = reader.ReadByte();
			int num = reader.ReadByte();
			ids = new uint[num];
			colorways = new byte[num];
			wins = new byte[num];
			for (int i = 0; i < num; i++)
			{
				ids[i] = reader.ReadPackedUInt32();
				colorways[i] = reader.ReadByte();
				wins[i] = reader.ReadByte();
			}
		}

		public void OnReceived()
		{
			if (!NetworkServer.active)
			{
				ArcadeHost.OnRaceMatchMessage(matchId, seed, round, ids, colorways, wins);
			}
		}
	}
	internal class RaceSnapshotMessage : INetMessage, ISerializableObject
	{
		private uint ownerNetId;

		private uint matchId;

		private byte round;

		private byte colorway;

		private byte state;

		private ushort sQ;

		private byte h;

		private byte speedQ;

		private byte laps;

		private ushort anchorQ;

		public void Set(uint ownerNetId, uint matchId, byte round, byte colorway, byte state, ushort sQ, byte h, byte speedQ, byte laps, ushort anchorQ)
		{
			this.ownerNetId = ownerNetId;
			this.matchId = matchId;
			this.round = round;
			this.colorway = colorway;
			this.state = state;
			this.sQ = sQ;
			this.h = h;
			this.speedQ = speedQ;
			this.laps = laps;
			this.anchorQ = anchorQ;
		}

		public void Serialize(NetworkWriter writer)
		{
			writer.WritePackedUInt32(ownerNetId);
			writer.WritePackedUInt32(matchId);
			writer.Write(round);
			writer.Write(colorway);
			writer.Write(state);
			writer.Write(sQ);
			writer.Write(h);
			writer.Write(speedQ);
			writer.Write(laps);
			writer.Write(anchorQ);
		}

		public void Deserialize(NetworkReader reader)
		{
			ownerNetId = reader.ReadPackedUInt32();
			matchId = reader.ReadPackedUInt32();
			round = reader.ReadByte();
			colorway = reader.ReadByte();
			state = reader.ReadByte();
			sQ = reader.ReadUInt16();
			h = reader.ReadByte();
			speedQ = reader.ReadByte();
			laps = reader.ReadByte();
			anchorQ = reader.ReadUInt16();
		}

		public void OnReceived()
		{
			if (NetworkServer.active)
			{
				if (!HostRelay.Relaying)
				{
					RaceSpectate.Store(ownerNetId, matchId, round, colorway, state, sQ, h, speedQ, laps, anchorQ);
					HostRelay.FanOut((INetMessage)(object)this, ownerNetId);
				}
			}
			else
			{
				RaceSpectate.Store(ownerNetId, matchId, round, colorway, state, sQ, h, speedQ, laps, anchorQ);
			}
		}
	}
	internal static class RaceSpectate
	{
		internal class Snapshot
		{
			public byte round;

			public byte colorway;

			public bool dead;

			public bool roping;

			public bool racing;

			public float s;

			public float h;

			public float speedPxS;

			public int laps;

			public float anchorX;

			public float receivedAt;
		}

		public static readonly Dictionary<uint, Snapshot> Latest = new Dictionary<uint, Snapshot>();

		public static uint ActiveMatchId;

		public static void Store(uint ownerNetId, uint matchId, byte round, byte colorway, byte state, ushort sQ, byte h, byte speedQ, byte laps, ushort anchorQ)
		{
			if (matchId != 0 && matchId == ActiveMatchId && !ArcadeSpectate.IsLocalPlayer(ownerNetId))
			{
				if (!Latest.TryGetValue(ownerNetId, out var value))
				{
					value = (Latest[ownerNetId] = new Snapshot());
				}
				value.round = round;
				value.colorway = colorway;
				value.dead = (state & 1) != 0;
				value.roping = (state & 2) != 0;
				value.racing = (state & 4) != 0;
				value.s = (float)(int)sQ * 2f;
				value.h = (int)h;
				value.speedPxS = (float)(int)speedQ * 3f;
				value.laps = laps;
				value.anchorX = (float)(int)anchorQ * 2f;
				value.receivedAt = Time.unscaledTime;
			}
		}

		public static void Clear()
		{
			Latest.Clear();
		}
	}
	internal static class ArcadeSpectate
	{
		internal class Snapshot
		{
			public byte colorway;

			public ushort score;

			public bool ducking;

			public bool gameOver;

			public byte playerY;

			public float speedPxS;

			public readonly List<(byte kind, byte x)> obstacles = new List<(byte, byte)>();

			public float receivedAt;
		}

		public static readonly Dictionary<uint, Snapshot> Latest = new Dictionary<uint, Snapshot>();

		public const float StaleSeconds = 1.2f;

		public static bool IsLocalPlayer(uint netId)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
			{
				if ((Object)(object)readOnlyInstances != (Object)null && ((NetworkBehaviour)readOnlyInstances).isLocalPlayer)
				{
					NetworkInstanceId netId2 = ((NetworkBehaviour)readOnlyInstances).netId;
					if (((NetworkInstanceId)(ref netId2)).Value == netId)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static void Store(uint ownerNetId, byte colorway, ushort score, byte state, byte playerY, byte speed, byte[] obKind, byte[] obX, int obCount)
		{
			if (!IsLocalPlayer(ownerNetId))
			{
				if (!Latest.TryGetValue(ownerNetId, out var value))
				{
					value = (Latest[ownerNetId] = new Snapshot());
				}
				value.colorway = colorway;
				value.score = score;
				value.ducking = (state & 1) != 0;
				value.gameOver = (state & 2) != 0;
				value.playerY = playerY;
				value.speedPxS = (float)(int)speed * 2f;
				value.obstacles.Clear();
				int num = Mathf.Min(obCount, 8);
				for (int i = 0; i < num; i++)
				{
					value.obstacles.Add((obKind[i], obX[i]));
				}
				value.receivedAt = Time.unscaledTime;
			}
		}

		public static void Clear()
		{
			Latest.Clear();
		}
	}
	internal static class ArcadeThemes
	{
		public struct Theme
		{
			public string name;

			public Color32 deep;

			public Color32 mid;

			public Color32 slab;

			public Color32 stal;

			public Color32 cap;

			public byte dress;
		}

		public const byte DressCaps = 1;

		public const byte DressMotes = 2;

		public const byte DressStrata = 4;

		public const byte DressGlow = 8;

		public static readonly Theme[] All = new Theme[12]
		{
			new Theme
			{
				name = "PLAINS",
				deep = new Color32((byte)44, (byte)40, (byte)32, byte.MaxValue),
				mid = new Color32((byte)82, (byte)70, (byte)48, byte.MaxValue),
				slab = new Color32((byte)118, (byte)98, (byte)64, byte.MaxValue),
				stal = new Color32((byte)64, (byte)54, (byte)40, byte.MaxValue),
				cap = new Color32((byte)98, (byte)148, (byte)70, byte.MaxValue),
				dress = 1
			},
			new Theme
			{
				name = "ROOST",
				deep = new Color32((byte)34, (byte)36, (byte)46, byte.MaxValue),
				mid = new Color32((byte)62, (byte)66, (byte)82, byte.MaxValue),
				slab = new Color32((byte)94, (byte)100, (byte)118, byte.MaxValue),
				stal = new Color32((byte)50, (byte)54, (byte)66, byte.MaxValue),
				cap = new Color32((byte)172, (byte)178, (byte)190, byte.MaxValue),
				dress = 5
			},
			new Theme
			{
				name = "AQUEDUCT",
				deep = new Color32((byte)52, (byte)38, (byte)26, byte.MaxValue),
				mid = new Color32((byte)98, (byte)70, (byte)42, byte.MaxValue),
				slab = new Color32((byte)136, (byte)100, (byte)58, byte.MaxValue),
				stal = new Color32((byte)76, (byte)54, (byte)34, byte.MaxValue),
				cap = new Color32((byte)192, (byte)160, (byte)104, byte.MaxValue),
				dress = 5
			},
			new Theme
			{
				name = "DELTA",
				deep = new Color32((byte)30, (byte)38, (byte)48, byte.MaxValue),
				mid = new Color32((byte)58, (byte)74, (byte)90, byte.MaxValue),
				slab = new Color32((byte)92, (byte)112, (byte)130, byte.MaxValue),
				stal = new Color32((byte)46, (byte)58, (byte)70, byte.MaxValue),
				cap = new Color32((byte)218, (byte)228, (byte)238, byte.MaxValue),
				dress = 3
			},
			new Theme
			{
				name = "ACRES",
				deep = new Color32((byte)30, (byte)26, (byte)24, byte.MaxValue),
				mid = new Color32((byte)56, (byte)46, (byte)40, byte.MaxValue),
				slab = new Color32((byte)82, (byte)66, (byte)54, byte.MaxValue),
				stal = new Color32((byte)44, (byte)36, (byte)32, byte.MaxValue),
				cap = new Color32((byte)214, (byte)118, (byte)44, byte.MaxValue),
				dress = 8
			},
			new Theme
			{
				name = "GROVE",
				deep = new Color32((byte)40, (byte)28, (byte)30, byte.MaxValue),
				mid = new Color32((byte)74, (byte)48, (byte)52, byte.MaxValue),
				slab = new Color32((byte)106, (byte)68, (byte)70, byte.MaxValue),
				stal = new Color32((byte)56, (byte)38, (byte)40, byte.MaxValue),
				cap = new Color32((byte)170, (byte)86, (byte)96, byte.MaxValue),
				dress = 9
			},
			new Theme
			{
				name = "SIREN",
				deep = new Color32((byte)34, (byte)40, (byte)40, byte.MaxValue),
				mid = new Color32((byte)70, (byte)78, (byte)74, byte.MaxValue),
				slab = new Color32((byte)104, (byte)112, (byte)104, byte.MaxValue),
				stal = new Color32((byte)52, (byte)60, (byte)56, byte.MaxValue),
				cap = new Color32((byte)160, (byte)98, (byte)58, byte.MaxValue),
				dress = 12
			},
			new Theme
			{
				name = "MEADOW",
				deep = new Color32((byte)36, (byte)32, (byte)52, byte.MaxValue),
				mid = new Color32((byte)66, (byte)58, (byte)94, byte.MaxValue),
				slab = new Color32((byte)96, (byte)86, (byte)130, byte.MaxValue),
				stal = new Color32((byte)50, (byte)44, (byte)72, byte.MaxValue),
				cap = new Color32((byte)152, (byte)134, (byte)202, byte.MaxValue),
				dress = 2
			},
			new Theme
			{
				name = "FOREST",
				deep = new Color32((byte)26, (byte)34, (byte)32, byte.MaxValue),
				mid = new Color32((byte)50, (byte)66, (byte)58, byte.MaxValue),
				slab = new Color32((byte)76, (byte)96, (byte)84, byte.MaxValue),
				stal = new Color32((byte)38, (byte)50, (byte)44, byte.MaxValue),
				cap = new Color32((byte)208, (byte)220, (byte)224, byte.MaxValue),
				dress = 3
			},
			new Theme
			{
				name = "MOON",
				deep = new Color32((byte)40, (byte)40, (byte)44, byte.MaxValue),
				mid = new Color32((byte)76, (byte)76, (byte)82, byte.MaxValue),
				slab = new Color32((byte)110, (byte)110, (byte)118, byte.MaxValue),
				stal = new Color32((byte)58, (byte)58, (byte)64, byte.MaxValue),
				cap = new Color32((byte)202, (byte)202, (byte)212, byte.MaxValue),
				dress = 4
			},
			new Theme
			{
				name = "VOID",
				deep = new Color32((byte)28, (byte)22, (byte)40, byte.MaxValue),
				mid = new Color32((byte)54, (byte)42, (byte)76, byte.MaxValue),
				slab = new Color32((byte)82, (byte)62, (byte)110, byte.MaxValue),
				stal = new Color32((byte)42, (byte)32, (byte)58, byte.MaxValue),
				cap = new Color32((byte)198, (byte)90, (byte)152, byte.MaxValue),
				dress = 2
			},
			new Theme
			{
				name = "SULFUR",
				deep = new Color32((byte)44, (byte)40, (byte)26, byte.MaxValue),
				mid = new Color32((byte)82, (byte)74, (byte)42, byte.MaxValue),
				slab = new Color32((byte)116, (byte)104, (byte)58, byte.MaxValue),
				stal = new Color32((byte)62, (byte)56, (byte)32, byte.MaxValue),
				cap = new Color32((byte)182, (byte)192, (byte)72, byte.MaxValue),
				dress = 9
			}
		};

		public static Theme RollTheme(ref uint rngState, string destinationScene)
		{
			Theme result = All[ArcadeRng.Next(ref rngState, All.Length)];
			int num = ForScene(destinationScene);
			if (num < 0)
			{
				return result;
			}
			return All[num];
		}

		public static int ForScene(string scene)
		{
			if (string.IsNullOrEmpty(scene))
			{
				return -1;
			}
			int num = Lookup(scene);
			if (num < 0 && scene.Length > 2 && scene[0] == 'i' && scene[1] == 't')
			{
				num = Lookup(scene.Substring(2));
			}
			return num;
			static int Lookup(string s)
			{
				switch (s)
				{
				case "habitatfall":
				case "golemplains":
				case "golemplains2":
				case "lakes":
				case "lakesnight":
				case "habitat":
					return 0;
				case "blackbeach2":
				case "blackbeach":
					return 1;
				case "villagenight":
				case "goolake":
				case "village":
					return 2;
				case "ancientloft":
				case "frozenwall":
					return 3;
				case "wispgraveyard":
				case "artifactworld":
				case "lemuriantemple":
					return 4;
				case "rootjungle":
				case "helminthroost":
				case "dampcavesimple":
					return 5;
				case "shipgraveyard":
					return 6;
				case "skymeadow":
					return 7;
				case "snowyforest":
				case "foggyswamp":
					return 8;
				case "moon2":
				case "moon":
					return 9;
				case "arena":
				case "voidstage":
				case "voidraid":
					return 10;
				case "sulfurpools":
				case "goldshores":
					return 11;
				default:
					return -1;
				}
			}
		}

		public static Color32 Scale(Color32 c, float f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			return new Color32((byte)Mathf.Clamp((float)(int)c.r * f, 0f, 255f), (byte)Mathf.Clamp((float)(int)c.g * f, 0f, 255f), (byte)Mathf.Clamp((float)(int)c.b * f, 0f, 255f), byte.MaxValue);
		}

		public static uint DressHash(int x, int y)
		{
			int num = x * 374761393 + y * 668265263;
			int num2 = (num ^ (num >>> 13)) * 1274126177;
			return (uint)(num2 ^ (num2 >>> 16));
		}

		public static bool StrataBand(int x, int y, int groupShift, int salt, bool drift, int period, int thickness)
		{
			return (y + (int)(DressHash(x >> groupShift, salt) % 5) + (drift ? (x >> 3) : 0)) % period < thickness;
		}

		public static bool AccentSeed(int x, int y, int rarity)
		{
			return DressHash(x, y) % (uint)rarity == 0;
		}
	}
	internal static class CommandoSprites
	{
		public enum Critter
		{
			Lemurian,
			Golem,
			Child,
			Drone
		}

		private class Anim
		{
			public Sprite[] frames;

			public float[] frameEnds;

			public Vector2 size;

			public int IndexAt(float t)
			{
				float num = frameEnds[frameEnds.Length - 1];
				if (num <= 0f)
				{
					return 0;
				}
				float num2 = t % num;
				for (int i = 0; i < frameEnds.Length; i++)
				{
					if (num2 < frameEnds[i])
					{
						return i;
					}
				}
				return frames.Length - 1;
			}

			public Sprite At(float t)
			{
				return frames[IndexAt(t)];
			}
		}

		private const string Dir = "RoR2/Base/loadingbasic/";

		private static readonly string[] CritterKeys = new string[4] { "RoR2/Base/loadingbasic/ssaLemurianWalk.asset", "RoR2/Base/loadingbasic/ssaGolem.asset", "RoR2/Base/loadingbasic/ssaChildWalk.asset", "RoR2/Base/loadingbasic/ssaDroneHover.asset" };

		private static readonly Color32[] RampSrc = (Color32[])(object)new Color32[4]
		{
			new Color32((byte)131, (byte)69, (byte)39, byte.MaxValue),
			new Color32((byte)193, (byte)128, (byte)62, byte.MaxValue),
			new Color32((byte)223, (byte)183, (byte)98, byte.MaxValue),
			new Color32((byte)244, (byte)243, (byte)183, byte.MaxValue)
		};

		private static readonly float[] RampDrift = new float[4] { 0f, 10f, 21f, 39f };

		private static readonly float[] RampSat = new float[4] { 0.7f, 0.68f, 0.56f, 0.25f };

		private static readonly float[] RampVal = new float[4] { 0.51f, 0.76f, 0.87f, 0.96f };

		private const float BaseHue = 20f;

		private static readonly float[] Hues = new float[16]
		{
			20f,
			355f,
			48f,
			85f,
			125f,
			165f,
			190f,
			210f,
			235f,
			262f,
			285f,
			315f,
			335f,
			float.NaN,
			float.NaN,
			float.NaN
		};

		private const int PastelIndex = 12;

		private static readonly float[][] NeutralVals = new float[3][]
		{
			new float[4] { 0.62f, 0.78f, 0.9f, 0.98f },
			new float[4] { 0.38f, 0.52f, 0.62f, 0.72f },
			new float[4] { 0.16f, 0.24f, 0.3f, 0.38f }
		};

		public const int ColorwayCount = 16;

		public static readonly string[] ColorwayNames = new string[16]
		{
			"Orange", "Red", "Yellow", "Lime", "Green", "Teal", "Cyan", "Azure", "Blue", "Indigo",
			"Purple", "Magenta", "Pink", "White", "Grey", "Black"
		};

		private static bool loadStarted;

		private static Anim[] commando;

		private static bool[][] commandoMasks;

		private static readonly Anim[] critters = new Anim[4];

		private static readonly List<Texture2D> ownedTextures = new List<Texture2D>();

		private static int pendingLoads;

		public static bool Ready { get; private set; }

		public static bool Failed { get; private set; }

		public static Vector2 CommandoSize => commando[0].size;

		public static void EnsureLoading()
		{
			if (loadStarted)
			{
				return;
			}
			loadStarted = true;
			pendingLoads = 1 + CritterKeys.Length;
			LoadSsa("RoR2/Base/loadingbasic/ssaCommandoWalk.asset", delegate(SimpleSpriteAnimation anim)
			{
				try
				{
					BuildCommandoColorways(anim);
				}
				catch (Exception ex)
				{
					Failed = true;
					ScorchedVoxelsPlugin.Log.LogWarning((object)("[ScorchedVoxels] commando recolor failed, arcade disabled: " + ex.Message));
				}
			});
			for (int num = 0; num < CritterKeys.Length; num++)
			{
				int idx = num;
				LoadSsa(CritterKeys[idx], delegate(SimpleSpriteAnimation anim)
				{
					critters[idx] = FromSsa(anim);
				});
			}
		}

		private static void LoadSsa(string key, Action<SimpleSpriteAnimation> onLoaded)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				AsyncOperationHandle<SimpleSpriteAnimation> val = Addressables.LoadAssetAsync<SimpleSpriteAnimation>((object)key);
				val.Completed += delegate(AsyncOperationHandle<SimpleSpriteAnimation> op)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					//IL_0008: Invalid comparison between Unknown and I4
					if ((int)op.Status == 1 && (Object)(object)op.Result != (Object)null && op.Result.frames != null && op.Result.frames.Length != 0)
					{
						onLoaded(op.Result);
					}
					else
					{
						Failed = true;
						ScorchedVoxelsPlugin.Log.LogWarning((object)("[ScorchedVoxels] arcade sprite load failed (" + key + ") — arcade disabled"));
					}
					if (--pendingLoads == 0 && !Failed)
					{
						Ready = true;
					}
				};
			}
			catch (Exception ex)
			{
				Failed = true;
				ScorchedVoxelsPlugin.Log.LogWarning((object)("[ScorchedVoxels] arcade sprite load threw (" + key + "): " + ex.Message));
			}
		}

		private static Anim FromSsa(SimpleSpriteAnimation ssa)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			int num = ssa.frames.Length;
			Anim anim = new Anim
			{
				frames = (Sprite[])(object)new Sprite[num],
				frameEnds = new float[num]
			};
			float num2 = ((ssa.frameRate > 0f) ? ssa.frameRate : 60f);
			for (int i = 0; i < num; i++)
			{
				anim.frames[i] = ssa.frames[i].sprite;
				anim.frameEnds[i] = (float)ssa.frames[i].duration / num2;
			}
			for (int j = 1; j < num; j++)
			{
				if (anim.frameEnds[j] <= anim.frameEnds[j - 1])
				{
					anim.frameEnds[j] = anim.frameEnds[j - 1] + 1f / num2;
				}
			}
			Rect rect = anim.frames[0].rect;
			anim.size = new Vector2(((Rect)(ref rect)).width, ((Rect)(ref rect)).height);
			return anim;
		}

		private static void BuildCommandoColorways(SimpleSpriteAnimation ssa)
		{
			//IL_004d: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: 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_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: 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_0225: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: 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_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			Texture2D texture = ssa.frames[0].sprite.texture;
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			RenderTexture active = RenderTexture.active;
			Graphics.Blit((Texture)(object)texture, temporary);
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false);
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0, false);
			val.Apply(false, false);
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			Color32[] pixels = val.GetPixels32();
			Object.Destroy((Object)val);
			commandoMasks = new bool[ssa.frames.Length][];
			for (int i = 0; i < ssa.frames.Length; i++)
			{
				Rect rect = ssa.frames[i].sprite.rect;
				int num = (int)((Rect)(ref rect)).x;
				int num2 = (int)((Rect)(ref rect)).y;
				int num3 = (int)((Rect)(ref rect)).width;
				int num4 = (int)((Rect)(ref rect)).height;
				bool[] array = new bool[num3 * num4];
				for (int j = 0; j < num4; j++)
				{
					for (int k = 0; k < num3; k++)
					{
						array[j * num3 + k] = pixels[(num2 + j) * ((Texture)texture).width + num + k].a > 40;
					}
				}
				commandoMasks[i] = array;
			}
			commando = new Anim[16];
			Color32[] array2 = (Color32[])(object)new Color32[pixels.Length];
			Color32[] array3 = (Color32[])(object)new Color32[RampSrc.Length];
			for (int l = 0; l < 16; l++)
			{
				for (int m = 0; m < RampSrc.Length; m++)
				{
					array3[m] = ColorwayColor(l, m);
				}
				for (int n = 0; n < pixels.Length; n++)
				{
					Color32 val2 = pixels[n];
					if (val2.a == 0)
					{
						array2[n] = val2;
						continue;
					}
					int num5 = MatchRamp(val2);
					array2[n] = (Color32)((num5 >= 0) ? new Color32(array3[num5].r, array3[num5].g, array3[num5].b, val2.a) : val2);
				}
				Texture2D val3 = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false)
				{
					filterMode = (FilterMode)0,
					wrapMode = (TextureWrapMode)1
				};
				val3.SetPixels32(array2);
				val3.Apply(false, true);
				ownedTextures.Add(val3);
				Anim anim = new Anim
				{
					frames = (Sprite[])(object)new Sprite[ssa.frames.Length],
					frameEnds = new float[ssa.frames.Length]
				};
				float num6 = ((ssa.frameRate > 0f) ? ssa.frameRate : 60f);
				for (int num7 = 0; num7 < ssa.frames.Length; num7++)
				{
					Rect rect2 = ssa.frames[num7].sprite.rect;
					anim.frames[num7] = Sprite.Create(val3, rect2, new Vector2(0.5f, 0f), 100f);
					anim.frameEnds[num7] = (float)ssa.frames[num7].duration / num6;
				}
				for (int num8 = 1; num8 < anim.frameEnds.Length; num8++)
				{
					if (anim.frameEnds[num8] <= anim.frameEnds[num8 - 1])
					{
						anim.frameEnds[num8] = anim.frameEnds[num8 - 1] + 1f / num6;
					}
				}
				Rect rect3 = anim.frames[0].rect;
				anim.size = new Vector2(((Rect)(ref rect3)).width, ((Rect)(ref rect3)).height);
				commando[l] = anim;
			}
		}

		private static int MatchRamp(Color32 p)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			//IL_002b: 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)
			for (int i = 0; i < RampSrc.Length; i++)
			{
				Color32 val = RampSrc[i];
				if (Mathf.Abs(p.r - val.r) <= 8 && Mathf.Abs(p.g - val.g) <= 8 && Mathf.Abs(p.b - val.b) <= 8)
				{
					return i;
				}
			}
			return -1;
		}

		private static Color32 ColorwayColor(int colorway, int step)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			float num = Hues[colorway];
			Color val;
			if (float.IsNaN(num))
			{
				val = Color.HSVToRGB(0f, 0f, NeutralVals[colorway - 13][step]);
			}
			else
			{
				float num2 = RampSat[step];
				float num3 = RampVal[step];
				if (colorway == 12)
				{
					num2 *= 0.55f;
					num3 = Mathf.Min(1f, num3 + 0.22f * (1f - num3) + 0.1f);
				}
				val = Color.HSVToRGB(Mathf.Repeat(num + RampDrift[step], 360f) / 360f, num2, num3);
			}
			return new Color32((byte)Mathf.RoundToInt(val.r * 255f), (byte)Mathf.RoundToInt(val.g * 255f), (byte)Mathf.RoundToInt(val.b * 255f), byte.MaxValue);
		}

		public static Sprite CommandoFrame(int colorway, float t)
		{
			return commando[Mod16(colorway)].At(t);
		}

		public static bool CommandoOpaque(float t, int px, int py)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Vector2 size = commando[0].size;
			int num = (int)size.x;
			int num2 = (int)size.y;
			if (px < 0 || px >= num || py < 0 || py >= num2)
			{
				return false;
			}
			return commandoMasks[commando[0].IndexAt(t)][py * num + px];
		}

		public static Color Tint(int colorway)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			Color32 val = ColorwayColor(Mod16(colorway), 1);
			return new Color((float)(int)val.r / 255f, (float)(int)val.g / 255f, (float)(int)val.b / 255f, 1f);
		}

		public static Sprite CritterFrame(Critter c, float t)
		{
			return critters[(int)c].At(t);
		}

		public static Vector2 CritterSize(Critter c)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return critters[(int)c].size;
		}

		private static int Mod16(int i)
		{
			return (i % 16 + 16) % 16;
		}

		public static int ColorwayFor(uint userNetId)
		{
			return (int)(userNetId % 16);
		}
	}
	internal static class DecorStamps
	{
		public const int Count = 25;

		public const int W = 40;

		public const int H = 44;

		private static int DRng(ref uint st, int max)
		{
			return ArcadeRng.Next(ref st, max);
		}

		public static int Raster(int id, byte[] cv, ref uint st)
		{
			Array.Clear(cv, 0, cv.Length);
			int num = 12;
			int num2 = 12;
			switch (id)
			{
			case 0:
			{
				int num23 = 4 + DRng(ref st, 4);
				Disc(num23, num23 - 1, num23, 1);
				Disc(num23 - 1, num23, num23 - 3, 2);
				num = 2 * num23 + 1;
				num2 = 2 * num23;
				break;
			}
			case 1:
			{
				int num12 = 3 + DRng(ref st, 3);
				Disc(num12, num12 - 1, num12, 1);
				Disc(2 * num12 + 2, num12 - 2, num12 - 1, 1);
				Px(num12 - 1, 2 * num12 - 2, 2);
				num = 3 * num12 + 2;
				num2 = 2 * num12;
				break;
			}
			case 2:
			{
				int num5 = 8 + DRng(ref st, 7);
				int num6 = 2 + DRng(ref st, 2);
				TriUp(num6, 0, num6, num5, 1);
				Px(num6, num5 - 1, 2);
				num = 2 * num6 + 1;
				num2 = num5;
				break;
			}
			case 3:
			{
				int num34 = 7 + DRng(ref st, 6);
				TriUp(3, 0, 3, num34, 1);
				TriUp(9, 0, 3, num34 - 3 + DRng(ref st, 3), 1);
				TriUp(14, 0, 2, num34 - 4, 1);
				num = 17;
				num2 = num34;
				break;
			}
			case 4:
			{
				int num28 = 16 + DRng(ref st, 9);
				TriUp(3, 0, 3, num28, 1);
				Px(3, num28 - 1, 2);
				Px(2, num28 - 4, 2);
				num = 7;
				num2 = num28;
				break;
			}
			case 5:
			{
				int num10 = 4 + DRng(ref st, 2);
				int num11 = 0;
				for (int l = 0; l < 3 + DRng(ref st, 2); l++)
				{
					if (num10 <= 1)
					{
						break;
					}
					Disc(6, num11 + num10 - 1, num10, 1);
					Px(6, num11 + 2 * num10 - 2, 2);
					num11 += 2 * num10 - 2;
					num10--;
				}
				num = 13;
				num2 = num11 + 4;
				break;
			}
			case 6:
			{
				int num29 = 9 + DRng(ref st, 5);
				for (int num30 = 0; num30 < num29; num30++)
				{
					Rect(2 + num30 / 3, num30, 4, 1, 1);
				}
				Rect(2 + (num29 - 1) / 3, num29 - 1, 4, 1, 2);
				num = 7 + num29 / 3;
				num2 = num29;
				break;
			}
			case 7:
			{
				for (int num22 = 0; num22 < 7 + DRng(ref st, 4); num22++)
				{
					Rect(DRng(ref st, 16), DRng(ref st, 3), 1 + DRng(ref st, 2), 1 + DRng(ref st, 2), (byte)(1 + DRng(ref st, 2)));
				}
				num = 18;
				num2 = 5;
				break;
			}
			case 8:
			{
				int num19 = 8 + DRng(ref st, 5);
				Rect(1, 0, 4, num19, 1);
				Px(2, num19 - 1, 2);
				Px(3, num19 / 2, 3);
				num = 6;
				num2 = num19;
				break;
			}
			case 9:
			{
				int num18 = 9 + DRng(ref st, 4);
				Rect(1, 0, 2, num18, 1);
				Rect(10, 0, 2, num18, 1);
				Rect(0, num18, 13, 2, 1);
				Px(1, num18 - 1, 2);
				Px(11, num18 - 1, 2);
				num = 13;
				num2 = num18 + 2;
				break;
			}
			case 10:
			{
				int num14 = 5 + DRng(ref st, 4);
				Rect(1, 0, 3, num14, 1);
				Rect(1, num14, 3, 1, 2);
				Disc(8, 1, 2, 1);
				num = 11;
				num2 = num14 + 1;
				break;
			}
			case 11:
				Rect(0, 0, 14 + DRng(ref st, 5), 2, 1);
				Rect(2, 2, 10, 2, 1);
				Rect(4, 4, 6, 2, 2);
				num = 19;
				num2 = 6;
				break;
			case 12:
			{
				for (int j = 0; j < 5 + DRng(ref st, 3); j++)
				{
					Rect(j * 2 + DRng(ref st, 2), 0, 1, 2 + DRng(ref st, 3), 3);
				}
				num = 14;
				num2 = 5;
				break;
			}
			case 13:
			{
				for (int num31 = 0; num31 < 2 + DRng(ref st, 2); num31++)
				{
					int num32 = num31 * 5 + 2;
					int num33 = 2 + DRng(ref st, 2);
					Rect(num32, 0, 1, num33, 2);
					Disc(num32, num33 + 1, 2, 3);
				}
				num = 14;
				num2 = 7;
				break;
			}
			case 14:
				Rect(0, 0, 12, 1, 2);
				TriUp(3, 1, 2, 6 + DRng(ref st, 3), 3);
				TriUp(7, 1, 2, 4 + DRng(ref st, 3), 3);
				TriUp(10, 1, 1, 5, 3);
				num = 13;
				num2 = 11;
				break;
			case 15:
			{
				int num25 = 4 + DRng(ref st, 2);
				for (int num26 = 0; num26 < num25; num26++)
				{
					int num27 = 6 - Mathf.Abs(num26 - num25 / 2);
					Rect(num26 * 3, 0, 1, num27, 2);
					Px(num26 * 3 + 1, num27 - 1, 2);
				}
				num = num25 * 3;
				num2 = 7;
				break;
			}
			case 16:
			{
				int num24 = 8 + DRng(ref st, 6);
				TriDown(3, num24 - 1, 3, num24, 1);
				TriDown(9, num24 - 1, 3, num24 - 3, 1);
				TriDown(14, num24 - 1, 2, num24 - 5, 1);
				num = 17;
				num2 = num24;
				break;
			}
			case 17:
			{
				int num20 = 5 + DRng(ref st, 4);
				for (int num21 = 0; num21 < num20; num21++)
				{
					TriDown(num21 * 3 + 1, 5, 1, 3 + DRng(ref st, 3), 2);
				}
				num = num20 * 3;
				num2 = 6;
				break;
			}
			case 18:
			{
				int num15 = 10 + DRng(ref st, 7);
				for (int n = 0; n < 3; n++)
				{
					int num16 = n * 4 + 1;
					for (int num17 = 0; num17 < num15 - n * 2; num17++)
					{
						Px(num16 + ((num17 / 3) & 1), num15 - 1 - num17, 2);
					}
					Px(num16, num15 - 1 - (num15 - n * 2) + 1, 3);
				}
				num = 11;
				num2 = num15;
				break;
			}
			case 19:
			{
				int num13 = 8 + DRng(ref st, 4);
				for (int m = 0; m < num13; m++)
				{
					Px(6 - m / 2, num13 - 1 - m, 2);
					Px(7 + m / 3, num13 - 1 - m, 2);
					if (m > 3)
					{
						Px(10 + m / 3, num13 - 1 - m, 2);
					}
				}
				num = 15;
				num2 = num13;
				break;
			}
			case 20:
				TriDown(3, 7, 2, 6 + DRng(ref st, 2), 3);
				TriDown(8, 7, 2, 4, 3);
				TriDown(12, 7, 1, 5, 3);
				Rect(0, 7, 14, 1, 2);
				num = 14;
				num2 = 8;
				break;
			case 21:
			{
				int num9 = 8 + DRng(ref st, 7);
				for (int k = 0; k < num9; k++)
				{
					if ((k & 1) == 0)
					{
						Rect(k, k / 2, 2, 1, 3);
					}
				}
				num = num9 + 2;
				num2 = num9 / 2 + 1;
				break;
			}
			case 22:
			{
				int num8 = 4 + DRng(ref st, 3);
				Disc(num8, num8, num8, 1);
				Ring(num8, num8, num8 - 2, 3);
				num = 2 * num8 + 1;
				num2 = 2 * num8 + 1;
				break;
			}
			case 23:
			{
				int num7 = 4 + DRng(ref st, 2);
				Ring(num7, num7, num7, 2);
				Ring(num7, num7, num7 - 2, 2);
				Px(num7, num7, 2);
				num = 2 * num7 + 1;
				num2 = 2 * num7 + 1;
				break;
			}
			default:
			{
				int num3 = 12 + DRng(ref st, 7);
				for (int i = 0; i < num3; i++)
				{
					int num4 = Mathf.Max(1, 3 - Mathf.Abs(i - num3 / 2) * 6 / num3);
					Rect(i, 2 - num4 / 2, 1, num4, 1);
				}
				num = num3;
				num2 = 5;
				break;
			}
			}
			return (Mathf.Min(num, 40) << 8) | Mathf.Min(num2, 44);
			void Disc(int cx, int cy, int r, byte s)
			{
				for (int num35 = -r; num35 <= r; num35++)
				{
					for (int num36 = -r; num36 <= r; num36++)
					{
						if (num35 * num35 + num36 * num36 <= r * r)
						{
							Px(cx + num35, cy + num36, s);
						}
					}
				}
			}
			void Px(int x, int y, byte s)
			{
				if (x >= 0 && y >= 0 && x < 40 && y < 44)
				{
					cv[y * 40 + x] = s;
				}
			}
			void Rect(int x, int y, int rw, int rh, byte s)
			{
				for (int num35 = 0; num35 < rw; num35++)
				{
					for (int num36 = 0; num36 < rh; num36++)
					{
						Px(x + num35, y + num36, s);
					}
				}
			}
			void Ring(int cx, int cy, int r, byte s)
			{
				for (int num35 = -r; num35 <= r; num35++)
				{
					for (int num36 = -r; num36 <= r; num36++)
					{
						int num37 = num35 * num35 + num36 * num36;
						if (num37 <= r * r && num37 > (r - 1) * (r - 1))
						{
							Px(cx + num35, cy + num36, s);
						}
					}
				}
			}
			void TriDown(int cx, int topY, int halfW, int ht, byte s)
			{
				for (int num35 = 0; num35 < ht; num35++)
				{
					int num36 = Mathf.Max(halfW * (ht - num35) / ht, 0);
					for (int num37 = -num36; num37 <= num36; num37++)
					{
						Px(cx + num37, topY - num35, s);
					}
				}
			}
			void TriUp(int cx, int baseY, int halfW, int ht, byte s)
			{
				for (int num35 = 0; num35 < ht; num35++)
				{
					int num36 = Mathf.Max(halfW * (ht - num35) / ht, 0);
					for (int num37 = -num36; num37 <= num36; num37++)
					{
						Px(cx + num37, baseY + num35, s);
					}
				}
			}
		}
	}
	internal static class PetSprite
	{
		public delegate void SetPx(int x, int y, byte r, byte g, byte b);

		public enum Shape
		{
			Classic,
			Round,
			Tall,
			Squat,
			Pear,
			Dome,
			Brick,
			Wedge
		}

		public enum Pattern
		{
			Solid,
			Speckled,
			Banded,
			Spotted,
			Patched,
			Gradient,
			Mottled
		}

		public enum EyeStyle
		{
			Classic,
			Warm,
			Jade,
			Sky,
			Sparkle,
			Odd
		}

		public enum Accessory
		{
			None,
			MossTuft,
			Mushroom,
			CrystalCrown,
			HornNubs,
			Antenna,
			BackSpikes,
			Sprout,
			Flower,
			TopHat,
			PartyCone,
			SnailShell,
			CatEars,
			BunnyEars,
			Halo,
			Bow,
			Pebblet,
			Feather,
			Twig,
			Antlers,
			Lichen,
			Barnacles,
			CrystalStud,
			Candle,
			Fin,
			TailNub,
			Scarf
		}

		public enum Aura
		{
			None,
			GlowRim,
			SparkleField,
			Drips,
			OrbitMote
		}

		public enum Foil
		{
			None,
			Prismatic,
			LiquidGold,
			Starfield,
			Ripple,
			VoidSkin,
			ChefFire
		}

		public struct Look
		{
			public byte bodyR;

			public byte bodyG;

			public byte bodyB;

			public byte bellyR;

			public byte bellyG;

			public byte bellyB;

			public byte speckR;

			public byte speckG;

			public byte speckB;

			public int eyeGap;

			public uint salt;

			public bool shiny;

			public int shinyCoat;

			public Shape shape;

			public Pattern pattern;

			public EyeStyle eyes;

			public Accessory accessory;

			public Aura aura;

			public bool blush;

			public Foil foil;
		}

		public const int Stages = 5;

		public static readonly int[] W = new int[5] { 5, 7, 10, 14, 18 };

		public static readonly int[] H = new int[5] { 4, 5, 8, 11, 12 };

		private static readonly byte[,] Body = new byte[5, 3]
		{
			{ 118, 120, 128 },
			{ 130, 118, 102 },
			{ 144, 120, 98 },
			{ 152, 112, 80 },
			{ 166, 98, 60 }
		};

		private static readonly byte[,] ShinyCoat = new byte[6, 3]
		{
			{ 96, 156, 118 },
			{ 176, 112, 130 },
			{ 182, 152, 76 },
			{ 118, 152, 176 },
			{ 142, 110, 172 },
			{ 106, 140, 94 }
		};

		private static readonly string[] ShinyNames = new string[6] { "JADE", "ROS