Decompiled source of PaintCan v1.3.0

PaintCan.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using SFQoL;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("PaintCan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0+b4e2b71dc2ee78478f5eb776f43374d1987240cf")]
[assembly: AssemblyProduct("PaintCan")]
[assembly: AssemblyTitle("PaintCan")]
[assembly: AssemblyVersion("1.3.0.0")]
namespace SFQoL
{
	internal static class TeamPalette
	{
		public const int Families = 5;

		public const int Yellow = 0;

		public const int Blue = 1;

		public const int Red = 2;

		public const int Green = 3;

		public const int Purple = 4;

		public static readonly string[] Names = new string[5] { "YELLOW", "BLUE", "RED", "GREEN", "PURPLE" };

		public static readonly string[,] ShadeNames = new string[5, 2]
		{
			{ "YELLOW", "ORANGE" },
			{ "BLUE", "CYAN" },
			{ "RED", "DARK RED" },
			{ "GREEN", "LIME" },
			{ "PURPLE", "PINK" }
		};

		private static readonly int[] gameSlot = new int[5] { 0, 1, 2, -1, -1 };

		private static readonly Color[] lead = (Color[])(object)new Color[5]
		{
			Color32.op_Implicit(new Color32((byte)242, (byte)194, (byte)48, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)79, (byte)127, (byte)208, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)217, (byte)68, (byte)58, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)35, (byte)133, (byte)58, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)155, (byte)77, byte.MaxValue, byte.MaxValue))
		};

		private static readonly Color[] mate = (Color[])(object)new Color[5]
		{
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)106, (byte)0, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)51, (byte)230, byte.MaxValue, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)138, (byte)28, (byte)28, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)125, (byte)227, (byte)107, byte.MaxValue)),
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)110, (byte)199, byte.MaxValue))
		};

		public static bool Clash(int a, int b)
		{
			if (a < 0 || b < 0)
			{
				return false;
			}
			if (a == b)
			{
				return true;
			}
			if ((a != 0 || b != 2) && (a != 2 || b != 0) && (a != 1 || b != 4))
			{
				if (a == 4)
				{
					return b == 1;
				}
				return false;
			}
			return true;
		}

		public static int GameSlot(int family)
		{
			if (family < 0 || family >= 5)
			{
				return -1;
			}
			return gameSlot[family];
		}

		public static Color Shade(int family, int shade)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (family < 0 || family >= 5)
			{
				return Color.white;
			}
			if (shade == 0)
			{
				ControllerHandler instance = ControllerHandler.Instance;
				int num = gameSlot[family];
				if (num >= 0 && (Object)(object)instance != (Object)null && instance.colors != null && num < instance.colors.Length && (Object)(object)instance.colors[num] != (Object)null)
				{
					Color color = instance.colors[num].color;
					color.a = 1f;
					return color;
				}
				return lead[family];
			}
			return mate[family];
		}

		public static int TeamOf(int slot)
		{
			switch (slot)
			{
			default:
				return -1;
			case 2:
			case 3:
				return 1;
			case 0:
			case 1:
				return 0;
			}
		}

		public static int DefaultFamily(int team)
		{
			return (team == 1) ? 1 : 0;
		}

		public static bool HasHue(Color c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(c, ref num, ref num2, ref num3);
			if (num2 > 0.3f)
			{
				return num3 > 0.2f;
			}
			return false;
		}

		public static int Nearest(Color c, out int shade)
		{
			//IL_0003: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			shade = 0;
			if (!HasHue(c))
			{
				return -1;
			}
			Vector3 val = OkLab(c);
			int result = -1;
			float num = float.MaxValue;
			for (int i = 0; i < 5; i++)
			{
				for (int j = 0; j < 2; j++)
				{
					Vector3 val2 = OkLab(Shade(i, j)) - val;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = i;
						shade = j;
					}
				}
			}
			return result;
		}

		public static int Nearest(Color c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			int shade;
			return Nearest(c, out shade);
		}

		public static int Of(Color c, out int shade)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = OkLab(c);
			int result = 0;
			float num = float.MaxValue;
			shade = 0;
			for (int i = 0; i < 5; i++)
			{
				for (int j = 0; j < 2; j++)
				{
					Vector3 val2 = OkLab(Shade(i, j)) - val;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = i;
						shade = j;
					}
				}
			}
			return result;
		}

		public static string NameOf(Color c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			int shade;
			int num = Of(c, out shade);
			return ShadeNames[num, shade];
		}

		public static int Lead(int team, List<Controller> players)
		{
			int num = -1;
			if (players == null)
			{
				return -1;
			}
			for (int i = 0; i < players.Count; i++)
			{
				Controller val = players[i];
				if (!((Object)(object)val == (Object)null) && TeamOf(val.playerID) == team && (num < 0 || val.playerID < num))
				{
					num = val.playerID;
				}
			}
			return num;
		}

		private static float Lin(float c)
		{
			if (!(c <= 0.04045f))
			{
				return Mathf.Pow((c + 0.055f) / 1.055f, 2.4f);
			}
			return c / 12.92f;
		}

		private static float Cbrt(float x)
		{
			if (!(x < 0f))
			{
				return Mathf.Pow(x, 1f / 3f);
			}
			return 0f - Mathf.Pow(0f - x, 1f / 3f);
		}

		public static Vector3 OkLab(Color c)
		{
			//IL_0000: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			float num = Lin(c.r);
			float num2 = Lin(c.g);
			float num3 = Lin(c.b);
			float num4 = Cbrt(0.41222146f * num + 0.53633255f * num2 + 0.051445995f * num3);
			float num5 = Cbrt(0.2119035f * num + 0.6806995f * num2 + 0.10739696f * num3);
			float num6 = Cbrt(0.08830246f * num + 0.28171885f * num2 + 0.6299787f * num3);
			return new Vector3(0.21045426f * num4 + 0.7936178f * num5 - 0.004072047f * num6, 1.9779985f * num4 - 2.4285922f * num5 + 0.4505937f * num6, 0.025904037f * num4 + 0.78277177f * num5 - 0.80867577f * num6);
		}
	}
	internal sealed class TeamState
	{
		public readonly int[] Family = new int[2] { -1, -1 };

		public readonly int[] LeadShade = new int[2];

		public void Reset()
		{
			Family[0] = (Family[1] = -1);
			LeadShade[0] = (LeadShade[1] = 0);
		}

		public void Resolve(List<Controller> players, Func<int, Color?> own)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			int num = TeamPalette.Lead(0, players);
			int num2 = TeamPalette.Lead(1, players);
			for (int i = 0; i < 2; i++)
			{
				int num3 = ((i == 0) ? num : num2);
				if (num3 >= 0 && Family[i] < 0)
				{
					Color? val = own?.Invoke(num3);
					int shade = 0;
					int num4 = (val.HasValue ? TeamPalette.Nearest(val.Value, out shade) : (-1));
					Family[i] = ((num4 >= 0) ? num4 : TeamPalette.DefaultFamily(i));
					LeadShade[i] = ((num4 >= 0) ? shade : 0);
				}
			}
			if (num >= 0 && num2 >= 0 && TeamPalette.Clash(Family[0], Family[1]))
			{
				Family[1] = Away(Family[0], TeamPalette.DefaultFamily(1));
				LeadShade[1] = 0;
			}
		}

		private static int Away(int other, int want)
		{
			if (!TeamPalette.Clash(other, want))
			{
				return want;
			}
			for (int i = 0; i < 5; i++)
			{
				if (!TeamPalette.Clash(other, i))
				{
					return i;
				}
			}
			return want;
		}

		public bool CanTake(int team, int family, int shade, List<Controller> players)
		{
			if (team < 0 || team > 1 || family < 0)
			{
				return false;
			}
			if (family == Family[team])
			{
				return shade != LeadShade[team];
			}
			int num = 1 - team;
			if (TeamPalette.Lead(num, players) < 0)
			{
				return true;
			}
			return !TeamPalette.Clash(family, Family[num]);
		}

		public void Take(int team, int family, int shade)
		{
			Family[team] = family;
			LeadShade[team] = shade;
		}

		public int FamilyOf(Controller p, List<Controller> players, out int shade)
		{
			shade = 0;
			int num = (((Object)(object)p != (Object)null) ? TeamPalette.TeamOf(p.playerID) : (-1));
			if (num < 0)
			{
				return -1;
			}
			shade = ((TeamPalette.Lead(num, players) == p.playerID) ? LeadShade[num] : (1 - LeadShade[num]));
			return Family[num];
		}

		public bool Wears(int team, int family, int shade)
		{
			if (Family[team] == family)
			{
				return LeadShade[team] == shade;
			}
			return false;
		}
	}
}
namespace PaintCan
{
	public static class PaintCanApi
	{
		public static bool HandlesTeams => true;

		public static Material PatternedText(Controller player, Material fontMaterial)
		{
			Pattern pattern = Worn(player);
			if (pattern == null || !((Object)(object)fontMaterial != (Object)null))
			{
				return null;
			}
			return pattern.DigitMaterial(fontMaterial);
		}

		public static Sprite PatternedSprite(Controller player, Sprite shape)
		{
			Pattern pattern = Worn(player);
			if (pattern == null || !((Object)(object)shape != (Object)null))
			{
				return null;
			}
			return pattern.Head(shape, 192);
		}

		public static void PrepareSprite(Sprite shape)
		{
			Pattern.QueueShape(shape);
		}

		private static Pattern Worn(Controller player)
		{
			if ((Object)(object)player == (Object)null || MatchmakingHandler.IsNetworkMatch)
			{
				return null;
			}
			CharacterInformation component = ((Component)player).GetComponent<CharacterInformation>();
			if (!((Object)(object)component != (Object)null))
			{
				return null;
			}
			return Pattern.Of(component.myMaterial);
		}
	}
	internal class CanSpawner : MonoBehaviour
	{
		private Can can;

		private void Update()
		{
			Palette.Tick();
			if (MatchmakingHandler.IsNetworkMatch)
			{
				if ((Object)(object)can != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)can).gameObject);
				}
				return;
			}
			Pattern.WarmUp();
			if (!((Object)(object)can != (Object)null) && GameManager.stillInMenu && !((Object)(object)GameManager.Instance == (Object)null) && Palette.Count != 0)
			{
				Transform val = ((Component)GameManager.Instance).transform.Find("Map");
				if (!((Object)(object)val == (Object)null))
				{
					can = Can.Build(val);
				}
			}
		}
	}
	internal class Can : MonoBehaviour
	{
		private const float PivotHeight = 0.38f;

		private const float BailRadius = 0.58f;

		private const float MaxForward = 1.4835298f;

		private const float MaxBack = -0.34906584f;

		private const float PaintTop = 0.55f;

		private static readonly Color BodyTone = new Color(0.22f, 0.22f, 0.22f);

		private static readonly Color RimTone = new Color(0.3f, 0.3f, 0.3f);

		private static readonly Color WireTone = new Color(0.34f, 0.34f, 0.34f);

		private static readonly Color GripTone = new Color(0f, 0f, 0f);

		private static readonly Vector3[] Drips = (Vector3[])(object)new Vector3[7]
		{
			new Vector3(-0.4f, 0.42f, 0.07f),
			new Vector3(-0.27f, 0.8f, 0.09f),
			new Vector3(-0.12f, 0.5f, 0.08f),
			new Vector3(0.03f, 0.95f, 0.1f),
			new Vector3(0.18f, 0.62f, 0.08f),
			new Vector3(0.31f, 0.85f, 0.09f),
			new Vector3(0.42f, 0.38f, 0.07f)
		};

		private static Material baseMat;

		private static Material[] rainbowPaint;

		private static readonly Dictionary<Color, Material> tinted = new Dictionary<Color, Material>();

		private Rigidbody rig;

		private Transform bail;

		private float side;

		private float bailAngle = 0.05f;

		private float bailSpin;

		private Vector3 lastVelocity;

		private readonly List<Renderer> paintParts = new List<Renderer>();

		private Vector3 home;

		private float cooldown;

		private int offer = -1;

		public unsafe static Can Build(Transform map)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: 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_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.75f;
			int layer = PickLayer(map);
			FindBaseMaterial(map);
			GameObject val = new GameObject("PaintCan");
			val.layer = layer;
			val.transform.SetParent(map, false);
			val.transform.position = new Vector3(0f, -8f, 10f);
			val.transform.localScale = Vector3.one * num;
			Transform transform = val.transform;
			Can can = val.AddComponent<Can>();
			can.side = (((Object)(object)Camera.main != (Object)null && ((Component)Camera.main).transform.position.x > 0f) ? 1f : (-1f));
			Material mat = Tint(BodyTone);
			Material mat2 = Tint(RimTone);
			Part(transform, (PrimitiveType)2, new Vector3(0f, 0f, 0f), new Vector3(1f, 0.6f, 1f), mat);
			Part(transform, (PrimitiveType)2, new Vector3(0f, 0.6f, 0f), new Vector3(1.07f, 0.04f, 1.07f), mat2);
			Part(transform, (PrimitiveType)2, new Vector3(0f, -0.6f, 0f), new Vector3(1.07f, 0.04f, 1.07f), mat2);
			Part(transform, (PrimitiveType)2, new Vector3(0f, 0.36f, 0f), new Vector3(1.03f, 0.015f, 1.03f), mat2);
			Part(transform, (PrimitiveType)2, new Vector3(0f, -0.4f, 0f), new Vector3(1.03f, 0.015f, 1.03f), mat2);
			Part(transform, (PrimitiveType)2, new Vector3(0f, 0.38f, -0.58f), new Vector3(0.16f, 0.05f, 0.16f), mat2, faceCamera: true);
			Part(transform, (PrimitiveType)2, new Vector3(0f, 0.38f, 0.58f), new Vector3(0.16f, 0.05f, 0.16f), mat2, faceCamera: true);
			can.paintParts.Add(Part(transform, (PrimitiveType)2, new Vector3(0f, 0.65f, 0f), new Vector3(0.9f, 0.03f, 0.9f), mat));
			can.paintParts.Add(Part(transform, (PrimitiveType)2, new Vector3(0f, 0.52f, 0f), new Vector3(1.025f, 0.07f, 1.025f), mat));
			Vector3[] drips = Drips;
			foreach (Vector3 val2 in drips)
			{
				float num2 = can.side * (Mathf.Sqrt(0.25f - val2.x * val2.x) + 0.01f);
				float y = val2.y;
				float z = val2.z;
				can.paintParts.Add(Part(transform, (PrimitiveType)1, new Vector3(num2, 0.55f - y * 0.5f, val2.x), new Vector3(z, y * 0.5f, z), mat));
				can.paintParts.Add(Part(transform, (PrimitiveType)0, new Vector3(num2, 0.55f - y + z * 0.5f, val2.x), Vector3.one * z * 1.35f, mat));
			}
			can.bail = BuildBail(transform);
			val.AddComponent<BoxCollider>().size = new Vector3(1.07f, 1.28f, 1.07f);
			Rigidbody val3 = val.AddComponent<Rigidbody>();
			val3.mass = 55f;
			val3.drag = 0.3f;
			val3.angularDrag = 0.8f;
			val3.constraints = (RigidbodyConstraints)98;
			val3.interpolation = (RigidbodyInterpolation)1;
			val3.collisionDetectionMode = (CollisionDetectionMode)1;
			can.rig = val3;
			can.home = val.transform.position;
			can.PoseBail();
			can.Offer(Palette.NextOffer(-1));
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[9] { "Paint can placed at ", null, null, null, null, null, null, null, null };
			Vector3 val4 = can.home;
			obj[1] = ((object)(*(Vector3*)(&val4))/*cast due to .constrained prefix*/).ToString();
			obj[2] = " on layer ";
			obj[3] = layer.ToString();
			obj[4] = " using material '";
			obj[5] = ((Object)baseMat).name;
			obj[6] = "' (";
			obj[7] = ((Object)baseMat.shader).name;
			obj[8] = ").";
			log.LogInfo((object)string.Concat(obj));
			return can;
		}

		private static Transform BuildBail(Transform can)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = new GameObject("Bail").transform;
			((Component)transform).gameObject.layer = ((Component)can).gameObject.layer;
			transform.SetParent(can, false);
			transform.localPosition = new Vector3(0f, 0.38f, 0f);
			Material mat = Tint(WireTone);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, 0f, 0.58f);
			Vector3 val2 = default(Vector3);
			for (int i = 1; i <= 14; i++)
			{
				float num = (float)Math.PI * (float)i / 14f;
				((Vector3)(ref val2))..ctor(0f, 0.58f * Mathf.Sin(num), 0.58f * Mathf.Cos(num));
				Vector3 val3 = val2 - val;
				((Component)Part(transform, (PrimitiveType)2, (val + val2) * 0.5f, new Vector3(0.05f, ((Vector3)(ref val3)).magnitude * 0.5f + 0.012f, 0.05f), mat)).transform.localRotation = Quaternion.FromToRotation(Vector3.up, val3);
				val = val2;
			}
			((Component)Part(transform, (PrimitiveType)2, new Vector3(0f, 0.58f, 0f), new Vector3(0.11f, 0.15f, 0.11f), Tint(GripTone))).transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			return transform;
		}

		private static void FindBaseMaterial(Transform map)
		{
			if ((Object)(object)baseMat != (Object)null)
			{
				return;
			}
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if (((Object)val).name == "WeaponMaterial")
				{
					baseMat = val;
					break;
				}
			}
			if ((Object)(object)baseMat == (Object)null)
			{
				Plugin.Log.LogWarning((object)"WeaponMaterial not found; using the lobby's material for the can.");
				MeshRenderer[] componentsInChildren = ((Component)map).GetComponentsInChildren<MeshRenderer>();
				foreach (MeshRenderer val2 in componentsInChildren)
				{
					if ((Object)(object)((Renderer)val2).sharedMaterial != (Object)null)
					{
						baseMat = ((Renderer)val2).sharedMaterial;
						break;
					}
				}
			}
			tinted.Clear();
		}

		private static Material Tint(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			if (tinted.TryGetValue(c, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			value = new Material(baseMat);
			((Object)value).name = "PaintCan " + ColorUtility.ToHtmlStringRGB(c);
			value.color = c;
			((Object)value).hideFlags = (HideFlags)32;
			tinted[c] = value;
			return value;
		}

		private static Renderer Part(Transform parent, PrimitiveType type, Vector3 pos, Vector3 scale, Material mat, bool faceCamera = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive(type);
			Object.DestroyImmediate((Object)(object)val.GetComponent<Collider>());
			val.layer = ((Component)parent).gameObject.layer;
			val.transform.SetParent(parent, false);
			val.transform.localPosition = pos;
			val.transform.localScale = scale;
			if (faceCamera)
			{
				val.transform.localRotation = Quaternion.Euler(0f, 0f, 90f);
			}
			Renderer component = val.GetComponent<Renderer>();
			if ((Object)(object)mat != (Object)null)
			{
				component.sharedMaterial = mat;
			}
			return component;
		}

		private static int PickLayer(Transform map)
		{
			int num = 0;
			Collider[] componentsInChildren = ((Component)map).GetComponentsInChildren<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).GetComponent<Rigidbody>() == (Object)null)
				{
					num = ((Component)val).gameObject.layer;
					break;
				}
			}
			if (Fits(num, num))
			{
				return num;
			}
			for (int j = 0; j < 32; j++)
			{
				if ((j < 8 || j > 11) && Fits(j, num))
				{
					return j;
				}
			}
			Plugin.Log.LogWarning((object)"No layer collides with both players and the lobby; using the lobby's.");
			return num;
		}

		private static bool Fits(int l, int mapLayer)
		{
			for (int i = 8; i <= 11; i++)
			{
				if (Physics.GetIgnoreLayerCollision(l, i))
				{
					return false;
				}
			}
			if (!Physics.GetIgnoreLayerCollision(l, mapLayer))
			{
				return !Physics.GetIgnoreLayerCollision(l, l);
			}
			return false;
		}

		private void Update()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			cooldown -= Time.deltaTime;
			Vector3 position = ((Component)this).transform.position;
			if (position.y < -35f || Mathf.Abs(position.z) > 45f)
			{
				Respawn();
			}
			if (!Palette.IsFree(offer))
			{
				Offer(Palette.NextOffer(offer));
			}
			SwingBail(Time.deltaTime);
		}

		private void SwingBail(float dt)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (!(dt <= 0f))
			{
				Vector3 velocity = rig.velocity;
				Vector3 val = velocity - lastVelocity;
				lastVelocity = velocity;
				Vector3 val2 = ((Component)this).transform.InverseTransformDirection(Physics.gravity - Vector3.ClampMagnitude(val / dt, 60f));
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor(side * Mathf.Cos(bailAngle), 0f - Mathf.Sin(bailAngle), 0f);
				float num = 0.4f * ((Component)this).transform.lossyScale.y;
				bailSpin += Vector3.Dot(val2, val3) / num * dt;
				if (((Vector3)(ref val)).magnitude > 3f)
				{
					bailSpin -= Mathf.Sign(bailAngle) * Mathf.Min(((Vector3)(ref val)).magnitude, 25f) * 0.6f;
				}
				bailSpin *= Mathf.Exp(-0.8f * dt);
				bailAngle += bailSpin * dt;
				if (bailAngle > 1.4835298f)
				{
					bailAngle = 1.4835298f;
					bailSpin = (0f - bailSpin) * 0.3f;
				}
				if (bailAngle < -0.34906584f)
				{
					bailAngle = -0.34906584f;
					bailSpin = (0f - bailSpin) * 0.3f;
				}
				PoseBail();
			}
		}

		private void PoseBail()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			bail.localRotation = Quaternion.Euler(0f, 0f, (0f - side) * bailAngle * 57.29578f);
		}

		private void Respawn()
		{
			//IL_0006: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			rig.velocity = Vector3.zero;
			rig.angularVelocity = Vector3.zero;
			rig.position = home;
			rig.rotation = Quaternion.identity;
			((Component)this).transform.position = home;
			((Component)this).transform.rotation = Quaternion.identity;
			lastVelocity = Vector3.zero;
			bailAngle = 0.05f;
			bailSpin = 0f;
		}

		private void Offer(int index)
		{
			offer = index;
			if (index >= 0)
			{
				SetPaint(Palette.Get(index));
			}
		}

		private Material SetPaint(Material playerMat)
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)playerMat == (Object)(object)Palette.RainbowMat)
			{
				if (rainbowPaint == null)
				{
					rainbowPaint = (Material[])(object)new Material[Drips.Length];
					for (int i = 0; i < Drips.Length; i++)
					{
						rainbowPaint[i] = Palette.MakeSwirl((float)i / (float)Drips.Length);
					}
				}
				if ((Object)(object)rainbowPaint[0] != (Object)null)
				{
					for (int j = 0; j < paintParts.Count; j++)
					{
						paintParts[j].sharedMaterial = rainbowPaint[(j >= 2) ? Mathf.Min((j - 2) / 2, Drips.Length - 1) : 0];
					}
					return rainbowPaint[0];
				}
			}
			Pattern pattern = Pattern.Of(playerMat);
			if (pattern != null && (Object)(object)pattern.Paint != (Object)null)
			{
				Material val = Tint(pattern.Base);
				for (int k = 0; k < paintParts.Count; k++)
				{
					paintParts[k].sharedMaterial = ((k >= 2 && (k - 2) % 2 == 1) ? val : pattern.Paint);
				}
				return pattern.Paint;
			}
			Material val2 = Tint(((Object)(object)playerMat == (Object)(object)Palette.RainbowMat) ? Palette.RainbowColour : playerMat.color);
			foreach (Renderer paintPart in paintParts)
			{
				paintPart.sharedMaterial = val2;
			}
			return val2;
		}

		private static Material[] RainbowSplash()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Material[] array = (Material[])(object)new Material[8];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = Tint(Palette.Hue((float)i / (float)array.Length));
			}
			return array;
		}

		public void OnPunched(Controller who, PunchForce fist, Vector3 point)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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 (cooldown > 0f)
			{
				return;
			}
			cooldown = 0.2f;
			if (!Palette.IsFree(offer))
			{
				return;
			}
			Material val = Palette.Give(who, offer);
			if ((Object)(object)val == (Object)null)
			{
				if (TeamColours.On)
				{
					Offer(Palette.NextOffer(offer));
				}
				return;
			}
			Pattern pattern = Pattern.Of(val);
			Material[] mats = (Material[])(((Object)(object)val == (Object)(object)Palette.RainbowMat) ? ((Array)RainbowSplash()) : ((Array)((pattern == null) ? new Material[1] { Tint(val.color) } : new Material[2]
			{
				Tint(pattern.Base),
				Tint(pattern.Accent)
			})));
			Vector3 push = (((Object)(object)fist != (Object)null) ? (point - ((Component)fist).transform.position) : Vector3.zero);
			Splash.Burst(point, push, mats, 0.75f, ((Component)this).transform.parent);
			Offer(Palette.NextOffer(offer));
			if ((Object)(object)fist != (Object)null && fist.clips != null && fist.clips.Length != 0)
			{
				AudioSource componentInChildren = ((Component)who).GetComponentInChildren<AudioSource>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.PlayOneShot(fist.clips[Random.Range(0, fist.clips.Length)], 0.7f);
				}
			}
		}
	}
	internal static class Palette
	{
		public const string DefaultList = "P1, P2, P3, P4, #FF6A00, #9B4DFF, #707070, #33E6FF, #F2F2F2, #262626, #7B3F00, #06402B, RAINBOW, ZEBRA, CANDY, BEE, LEOPARD, MISSING";

		private const int FixedOffers = 4;

		private const string RainbowToken = "RAINBOW";

		private const float RainbowPeriod = 6f;

		private static Material[] mats;

		private static string[] tokens;

		private static int[] cycle;

		private static int normalCount;

		private static readonly int[] slotColour = new int[4] { -1, -1, -1, -1 };

		private static string[] savedTokens;

		private static readonly Color[] RainbowStops = (Color[])(object)new Color[8]
		{
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)59, (byte)59, byte.MaxValue)),
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)140, (byte)26, byte.MaxValue)),
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)224, (byte)26, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)59, (byte)224, (byte)74, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)26, (byte)217, byte.MaxValue, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)59, (byte)107, byte.MaxValue, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)155, (byte)77, byte.MaxValue, byte.MaxValue)),
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)59, (byte)200, byte.MaxValue))
		};

		private static Vector3[] stopsLab;

		private const float StripeRepeats = 0.6f;

		private const float StripeLean = 0.14f;

		private const float StripeScroll = 0.3f;

		private const int StripeW = 128;

		private const int StripeH = 8;

		private const int TableSize = 512;

		private static Texture2D stripeTex;

		private static Color32[] stripeTable;

		private static Color32[] stripePixels;

		private static int stripeFrame = -1;

		private static float stripeShift;

		private static readonly FieldInfo winColorsField = WinField("mPlayerColors");

		private static readonly FieldInfo winTextsField = WinField("mPlayerWinTexts");

		private static readonly FieldInfo lineStartMatField = Private(typeof(SetLinePositions), "startMat");

		internal static readonly FieldInfo blockStartColorField = Private(typeof(BlockAnimation), "startColor");

		private static string SavePath => Path.Combine(Paths.ConfigPath, "PaintCan.colours.txt");

		public static Material RainbowMat { get; private set; }

		public static Color RainbowColour => Hue(Time.unscaledTime / 6f);

		public static Material RainbowLines { get; private set; }

		public static int Count
		{
			get
			{
				if (!Ensure())
				{
					return 0;
				}
				return mats.Length;
			}
		}

		public static Color Hue(float h)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Blend(h, 0f);
		}

		private static Color Blend(float h, float hold)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if (stopsLab == null)
			{
				stopsLab = Array.ConvertAll(RainbowStops, ToOkLab);
			}
			float num = (h - Mathf.Floor(h)) * (float)stopsLab.Length;
			int num2 = Mathf.FloorToInt(num) % stopsLab.Length;
			float num3 = Mathf.Clamp01((num - Mathf.Floor(num) - hold) / (1f - hold));
			num3 = Mathf.Lerp(num3, num3 * num3 * (3f - 2f * num3), 0.5f);
			return FromOkLab(Vector3.Lerp(stopsLab[num2], stopsLab[(num2 + 1) % stopsLab.Length], num3));
		}

		private static Material MakeStripes(Material from)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			stripeTable = (Color32[])(object)new Color32[512];
			for (int i = 0; i < 512; i++)
			{
				stripeTable[i] = Color32.op_Implicit(Blend(((float)i + 0.5f) / 512f, 0.45f));
			}
			stripePixels = (Color32[])(object)new Color32[1024];
			stripeTex = new Texture2D(128, 8, (TextureFormat)4, false);
			((Object)stripeTex).name = "PaintCan stripes";
			((Texture)stripeTex).wrapMode = (TextureWrapMode)1;
			((Texture)stripeTex).filterMode = (FilterMode)1;
			((Object)stripeTex).hideFlags = (HideFlags)32;
			DrawStripes(0f);
			return new Material(from)
			{
				name = "PaintCan rainbow stripes",
				mainTexture = (Texture)(object)stripeTex,
				color = Color.white,
				hideFlags = (HideFlags)32
			};
		}

		public static Material MakeSwirl(float start)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			ControllerHandler instance = ControllerHandler.Instance;
			if ((Object)(object)instance == (Object)null || instance.colors == null || instance.colors.Length == 0)
			{
				return null;
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
			((Object)val).name = "PaintCan swirl";
			((Texture)val).wrapMode = (TextureWrapMode)0;
			((Texture)val).filterMode = (FilterMode)1;
			((Object)val).hideFlags = (HideFlags)32;
			Color32[] array = (Color32[])(object)new Color32[16384];
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num = ((float)j + 0.5f) / 128f;
					float num2 = ((float)i + 0.5f) / 128f;
					array[i * 128 + j] = Color32.op_Implicit(Blend(start + 0.35f * num2 + 0.06f * Mathf.Sin(num * 2f * (float)Math.PI), 0.45f));
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			return new Material(instance.colors[0])
			{
				name = "PaintCan rainbow swirl",
				mainTexture = (Texture)(object)val,
				color = Color.white,
				hideFlags = (HideFlags)32
			};
		}

		public static Color StripeColourAt(float u)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (stripeTable == null)
			{
				return RainbowColour;
			}
			float num = 0.07f + stripeShift + 0.6f * Mathf.Clamp01(u);
			int num2 = (int)((num - Mathf.Floor(num)) * 512f);
			return Color32.op_Implicit(stripeTable[(num2 < 512) ? num2 : 0]);
		}

		private static void DrawStripes(float shift)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			stripeShift = shift;
			for (int i = 0; i < 8; i++)
			{
				float num = 0.14f * ((float)i + 0.5f) / 8f + shift;
				for (int j = 0; j < 128; j++)
				{
					float num2 = num + 0.6f * ((float)j + 0.5f) / 128f;
					int num3 = (int)((num2 - Mathf.Floor(num2)) * 512f);
					stripePixels[i * 128 + j] = stripeTable[(num3 < 512) ? num3 : 0];
				}
			}
			stripeTex.SetPixels32(stripePixels);
			stripeTex.Apply(false);
		}

		private static float ToLinear(float c)
		{
			if (!(c <= 0.04045f))
			{
				return Mathf.Pow((c + 0.055f) / 1.055f, 2.4f);
			}
			return c / 12.92f;
		}

		private static float ToGamma(float c)
		{
			c = Mathf.Clamp01(c);
			if (!(c <= 0.0031308f))
			{
				return 1.055f * Mathf.Pow(c, 5f / 12f) - 0.055f;
			}
			return c * 12.92f;
		}

		private static Vector3 ToOkLab(Color c)
		{
			//IL_0000: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			float num = ToLinear(c.r);
			float num2 = ToLinear(c.g);
			float num3 = ToLinear(c.b);
			float num4 = Cbrt(0.41222146f * num + 0.53633255f * num2 + 0.051445995f * num3);
			float num5 = Cbrt(0.2119035f * num + 0.6806995f * num2 + 0.10739696f * num3);
			float num6 = Cbrt(0.08830246f * num + 0.28171885f * num2 + 0.6299787f * num3);
			return new Vector3(0.21045426f * num4 + 0.7936178f * num5 - 0.004072047f * num6, 1.9779985f * num4 - 2.4285922f * num5 + 0.4505937f * num6, 0.025904037f * num4 + 0.78277177f * num5 - 0.80867577f * num6);
		}

		private static Color FromOkLab(Vector3 lab)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			float num = lab.x + 0.39633778f * lab.y + 0.21580376f * lab.z;
			float num2 = lab.x - 0.105561346f * lab.y - 0.06385417f * lab.z;
			float num3 = lab.x - 0.08948418f * lab.y - 1.2914855f * lab.z;
			num = num * num * num;
			num2 = num2 * num2 * num2;
			num3 = num3 * num3 * num3;
			return new Color(ToGamma(4.0767417f * num - 3.3077116f * num2 + 0.23096994f * num3), ToGamma(-1.268438f * num + 2.6097574f * num2 - 0.34131938f * num3), ToGamma(-0.004196077f * num - 0.7034186f * num2 + 1.7076147f * num3));
		}

		private static float Cbrt(float x)
		{
			if (!(x < 0f))
			{
				return Mathf.Pow(x, 1f / 3f);
			}
			return 0f - Mathf.Pow(0f - x, 1f / 3f);
		}

		public static void Tick()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			TeamColours.Tick();
			if ((Object)(object)RainbowMat != (Object)null)
			{
				RainbowMat.color = RainbowColour;
			}
			if ((Object)(object)stripeTex != (Object)null && stripeFrame != Time.frameCount)
			{
				stripeFrame = Time.frameCount;
				DrawStripes((0f - Time.unscaledTime) * 0.3f);
			}
		}

		public static void Load()
		{
			if (!Plugin.RememberColours.Value)
			{
				return;
			}
			try
			{
				if (File.Exists(SavePath))
				{
					string[] array = File.ReadAllLines(SavePath);
					savedTokens = new string[4];
					for (int i = 0; i < 4 && i < array.Length; i++)
					{
						savedTokens[i] = array[i].Trim();
					}
					if (mats != null)
					{
						ApplySaved();
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't read saved colours: " + ex.Message));
			}
		}

		private static void ApplySaved()
		{
			for (int i = 0; i < 4; i++)
			{
				string text = savedTokens[i];
				if (!string.IsNullOrEmpty(text) && !(text == "-"))
				{
					int num = Array.IndexOf(tokens, text);
					if (num >= 0)
					{
						slotColour[i] = num;
					}
				}
			}
			savedTokens = null;
		}

		private static void Save()
		{
			if (!Plugin.RememberColours.Value || tokens == null)
			{
				return;
			}
			try
			{
				string[] array = new string[4];
				for (int i = 0; i < 4; i++)
				{
					array[i] = ((slotColour[i] >= 0 && slotColour[i] < tokens.Length) ? tokens[slotColour[i]] : "-");
				}
				File.WriteAllText(SavePath, string.Join("\n", array) + "\n");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't save colours: " + ex.Message));
			}
		}

		public static void OnRememberChanged()
		{
			if (Plugin.RememberColours.Value)
			{
				Save();
			}
		}

		private static FieldInfo WinField(string name)
		{
			return Private(typeof(WinCounterUI), name);
		}

		private static FieldInfo Private(Type type, string name)
		{
			return type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
		}

		public static Material Make(Color c, string name)
		{
			//IL_0015: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (!Ensure())
			{
				return null;
			}
			return new Material(ControllerHandler.Instance.colors[0])
			{
				name = name,
				color = c,
				hideFlags = (HideFlags)32
			};
		}

		public static Material Get(int index)
		{
			if (!Ensure())
			{
				return null;
			}
			return mats[index];
		}

		private static bool Ensure()
		{
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Expected O, but got Unknown
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			if (mats != null && mats.Length != 0 && (Object)(object)mats[mats.Length - 1] != (Object)null)
			{
				return true;
			}
			ControllerHandler instance = ControllerHandler.Instance;
			if ((Object)(object)instance == (Object)null || instance.colors == null || instance.colors.Length == 0)
			{
				return false;
			}
			List<Material> list = new List<Material>();
			List<string> list2 = new List<string>();
			RainbowMat = null;
			string[] array = "P1, P2, P3, P4, #FF6A00, #9B4DFF, #707070, #33E6FF, #F2F2F2, #262626, #7B3F00, #06402B, RAINBOW, ZEBRA, CANDY, BEE, LEOPARD, MISSING".Split(new char[1] { ',' });
			Color color = default(Color);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length == 0)
				{
					continue;
				}
				if (text.Length == 2 && (text[0] == 'P' || text[0] == 'p') && text[1] >= '1' && text[1] <= '4')
				{
					int num = text[1] - 49;
					if (num < instance.colors.Length)
					{
						list.Add(instance.colors[num]);
						list2.Add(text);
					}
					continue;
				}
				bool flag = text == "RAINBOW";
				Pattern pattern = Pattern.ByToken(text);
				if (flag)
				{
					color = RainbowColour;
				}
				else if (pattern != null)
				{
					color = pattern.Base;
				}
				else if (!ColorUtility.TryParseHtmlString(text, ref color))
				{
					Plugin.Log.LogWarning((object)("Bad palette colour '" + text + "', skipping it."));
					continue;
				}
				Material val = new Material(instance.colors[0]);
				((Object)val).name = "PaintCan " + text;
				val.color = color;
				((Object)val).hideFlags = (HideFlags)32;
				if (flag)
				{
					RainbowMat = val;
					if ((Object)(object)RainbowLines == (Object)null)
					{
						RainbowLines = MakeStripes(instance.colors[0]);
					}
				}
				if (pattern != null)
				{
					pattern.Mat = val;
				}
				list.Add(val);
				list2.Add(text);
			}
			if (list.Count == 0)
			{
				list.AddRange(instance.colors);
				Material[] colors = instance.colors;
				foreach (Material val2 in colors)
				{
					list2.Add(((Object)val2).name);
				}
			}
			normalCount = list.Count;
			for (int j = 0; j < 5; j++)
			{
				for (int k = 0; k < 2; k++)
				{
					int num2 = TeamPalette.GameSlot(j);
					Material val3;
					if (k == 0 && num2 >= 0 && num2 < instance.colors.Length)
					{
						val3 = instance.colors[num2];
					}
					else
					{
						val3 = new Material(instance.colors[0]);
						((Object)val3).name = "PaintCan team " + TeamPalette.Names[j] + " " + k;
						val3.color = TeamPalette.Shade(j, k);
						((Object)val3).hideFlags = (HideFlags)32;
					}
					list.Add(val3);
					list2.Add("TEAM-" + TeamPalette.Names[j] + "-" + k);
				}
			}
			mats = list.ToArray();
			tokens = list2.ToArray();
			cycle = new int[normalCount];
			for (int l = 0; l < cycle.Length; l++)
			{
				cycle[l] = l;
			}
			Shuffle(-1);
			if (savedTokens != null && tokens.Length == mats.Length)
			{
				ApplySaved();
			}
			return true;
		}

		private static int IndexOfGameColour(int slot)
		{
			ControllerHandler instance = ControllerHandler.Instance;
			if ((Object)(object)instance != (Object)null && slot < instance.colors.Length)
			{
				int num = Array.IndexOf(mats, instance.colors[slot]);
				if (num >= 0)
				{
					return num;
				}
			}
			return slot % normalCount;
		}

		public static int Current(int slot)
		{
			if (!Ensure())
			{
				return 0;
			}
			int num = slotColour[slot];
			if (num < 0 || num >= mats.Length)
			{
				return IndexOfGameColour(slot);
			}
			return num;
		}

		private static bool UsedByOther(int index, Controller self)
		{
			foreach (Controller activePlayer in ControllerHandler.Instance.ActivePlayers)
			{
				if (!((Object)(object)activePlayer == (Object)(object)self) && activePlayer.playerID >= 0 && activePlayer.playerID <= 3 && Current(activePlayer.playerID) == index)
				{
					return true;
				}
			}
			return false;
		}

		private static int FreeFrom(int start, Controller self)
		{
			for (int i = 0; i < normalCount; i++)
			{
				int num = (start + i) % normalCount;
				if (!UsedByOther(num, self))
				{
					return num;
				}
			}
			return -1;
		}

		private static void Shuffle(int last)
		{
			int num = cycle.Length;
			for (int num2 = num - 1; num2 > 4; num2--)
			{
				int num3 = Random.Range(4, num2 + 1);
				int num4 = cycle[num2];
				cycle[num2] = cycle[num3];
				cycle[num3] = num4;
			}
			if (num > 5 && cycle[4] == last)
			{
				int num5 = Random.Range(5, num);
				cycle[4] = cycle[num5];
				cycle[num5] = last;
			}
		}

		public static int NextOffer(int current)
		{
			if (!Ensure() || (Object)(object)ControllerHandler.Instance == (Object)null)
			{
				return -1;
			}
			if (TeamColours.On)
			{
				return NextTeamOffer(current);
			}
			for (int i = ((current < 0) ? (-1) : Array.IndexOf(cycle, current)) + 1; i < cycle.Length; i++)
			{
				if (!UsedByOther(cycle[i], null))
				{
					return cycle[i];
				}
			}
			Shuffle(current);
			for (int j = 0; j < cycle.Length; j++)
			{
				if (!UsedByOther(cycle[j], null))
				{
					return cycle[j];
				}
			}
			return -1;
		}

		public static bool IsFree(int index)
		{
			if (!Ensure() || (Object)(object)ControllerHandler.Instance == (Object)null || index < 0 || index >= mats.Length)
			{
				return false;
			}
			if (TeamColours.On)
			{
				int shade;
				int num = TeamEntry(index, out shade);
				if (num >= 0)
				{
					return !TeamColours.LeadWears(num, shade);
				}
				return false;
			}
			if (index < normalCount)
			{
				return !UsedByOther(index, null);
			}
			return false;
		}

		public static Material TeamMat(int family, int shade)
		{
			if (!Ensure() || family < 0 || family >= 5)
			{
				return null;
			}
			return mats[normalCount + family * 2 + shade];
		}

		private static int TeamEntry(int index, out int shade)
		{
			int num = index - normalCount;
			shade = ((num >= 0) ? (num % 2) : 0);
			if (num < 0 || num / 2 >= 5)
			{
				return -1;
			}
			return num / 2;
		}

		private static int NextTeamOffer(int current)
		{
			int num = 10;
			int shade;
			int num2 = ((TeamEntry(current, out shade) >= 0) ? (current - normalCount) : (-1));
			for (int i = 1; i <= num; i++)
			{
				int num3 = (num2 + i + num) % num;
				if (!TeamColours.LeadWears(num3 / 2, num3 % 2))
				{
					return normalCount + num3;
				}
			}
			return -1;
		}

		public static Color? OwnColour(int slot)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if (!Ensure() || slot < 0 || slot > 3)
			{
				return null;
			}
			int num = slotColour[slot];
			if (num < 0 || num >= normalCount)
			{
				return null;
			}
			Material val = mats[num];
			if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)RainbowMat || Pattern.Of(val) != null)
			{
				return null;
			}
			return val.color;
		}

		public static void Restore(Controller player)
		{
			if (Ensure() && player.playerID >= 0 && player.playerID <= 3)
			{
				Apply(player, mats[Current(player.playerID)]);
			}
		}

		public static void Wear(Controller player, Material mat)
		{
			if ((Object)(object)mat != (Object)null)
			{
				Apply(player, mat);
			}
		}

		public static void OnJoined(Controller player)
		{
			if (!Ensure() || player.playerID < 0 || player.playerID > 3)
			{
				return;
			}
			if (TeamColours.On)
			{
				TeamColours.Tick();
				return;
			}
			int num = Current(player.playerID);
			int num2 = FreeFrom(num, player);
			if (num2 >= 0)
			{
				if (num2 != num)
				{
					slotColour[player.playerID] = num2;
					Save();
				}
				if (num2 != IndexOfGameColour(player.playerID) || slotColour[player.playerID] >= 0)
				{
					Apply(player, mats[num2]);
				}
			}
		}

		public static Material Give(Controller player, int index)
		{
			if (!Ensure() || player.playerID < 0 || player.playerID > 3 || index < 0 || index >= mats.Length)
			{
				return null;
			}
			if (TeamColours.On)
			{
				int shade;
				int num = TeamEntry(index, out shade);
				if (num < 0 || !TeamColours.Take(player, num, shade))
				{
					Plugin.Log.LogDebug((object)("P" + (player.playerID + 1) + " can't take team " + ((num >= 0) ? TeamPalette.ShadeNames[num, shade] : "?") + " (only a team's lead picks, never too close to the other team)"));
					return null;
				}
				Plugin.Log.LogDebug((object)("P" + (player.playerID + 1) + " took team " + TeamPalette.ShadeNames[num, shade]));
				return mats[index];
			}
			if (index >= normalCount)
			{
				return null;
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			slotColour[player.playerID] = index;
			Save();
			Apply(player, mats[index]);
			Plugin.Log.LogDebug((object)("P" + (player.playerID + 1) + " took " + tokens[index] + " (" + stopwatch.Elapsed.TotalMilliseconds.ToString("0.0") + " ms)"));
			return mats[index];
		}

		private static void Apply(Controller player, Material mat)
		{
			//IL_0008: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)player).gameObject;
			Color color = mat.color;
			Rainbow rainbow = gameObject.GetComponent<Rainbow>();
			if ((Object)(object)mat == (Object)(object)RainbowMat && (Object)(object)mat != (Object)null)
			{
				if ((Object)(object)rainbow == (Object)null)
				{
					rainbow = gameObject.AddComponent<Rainbow>();
				}
				((Behaviour)rainbow).enabled = true;
				rainbow.Refresh();
			}
			else if ((Object)(object)rainbow != (Object)null)
			{
				((Behaviour)rainbow).enabled = false;
				Object.Destroy((Object)(object)rainbow);
			}
			Pattern pattern = Pattern.Of(mat);
			Material val = (((Object)(object)mat == (Object)(object)RainbowMat && (Object)(object)RainbowLines != (Object)null) ? RainbowLines : mat);
			if (pattern != null && (Object)(object)pattern.Lines != (Object)null)
			{
				val = pattern.Lines;
			}
			LineRenderer[] componentsInChildren = gameObject.GetComponentsInChildren<LineRenderer>();
			foreach (LineRenderer val2 in componentsInChildren)
			{
				if (!InWeapons(((Component)val2).transform))
				{
					((Renderer)val2).sharedMaterial = val;
				}
			}
			SpriteRenderer[] componentsInChildren2 = gameObject.GetComponentsInChildren<SpriteRenderer>();
			foreach (SpriteRenderer val3 in componentsInChildren2)
			{
				if (!InWeapons(((Component)val3).transform) && !(((Component)((Component)val3).transform).tag == "DontChangeColor"))
				{
					val3.color = color;
				}
			}
			gameObject.GetComponent<CharacterInformation>().myMaterial = mat;
			SetColorWhenDamaged[] componentsInChildren3 = gameObject.GetComponentsInChildren<SetColorWhenDamaged>(true);
			foreach (SetColorWhenDamaged val4 in componentsInChildren3)
			{
				if ((Object)(object)((Component)val4).GetComponent<SpriteRenderer>() != (Object)null && ((Component)((Component)val4).transform).tag != "DontChangeColor")
				{
					val4.startColor = color;
				}
				if ((Object)(object)((Component)val4).GetComponent<MeshRenderer>() != (Object)null)
				{
					val4.startMat = mat;
				}
			}
			SetLinePositions[] componentsInChildren4 = gameObject.GetComponentsInChildren<SetLinePositions>(true);
			foreach (SetLinePositions val5 in componentsInChildren4)
			{
				if (!InWeapons(((Component)val5).transform))
				{
					lineStartMatField.SetValue(val5, val);
				}
			}
			BlockAnimation[] componentsInChildren5 = gameObject.GetComponentsInChildren<BlockAnimation>(true);
			foreach (BlockAnimation obj in componentsInChildren5)
			{
				blockStartColorField.SetValue(obj, color);
			}
			SetImageColor[] componentsInChildren6 = gameObject.GetComponentsInChildren<SetImageColor>(true);
			for (int i = 0; i < componentsInChildren6.Length; i++)
			{
				Image component = ((Component)componentsInChildren6[i]).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					((Graphic)component).color = color;
				}
			}
			SetParticleColor[] componentsInChildren7 = gameObject.GetComponentsInChildren<SetParticleColor>(true);
			foreach (SetParticleColor obj2 in componentsInChildren7)
			{
				ParticleSystemRenderer component2 = ((Component)obj2).GetComponent<ParticleSystemRenderer>();
				ParticleSystem component3 = ((Component)obj2).GetComponent<ParticleSystem>();
				if (obj2.setMaterialInstead && (Object)(object)component2 != (Object)null)
				{
					((Renderer)component2).sharedMaterial = mat;
				}
				else if ((Object)(object)component3 != (Object)null)
				{
					MainModule main = component3.main;
					((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color);
				}
			}
			Pattern.WearHead(gameObject, pattern);
			SetWinColour(Object.FindObjectOfType<WinCounterUI>(), player.playerID, color, pattern);
		}

		internal static void SetWinColour(WinCounterUI win, int slot, Color col, Pattern pattern = null)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)win == (Object)null) && (object)winColorsField != null && (object)winTextsField != null)
			{
				Color[] array = winColorsField.GetValue(win) as Color[];
				TextMeshProUGUI[] array2 = winTextsField.GetValue(win) as TextMeshProUGUI[];
				if (array != null && slot < array.Length)
				{
					array[slot] = col;
				}
				if (array2 != null && slot < array2.Length && (Object)(object)array2[slot] != (Object)null)
				{
					((Graphic)array2[slot]).color = Pattern.Digits(array2[slot], pattern, col);
				}
			}
		}

		internal static bool InWeapons(Transform t)
		{
			return (Object)(object)((Component)t).GetComponentInParent<Weapons>() != (Object)null;
		}
	}
	[HarmonyPatch(typeof(ControllerHandler), "CreatePlayer")]
	internal static class CreatePlayerPatch
	{
		private static void Postfix(Controller __result)
		{
			if (!((Object)(object)__result == (Object)null) && !MatchmakingHandler.IsNetworkMatch)
			{
				Palette.OnJoined(__result);
			}
		}
	}
	[HarmonyPatch(typeof(PunchForce), "OnCollisionEnter")]
	internal static class PunchPatch
	{
		private static void Prefix(Collision collision, Fighting ___fighting, out bool __state)
		{
			__state = false;
			if (!((Object)(object)___fighting == (Object)null) && !((Object)(object)collision.rigidbody == (Object)null) && !((Object)(object)((Component)collision.rigidbody).GetComponent<Can>() == (Object)null))
			{
				__state = !___fighting.attackedNonTargetRigs.Contains(collision.rigidbody);
			}
		}

		private static void Postfix(PunchForce __instance, Collision collision, Fighting ___fighting, bool __state)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if (__state && ___fighting.attackedNonTargetRigs.Contains(collision.rigidbody) && !MatchmakingHandler.IsNetworkMatch)
			{
				Controller component = ((Component)((Component)__instance).transform.root).GetComponent<Controller>();
				if (!((Object)(object)component == (Object)null) && !component.isAI && !((Object)(object)ControllerHandler.Instance == (Object)null) && ControllerHandler.Instance.players.Contains(component))
				{
					Vector3 point = ((collision.contacts.Length != 0) ? ((ContactPoint)(ref collision.contacts[0])).point : collision.transform.position);
					((Component)collision.rigidbody).GetComponent<Can>().OnPunched(component, __instance, point);
				}
			}
		}
	}
	internal class Pattern
	{
		private class HeadSource
		{
			public Color32[] px;

			public int w;

			public int h;

			public Vector2 pivot;

			public float ppu;
		}

		public readonly string Token;

		public readonly Color Base;

		public readonly Color Accent;

		private readonly float lineAlong;

		private readonly float lineAcross;

		private readonly float head;

		private readonly float digit;

		private readonly float paintAlong;

		private readonly float paintAcross;

		private readonly float paintPhase;

		private readonly Func<Pattern, float, float, int, Color> sample;

		private readonly Func<Pattern, float, float, int, Color> paintSample;

		public Material Mat;

		private Material lines;

		private Material paint;

		private Texture2D digitTex;

		private readonly Dictionary<Sprite, Sprite> heads = new Dictionary<Sprite, Sprite>();

		private readonly Dictionary<Material, Material> digitMats = new Dictionary<Material, Material>();

		public static readonly Pattern[] All = new Pattern[5]
		{
			new Pattern("ZEBRA", Color32.op_Implicit(new Color32((byte)242, (byte)242, (byte)242, byte.MaxValue)), Color32.op_Implicit(new Color32((byte)20, (byte)20, (byte)20, byte.MaxValue)), 5f, 0.5f, 2.2f, 2.5f, 2f, 0.3f, Zebra),
			new Pattern("CANDY", Color32.op_Implicit(new Color32((byte)227, (byte)32, (byte)46, byte.MaxValue)), Color32.op_Implicit(new Color32((byte)247, (byte)242, (byte)242, byte.MaxValue)), 4f, 1f, 2f, 2f, 2f, 0.15f, Candy),
			new Pattern("BEE", Color32.op_Implicit(new Color32(byte.MaxValue, (byte)196, (byte)20, byte.MaxValue)), Color32.op_Implicit(new Color32((byte)26, (byte)26, (byte)26, byte.MaxValue)), 3.5f, 0.5f, 1.8f, 2f, 2f, 0f, Bee),
			new Pattern("LEOPARD", Color32.op_Implicit(new Color32((byte)178, (byte)108, (byte)44, byte.MaxValue)), Color32.op_Implicit(new Color32((byte)32, (byte)19, (byte)10, byte.MaxValue)), 7f, 0.9f, 3.2f, 2.4f, 3f, 0.15f, Leopard, LeopardPaint),
			new Pattern("MISSING", Color32.op_Implicit(new Color32(byte.MaxValue, (byte)0, (byte)220, byte.MaxValue)), Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)), 8f, 2f, 4f, 3f, 3f, 1f, Missing, null, (float)Math.PI / 2f)
		};

		private static readonly Color LeopardInner = Color32.op_Implicit(new Color32((byte)138, (byte)80, (byte)30, byte.MaxValue));

		private const int HeadSize = 128;

		private static readonly Dictionary<Sprite, HeadSource> sources = new Dictionary<Sprite, HeadSource>();

		private static int warmStep;

		private static float warmTotal;

		private static float warmWorst;

		internal const int ApiSpriteSize = 192;

		private static readonly List<Sprite> warmShapes = new List<Sprite>();

		private static int shapeStep;

		private static readonly Dictionary<TextMeshProUGUI, Material> digitOriginals = new Dictionary<TextMeshProUGUI, Material>();

		private static readonly HashSet<TextMeshProUGUI> gradientDigits = new HashSet<TextMeshProUGUI>();

		public Material Lines
		{
			get
			{
				if ((Object)(object)lines == (Object)null)
				{
					lines = Textured(Draw(Token + " lines", 128, 16, (TextureWrapMode)1, 0, (float u, float v) => new Vector2(u * lineAlong, v * lineAcross)), "PaintCan " + Token + " lines");
				}
				return lines;
			}
		}

		public Material Paint
		{
			get
			{
				if ((Object)(object)paint == (Object)null)
				{
					paint = Textured(Draw(Token + " paint", 64, 64, (TextureWrapMode)0, 0, (float u, float v) => new Vector2(v * paintAlong, paintAcross * Mathf.Sin((float)Math.PI * 2f * u + paintPhase)), paintSample, 1), "PaintCan " + Token + " paint");
				}
				return paint;
			}
		}

		private Pattern(string token, Color baseColour, Color accent, float lineAlong, float lineAcross, float head, float digit, float paintAlong, float paintAcross, Func<Pattern, float, float, int, Color> sample, Func<Pattern, float, float, int, Color> paintSample = null, float paintPhase = 0f)
		{
			//IL_0024: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			Token = token;
			Base = baseColour;
			Accent = accent;
			this.lineAlong = lineAlong;
			this.lineAcross = lineAcross;
			this.head = head;
			this.digit = digit;
			this.paintAlong = paintAlong;
			this.paintAcross = paintAcross;
			this.sample = sample;
			this.paintSample = paintSample ?? sample;
			this.paintPhase = paintPhase;
		}

		public static Pattern ByToken(string token)
		{
			Pattern[] all = All;
			foreach (Pattern pattern in all)
			{
				if (pattern.Token == token)
				{
					return pattern;
				}
			}
			return null;
		}

		public static Pattern Of(Material mat)
		{
			if ((Object)(object)mat == (Object)null)
			{
				return null;
			}
			Pattern[] all = All;
			foreach (Pattern pattern in all)
			{
				if ((Object)(object)pattern.Mat == (Object)(object)mat)
				{
					return pattern;
				}
			}
			return null;
		}

		private static float Frac(float x)
		{
			return x - Mathf.Floor(x);
		}

		private static Color Zebra(Pattern pat, float p, float q, int wrapQ)
		{
			//IL_0030: 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 (!(Frac(p + 0.5f * q + 0.08f * Mathf.Sin((float)Math.PI * 2f * q)) < 0.42f))
			{
				return pat.Base;
			}
			return pat.Accent;
		}

		private static Color Candy(Pattern pat, float p, float q, int wrapQ)
		{
			//IL_0017: 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)
			if (!(Frac(p + q) < 0.5f))
			{
				return pat.Accent;
			}
			return pat.Base;
		}

		private static Color Bee(Pattern pat, float p, float q, int wrapQ)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!(Frac(p) < 0.45f))
			{
				return pat.Base;
			}
			return pat.Accent;
		}

		private static Color Missing(Pattern pat, float p, float q, int wrapQ)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (((Mathf.FloorToInt(p) + Mathf.FloorToInt(q)) & 1) != 0)
			{
				return pat.Accent;
			}
			return pat.Base;
		}

		private static Color Leopard(Pattern pat, float p, float q, int wrapQ)
		{
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.FloorToInt(q);
			float num2 = 9f;
			float num3 = 9f;
			bool flag = false;
			for (int i = -1; i <= 1; i++)
			{
				int num4 = num + i;
				int num5 = ((wrapQ > 0) ? ((num4 % wrapQ + wrapQ) % wrapQ) : num4);
				float num6 = (float)(num5 & 1) * 0.5f;
				int num7 = Mathf.FloorToInt(p - num6);
				for (int j = -1; j <= 1; j++)
				{
					int num8 = num7 + j;
					float num9 = (float)num8 + num6 + 0.5f + 0.24f * (Hash(num8, num5, 1) - 0.5f);
					float num10 = (float)num4 + 0.5f + 0.24f * (Hash(num8, num5, 2) - 0.5f);
					if (Hash(num8, num5, 8) > 0.35f)
					{
						float num11 = (float)num8 + num6 + 0.12f * (Hash(num8, num5, 9) - 0.5f);
						float num12 = (float)num4 + 0.12f * (Hash(num8, num5, 10) - 0.5f);
						float num13 = 0.04f + 0.04f * Hash(num8, num5, 11);
						float num14 = (p - num11) / (1f + 0.5f * Hash(num8, num5, 12));
						float num15 = q - num12;
						num3 = Mathf.Min(num3, Mathf.Sqrt(num14 * num14 + num15 * num15) - num13);
					}
					float num16 = p - num9;
					float num17 = q - num10;
					float num18 = Mathf.Sqrt(num16 * num16 + num17 * num17);
					if (!(num18 > 0.52f))
					{
						float num19 = Mathf.Atan2(num17, num16);
						float num20 = (float)Math.PI * 2f * Hash(num8, num5, 3);
						float num21 = 0.24f + 0.08f * Hash(num8, num5, 4);
						float num22 = num21 * (1f + 0.12f * Mathf.Sin(2f * num19 + num20) + 0.07f * Mathf.Sin(3f * num19 + 2f * num20));
						if (num18 < num22 * 0.85f)
						{
							flag = true;
						}
						int num23 = 3 + (int)(Hash(num8, num5, 5) * 2.999f);
						float num24 = (float)Math.PI * 2f / (float)num23;
						int num25 = Mathf.FloorToInt((num19 - num20) / num24);
						num25 = (num25 % num23 + num23) % num23;
						float num26 = num19 - num20 - Mathf.Floor((num19 - num20) / num24) * num24;
						float num27 = 0.5f * num24 * (0.6f + 0.28f * Hash(num8 * 7 + num25, num5, 6));
						float num28 = Mathf.Abs(num26 - 0.5f * num24);
						float num29 = (0.06f + 0.035f * Hash(num8 * 7 + num25, num5, 7)) * num21 / 0.28f;
						float num30 = num18 - num22 + 0.012f * Mathf.Sin(11f * num19 + num20);
						float num32;
						if (num28 < num27)
						{
							float num31 = num28 / num27;
							num32 = Mathf.Abs(num30) - num29 * (1f - 0.45f * num31 * num31);
						}
						else
						{
							float num33 = num22 * (num28 - num27);
							num32 = Mathf.Sqrt(num30 * num30 + num33 * num33) - num29 * 0.55f;
						}
						num2 = Mathf.Min(num2, num32);
					}
				}
			}
			if (num2 < 0f || num3 < 0f)
			{
				return pat.Accent;
			}
			if (!flag)
			{
				return pat.Base;
			}
			return LeopardInner;
		}

		private static Color LeopardPaint(Pattern pat, float p, float q, int wrapQ)
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.RoundToInt(q / 0.3f);
			for (int i = -1; i <= 1; i++)
			{
				int num2 = num + i;
				float num3 = (float)(num2 & 1) * 0.5f;
				int num4 = Mathf.FloorToInt(p - num3);
				for (int j = -1; j <= 1; j++)
				{
					int num5 = num4 + j;
					float num6 = (float)num5 + num3 + 0.5f + 0.3f * (Hash(num5, num2, 21) - 0.5f);
					float num7 = (float)num2 * 0.3f + 0.08f * (Hash(num5, num2, 22) - 0.5f);
					float num8 = 0.13f + 0.07f * Hash(num5, num2, 23);
					float num9 = (p - num6) * (0.8f + 0.4f * Hash(num5, num2, 24));
					float num10 = q - num7;
					float num11 = Mathf.Atan2(num10, num9);
					num8 *= 1f + 0.1f * Mathf.Sin(3f * num11 + 6.28f * Hash(num5, num2, 25));
					if (num9 * num9 + num10 * num10 < num8 * num8)
					{
						return pat.Accent;
					}
				}
			}
			return pat.Base;
		}

		private static float Hash(int x, int y, int salt)
		{
			int num = x * 374761393 + y * 668265263 + salt * -2048144777;
			int num2 = (num ^ (num >>> 13)) * 1274126177;
			return (float)(uint)((num2 ^ (num2 >>> 16)) & 0xFFFFFF) / 16777216f;
		}

		private Color Pixel(float x0, float x1, float y0, float y1, int wrapQ, Func<float, float, Vector2> map, Func<Pattern, float, float, int, Color> fn, int ss)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			Color val = Color.clear;
			for (int i = 0; i < ss; i++)
			{
				for (int j = 0; j < ss; j++)
				{
					Vector2 val2 = map(Mathf.Lerp(x0, x1, ((float)j + 0.5f) / (float)ss), Mathf.Lerp(y0, y1, ((float)i + 0.5f) / (float)ss));
					val += fn(this, val2.x, val2.y, wrapQ);
				}
			}
			Color result = val / (float)(ss * ss);
			result.a = 1f;
			return result;
		}

		private Texture2D Draw(string name, int w, int h, TextureWrapMode wrap, int wrapQ, Func<float, float, Vector2> map, Func<Pattern, float, float, int, Color> fn = null, int ss = 2)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(w, h, (TextureFormat)4, true);
			((Object)val).name = "PaintCan " + name;
			((Texture)val).wrapMode = wrap;
			((Texture)val).filterMode = (FilterMode)2;
			((Texture)val).anisoLevel = 4;
			((Object)val).hideFlags = (HideFlags)32;
			if (fn == null)
			{
				fn = sample;
			}
			Color32[] array = (Color32[])(object)new Color32[w * h];
			for (int i = 0; i < h; i++)
			{
				for (int j = 0; j < w; j++)
				{
					array[i * w + j] = Color32.op_Implicit(Pixel((float)j / (float)w, ((float)j + 1f) / (float)w, (float)i / (float)h, ((float)i + 1f) / (float)h, wrapQ, map, fn, ss));
				}
			}
			val.SetPixels32(array);
			val.Apply(true);
			return val;
		}

		private static Material Textured(Texture2D tex, string name)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			ControllerHandler instance = ControllerHandler.Instance;
			if ((Object)(object)instance == (Object)null || instance.colors == null || instance.colors.Length == 0)
			{
				return null;
			}
			return new Material(instance.colors[0])
			{
				name = name,
				mainTexture = (Texture)(object)tex,
				color = Color.white,
				hideFlags = (HideFlags)32
			};
		}

		public Sprite Head(Sprite original, int maxSize = 128)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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)
			if ((Object)(object)original == (Object)null)
			{
				return null;
			}
			if (heads.TryGetValue(original, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			value = null;
			try
			{
				HeadSource headSource = Source(original, maxSize);
				if (headSource != null)
				{
					int w = headSource.w;
					int h = headSource.h;
					float aspect = (float)w / (float)h;
					Texture2D val = Draw(Token + " head", w, h, (TextureWrapMode)1, 0, (float u, float v) => new Vector2(v * head, u * head * aspect), null, 1);
					Color32[] pixels = val.GetPixels32();
					for (int num = 0; num < pixels.Length; num++)
					{
						Color32 val2 = headSource.px[num];
						Color32 val3 = pixels[num];
						pixels[num] = new Color32((byte)(val3.r * val2.r / 255), (byte)(val3.g * val2.g / 255), (byte)(val3.b * val2.b / 255), val2.a);
					}
					val.SetPixels32(pixels);
					val.Apply(true, true);
					value = Sprite.Create(val, new Rect(0f, 0f, (float)w, (float)h), headSource.pivot, headSource.ppu);
					((Object)value).name = "PaintCan " + Token + " head";
					((Object)value).hideFlags = (HideFlags)32;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't paint the " + Token + " head, it gets the plain colour: " + ex.Message));
				value = null;
			}
			heads[original] = value;
			return value;
		}

		private static HeadSource Source(Sprite original, int maxSize)
		{
			//IL_0014: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			if (sources.TryGetValue(original, out var value))
			{
				return value;
			}
			value = null;
			Rect textureRect = original.textureRect;
			int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
			int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
			Color32[] array = ReadPixels(original.texture, textureRect, num, num2);
			if (array != null)
			{
				float num3 = Mathf.Min(1f, (float)maxSize / (float)Mathf.Max(num, num2));
				int num4 = Mathf.Max(1, Mathf.RoundToInt((float)num * num3));
				int num5 = Mathf.Max(1, Mathf.RoundToInt((float)num2 * num3));
				Color32[] array2 = (Color32[])(object)new Color32[num4 * num5];
				for (int i = 0; i < num5; i++)
				{
					for (int j = 0; j < num4; j++)
					{
						int num6 = j * num / num4;
						int num7 = Mathf.Max(num6 + 1, (j + 1) * num / num4);
						int num8 = i * num2 / num5;
						int num9 = Mathf.Max(num8 + 1, (i + 1) * num2 / num5);
						int num10 = 0;
						int num11 = 0;
						int num12 = 0;
						int num13 = 0;
						int num14 = 0;
						for (int k = num8; k < num9; k++)
						{
							for (int l = num6; l < num7; l++)
							{
								Color32 val = array[k * num + l];
								num10 += val.r;
								num11 += val.g;
								num12 += val.b;
								num13 += val.a;
								num14++;
							}
						}
						array2[i * num4 + j] = new Color32((byte)(num10 / num14), (byte)(num11 / num14), (byte)(num12 / num14), (byte)(num13 / num14));
					}
				}
				Vector2 val2 = original.pivot - original.textureRectOffset;
				value = new HeadSource
				{
					px = array2,
					w = num4,
					h = num5,
					pivot = new Vector2(val2.x / (float)num, val2.y / (float)num2),
					ppu = original.pixelsPerUnit * (float)num4 / (float)num
				};
			}
			sources[original] = value;
			return value;
		}

		public static void WarmUp()
		{
			int num = All.Length * 4;
			if (warmStep >= num)
			{
				WarmShapes();
				return;
			}
			ControllerHandler instance = ControllerHandler.Instance;
			if ((Object)(object)instance == (Object)null || instance.colors == null || instance.colors.Length == 0)
			{
				return;
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			Pattern pattern = All[warmStep / 4];
			switch (warmStep % 4)
			{
			case 0:
				if ((Object)(object)pattern.Lines == (Object)null)
				{
					return;
				}
				break;
			case 1:
				if ((Object)(object)pattern.Paint == (Object)null)
				{
					return;
				}
				break;
			case 2:
				pattern.DigitTexture();
				break;
			case 3:
			{
				Sprite val = AnyHead(instance);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				pattern.Head(val);
				break;
			}
			}
			float num2 = (float)stopwatch.Elapsed.TotalMilliseconds;
			warmTotal += num2;
			warmWorst = Mathf.Max(warmWorst, num2);
			if (++warmStep == num)
			{
				Plugin.Log.LogDebug((object)("Patterns ready: " + warmTotal.ToString("0") + " ms over " + num + " frames, slowest " + warmWorst.ToString("0.0") + " ms"));
			}
		}

		internal static void QueueShape(Sprite shape)
		{
			if ((Object)(object)shape != (Object)null && !warmShapes.Contains(shape))
			{
				warmShapes.Add(shape);
			}
		}

		private static void WarmShapes()
		{
			if (shapeStep < warmShapes.Count * All.Length)
			{
				Sprite val = warmShapes[shapeStep / All.Length];
				if ((Object)(object)val != (Object)null)
				{
					All[shapeStep % All.Length].Head(val, 192);
				}
				shapeStep++;
			}
		}

		private static Sprite AnyHead(ControllerHandler handler)
		{
			if (handler.players == null)
			{
				return null;
			}
			foreach (Controller player in handler.players)
			{
				if ((Object)(object)player == (Object)null)
				{
					continue;
				}
				PatternHead component = ((Component)player).GetComponent<PatternHead>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.original != (Object)null)
				{
					return component.original;
				}
				SpriteRenderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<SpriteRenderer>();
				foreach (SpriteRenderer val in componentsInChildren)
				{
					if (((Object)val).name == "headRenderer" && !Palette.InWeapons(((Component)val).transform) && (Object)(object)val.sprite != (Object)null && !((Object)val.sprite).name.StartsWith("PaintCan"))
					{
						return val.sprite;
					}
				}
			}
			return null;
		}

		private static Color32[] ReadPixels(Texture2D src, Rect r, int w, int h)
		{
			//IL_0099: 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_00b1: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)src == (Object)null || w <= 0 || h <= 0)
			{
				return null;
			}
			try
			{
				Color[] pixels = src.GetPixels(Mathf.RoundToInt(((Rect)(ref r)).x), Mathf.RoundToInt(((Rect)(ref r)).y), w, h);
				Color32[] array = (Color32[])(object)new Color32[pixels.Length];
				for (int i = 0; i < pixels.Length; i++)
				{
					array[i] = Color32.op_Implicit(pixels[i]);
				}
				return array;
			}
			catch (UnityException)
			{
			}
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)src).width, ((Texture)src).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)1);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)src, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(w, h, (TextureFormat)4, false);
				val.ReadPixels(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, (float)w, (float)h), 0, 0);
				val.Apply(false);
				Color32[] pixels2 = val.GetPixels32();
				Object.Destroy((Object)val);
				return pixels2;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		public static Color Digits(TextMeshProUGUI text, Pattern pat, Color plain)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			Material value;
			bool flag = digitOriginals.TryGetValue(text, out value);
			if (gradientDigits.Remove(text))
			{
				((TMP_Text)text).enableVertexGradient = false;
			}
			if (pat == null)
			{
				if (flag)
				{
					((TMP_Text)text).fontSharedMaterial = value;
					digitOriginals.Remove(text);
				}
				return plain;
			}
			if (!flag)
			{
				value = ((TMP_Text)text).fontSharedMaterial;
				digitOriginals[text] = value;
			}
			Material val = pat.DigitMaterial(value);
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)((TMP_Text)text).fontSharedMaterial != (Object)(object)val)
				{
					((TMP_Text)text).fontSharedMaterial = val;
				}
				return Color.white;
			}
			if (flag)
			{
				((TMP_Text)text).fontSharedMaterial = value;
			}
			((TMP_Text)text).enableVertexGradient = true;
			((TMP_Text)text).colorGradient = new VertexGradient(pat.Base, pat.Base, pat.Accent, pat.Accent);
			gradientDigits.Add(text);
			return Color.white;
		}

		private Texture2D DigitTexture()
		{
			if ((Object)(object)digitTex == (Object)null)
			{
				digitTex = Draw(Token + " digits", 64, 64, (TextureWrapMode)0, 0, (float u, float v) => new Vector2(v * digit, u * digit));
			}
			return digitTex;
		}

		internal Material DigitMaterial(Material original)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)original == (Object)null)
			{
				return null;
			}
			if (digitMats.TryGetValue(original, out var value))
			{
				return value;
			}
			value = new Material(original);
			if (!value.HasProperty("_FaceTex"))
			{
				Shader val = Shader.Find("TextMeshPro/Distance Field");
				if ((Object)(object)val != (Object)null)
				{
					value.shader = val;
				}
			}
			if (value.HasProperty("_FaceTex"))
			{
				((Object)value).name = ((Object)original).name + " (PaintCan " + Token + ")";
				value.SetTexture("_FaceTex", (Texture)(object)DigitTexture());
				value.SetTextureScale("_FaceTex", Vector2.one);
				value.SetTextureOffset("_FaceTex", Vector2.zero);
				if (value.HasProperty("_FaceColor"))
				{
					value.SetColor("_FaceColor", Color.white);
				}
				((Object)value).hideFlags = (HideFlags)32;
			}
			else
			{
				Plugin.Log.LogWarning((object)("The win counter's font shader has no face texture; " + Token + " digits use a gradient."));
				Object.Destroy((Object)(object)value);
				value = null;
			}
			digitMats[original] = value;
			return value;
		}

		public static void WearHead(GameObject player, Pattern pat)
		{
			//IL_00ce: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			PatternHead patternHead = player.GetComponent<PatternHead>();
			if (pat == null)
			{
				if ((Object)(object)patternHead != (Object)null)
				{
					patternHead.Restore();
					Object.Destroy((Object)(object)patternHead);
				}
				return;
			}
			if ((Object)(object)patternHead == (Object)null)
			{
				SpriteRenderer val = null;
				SpriteRenderer[] componentsInChildren = player.GetComponentsInChildren<SpriteRenderer>();
				foreach (SpriteRenderer val2 in componentsInChildren)
				{
					if (((Object)val2).name == "headRenderer" && !Palette.InWeapons(((Component)val2).transform))
					{
						val = val2;
						break;
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				patternHead = player.AddComponent<PatternHead>();
				patternHead.head = val;
				patternHead.original = val.sprite;
			}
			Sprite val3 = pat.Head(patternHead.original);
			if ((Object)(object)val3 == (Object)null)
			{
				patternHead.Restore();
				Object.Destroy((Object)(object)patternHead);
				return;
			}
			patternHead.head.sprite = val3;
			patternHead.head.color = Color.white;
			patternHead.baseColour = pat.Base;
			patternHead.LateUpdate();
		}
	}
	internal class PatternHead : MonoBehaviour
	{
		public SpriteRenderer head;

		public Sprite original;

		public Color baseColour;

		private HealthHandler health;

		public void LateUpdate()
		{
			//IL_0054: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)head == (Object)null))
			{
				if ((Object)(object)health == (Object)null)
				{
					health = ((Component)head).GetComponentInParent<HealthHandler>();
				}
				head.color = (((Object)(object)health != (Object)null && health.sinceDamage < 0.1f) ? Color.red : Color.white);
				SetColorWhenDamaged[] components = ((Component)head).GetComponents<SetColorWhenDamaged>();
				foreach (SetColorWhenDamaged obj in components)
				{
					((Behaviour)obj).enabled = false;
					obj.startColor = baseColour;
				}
			}
		}

		public void Restore()
		{
			if (!((Object)(object)head == (Object)null))
			{
				if ((Object)(object)original != (Object)null)
				{
					head.sprite = original;
				}
				SetColorWhenDamaged[] components = ((Component)head).GetComponents<SetColorWhenDamaged>();
				for (int i = 0; i < components.Length; i++)
				{
					((Behaviour)components[i]).enabled = true;
				}
			}
		}
	}
	[BepInPlugin("stickfight.paintcan", "PaintCan", "1.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "stickfight.paintcan";

		public const string Name = "PaintCan";

		public const string Version = "1.3.0";

		internal const float CanZ = 10f;

		internal const float CanY = -8f;

		internal const float CanSize = 0.75f;

		internal const float CanMass = 55f;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> RememberColours;

		private void Awake()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			RememberColours = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RememberColours", false, "Keep each player slot's colour after the game is closed. Off: colours reset when the game closes.");
			RememberColours.SettingChanged += delegate
			{
				Palette.OnRememberChanged();
			};
			Palette.Load();
			new Harmony("stickfight.paintcan").PatchAll(typeof(Plugin).Assembly);
			GameObject val = new GameObject("PaintCanManager");
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<CanSpawner>();
			Log.LogInfo((object)"PaintCan 1.3.0 loaded.");
		}
	}
	internal class Rainbow : MonoBehaviour
	{
		private readonly List<SpriteRenderer> sprites = new List<SpriteRenderer>();

		private readonly List<SetColorWhenDamaged> flashers = new List<SetColorWhenDamaged>();

		private readonly List<BlockAnimation> blocks = new List<BlockAnimation>();

		private readonly List<Image> images = new List<Image>();

		p