Decompiled source of BigWalkSprays v1.0.1

plugins/BigWalkSprays.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Mirror;
using Rewired;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BigWalkSprays")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("TF2-style sprays for Big Walk")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("BigWalkSprays")]
[assembly: AssemblyTitle("BigWalkSprays")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BigWalkSprays
{
	internal static class ImageDecoders
	{
		public static bool IsPng(byte[] d)
		{
			return d != null && d.Length > 8 && d[0] == 137 && d[1] == 80 && d[2] == 78 && d[3] == 71;
		}

		public static bool IsJpeg(byte[] d)
		{
			return d != null && d.Length > 3 && d[0] == byte.MaxValue && d[1] == 216 && d[2] == byte.MaxValue;
		}

		private static bool IsGif(byte[] d)
		{
			return d != null && d.Length > 13 && d[0] == 71 && d[1] == 73 && d[2] == 70 && d[3] == 56;
		}

		private static bool IsBmp(byte[] d)
		{
			return d != null && d.Length > 54 && d[0] == 66 && d[1] == 77;
		}

		public static bool TryDecode(byte[] d, int maxDim, out int w, out int h, out Color32[] px, out string err)
		{
			w = (h = 0);
			px = null;
			err = null;
			try
			{
				if (IsPng(d))
				{
					return PngCodec.TryDecode(d, maxDim, out w, out h, out px, out err);
				}
				if (IsGif(d))
				{
					return DecodeGif(d, maxDim, out w, out h, out px, out err);
				}
				if (IsBmp(d))
				{
					return DecodeBmp(d, maxDim, out w, out h, out px, out err);
				}
				err = "unsupported format (supported: png, jpg, gif, bmp)";
				return false;
			}
			catch (Exception ex)
			{
				err = ex.Message;
				px = null;
				return false;
			}
		}

		private static bool DecodeGif(byte[] d, int maxDim, out int width, out int height, out Color32[] pixels, out string err)
		{
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			width = (height = 0);
			pixels = null;
			err = null;
			int num = d[6] | (d[7] << 8);
			int num2 = d[8] | (d[9] << 8);
			if (num < 1 || num2 < 1 || num > maxDim || num2 > maxDim)
			{
				err = "bad GIF dimensions";
				return false;
			}
			int num3 = d[10];
			int i = 13;
			byte[] array = null;
			if ((num3 & 0x80) != 0)
			{
				int num4 = 3 << (num3 & 7) + 1;
				if (i + num4 > d.Length)
				{
					err = "truncated GIF";
					return false;
				}
				array = new byte[num4];
				Buffer.BlockCopy(d, i, array, 0, num4);
				i += num4;
			}
			int num5 = -1;
			Color32[] array2 = (Color32[])(object)new Color32[num * num2];
			while (i < d.Length)
			{
				switch (d[i++])
				{
				case 33:
				{
					if (i >= d.Length)
					{
						break;
					}
					int num18 = d[i++];
					if (num18 == 249 && i + 5 < d.Length)
					{
						num5 = (((d[i + 1] & 1) != 0) ? d[i + 4] : (-1));
					}
					int num19;
					for (; i < d.Length; i += num19)
					{
						num19 = d[i++];
						if (num19 == 0)
						{
							break;
						}
					}
					continue;
				}
				case 44:
				{
					if (i + 9 > d.Length)
					{
						break;
					}
					int num6 = d[i] | (d[i + 1] << 8);
					int num7 = d[i + 2] | (d[i + 3] << 8);
					int num8 = d[i + 4] | (d[i + 5] << 8);
					int num9 = d[i + 6] | (d[i + 7] << 8);
					int num10 = d[i + 8];
					i += 9;
					if (num8 < 1 || num9 < 1 || (long)num8 * (long)num9 > 16777216)
					{
						err = "bad GIF frame size";
						return false;
					}
					byte[] array3 = array;
					if ((num10 & 0x80) != 0)
					{
						int num11 = 3 << (num10 & 7) + 1;
						if (i + num11 > d.Length)
						{
							err = "truncated GIF";
							return false;
						}
						array3 = new byte[num11];
						Buffer.BlockCopy(d, i, array3, 0, num11);
						i += num11;
					}
					if (array3 == null)
					{
						err = "GIF has no color table";
						return false;
					}
					bool flag = (num10 & 0x40) != 0;
					if (i >= d.Length)
					{
						err = "truncated GIF";
						return false;
					}
					int num12 = d[i++];
					if (num12 < 2 || num12 > 8)
					{
						err = "bad GIF LZW size";
						return false;
					}
					MemoryStream memoryStream = new MemoryStream();
					int num13;
					for (; i < d.Length; i += num13)
					{
						num13 = d[i++];
						if (num13 == 0)
						{
							break;
						}
						if (i + num13 > d.Length)
						{
							num13 = d.Length - i;
						}
						memoryStream.Write(d, i, num13);
					}
					byte[] array4 = LzwDecode(memoryStream.ToArray(), num12, num8 * num9);
					for (int j = 0; j < num9; j++)
					{
						int num14 = (flag ? InterlacedRow(j, num9) : j);
						int num15 = num7 + num14;
						if (num15 >= num2)
						{
							continue;
						}
						for (int k = 0; k < num8; k++)
						{
							int num16 = num6 + k;
							if (num16 < num)
							{
								int num17 = array4[j * num8 + k];
								if (num17 != num5 && num17 * 3 + 2 < array3.Length)
								{
									array2[(num2 - 1 - num15) * num + num16] = new Color32(array3[num17 * 3], array3[num17 * 3 + 1], array3[num17 * 3 + 2], byte.MaxValue);
								}
							}
						}
					}
					width = num;
					height = num2;
					pixels = array2;
					return true;
				}
				}
				break;
			}
			err = "GIF contains no image";
			return false;
		}

		private static int InterlacedRow(int r, int h)
		{
			int num = (h + 7) / 8;
			int num2 = (h + 3) / 8;
			int num3 = (h + 1) / 4;
			if (r < num)
			{
				return r * 8;
			}
			r -= num;
			if (r < num2)
			{
				return 4 + r * 8;
			}
			r -= num2;
			if (r < num3)
			{
				return 2 + r * 4;
			}
			r -= num3;
			return 1 + r * 2;
		}

		private static byte[] LzwDecode(byte[] data, int minCode, int pixelCount)
		{
			int num = 1 << minCode;
			int num2 = num + 1;
			int num3 = num2 + 1;
			int num4 = minCode + 1;
			int num5 = (1 << num4) - 1;
			short[] array = new short[4096];
			byte[] array2 = new byte[4096];
			byte[] array3 = new byte[4097];
			for (int i = 0; i < num; i++)
			{
				array2[i] = (byte)i;
			}
			byte[] array4 = new byte[pixelCount];
			int num6 = 0;
			int num7 = 0;
			int j = 0;
			int num8 = 0;
			int num9 = -1;
			byte b = 0;
			while (num6 < pixelCount)
			{
				for (; j < num4; j += 8)
				{
					if (num8 >= data.Length)
					{
						return array4;
					}
					num7 |= data[num8++] << j;
				}
				int num10 = num7 & num5;
				num7 >>= num4;
				j -= num4;
				if (num10 == num)
				{
					num4 = minCode + 1;
					num5 = (1 << num4) - 1;
					num3 = num2 + 1;
					num9 = -1;
					continue;
				}
				if (num10 == num2)
				{
					break;
				}
				if (num9 == -1)
				{
					if (num10 >= num)
					{
						break;
					}
					array4[num6++] = array2[num10];
					num9 = num10;
					b = array2[num10];
					continue;
				}
				int num11 = num10;
				int num12 = 0;
				if (num10 >= num3)
				{
					if (num10 > num3)
					{
						break;
					}
					array3[num12++] = b;
					num10 = num9;
				}
				while (num10 >= num)
				{
					if (num12 >= 4096)
					{
						return array4;
					}
					array3[num12++] = array2[num10];
					num10 = array[num10];
				}
				b = array2[num10];
				array3[num12++] = b;
				while (num12 > 0 && num6 < pixelCount)
				{
					array4[num6++] = array3[--num12];
				}
				if (num3 < 4096)
				{
					array[num3] = (short)num9;
					array2[num3] = b;
					num3++;
					if ((num3 & num5) == 0 && num4 < 12)
					{
						num4++;
						num5 = (1 << num4) - 1;
					}
				}
				num9 = num11;
			}
			return array4;
		}

		private static int I32(byte[] d, int p)
		{
			return d[p] | (d[p + 1] << 8) | (d[p + 2] << 16) | (d[p + 3] << 24);
		}

		private static bool DecodeBmp(byte[] d, int maxDim, out int width, out int height, out Color32[] pixels, out string err)
		{
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			width = (height = 0);
			pixels = null;
			err = null;
			int num = I32(d, 10);
			int num2 = I32(d, 14);
			if (num2 < 40)
			{
				err = "unsupported BMP header";
				return false;
			}
			int num3 = I32(d, 18);
			int num4 = I32(d, 22);
			int num5 = d[28] | (d[29] << 8);
			int num6 = I32(d, 30);
			int num7 = I32(d, 46);
			bool flag = num4 < 0;
			int num8 = Math.Abs(num4);
			if (num3 < 1 || num8 < 1 || num3 > maxDim || num8 > maxDim)
			{
				err = "bad BMP dimensions";
				return false;
			}
			if (num6 != 0 && (num6 != 3 || num5 != 32))
			{
				err = "compressed BMP unsupported";
				return false;
			}
			if (num5 != 8 && num5 != 24 && num5 != 32)
			{
				err = "BMP bit depth " + num5 + " unsupported (use 8/24/32)";
				return false;
			}
			byte[] array = null;
			if (num5 == 8)
			{
				int num9 = ((num7 > 0) ? num7 : 256);
				int num10 = 14 + num2;
				if (num10 + num9 * 4 > d.Length)
				{
					err = "truncated BMP palette";
					return false;
				}
				array = new byte[num9 * 4];
				Buffer.BlockCopy(d, num10, array, 0, num9 * 4);
			}
			long num11 = ((long)num3 * (long)num5 + 31) / 32 * 4;
			if (num < 0 || num + num11 * num8 > d.Length)
			{
				err = "truncated BMP data";
				return false;
			}
			Color32[] array2 = (Color32[])(object)new Color32[num3 * num8];
			bool flag2 = false;
			for (int i = 0; i < num8; i++)
			{
				int num12 = (int)(num + num11 * i);
				int num13 = (flag ? (num8 - 1 - i) : i) * num3;
				for (int j = 0; j < num3; j++)
				{
					byte b = byte.MaxValue;
					byte b4;
					byte b3;
					byte b2;
					switch (num5)
					{
					case 8:
					{
						int num15 = d[num12 + j];
						if (num15 * 4 + 3 >= array.Length)
						{
							b4 = (b3 = (b2 = 0));
							break;
						}
						b2 = array[num15 * 4];
						b3 = array[num15 * 4 + 1];
						b4 = array[num15 * 4 + 2];
						break;
					}
					case 24:
					{
						int num16 = num12 + j * 3;
						b2 = d[num16];
						b3 = d[num16 + 1];
						b4 = d[num16 + 2];
						break;
					}
					default:
					{
						int num14 = num12 + j * 4;
						b2 = d[num14];
						b3 = d[num14 + 1];
						b4 = d[num14 + 2];
						b = d[num14 + 3];
						if (b != 0)
						{
							flag2 = true;
						}
						break;
					}
					}
					array2[num13 + j] = new Color32(b4, b3, b2, b);
				}
			}
			if (num5 == 32 && !flag2)
			{
				for (int k = 0; k < array2.Length; k++)
				{
					Color32 val = array2[k];
					array2[k] = new Color32(val.r, val.g, val.b, byte.MaxValue);
				}
			}
			width = num3;
			height = num8;
			pixels = array2;
			return true;
		}
	}
	internal static class RewiredLock
	{
		private static bool locked;

		private static bool broken;

		public static void Set(bool lockInput)
		{
			if (broken || locked == lockInput)
			{
				return;
			}
			try
			{
				int playerCount = ReInput.players.playerCount;
				for (int i = 0; i < playerCount; i++)
				{
					Player player = ReInput.players.GetPlayer(i);
					if (player != null)
					{
						player.controllers.maps.SetAllMapsEnabled(!lockInput);
					}
				}
				locked = lockInput;
			}
			catch (Exception ex)
			{
				broken = true;
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Rewired input lock failed (menu will not freeze movement): " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class InputBlock
	{
		internal static bool Bypass;

		private static bool Blocking => SprayManager.MenuOpen && !Bypass;

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPrefix]
		private static bool LockState(CursorLockMode value)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			return !Blocking || (int)value == 0;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPrefix]
		private static bool Visible(bool value)
		{
			return !Blocking || value;
		}
	}
	public class MirrorNet : ISprayNet
	{
		private const ushort MsgId = 45466;

		private const int MaxPacket = 65536;

		public event Action<byte[]> OnReceive;

		public void Tick()
		{
			if (NetworkClient.active && !NetworkClient.handlers.ContainsKey((ushort)45466))
			{
				NetworkClient.handlers[(ushort)45466] = DelegateSupport.ConvertDelegate<NetworkMessageDelegate>((Delegate)new Action<NetworkConnection, NetworkReader, int>(OnClientMessage));
			}
			if (NetworkServer.active && !NetworkServer.handlers.ContainsKey((ushort)45466))
			{
				NetworkServer.handlers[(ushort)45466] = DelegateSupport.ConvertDelegate<NetworkMessageDelegate>((Delegate)new Action<NetworkConnection, NetworkReader, int>(OnServerMessage));
			}
		}

		public void Broadcast(byte[] payload)
		{
			if (payload != null && payload.Length <= 65536)
			{
				if (NetworkServer.active)
				{
					SendToAll(payload, 0);
				}
				else if (NetworkClient.active && NetworkClient.connection != null)
				{
					NetworkWriter val = Frame(payload);
					NetworkClient.connection.Send(val.ToArraySegment(), Channels.Reliable);
				}
			}
		}

		private static byte[] ReadPayload(NetworkReader r)
		{
			int num = NetworkReaderExtensions.ReadInt(r);
			if (num <= 0 || num > 65536 || num > r.Remaining)
			{
				return null;
			}
			Il2CppStructArray<byte> val = new Il2CppStructArray<byte>((long)num);
			r.ReadBytes(val, num);
			return Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)val);
		}

		private void OnClientMessage(NetworkConnection conn, NetworkReader reader, int channelId)
		{
			byte[] array = ReadPayload(reader);
			if (array != null)
			{
				this.OnReceive?.Invoke(array);
			}
		}

		private void OnServerMessage(NetworkConnection conn, NetworkReader reader, int channelId)
		{
			byte[] array = ReadPayload(reader);
			if (array != null)
			{
				SendToAll(array, conn.connectionId);
			}
		}

		private static NetworkWriter Frame(byte[] payload)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			NetworkWriter val = new NetworkWriter();
			NetworkWriterExtensions.WriteUShort(val, (ushort)45466);
			NetworkWriterExtensions.WriteInt(val, payload.Length);
			val.WriteBytes(Il2CppStructArray<byte>.op_Implicit(payload), 0, payload.Length);
			return val;
		}

		private static void SendToAll(byte[] payload, int exceptConnId)
		{
			NetworkWriter val = Frame(payload);
			ArraySegment<byte> val2 = val.ToArraySegment();
			Enumerator<int, NetworkConnectionToClient> enumerator = NetworkServer.connections.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<int, NetworkConnectionToClient> current = enumerator.Current;
				NetworkConnectionToClient value = current.Value;
				if (value != null && ((NetworkConnection)value).connectionId != exceptConnId)
				{
					((NetworkConnection)value).Send(val2, Channels.Reliable);
				}
			}
		}
	}
	internal static class PngCodec
	{
		private static readonly byte[] Sig = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 };

		private static uint[] crcTable;

		public static bool TryDecode(byte[] data, int maxDim, out int width, out int height, out Color32[] pixels, out string error)
		{
			width = (height = 0);
			pixels = null;
			error = null;
			try
			{
				return DecodeInner(data, maxDim, out width, out height, out pixels, out error);
			}
			catch (Exception ex)
			{
				error = ex.Message;
				pixels = null;
				return false;
			}
		}

		private static bool Fail(out string error, string msg)
		{
			error = msg;
			return false;
		}

		private static bool DecodeInner(byte[] data, int maxDim, out int width, out int height, out Color32[] pixels, out string error)
		{
			//IL_07df: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
			width = (height = 0);
			pixels = null;
			error = null;
			if (data == null || data.Length < 33)
			{
				return Fail(out error, "too short");
			}
			for (int i = 0; i < 8; i++)
			{
				if (data[i] != Sig[i])
				{
					return Fail(out error, "not a PNG");
				}
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			bool flag = false;
			bool flag2 = false;
			byte[] array = null;
			byte[] array2 = null;
			MemoryStream memoryStream = new MemoryStream();
			int num6 = 8;
			while (!flag2 && num6 + 12 <= data.Length)
			{
				int num7 = ReadInt(data, num6);
				string text = Encoding.ASCII.GetString(data, num6 + 4, 4);
				int num8 = num6 + 8;
				if (num7 < 0 || (long)num8 + (long)num7 + 4 > data.Length)
				{
					return Fail(out error, "truncated chunk");
				}
				switch (text)
				{
				case "IHDR":
					if (num7 < 13)
					{
						return Fail(out error, "bad IHDR");
					}
					num = ReadInt(data, num8);
					num2 = ReadInt(data, num8 + 4);
					num3 = data[num8 + 8];
					num4 = data[num8 + 9];
					num5 = data[num8 + 12];
					flag = true;
					break;
				case "PLTE":
					array = new byte[num7];
					Buffer.BlockCopy(data, num8, array, 0, num7);
					break;
				case "tRNS":
					array2 = new byte[num7];
					Buffer.BlockCopy(data, num8, array2, 0, num7);
					break;
				case "IDAT":
					memoryStream.Write(data, num8, num7);
					break;
				case "IEND":
					flag2 = true;
					break;
				}
				num6 = num8 + num7 + 4;
			}
			if (!flag)
			{
				return Fail(out error, "no IHDR");
			}
			if (num < 1 || num2 < 1 || num > maxDim || num2 > maxDim)
			{
				return Fail(out error, "bad or too large dimensions " + num + "x" + num2);
			}
			if (num5 != 0)
			{
				return Fail(out error, "interlaced PNGs unsupported (re-save without interlacing)");
			}
			int num9;
			switch (num4)
			{
			case 0:
				num9 = 1;
				if (num3 != 1 && num3 != 2 && num3 != 4 && num3 != 8 && num3 != 16)
				{
					return Fail(out error, "bad depth");
				}
				break;
			case 2:
				num9 = 3;
				if (num3 != 8 && num3 != 16)
				{
					return Fail(out error, "bad depth");
				}
				break;
			case 3:
				num9 = 1;
				if (num3 != 1 && num3 != 2 && num3 != 4 && num3 != 8)
				{
					return Fail(out error, "bad depth");
				}
				if (array == null)
				{
					return Fail(out error, "missing palette");
				}
				break;
			case 4:
				num9 = 2;
				if (num3 != 8 && num3 != 16)
				{
					return Fail(out error, "bad depth");
				}
				break;
			case 6:
				num9 = 4;
				if (num3 != 8 && num3 != 16)
				{
					return Fail(out error, "bad depth");
				}
				break;
			default:
				return Fail(out error, "bad color type");
			}
			int num10 = num9 * num3;
			int num11 = Math.Max(1, num10 / 8);
			int num12 = (int)(((long)num * (long)num10 + 7) / 8);
			long num13 = (long)(num12 + 1) * (long)num2;
			if (num13 > 67108864)
			{
				return Fail(out error, "image too large");
			}
			byte[] array3 = new byte[num13];
			memoryStream.Position = 0L;
			using (ZLibStream zLibStream = new ZLibStream(memoryStream, CompressionMode.Decompress))
			{
				long num14;
				int num15;
				for (num14 = 0L; num14 < num13; num14 += num15)
				{
					num15 = zLibStream.Read(array3, (int)num14, (int)(num13 - num14));
					if (num15 <= 0)
					{
						break;
					}
				}
				if (num14 < num13)
				{
					return Fail(out error, "truncated image data");
				}
			}
			int num16 = num12 + 1;
			for (int j = 0; j < num2; j++)
			{
				int num17 = j * num16;
				int num18 = array3[num17];
				int num19 = num17 + 1;
				int num20 = ((j > 0) ? (num19 - num16) : (-1));
				for (int k = 0; k < num12; k++)
				{
					int num21 = ((k >= num11) ? array3[num19 + k - num11] : 0);
					int num22 = ((num20 >= 0) ? array3[num20 + k] : 0);
					int c = ((k >= num11 && num20 >= 0) ? array3[num20 + k - num11] : 0);
					int num23 = array3[num19 + k];
					switch (num18)
					{
					case 1:
						num23 += num21;
						break;
					case 2:
						num23 += num22;
						break;
					case 3:
						num23 += num21 + num22 >> 1;
						break;
					case 4:
						num23 += Paeth(num21, num22, c);
						break;
					default:
						return Fail(out error, "bad filter type");
					case 0:
						break;
					}
					array3[num19 + k] = (byte)num23;
				}
			}
			Color32[] array4 = (Color32[])(object)new Color32[num * num2];
			int step = ((num3 >= 8) ? (num3 / 8) : 0);
			int num24 = (1 << Math.Min(num3, 8)) - 1;
			for (int l = 0; l < num2; l++)
			{
				int rowStart = l * num16 + 1;
				int num25 = (num2 - 1 - l) * num;
				for (int m = 0; m < num; m++)
				{
					byte b = byte.MaxValue;
					byte b2;
					byte b3;
					byte b4;
					switch (num4)
					{
					case 0:
					{
						int num27 = Sample(array3, rowStart, m, 0, 1, num3, step);
						if (num3 < 8)
						{
							num27 = num27 * 255 / num24;
						}
						b2 = (b3 = (b4 = (byte)num27));
						break;
					}
					case 2:
						b2 = (byte)Sample(array3, rowStart, m, 0, 3, num3, step);
						b3 = (byte)Sample(array3, rowStart, m, 1, 3, num3, step);
						b4 = (byte)Sample(array3, rowStart, m, 2, 3, num3, step);
						break;
					case 3:
					{
						int num26 = Sample(array3, rowStart, m, 0, 1, num3, step);
						if (num26 * 3 + 2 >= array.Length)
						{
							b2 = (b3 = (b4 = 0));
						}
						else
						{
							b2 = array[num26 * 3];
							b3 = array[num26 * 3 + 1];
							b4 = array[num26 * 3 + 2];
						}
						if (array2 != null && num26 < array2.Length)
						{
							b = array2[num26];
						}
						break;
					}
					case 4:
						b2 = (b3 = (b4 = (byte)Sample(array3, rowStart, m, 0, 2, num3, step)));
						b = (byte)Sample(array3, rowStart, m, 1, 2, num3, step);
						break;
					default:
						b2 = (byte)Sample(array3, rowStart, m, 0, 4, num3, step);
						b3 = (byte)Sample(array3, rowStart, m, 1, 4, num3, step);
						b4 = (byte)Sample(array3, rowStart, m, 2, 4, num3, step);
						b = (byte)Sample(array3, rowStart, m, 3, 4, num3, step);
						break;
					}
					array4[num25 + m] = new Color32(b2, b3, b4, b);
				}
			}
			width = num;
			height = num2;
			pixels = array4;
			return true;
		}

		private static int Sample(byte[] raw, int rowStart, int x, int k, int channels, int depth, int step)
		{
			if (depth < 8)
			{
				int num = x * depth;
				int num2 = 8 - depth - (num & 7);
				return (raw[rowStart + (num >> 3)] >> num2) & ((1 << depth) - 1);
			}
			return raw[rowStart + (x * channels + k) * step];
		}

		private static int Paeth(int a, int b, int c)
		{
			int num = a + b - c;
			int num2 = Math.Abs(num - a);
			int num3 = Math.Abs(num - b);
			int num4 = Math.Abs(num - c);
			if (num2 <= num3 && num2 <= num4)
			{
				return a;
			}
			return (num3 <= num4) ? b : c;
		}

		private static int ReadInt(byte[] d, int p)
		{
			return (d[p] << 24) | (d[p + 1] << 16) | (d[p + 2] << 8) | d[p + 3];
		}

		public static Color32[] Resize(Color32[] src, int sw, int sh, int dw, int dh)
		{
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			if (sw == dw && sh == dh)
			{
				return src;
			}
			Color32[] array = (Color32[])(object)new Color32[dw * dh];
			for (int i = 0; i < dh; i++)
			{
				int num = (int)((long)i * (long)sh / dh);
				int num2 = Math.Max(num + 1, (int)((long)(i + 1) * (long)sh / dh));
				for (int j = 0; j < dw; j++)
				{
					int num3 = (int)((long)j * (long)sw / dw);
					int num4 = Math.Max(num3 + 1, (int)((long)(j + 1) * (long)sw / dw));
					double num5 = 0.0;
					double num6 = 0.0;
					double num7 = 0.0;
					double num8 = 0.0;
					int num9 = 0;
					for (int k = num; k < num2 && k < sh; k++)
					{
						for (int l = num3; l < num4 && l < sw; l++)
						{
							Color32 val = src[k * sw + l];
							double num10 = (int)val.a;
							num5 += (double)(int)val.r * num10;
							num6 += (double)(int)val.g * num10;
							num7 += (double)(int)val.b * num10;
							num8 += num10;
							num9++;
						}
					}
					if (num8 > 0.0 && num9 > 0)
					{
						array[i * dw + j] = new Color32((byte)(num5 / num8 + 0.5), (byte)(num6 / num8 + 0.5), (byte)(num7 / num8 + 0.5), (byte)(num8 / (double)num9 + 0.5));
					}
					else
					{
						array[i * dw + j] = new Color32((byte)0, (byte)0, (byte)0, (byte)0);
					}
				}
			}
			return array;
		}

		public static byte[] Encode(int w, int h, Color32[] px)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			int num = w * 4;
			byte[] array = new byte[(num + 1) * h];
			for (int i = 0; i < h; i++)
			{
				int num2 = (h - 1 - i) * w;
				int num3 = i * (num + 1);
				array[num3] = 1;
				for (int j = 0; j < w; j++)
				{
					Color32 val = px[num2 + j];
					int num4 = num3 + 1 + j * 4;
					array[num4] = val.r;
					array[num4 + 1] = val.g;
					array[num4 + 2] = val.b;
					array[num4 + 3] = val.a;
				}
				for (int num5 = num - 1; num5 >= 4; num5--)
				{
					array[num3 + 1 + num5] = (byte)(array[num3 + 1 + num5] - array[num3 + 1 + num5 - 4]);
				}
			}
			byte[] data;
			using (MemoryStream memoryStream = new MemoryStream())
			{
				using (ZLibStream zLibStream = new ZLibStream(memoryStream, CompressionLevel.Optimal, leaveOpen: true))
				{
					zLibStream.Write(array, 0, array.Length);
				}
				data = memoryStream.ToArray();
			}
			using MemoryStream memoryStream2 = new MemoryStream();
			memoryStream2.Write(Sig, 0, 8);
			byte[] array2 = new byte[13];
			WriteInt(array2, 0, w);
			WriteInt(array2, 4, h);
			array2[8] = 8;
			array2[9] = 6;
			array2[10] = 0;
			array2[11] = 0;
			array2[12] = 0;
			WriteChunk(memoryStream2, "IHDR", array2);
			WriteChunk(memoryStream2, "IDAT", data);
			WriteChunk(memoryStream2, "IEND", new byte[0]);
			return memoryStream2.ToArray();
		}

		private static void WriteInt(byte[] d, int p, int v)
		{
			d[p] = (byte)(v >> 24);
			d[p + 1] = (byte)(v >> 16);
			d[p + 2] = (byte)(v >> 8);
			d[p + 3] = (byte)v;
		}

		private static void WriteChunk(Stream s, string type, byte[] data)
		{
			byte[] array = new byte[4];
			WriteInt(array, 0, data.Length);
			s.Write(array, 0, 4);
			byte[] bytes = Encoding.ASCII.GetBytes(type);
			s.Write(bytes, 0, 4);
			s.Write(data, 0, data.Length);
			uint v = Crc(Crc(uint.MaxValue, bytes), data) ^ 0xFFFFFFFFu;
			byte[] array2 = new byte[4];
			WriteInt(array2, 0, (int)v);
			s.Write(array2, 0, 4);
		}

		private static uint Crc(uint c, byte[] buf)
		{
			if (crcTable == null)
			{
				uint[] array = new uint[256];
				for (uint num = 0u; num < 256; num++)
				{
					uint num2 = num;
					for (int i = 0; i < 8; i++)
					{
						num2 = (((num2 & 1) != 0) ? (0xEDB88320u ^ (num2 >> 1)) : (num2 >> 1));
					}
					array[num] = num2;
				}
				crcTable = array;
			}
			foreach (byte b in buf)
			{
				c = crcTable[(c ^ b) & 0xFF] ^ (c >> 8);
			}
			return c;
		}
	}
	[BepInPlugin("com.gogogadgetjustice.bigwalk.sprays", "Big Walk Sprays", "0.2.0")]
	public class Plugin : BasePlugin
	{
		internal static Plugin Instance;

		internal static ConfigEntry<float> Lifetime;

		internal static ConfigEntry<float> SprayWorldSize;

		internal static ConfigEntry<float> MaxRange;

		internal static ConfigEntry<float> Cooldown;

		internal static ConfigEntry<float> Volume;

		internal static ConfigEntry<KeyCode> MenuKey;

		internal static ConfigEntry<KeyCode> SprayKey;

		internal static ConfigEntry<KeyCode> DeleteLastKey;

		internal static ConfigEntry<KeyCode> DeleteAllKey;

		internal static ConfigEntry<int> MaxPerPlayer;

		internal static ConfigEntry<string> SelectedSound;

		internal static string SprayDir;

		internal static string SoundDir;

		public override void Load()
		{
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Lifetime = ((BasePlugin)this).Config.Bind<float>("Sprays", "SprayLifetimeSeconds", 0f, "How long sprays stay up on YOUR screen, in seconds. 0 = never expire.");
			MaxPerPlayer = ((BasePlugin)this).Config.Bind<int>("Sprays", "MaxSpraysPerPlayer", 10, "Max sprays shown per player (oldest is removed first). 0 = unlimited.");
			SprayWorldSize = ((BasePlugin)this).Config.Bind<float>("Sprays", "WorldSize", 1f, "Spray width/height in metres.");
			MaxRange = ((BasePlugin)this).Config.Bind<float>("Sprays", "MaxRange", 4f, "Max distance to a wall you can spray.");
			Cooldown = ((BasePlugin)this).Config.Bind<float>("Sprays", "CooldownSeconds", 3f, "Min time between your sprays.");
			Volume = ((BasePlugin)this).Config.Bind<float>("Sounds", "Volume", 1f, "Spray sound volume (0-1).");
			MenuKey = ((BasePlugin)this).Config.Bind<KeyCode>("Input", "MenuKey", (KeyCode)284, "Opens the spray/sound picker.");
			SprayKey = ((BasePlugin)this).Config.Bind<KeyCode>("Input", "SprayKey", (KeyCode)102, "Sprays the selected image.");
			DeleteLastKey = ((BasePlugin)this).Config.Bind<KeyCode>("Input", "DeleteLastKey", (KeyCode)99, "Removes your most recent spray (for everyone); repeat to go further back.");
			DeleteAllKey = ((BasePlugin)this).Config.Bind<KeyCode>("Input", "DeleteAllKey", (KeyCode)118, "Clears every spray from your own screen (local only).");
			string text = null;
			try
			{
				text = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(text))
			{
				text = Path.Combine(Paths.PluginPath, "BigWalkSprays");
			}
			SprayDir = Path.Combine(text, "sprays");
			SoundDir = Path.Combine(text, "spraysounds");
			Directory.CreateDirectory(SprayDir);
			Directory.CreateDirectory(SoundDir);
			SelectedSound = ((BasePlugin)this).Config.Bind<string>("Sounds", "SelectedSound", "", "File name in spraysounds (blank = default spray.ogg).");
			new Harmony("com.you.bigwalk.sprays").PatchAll(typeof(InputBlock));
			ClassInjector.RegisterTypeInIl2Cpp<SprayManager>();
			((BasePlugin)this).AddComponent<SprayManager>();
			((BasePlugin)this).Log.LogInfo((object)("Sprays loaded. Images: " + SprayDir + " | Sounds: " + SoundDir));
		}
	}
	public interface ISprayNet
	{
		event Action<byte[]> OnReceive;

		void Broadcast(byte[] payload);

		void Tick();
	}
	public class NullNet : ISprayNet
	{
		public event Action<byte[]> OnReceive;

		public void Tick()
		{
		}

		public void Broadcast(byte[] payload)
		{
			this.OnReceive?.Invoke(payload);
		}
	}
	internal class ActiveSpray
	{
		public GameObject Go;

		public float Expires;

		public int Owner;

		public int Seq;
	}
	internal class PendingSpray
	{
		public Vector3 Pos;

		public Vector3 Normal;

		public Vector3 Up;

		public float Size;

		public int Owner;

		public int Seq;

		public string Sound = "";
	}
	internal class Prepared
	{
		public string Path;

		public DateTime Stamp;

		public string Hash;

		public byte[] Png;

		public bool Ready;

		public bool Failed;
	}
	public class SprayManager : MonoBehaviour
	{
		private const byte MsgSpray = 1;

		private const byte MsgImage = 2;

		private const byte MsgRequest = 3;

		private const byte MsgDelete = 4;

		private const int MaxImageBytes = 49152;

		private const int MaxDim = 384;

		private ISprayNet net;

		private static bool menuOpen;

		private readonly int myId = Guid.NewGuid().GetHashCode();

		private int mySeq;

		private float lastSpray;

		private Vector2 scroll;

		private int tab;

		private string[] files = new string[0];

		private string[] soundFiles = new string[0];

		private string selectedSound = "";

		private Prepared armed;

		private readonly Dictionary<string, Prepared> prepared = new Dictionary<string, Prepared>();

		private readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>();

		private readonly Dictionary<string, byte[]> pngBytes = new Dictionary<string, byte[]>();

		private readonly Dictionary<string, List<PendingSpray>> pending = new Dictionary<string, List<PendingSpray>>();

		private readonly HashSet<string> sentHashes = new HashSet<string>();

		private readonly List<ActiveSpray> active = new List<ActiveSpray>();

		private Material baseMat;

		private UnityWebRequest jpgReq;

		private Prepared jpgTarget;

		private GameObject soundHost;

		private readonly Dictionary<string, AudioSource> holders = new Dictionary<string, AudioSource>();

		private readonly Dictionary<string, UnityWebRequest> clipReqs = new Dictionary<string, UnityWebRequest>();

		private string hudMsg;

		private float hudUntil;

		private static readonly string[] ImageExts = new string[5] { ".png", ".jpg", ".jpeg", ".gif", ".bmp" };

		internal static bool MenuOpen => menuOpen;

		public SprayManager(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Start()
		{
			net = new MirrorNet();
			net.OnReceive += HandlePacket;
			string fullPath = Path.GetFullPath(Path.Combine(Plugin.SprayDir, ".."));
			string[] array = new string[3] { "spray.ogg", "spray.wav", "spray.mp3" };
			foreach (string path in array)
			{
				string path2 = Path.Combine(fullPath, path);
				if (File.Exists(path2))
				{
					LoadClip("", path2);
					break;
				}
			}
			soundFiles = ScanSounds();
			string[] array2 = soundFiles;
			foreach (string path3 in array2)
			{
				LoadClip(Path.GetFileName(path3), path3);
			}
			selectedSound = Plugin.SelectedSound.Value ?? "";
		}

		private void Update()
		{
			//IL_0026: 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_0057: 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)
			PollClips();
			PollJpg();
			net.Tick();
			InputBlock.Bypass = true;
			bool keyDown = Input.GetKeyDown(Plugin.MenuKey.Value);
			bool flag = !menuOpen && Input.GetKeyDown(Plugin.SprayKey.Value);
			bool flag2 = !menuOpen && Input.GetKeyDown(Plugin.DeleteLastKey.Value);
			bool flag3 = !menuOpen && Input.GetKeyDown(Plugin.DeleteAllKey.Value);
			InputBlock.Bypass = false;
			if (keyDown)
			{
				SetMenu(!menuOpen);
			}
			else if (flag)
			{
				TrySpray();
			}
			else if (flag2)
			{
				DeleteLast();
			}
			else if (flag3)
			{
				DeleteAll();
			}
			if (armed != null && !armed.Ready && !armed.Failed && Time.time > hudUntil - 0.5f)
			{
				hudUntil = Time.time + 1f;
			}
			for (int num = active.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)active[num].Go == (Object)null || Time.time >= active[num].Expires)
				{
					if ((Object)(object)active[num].Go != (Object)null)
					{
						Object.Destroy((Object)(object)active[num].Go);
					}
					active.RemoveAt(num);
				}
			}
		}

		private void OnDestroy()
		{
			RewiredLock.Set(lockInput: false);
		}

		private void SetMenu(bool open)
		{
			menuOpen = open;
			RewiredLock.Set(open);
			InputBlock.Bypass = true;
			if (open)
			{
				files = ScanFiles();
				soundFiles = ScanSounds();
				string[] array = soundFiles;
				foreach (string path in array)
				{
					LoadClip(Path.GetFileName(path), path);
				}
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			else
			{
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
			}
			InputBlock.Bypass = false;
		}

		private string[] ScanFiles()
		{
			try
			{
				List<string> list = new List<string>();
				string[] array = Directory.GetFiles(Plugin.SprayDir, "*", SearchOption.AllDirectories);
				foreach (string text in array)
				{
					if (Array.IndexOf(ImageExts, Path.GetExtension(text).ToLowerInvariant()) >= 0)
					{
						list.Add(text);
					}
				}
				list.Sort();
				return list.ToArray();
			}
			catch
			{
				return new string[0];
			}
		}

		private void OnGUI()
		{
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			if (menuOpen)
			{
				DrawMenu();
			}
			else
			{
				if (Time.time >= hudUntil)
				{
					return;
				}
				string text = hudMsg;
				if (text == null)
				{
					if (armed == null)
					{
						return;
					}
					string fileName = Path.GetFileName(armed.Path);
					text = (armed.Failed ? ("Couldn't load " + fileName + " (see log)") : (armed.Ready ? (fileName + "  -  press " + ((object)Plugin.SprayKey.Value/*cast due to .constrained prefix*/).ToString() + " to spray  (" + ((object)Plugin.MenuKey.Value/*cast due to .constrained prefix*/).ToString() + " to change)") : ("Loading " + fileName + "...")));
				}
				GUI.Box(new Rect((float)Screen.width / 2f - 240f, (float)(Screen.height - 80), 480f, 28f), text);
			}
		}

		private void DrawMenu()
		{
			//IL_002e: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor((float)(Screen.width / 2 - 200), (float)(Screen.height / 2 - 250), 400f, 500f);
			GUI.Box(val, "Spray menu  -  pick one, then press " + ((object)Plugin.SprayKey.Value/*cast due to .constrained prefix*/).ToString());
			float num = (((Rect)(ref val)).width - 20f) / 2f;
			if (GUI.Button(new Rect(((Rect)(ref val)).x + 10f, ((Rect)(ref val)).y + 28f, num, 28f), (tab == 0) ? "[ Sprays ]" : "Sprays"))
			{
				tab = 0;
				scroll = Vector2.zero;
			}
			if (GUI.Button(new Rect(((Rect)(ref val)).x + 10f + num, ((Rect)(ref val)).y + 28f, num, 28f), (tab == 1) ? "[ Sounds ]" : "Sounds"))
			{
				tab = 1;
				scroll = Vector2.zero;
			}
			GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 10f, ((Rect)(ref val)).y + 62f, ((Rect)(ref val)).width - 20f, ((Rect)(ref val)).height - 72f));
			scroll = GUILayout.BeginScrollView(scroll, (Il2CppReferenceArray<GUILayoutOption>)null);
			if (tab == 0)
			{
				DrawSprays();
			}
			else
			{
				DrawSounds();
			}
			GUILayout.EndScrollView();
			if (GUILayout.Button("Close", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				SetMenu(open: false);
			}
			GUILayout.EndArea();
		}

		private void DrawSprays()
		{
			string text = ((armed != null) ? armed.Path : "");
			if (files.Length == 0)
			{
				GUILayout.Label("No images in:\n" + Plugin.SprayDir + "\n(png, jpg, gif, bmp)", (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			string[] array = files;
			foreach (string text2 in array)
			{
				string text3 = ((text2 == text) ? "* " : "") + Path.GetFileName(text2);
				if (GUILayout.Button(text3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }))
				{
					Arm(text2);
					SetMenu(open: false);
				}
			}
		}

		private void DrawSounds()
		{
			string text = selectedSound;
			if (GUILayout.Button(((text == "") ? "* " : "") + "Default (spray sound)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }))
			{
				SelectSound("");
			}
			string[] array = soundFiles;
			foreach (string path in array)
			{
				string fileName = Path.GetFileName(path);
				if (GUILayout.Button(((fileName == text) ? "* " : "") + fileName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }))
				{
					SelectSound(fileName);
				}
			}
			if (soundFiles.Length == 0)
			{
				GUILayout.Label("Put .ogg / .wav / .mp3 files in:\n" + Plugin.SoundDir, (Il2CppReferenceArray<GUILayoutOption>)null);
			}
		}

		private void SelectSound(string name)
		{
			selectedSound = name;
			Plugin.SelectedSound.Value = name;
			AudioSource holder = GetHolder(name);
			if ((Object)(object)holder != (Object)null && (Object)(object)holder.clip != (Object)null)
			{
				holder.Play();
			}
			else
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Sound '" + name + "' isn't loaded (yet)."));
			}
		}

		private void Hud(string msg)
		{
			hudMsg = msg;
			hudUntil = Time.time + 2f;
		}

		private void Arm(string path)
		{
			DateTime lastWriteTimeUtc;
			try
			{
				lastWriteTimeUtc = File.GetLastWriteTimeUtc(path);
			}
			catch
			{
				return;
			}
			if (this.prepared.TryGetValue(path, out var value) && value.Stamp == lastWriteTimeUtc && value.Ready)
			{
				armed = value;
				hudMsg = null;
				hudUntil = Time.time + 6f;
				return;
			}
			Prepared prepared = new Prepared
			{
				Path = path,
				Stamp = lastWriteTimeUtc
			};
			this.prepared[path] = prepared;
			armed = prepared;
			hudMsg = null;
			hudUntil = Time.time + 6f;
			byte[] array;
			try
			{
				array = File.ReadAllBytes(path);
			}
			catch (Exception ex)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Can't read " + path + ": " + ex.Message));
				prepared.Failed = true;
				return;
			}
			int w;
			int h;
			Color32[] px;
			string err;
			if (ImageDecoders.IsJpeg(array))
			{
				StartJpg(prepared);
			}
			else if (!ImageDecoders.TryDecode(array, 4096, out w, out h, out px, out err))
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Can't decode " + Path.GetFileName(path) + ": " + err));
				prepared.Failed = true;
			}
			else
			{
				Finish(prepared, w, h, px, ImageDecoders.IsPng(array) ? array : null);
			}
		}

		private void StartJpg(Prepared p)
		{
			try
			{
				if (jpgReq != null)
				{
					try
					{
						jpgReq.Abort();
						jpgReq.Dispose();
					}
					catch
					{
					}
					jpgReq = null;
				}
				jpgReq = UnityWebRequestTexture.GetTexture(new Uri(Path.GetFullPath(p.Path)).AbsoluteUri);
				jpgReq.SendWebRequest();
				jpgTarget = p;
			}
			catch (Exception ex)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("JPEG load failed to start: " + ex.Message));
				p.Failed = true;
			}
		}

		private void PollJpg()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			if (jpgReq == null || !jpgReq.isDone)
			{
				return;
			}
			UnityWebRequest val = jpgReq;
			Prepared prepared = jpgTarget;
			jpgReq = null;
			jpgTarget = null;
			try
			{
				if ((int)val.result != 1)
				{
					((BasePlugin)Plugin.Instance).Log.LogWarning((object)("JPEG load failed: " + val.error));
					prepared.Failed = true;
					return;
				}
				Texture2D content = DownloadHandlerTexture.GetContent(val);
				int width = ((Texture)content).width;
				int height = ((Texture)content).height;
				if (width < 1 || height < 1 || width > 4096 || height > 4096)
				{
					Object.Destroy((Object)(object)content);
					prepared.Failed = true;
					((BasePlugin)Plugin.Instance).Log.LogWarning((object)("JPEG too large: " + width + "x" + height));
				}
				else
				{
					Color32[] opx = Il2CppArrayBase<Color32>.op_Implicit((Il2CppArrayBase<Color32>)(object)content.GetPixels32());
					Object.Destroy((Object)(object)content);
					Finish(prepared, width, height, opx, null);
				}
			}
			catch (Exception ex)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("JPEG decode failed: " + ex.Message));
				prepared.Failed = true;
			}
			finally
			{
				val.Dispose();
			}
		}

		private void Finish(Prepared p, int ow, int oh, Color32[] opx, byte[] rawPng)
		{
			byte[] array = null;
			int w = ow;
			int h = oh;
			Color32[] px = opx;
			if (rawPng != null && Math.Max(ow, oh) <= 384 && rawPng.Length <= 49152)
			{
				array = rawPng;
			}
			else
			{
				int num = 384;
				int num2 = 0;
				while (num2 < 8 && num >= 16)
				{
					float num3 = Math.Min(1f, (float)num / (float)Math.Max(ow, oh));
					int num4 = Math.Max(1, (int)((float)ow * num3));
					int num5 = Math.Max(1, (int)((float)oh * num3));
					Color32[] array2 = PngCodec.Resize(opx, ow, oh, num4, num5);
					byte[] array3 = PngCodec.Encode(num4, num5, array2);
					if (array3.Length <= 49152)
					{
						array = array3;
						w = num4;
						h = num5;
						px = array2;
						break;
					}
					num2++;
					num = (int)((float)num * 0.75f);
				}
			}
			if (array == null)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Couldn't shrink " + Path.GetFileName(p.Path) + " small enough to send."));
				p.Failed = true;
				return;
			}
			p.Png = array;
			p.Hash = Hash(array);
			if (!textures.ContainsKey(p.Hash))
			{
				textures[p.Hash] = MakeTexture(w, h, px);
			}
			pngBytes[p.Hash] = array;
			p.Ready = true;
		}

		private void TrySpray()
		{
			//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_00cf: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			if (armed == null)
			{
				Hud("Press " + ((object)Plugin.MenuKey.Value/*cast due to .constrained prefix*/).ToString() + " and pick a spray first");
			}
			else if (armed.Failed)
			{
				Hud("That image couldn't be loaded (see log)");
			}
			else if (!armed.Ready)
			{
				Hud("Still loading...");
			}
			else
			{
				if (Time.time - lastSpray < Plugin.Cooldown.Value)
				{
					return;
				}
				Camera main = Camera.main;
				if ((Object)(object)main == (Object)null)
				{
					return;
				}
				RaycastHit val = default(RaycastHit);
				if (!Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val, Plugin.MaxRange.Value, -1, (QueryTriggerInteraction)1))
				{
					Hud("No surface in range");
					return;
				}
				lastSpray = Time.time;
				Vector3 up = ((Mathf.Abs(((RaycastHit)(ref val)).normal.y) > 0.95f) ? ((Component)main).transform.up : Vector3.up);
				PendingSpray s = new PendingSpray
				{
					Pos = ((RaycastHit)(ref val)).point,
					Normal = ((RaycastHit)(ref val)).normal,
					Up = up,
					Size = Plugin.SprayWorldSize.Value,
					Owner = myId,
					Seq = ++mySeq,
					Sound = selectedSound
				};
				if (sentHashes.Add(armed.Hash))
				{
					net.Broadcast(WriteImage(armed.Hash, armed.Png));
				}
				net.Broadcast(WriteSpray(armed.Hash, s));
				if (!(net is NullNet))
				{
					PlaceSpray(armed.Hash, s);
				}
			}
		}

		private void PlaceSpray(string hash, PendingSpray s)
		{
			//IL_007d: 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)
			//IL_00c4: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if (!textures.TryGetValue(hash, out var value))
			{
				if (!pending.TryGetValue(hash, out var value2))
				{
					value2 = (pending[hash] = new List<PendingSpray>());
				}
				if (value2.Count == 0)
				{
					net.Broadcast(WriteRequest(hash));
				}
				value2.Add(s);
				return;
			}
			PlayAt(s.Sound, s.Pos);
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
			Object.Destroy((Object)(object)val.GetComponent<Collider>());
			((Object)val).name = "Spray";
			float num = (float)((Texture)value).width / (float)((Texture)value).height;
			val.transform.position = s.Pos + s.Normal * 0.01f;
			val.transform.rotation = Quaternion.LookRotation(-s.Normal, s.Up);
			val.transform.localScale = new Vector3(s.Size * num, s.Size, 1f);
			MeshRenderer component = val.GetComponent<MeshRenderer>();
			((Renderer)component).material = MakeMaterial(value);
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component).receiveShadows = false;
			float value3 = Plugin.Lifetime.Value;
			active.Add(new ActiveSpray
			{
				Go = val,
				Owner = s.Owner,
				Seq = s.Seq,
				Expires = ((value3 > 0f) ? (Time.time + value3) : float.PositiveInfinity)
			});
			EnforceCap(s.Owner);
		}

		private Material MakeMaterial(Texture2D tex)
		{
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			if ((Object)(object)baseMat == (Object)null)
			{
				string[] array = new string[3] { "Universal Render Pipeline/Unlit", "Sprites/Default", "Unlit/Transparent" };
				Shader val = null;
				string[] array2 = array;
				foreach (string text in array2)
				{
					val = Shader.Find(text);
					if ((Object)(object)val != (Object)null)
					{
						break;
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					((BasePlugin)Plugin.Instance).Log.LogError((object)"No usable shader found (stripped from build?)");
					val = Shader.Find("Hidden/InternalErrorShader");
				}
				baseMat = new Material(val);
				if (((Object)val).name.StartsWith("Universal"))
				{
					baseMat.SetFloat("_Surface", 1f);
					baseMat.SetFloat("_Blend", 0f);
					baseMat.SetFloat("_SrcBlend", 5f);
					baseMat.SetFloat("_DstBlend", 10f);
					baseMat.SetFloat("_ZWrite", 0f);
					baseMat.SetFloat("_Cull", 0f);
					baseMat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
					baseMat.SetOverrideTag("RenderType", "Transparent");
				}
				baseMat.renderQueue = 3000;
			}
			Material val2 = new Material(baseMat);
			val2.mainTexture = (Texture)(object)tex;
			if (val2.HasProperty("_BaseMap"))
			{
				val2.SetTexture("_BaseMap", (Texture)(object)tex);
			}
			return val2;
		}

		private void HandlePacket(byte[] data)
		{
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				using BinaryReader binaryReader = new BinaryReader(new MemoryStream(data));
				byte b = binaryReader.ReadByte();
				string text = binaryReader.ReadString();
				switch (b)
				{
				case 2:
				{
					int num = binaryReader.ReadInt32();
					if (num <= 0 || num > 49152 || textures.ContainsKey(text))
					{
						break;
					}
					byte[] array = binaryReader.ReadBytes(num);
					if (Hash(array) != text)
					{
						break;
					}
					Texture2D val = Decode(array);
					if ((Object)(object)val == (Object)null)
					{
						break;
					}
					textures[text] = val;
					pngBytes[text] = array;
					if (!pending.TryGetValue(text, out var value2))
					{
						break;
					}
					foreach (PendingSpray item in value2)
					{
						PlaceSpray(text, item);
					}
					pending.Remove(text);
					break;
				}
				case 1:
				{
					PendingSpray s = new PendingSpray
					{
						Pos = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()),
						Normal = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()),
						Up = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()),
						Size = Mathf.Clamp(binaryReader.ReadSingle(), 0.1f, 3f),
						Owner = binaryReader.ReadInt32(),
						Seq = binaryReader.ReadInt32(),
						Sound = SafeSoundName(binaryReader.ReadString())
					};
					PlaceSpray(text, s);
					break;
				}
				case 4:
				{
					int owner = binaryReader.ReadInt32();
					int seq = binaryReader.ReadInt32();
					RemoveSpray(owner, seq);
					break;
				}
				case 3:
				{
					if (pngBytes.TryGetValue(text, out var value))
					{
						net.Broadcast(WriteImage(text, value));
					}
					break;
				}
				}
			}
			catch (Exception ex)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Bad spray packet: " + ex.Message));
			}
		}

		private static byte[] WriteImage(string hash, byte[] png)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write((byte)2);
			binaryWriter.Write(hash);
			binaryWriter.Write(png.Length);
			binaryWriter.Write(png);
			return memoryStream.ToArray();
		}

		private static byte[] WriteRequest(string hash)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write((byte)3);
			binaryWriter.Write(hash);
			return memoryStream.ToArray();
		}

		private static byte[] WriteDelete(int owner, int seq)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write((byte)4);
			binaryWriter.Write("");
			binaryWriter.Write(owner);
			binaryWriter.Write(seq);
			return memoryStream.ToArray();
		}

		private static byte[] WriteSpray(string hash, PendingSpray s)
		{
			//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_0035: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write((byte)1);
			binaryWriter.Write(hash);
			Vector3[] array = (Vector3[])(object)new Vector3[3] { s.Pos, s.Normal, s.Up };
			foreach (Vector3 val in array)
			{
				binaryWriter.Write(val.x);
				binaryWriter.Write(val.y);
				binaryWriter.Write(val.z);
			}
			binaryWriter.Write(s.Size);
			binaryWriter.Write(s.Owner);
			binaryWriter.Write(s.Seq);
			binaryWriter.Write(s.Sound ?? "");
			return memoryStream.ToArray();
		}

		private void DeleteLast()
		{
			for (int num = active.Count - 1; num >= 0; num--)
			{
				if (active[num].Owner == myId)
				{
					int seq = active[num].Seq;
					if ((Object)(object)active[num].Go != (Object)null)
					{
						Object.Destroy((Object)(object)active[num].Go);
					}
					active.RemoveAt(num);
					net.Broadcast(WriteDelete(myId, seq));
					Hud("Removed your latest spray");
					return;
				}
			}
			Hud("You have no sprays to remove");
		}

		private void DeleteAll()
		{
			int count = active.Count;
			foreach (ActiveSpray item in active)
			{
				if ((Object)(object)item.Go != (Object)null)
				{
					Object.Destroy((Object)(object)item.Go);
				}
			}
			active.Clear();
			pending.Clear();
			Hud((count == 0) ? "No sprays to clear" : ("Cleared " + count + " spray(s) from your screen"));
		}

		private void RemoveSpray(int owner, int seq)
		{
			for (int i = 0; i < active.Count; i++)
			{
				if (active[i].Owner == owner && active[i].Seq == seq)
				{
					if ((Object)(object)active[i].Go != (Object)null)
					{
						Object.Destroy((Object)(object)active[i].Go);
					}
					active.RemoveAt(i);
					break;
				}
			}
		}

		private void EnforceCap(int owner)
		{
			int value = Plugin.MaxPerPlayer.Value;
			if (value <= 0)
			{
				return;
			}
			int num = 0;
			foreach (ActiveSpray item in active)
			{
				if (item.Owner == owner)
				{
					num++;
				}
			}
			int num2 = 0;
			while (num2 < active.Count && num > value)
			{
				if (active[num2].Owner == owner)
				{
					if ((Object)(object)active[num2].Go != (Object)null)
					{
						Object.Destroy((Object)(object)active[num2].Go);
					}
					active.RemoveAt(num2);
					num--;
				}
				else
				{
					num2++;
				}
			}
		}

		private static string[] ScanSounds()
		{
			try
			{
				List<string> list = new List<string>();
				string[] array = Directory.GetFiles(Plugin.SoundDir, "*", SearchOption.AllDirectories);
				foreach (string text in array)
				{
					string text2 = Path.GetExtension(text).ToLowerInvariant();
					if (text2 == ".ogg" || text2 == ".wav" || text2 == ".mp3")
					{
						list.Add(text);
					}
				}
				list.Sort();
				return list.ToArray();
			}
			catch
			{
				return new string[0];
			}
		}

		private static AudioType TypeFor(string path)
		{
			//IL_002d: 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_0032: 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)
			string text = Path.GetExtension(path).ToLowerInvariant();
			string text2 = text;
			if (!(text2 == ".wav"))
			{
				if (text2 == ".mp3")
				{
					return (AudioType)13;
				}
				return (AudioType)14;
			}
			return (AudioType)20;
		}

		private void LoadClip(string key, string path)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (holders.ContainsKey(key) || clipReqs.ContainsKey(key))
			{
				return;
			}
			try
			{
				UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(new Uri(Path.GetFullPath(path)).AbsoluteUri, TypeFor(path));
				audioClip.SendWebRequest();
				clipReqs[key] = audioClip;
			}
			catch (Exception ex)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Could not start loading sound " + path + ": " + ex.Message));
			}
		}

		private void PollClips()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Invalid comparison between Unknown and I4
			if (clipReqs.Count == 0)
			{
				return;
			}
			List<string> list = null;
			foreach (KeyValuePair<string, UnityWebRequest> clipReq in clipReqs)
			{
				if (clipReq.Value.isDone)
				{
					(list ?? (list = new List<string>())).Add(clipReq.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (string item in list)
			{
				UnityWebRequest val = clipReqs[item];
				clipReqs.Remove(item);
				try
				{
					if ((int)val.result == 1)
					{
						AudioClip content = DownloadHandlerAudioClip.GetContent(val);
						if ((Object)(object)content != (Object)null)
						{
							((Object)content).name = ((item == "") ? "default" : Path.GetFileNameWithoutExtension(item));
							holders[item] = MakeHolder(content);
							((BasePlugin)Plugin.Instance).Log.LogInfo((object)("Loaded sound '" + ((item == "") ? "(default)" : item) + "'"));
						}
						else
						{
							((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Sound '" + item + "' decoded to a null clip."));
						}
					}
					else
					{
						((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Sound '" + item + "' failed: " + val.error));
					}
				}
				catch (Exception ex)
				{
					((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Sound '" + item + "' exception: " + ex.Message));
				}
				finally
				{
					val.Dispose();
				}
			}
		}

		private AudioSource MakeHolder(AudioClip clip)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//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_002b: Expected O, but got Unknown
			if ((Object)(object)soundHost == (Object)null)
			{
				soundHost = new GameObject("SpraySoundHost")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)(object)soundHost);
			}
			GameObject val = new GameObject("SprayClip_" + ((Object)clip).name);
			val.transform.SetParent(soundHost.transform, false);
			AudioSource val2 = ((Il2CppObjectBase)val.AddComponent(Il2CppType.Of<AudioSource>())).Cast<AudioSource>();
			val2.clip = clip;
			val2.playOnAwake = false;
			val2.spatialBlend = 0f;
			return val2;
		}

		private AudioSource GetHolder(string name)
		{
			if (!string.IsNullOrEmpty(name) && holders.TryGetValue(name, out var value) && (Object)(object)value != (Object)null && (Object)(object)value.clip != (Object)null)
			{
				return value;
			}
			AudioSource value2;
			return (holders.TryGetValue("", out value2) && (Object)(object)value2 != (Object)null && (Object)(object)value2.clip != (Object)null) ? value2 : null;
		}

		private void PlayAt(string soundName, Vector3 pos)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				AudioSource holder = GetHolder(soundName);
				if ((Object)(object)holder == (Object)null)
				{
					((BasePlugin)Plugin.Instance).Log.LogInfo((object)"No spray sound loaded (put spray.ogg next to the sprays folder, or pick one in the Sounds tab).");
					return;
				}
				GameObject val = new GameObject("SprayPlay");
				val.transform.position = pos;
				AudioSource val2 = ((Il2CppObjectBase)val.AddComponent(Il2CppType.Of<AudioSource>())).Cast<AudioSource>();
				val2.clip = holder.clip;
				val2.playOnAwake = false;
				val2.spatialBlend = 1f;
				val2.rolloffMode = (AudioRolloffMode)1;
				val2.minDistance = 1f;
				val2.maxDistance = 30f;
				val2.volume = Mathf.Clamp01(Plugin.Volume.Value);
				val2.Play();
				Object.Destroy((Object)(object)val, holder.clip.length + 0.5f);
			}
			catch (Exception ex)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("Spray sound failed: " + ex.Message));
			}
		}

		private static string SafeSoundName(string n)
		{
			return (string.IsNullOrEmpty(n) || n.Length > 100) ? "" : n;
		}

		private static string Hash(byte[] b)
		{
			using SHA1 sHA = SHA1.Create();
			return BitConverter.ToString(sHA.ComputeHash(b)).Replace("-", "").Substring(0, 16);
		}

		private static Texture2D Decode(byte[] png)
		{
			if (!PngCodec.TryDecode(png, 1024, out var width, out var height, out var pixels, out var error))
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)("PNG decode failed: " + error));
				return null;
			}
			return MakeTexture(width, height, pixels);
		}

		private static Texture2D MakeTexture(int w, int h, Color32[] px)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			Texture2D val = new Texture2D(w, h, (TextureFormat)4, true);
			val.SetPixels32(Il2CppStructArray<Color32>.op_Implicit(px));
			val.Apply(true, false);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return val;
		}
	}
}