Decompiled source of DiscordBot v1.1.2

DiscordBot.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ServerSync;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using uGIF;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.1.2")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("DiscordBot")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("RustyMods")]
[assembly: AssemblyProduct("DiscordBot")]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<fb7af288-4992-4af4-b6b5-9c6416ee3ff2>Embedded]
	internal sealed class <fb7af288-4992-4af4-b6b5-9c6416ee3ff2>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[<fb7af288-4992-4af4-b6b5-9c6416ee3ff2>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <79c465b9-e19a-45b2-b8d4-89f0bda71d86>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <79c465b9-e19a-45b2-b8d4-89f0bda71d86>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <79c465b9-e19a-45b2-b8d4-89f0bda71d86>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	[<fb7af288-4992-4af4-b6b5-9c6416ee3ff2>Embedded]
	internal sealed class <a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace uGIF
{
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	public class GIFEncoder
	{
		public bool useGlobalColorTable = false;

		public Color32? transparent = null;

		public int repeat = -1;

		public int dispose = -1;

		public int quality = 10;

		private int delay = 0;

		private int width;

		private int height;

		private int transIndex;

		private bool started = false;

		private MemoryStream ms;

		private Color32[] pixels;

		private byte[] indexedPixels;

		private byte[] prevIndexedPixels;

		private int colorDepth;

		private byte[] colorTab;

		private bool[] usedEntry = new bool[256];

		private int palSize = 7;

		private bool firstFrame = true;

		private NeuQuant nq;

		public float FPS
		{
			set
			{
				delay = Mathf.RoundToInt(100f / value);
			}
		}

		public void AddFrame(Image im)
		{
			if (im == null)
			{
				throw new ArgumentNullException("im");
			}
			if (!started)
			{
				throw new InvalidOperationException("Start() must be called before AddFrame()");
			}
			if (firstFrame)
			{
				width = im.width;
				height = im.height;
			}
			pixels = im.pixels;
			RemapPixels();
			pixels = null;
			if (firstFrame)
			{
				WriteLSD();
				WritePalette();
				if (repeat >= 0)
				{
					WriteNetscapeExt();
				}
			}
			WriteGraphicCtrlExt();
			WriteImageDesc();
			if (!firstFrame && !useGlobalColorTable)
			{
				WritePalette();
			}
			WritePixels();
			firstFrame = false;
		}

		public void Finish()
		{
			if (!started)
			{
				throw new InvalidOperationException("Start() must be called before Finish()");
			}
			started = false;
			ms.WriteByte(59);
			ms.Flush();
			transIndex = 0;
			pixels = null;
			indexedPixels = null;
			prevIndexedPixels = null;
			colorTab = null;
			firstFrame = true;
			nq = null;
		}

		public void Start(MemoryStream os)
		{
			if (os == null)
			{
				throw new ArgumentNullException("os");
			}
			ms = os;
			started = true;
			WriteString("GIF89a");
		}

		private void RemapPixels()
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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: Unknown result type (might be due to invalid IL or missing references)
			int num = pixels.Length;
			indexedPixels = new byte[num];
			if (firstFrame || !useGlobalColorTable)
			{
				nq = new NeuQuant(pixels, num, quality);
				colorTab = nq.Process();
			}
			for (int i = 0; i < num; i++)
			{
				int num2 = nq.Map(pixels[i].r & 0xFF, pixels[i].g & 0xFF, pixels[i].b & 0xFF);
				usedEntry[num2] = true;
				indexedPixels[i] = (byte)num2;
				if (dispose == 1 && prevIndexedPixels != null)
				{
					if (indexedPixels[i] == prevIndexedPixels[i])
					{
						indexedPixels[i] = (byte)transIndex;
					}
					else
					{
						prevIndexedPixels[i] = (byte)num2;
					}
				}
			}
			colorDepth = 8;
			palSize = 7;
			if (transparent.HasValue)
			{
				Color32 value = transparent.Value;
				transIndex = nq.Map(value.b, value.g, value.r);
			}
			if (dispose == 1 && prevIndexedPixels == null)
			{
				prevIndexedPixels = indexedPixels.Clone() as byte[];
			}
		}

		private int FindClosest(Color32 c)
		{
			//IL_0018: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			if (colorTab == null)
			{
				return -1;
			}
			int r = c.r;
			int g = c.g;
			int b = c.b;
			int result = 0;
			int num = 16777216;
			int num2 = colorTab.Length;
			for (int i = 0; i < num2; i++)
			{
				int num3 = r - (colorTab[i++] & 0xFF);
				int num4 = g - (colorTab[i++] & 0xFF);
				int num5 = b - (colorTab[i] & 0xFF);
				int num6 = num3 * num3 + num4 * num4 + num5 * num5;
				int num7 = i / 3;
				if (usedEntry[num7] && num6 < num)
				{
					num = num6;
					result = num7;
				}
			}
			return result;
		}

		private void WriteGraphicCtrlExt()
		{
			ms.WriteByte(33);
			ms.WriteByte(249);
			ms.WriteByte(4);
			int num;
			int num2;
			if (!transparent.HasValue)
			{
				num = 0;
				num2 = 0;
			}
			else
			{
				num = 1;
				num2 = 2;
			}
			if (dispose >= 0)
			{
				num2 = dispose & 7;
			}
			num2 <<= 2;
			ms.WriteByte(Convert.ToByte(0 | num2 | 0 | num));
			WriteShort(delay);
			ms.WriteByte(Convert.ToByte(transIndex));
			ms.WriteByte(0);
		}

		private void WriteImageDesc()
		{
			ms.WriteByte(44);
			WriteShort(0);
			WriteShort(0);
			WriteShort(width);
			WriteShort(height);
			ms.WriteByte(0);
		}

		private void WriteLSD()
		{
			WriteShort(width);
			WriteShort(height);
			ms.WriteByte(Convert.ToByte(0xF0 | palSize));
			ms.WriteByte(0);
			ms.WriteByte(0);
		}

		private void WriteNetscapeExt()
		{
			ms.WriteByte(33);
			ms.WriteByte(byte.MaxValue);
			ms.WriteByte(11);
			WriteString("NETSCAPE2.0");
			ms.WriteByte(3);
			ms.WriteByte(1);
			WriteShort(repeat);
			ms.WriteByte(0);
		}

		private void WritePalette()
		{
			ms.Write(colorTab, 0, colorTab.Length);
			int num = 768 - colorTab.Length;
			for (int i = 0; i < num; i++)
			{
				ms.WriteByte(0);
			}
		}

		private void WritePixels()
		{
			LZWEncoder lZWEncoder = new LZWEncoder(width, height, indexedPixels, colorDepth);
			lZWEncoder.Encode(ms);
		}

		private void WriteShort(int value)
		{
			ms.WriteByte(Convert.ToByte(value & 0xFF));
			ms.WriteByte(Convert.ToByte((value >> 8) & 0xFF));
		}

		private void WriteString(string s)
		{
			char[] array = s.ToCharArray();
			for (int i = 0; i < array.Length; i++)
			{
				ms.WriteByte((byte)array[i]);
			}
		}
	}
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	public class Image
	{
		public int width;

		public int height;

		public Color32[] pixels;

		public Image(Texture2D f)
		{
			pixels = f.GetPixels32();
			width = ((Texture)f).width;
			height = ((Texture)f).height;
		}

		public Image(Image image)
		{
			pixels = image.pixels.Clone() as Color32[];
			width = image.width;
			height = image.height;
		}

		public Image(int width, int height)
		{
			this.width = width;
			this.height = height;
			pixels = (Color32[])(object)new Color32[width * height];
		}

		public void DrawImage(Image image, int i, int i2)
		{
			throw new NotImplementedException();
		}

		public Color32 GetPixel(int tw, int th)
		{
			//IL_0013: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			int num = th * width + tw;
			return pixels[num];
		}

		public void Flip()
		{
			//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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < height / 2; i++)
			{
				for (int j = 0; j < width; j++)
				{
					int num = i * width + j;
					int num2 = (height - i - 1) * width + j;
					Color32 val = pixels[num];
					pixels[num] = pixels[num2];
					pixels[num2] = val;
				}
			}
		}

		public void Resize(int scale)
		{
			//IL_0056: 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)
			if (scale <= 1)
			{
				return;
			}
			int num = width / scale;
			int num2 = height / scale;
			Color32[] array = (Color32[])(object)new Color32[num * num2];
			for (int i = 0; i < num2; i++)
			{
				for (int j = 0; j < num; j++)
				{
					array[i * num + j] = pixels[i * scale * width + j * scale];
				}
			}
			pixels = array;
			height = num2;
			width = num;
		}

		public void ResizeBilinear(int newWidth, int newHeight)
		{
			//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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			if (newWidth == width && newHeight == height)
			{
				return;
			}
			Color32[] array = pixels;
			Color32[] array2 = (Color32[])(object)new Color32[newWidth * newHeight];
			float num = 1f / ((float)newWidth / (float)(width - 1));
			float num2 = 1f / ((float)newHeight / (float)(height - 1));
			int num3 = width;
			for (int i = 0; i < newHeight; i++)
			{
				int num4 = Mathf.FloorToInt((float)i * num2);
				int num5 = num4 * num3;
				int num6 = (num4 + 1) * num3;
				int num7 = i * newWidth;
				for (int j = 0; j < newWidth; j++)
				{
					int num8 = (int)Mathf.Floor((float)j * num);
					float p = (float)j * num - (float)num8;
					array2[num7 + j] = ColorLerpUnclamped(Color32.op_Implicit(ColorLerpUnclamped(Color32.op_Implicit(array[num5 + num8]), Color32.op_Implicit(array[num5 + num8 + 1]), p)), Color32.op_Implicit(ColorLerpUnclamped(Color32.op_Implicit(array[num6 + num8]), Color32.op_Implicit(array[num6 + num8 + 1]), p)), (float)i * num2 - (float)num4);
				}
			}
			pixels = array2;
			height = newHeight;
			width = newWidth;
		}

		private Color32 ColorLerpUnclamped(Color A, Color B, float P)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_0017: 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_0023: 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_0033: 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_0043: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0063: 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)
			return Color32.op_Implicit(new Color(A.r + (B.r - A.r) * P, A.g + (B.g - A.g) * P, A.b + (B.b - A.b) * P, A.a + (B.a - A.a) * P));
		}
	}
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	public class LZWEncoder
	{
		private static readonly int EOF = -1;

		private byte[] pixAry;

		private int initCodeSize;

		private int curPixel;

		private static readonly int BITS = 12;

		private static readonly int HSIZE = 5003;

		private int n_bits;

		private int maxbits = BITS;

		private int maxcode;

		private int maxmaxcode = 1 << BITS;

		private int[] htab = new int[HSIZE];

		private int[] codetab = new int[HSIZE];

		private int hsize = HSIZE;

		private int free_ent = 0;

		private bool clear_flg = false;

		private int g_init_bits;

		private int ClearCode;

		private int EOFCode;

		private int cur_accum = 0;

		private int cur_bits = 0;

		private int[] masks = new int[17]
		{
			0, 1, 3, 7, 15, 31, 63, 127, 255, 511,
			1023, 2047, 4095, 8191, 16383, 32767, 65535
		};

		private int a_count;

		private byte[] accum = new byte[256];

		public LZWEncoder(int width, int height, byte[] pixels, int color_depth)
		{
			pixAry = pixels;
			initCodeSize = Math.Max(2, color_depth);
		}

		private void Add(byte c, Stream outs)
		{
			accum[a_count++] = c;
			if (a_count >= 254)
			{
				Flush(outs);
			}
		}

		private void ClearTable(Stream outs)
		{
			ResetCodeTable(hsize);
			free_ent = ClearCode + 2;
			clear_flg = true;
			Output(ClearCode, outs);
		}

		private void ResetCodeTable(int hsize)
		{
			for (int i = 0; i < hsize; i++)
			{
				htab[i] = -1;
			}
		}

		private void Compress(int init_bits, Stream outs)
		{
			g_init_bits = init_bits;
			clear_flg = false;
			n_bits = g_init_bits;
			maxcode = MaxCode(n_bits);
			ClearCode = 1 << init_bits - 1;
			EOFCode = ClearCode + 1;
			free_ent = ClearCode + 2;
			a_count = 0;
			int num = NextPixel();
			int num2 = 0;
			for (int num3 = hsize; num3 < 65536; num3 *= 2)
			{
				num2++;
			}
			num2 = 8 - num2;
			int num4 = hsize;
			ResetCodeTable(num4);
			Output(ClearCode, outs);
			int num5;
			while ((num5 = NextPixel()) != EOF)
			{
				int num3 = (num5 << maxbits) + num;
				int num6 = (num5 << num2) ^ num;
				if (htab[num6] == num3)
				{
					num = codetab[num6];
					continue;
				}
				if (htab[num6] >= 0)
				{
					int num7 = num4 - num6;
					if (num6 == 0)
					{
						num7 = 1;
					}
					while (true)
					{
						if ((num6 -= num7) < 0)
						{
							num6 += num4;
						}
						if (htab[num6] == num3)
						{
							break;
						}
						if (htab[num6] >= 0)
						{
							continue;
						}
						goto IL_0160;
					}
					num = codetab[num6];
					continue;
				}
				goto IL_0160;
				IL_0160:
				Output(num, outs);
				num = num5;
				if (free_ent < maxmaxcode)
				{
					codetab[num6] = free_ent++;
					htab[num6] = num3;
				}
				else
				{
					ClearTable(outs);
				}
			}
			Output(num, outs);
			Output(EOFCode, outs);
		}

		public void Encode(Stream os)
		{
			os.WriteByte(Convert.ToByte(initCodeSize));
			curPixel = 0;
			Compress(initCodeSize + 1, os);
			os.WriteByte(0);
		}

		private void Flush(Stream outs)
		{
			if (a_count > 0)
			{
				outs.WriteByte(Convert.ToByte(a_count));
				outs.Write(accum, 0, a_count);
				a_count = 0;
			}
		}

		private int MaxCode(int n_bits)
		{
			return (1 << n_bits) - 1;
		}

		private int NextPixel()
		{
			if (curPixel == pixAry.Length)
			{
				return EOF;
			}
			curPixel++;
			return pixAry[curPixel - 1] & 0xFF;
		}

		private void Output(int code, Stream outs)
		{
			cur_accum &= masks[cur_bits];
			if (cur_bits > 0)
			{
				cur_accum |= code << cur_bits;
			}
			else
			{
				cur_accum = code;
			}
			cur_bits += n_bits;
			while (cur_bits >= 8)
			{
				Add((byte)((uint)cur_accum & 0xFFu), outs);
				cur_accum >>= 8;
				cur_bits -= 8;
			}
			if (free_ent > maxcode || clear_flg)
			{
				if (clear_flg)
				{
					maxcode = MaxCode(n_bits = g_init_bits);
					clear_flg = false;
				}
				else
				{
					n_bits++;
					if (n_bits == maxbits)
					{
						maxcode = maxmaxcode;
					}
					else
					{
						maxcode = MaxCode(n_bits);
					}
				}
			}
			if (code == EOFCode)
			{
				while (cur_bits > 0)
				{
					Add((byte)((uint)cur_accum & 0xFFu), outs);
					cur_accum >>= 8;
					cur_bits -= 8;
				}
				Flush(outs);
			}
		}
	}
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	public class NeuQuant
	{
		private static readonly int netsize = 256;

		private static readonly int prime1 = 499;

		private static readonly int prime2 = 491;

		private static readonly int prime3 = 487;

		private static readonly int prime4 = 503;

		private static readonly int minpicturebytes = 3 * prime4;

		private static readonly int maxnetpos = netsize - 1;

		private static readonly int netbiasshift = 4;

		private static readonly int ncycles = 100;

		private static readonly int intbiasshift = 16;

		private static readonly int intbias = 1 << intbiasshift;

		private static readonly int gammashift = 10;

		private static readonly int gamma = 1 << gammashift;

		private static readonly int betashift = 10;

		private static readonly int beta = intbias >> betashift;

		private static readonly int betagamma = intbias << gammashift - betashift;

		private static readonly int initrad = netsize >> 3;

		private static readonly int radiusbiasshift = 6;

		private static readonly int radiusbias = 1 << radiusbiasshift;

		private static readonly int initradius = initrad * radiusbias;

		private static readonly int radiusdec = 30;

		private static readonly int alphabiasshift = 10;

		private static readonly int initalpha = 1 << alphabiasshift;

		private int alphadec;

		private static readonly int radbiasshift = 8;

		private static readonly int radbias = 1 << radbiasshift;

		private static readonly int alpharadbshift = alphabiasshift + radbiasshift;

		private static readonly int alpharadbias = 1 << alpharadbshift;

		private Color32[] thepicture;

		private int lengthcount;

		private int samplefac;

		private int[][] network;

		private int[] netindex = new int[256];

		private int[] bias = new int[netsize];

		private int[] freq = new int[netsize];

		private int[] radpower = new int[initrad];

		public NeuQuant(Color32[] thepic, int len, int sample)
		{
			thepicture = thepic;
			lengthcount = len;
			samplefac = sample;
			network = new int[netsize][];
			for (int i = 0; i < netsize; i++)
			{
				network[i] = new int[4];
				int[] array = network[i];
				array[0] = (array[1] = (array[2] = (i << netbiasshift + 8) / netsize));
				freq[i] = intbias / netsize;
				bias[i] = 0;
			}
		}

		private byte[] ColorMap()
		{
			byte[] array = new byte[3 * netsize];
			int[] array2 = new int[netsize];
			for (int i = 0; i < netsize; i++)
			{
				array2[network[i][3]] = i;
			}
			int num = 0;
			for (int j = 0; j < netsize; j++)
			{
				int num2 = array2[j];
				array[num++] = (byte)network[num2][0];
				array[num++] = (byte)network[num2][1];
				array[num++] = (byte)network[num2][2];
			}
			return array;
		}

		private void Inxbuild()
		{
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < netsize; i++)
			{
				int[] array = network[i];
				int num3 = i;
				int num4 = array[1];
				int[] array2;
				for (int j = i + 1; j < netsize; j++)
				{
					array2 = network[j];
					if (array2[1] < num4)
					{
						num3 = j;
						num4 = array2[1];
					}
				}
				array2 = network[num3];
				if (i != num3)
				{
					int j = array2[0];
					array2[0] = array[0];
					array[0] = j;
					j = array2[1];
					array2[1] = array[1];
					array[1] = j;
					j = array2[2];
					array2[2] = array[2];
					array[2] = j;
					j = array2[3];
					array2[3] = array[3];
					array[3] = j;
				}
				if (num4 != num)
				{
					netindex[num] = num2 + i >> 1;
					for (int j = num + 1; j < num4; j++)
					{
						netindex[j] = i;
					}
					num = num4;
					num2 = i;
				}
			}
			netindex[num] = num2 + maxnetpos >> 1;
			for (int j = num + 1; j < 256; j++)
			{
				netindex[j] = maxnetpos;
			}
		}

		private void Learn()
		{
			if (lengthcount < minpicturebytes)
			{
				samplefac = 1;
			}
			alphadec = 30 + (samplefac - 1) / 3;
			Color32[] array = thepicture;
			int num = 0;
			int num2 = lengthcount;
			int num3 = lengthcount / (3 * samplefac);
			int num4 = num3 / ncycles;
			int num5 = initalpha;
			int num6 = initradius;
			int num7 = num6 >> radiusbiasshift;
			if (num7 <= 1)
			{
				num7 = 0;
			}
			int i;
			for (i = 0; i < num7; i++)
			{
				radpower[i] = num5 * ((num7 * num7 - i * i) * radbias / (num7 * num7));
			}
			int num8 = ((lengthcount < minpicturebytes) ? 3 : ((lengthcount % prime1 != 0) ? (3 * prime1) : ((lengthcount % prime2 != 0) ? (3 * prime2) : ((lengthcount % prime3 == 0) ? (3 * prime4) : (3 * prime3)))));
			i = 0;
			while (i < num3)
			{
				int b = (array[num].r & 0xFF) << netbiasshift;
				int g = (array[num].g & 0xFF) << netbiasshift;
				int r = (array[num].b & 0xFF) << netbiasshift;
				int i2 = Contest(b, g, r);
				Altersingle(num5, i2, b, g, r);
				if (num7 != 0)
				{
					Alterneigh(num7, i2, b, g, r);
				}
				num += num8;
				if (num >= num2)
				{
					num -= lengthcount;
				}
				i++;
				if (num4 == 0)
				{
					num4 = 1;
				}
				if (i % num4 == 0)
				{
					num5 -= num5 / alphadec;
					num6 -= num6 / radiusdec;
					num7 = num6 >> radiusbiasshift;
					if (num7 <= 1)
					{
						num7 = 0;
					}
					for (i2 = 0; i2 < num7; i2++)
					{
						radpower[i2] = num5 * ((num7 * num7 - i2 * i2) * radbias / (num7 * num7));
					}
				}
			}
		}

		public int Map(int b, int g, int r)
		{
			int num = 1000;
			int result = -1;
			int num2 = netindex[g];
			int num3 = num2 - 1;
			while (num2 < netsize || num3 >= 0)
			{
				int[] array;
				int num5;
				int num4;
				if (num2 < netsize)
				{
					array = network[num2];
					num4 = array[1] - g;
					if (num4 >= num)
					{
						num2 = netsize;
					}
					else
					{
						num2++;
						if (num4 < 0)
						{
							num4 = -num4;
						}
						num5 = array[0] - b;
						if (num5 < 0)
						{
							num5 = -num5;
						}
						num4 += num5;
						if (num4 < num)
						{
							num5 = array[2] - r;
							if (num5 < 0)
							{
								num5 = -num5;
							}
							num4 += num5;
							if (num4 < num)
							{
								num = num4;
								result = array[3];
							}
						}
					}
				}
				if (num3 < 0)
				{
					continue;
				}
				array = network[num3];
				num4 = g - array[1];
				if (num4 >= num)
				{
					num3 = -1;
					continue;
				}
				num3--;
				if (num4 < 0)
				{
					num4 = -num4;
				}
				num5 = array[0] - b;
				if (num5 < 0)
				{
					num5 = -num5;
				}
				num4 += num5;
				if (num4 < num)
				{
					num5 = array[2] - r;
					if (num5 < 0)
					{
						num5 = -num5;
					}
					num4 += num5;
					if (num4 < num)
					{
						num = num4;
						result = array[3];
					}
				}
			}
			return result;
		}

		public byte[] Process()
		{
			Learn();
			Unbiasnet();
			Inxbuild();
			return ColorMap();
		}

		private void Unbiasnet()
		{
			for (int i = 0; i < netsize; i++)
			{
				network[i][0] >>= netbiasshift;
				network[i][1] >>= netbiasshift;
				network[i][2] >>= netbiasshift;
				network[i][3] = i;
			}
		}

		private void Alterneigh(int rad, int i, int b, int g, int r)
		{
			int num = i - rad;
			if (num < -1)
			{
				num = -1;
			}
			int num2 = i + rad;
			if (num2 > netsize)
			{
				num2 = netsize;
			}
			int num3 = i + 1;
			int num4 = i - 1;
			int num5 = 1;
			while (num3 < num2 || num4 > num)
			{
				int num6 = radpower[num5++];
				if (num3 < num2)
				{
					int[] array = network[num3++];
					array[0] -= num6 * (array[0] - b) / alpharadbias;
					array[1] -= num6 * (array[1] - g) / alpharadbias;
					array[2] -= num6 * (array[2] - r) / alpharadbias;
				}
				if (num4 > num)
				{
					int[] array = network[num4--];
					array[0] -= num6 * (array[0] - b) / alpharadbias;
					array[1] -= num6 * (array[1] - g) / alpharadbias;
					array[2] -= num6 * (array[2] - r) / alpharadbias;
				}
			}
		}

		private void Altersingle(int alpha, int i, int b, int g, int r)
		{
			int[] array = network[i];
			array[0] -= alpha * (array[0] - b) / initalpha;
			array[1] -= alpha * (array[1] - g) / initalpha;
			array[2] -= alpha * (array[2] - r) / initalpha;
		}

		private int Contest(int b, int g, int r)
		{
			int num = int.MaxValue;
			int num2 = num;
			int num3 = -1;
			int result = num3;
			for (int i = 0; i < netsize; i++)
			{
				int[] array = network[i];
				int num4 = array[0] - b;
				if (num4 < 0)
				{
					num4 = -num4;
				}
				int num5 = array[1] - g;
				if (num5 < 0)
				{
					num5 = -num5;
				}
				num4 += num5;
				num5 = array[2] - r;
				if (num5 < 0)
				{
					num5 = -num5;
				}
				num4 += num5;
				if (num4 < num)
				{
					num = num4;
					num3 = i;
				}
				int num6 = num4 - (bias[i] >> intbiasshift - netbiasshift);
				if (num6 < num2)
				{
					num2 = num6;
					result = i;
				}
				int num7 = freq[i] >> betashift;
				freq[i] -= num7;
				bias[i] += num7 << gammashift;
			}
			freq[num3] += beta;
			bias[num3] -= betagamma;
			return result;
		}
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		private static BaseUnityPlugin _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out var value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out var value2))
			{
				text = value2.Aggregate(text, [<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null)
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = [<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] [return: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(1)] (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += [<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (object _, EventArgs _) =>
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
				UpdatePlaceholderText(Localization.instance, key);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1];
				if (dictionary.ContainsKey(text))
				{
					Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
				}
				else
				{
					dictionary[text] = item;
				}
			}
			if (!dictionary.TryGetValue("English", out var value))
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected a file like " + plugin.Info.Metadata.Name + ".English.json or .yml.");
			}
			Dictionary<string, string> dictionary2 = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(value));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: English localization file was empty.");
			}
			string text2 = null;
			if (language != "English" && dictionary.TryGetValue(language, out var value2))
			{
				text2 = File.ReadAllText(value2);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in JsonConvert.DeserializeObject<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string> { ".json" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		[return: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		private static byte[] LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(2)]
		public static byte[] ReadEmbeddedFileBytes([<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(1)] string resourceFileName, Assembly containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace DiscordBot
{
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	[PublicAPI]
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	public static class API
	{
		public static List<Action> m_queue = new List<Action>();

		public static void RegisterCommand(string command, string description, [<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1, 1 })] Action<string[]> action, [<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })] Action<ZPackage> reaction, bool adminOnly, bool isSecret, string emoji)
		{
			if (DiscordCommands.loaded)
			{
				if (!DiscordCommands.m_commands.ContainsKey(command))
				{
					new DiscordCommands.DiscordCommand(command, description, action, reaction, adminOnly, isSecret, emoji);
					if (!isSecret)
					{
						new DiscordCommands.CommandTooltip(command, description, adminOnly, emoji);
					}
				}
				return;
			}
			m_queue.Add(delegate
			{
				if (!DiscordCommands.m_commands.ContainsKey(command))
				{
					new DiscordCommands.DiscordCommand(command, description, action, reaction, adminOnly, isSecret, emoji);
					if (!isSecret)
					{
						new DiscordCommands.CommandTooltip(command, description, adminOnly, emoji);
					}
				}
			});
		}

		public static void SendNotification(string message)
		{
			Discord.instance?.SendMessage(Webhook.Notifications, message);
		}

		public static void SendChat(string message)
		{
			Discord.instance?.SendMessage(Webhook.Chat, message);
		}
	}
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	[PublicAPI]
	public static class DiscordBot_API
	{
		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
		internal class Method
		{
			private const string Namespace = "DiscordBot";

			private const string ClassName = "API";

			private const string Assembly = "DiscordBot";

			private const string API_LOCATION = "DiscordBot.API, DiscordBot";

			private static readonly Dictionary<string, Type> CachedTypes = new Dictionary<string, Type>();

			[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
			private readonly MethodInfo info;

			[return: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 1, 2 })]
			public object[] Invoke([<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 1, 2 })] params object[] args)
			{
				object obj = info?.Invoke(null, args);
				object[] array = new object[args.Length + 1];
				array[0] = obj;
				Array.Copy(args, 0, array, 1, args.Length);
				return array;
			}

			public Method(string typeNameWithAssembly, string methodName, BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public)
			{
				if (!TryGetType(typeNameWithAssembly, out var type))
				{
					return;
				}
				if (type == null)
				{
					Debug.LogWarning((object)("Type resolution returned null for: '" + typeNameWithAssembly + "'"));
					return;
				}
				info = type.GetMethod(methodName, bindingFlags);
				if (info == null)
				{
					Debug.LogWarning((object)("Failed to find public static method '" + methodName + "' in type '" + type.FullName + "'. Verify the method name is correct, the method exists, and it is marked as public static. "));
				}
			}

			public Method(string methodName, BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public)
				: this("DiscordBot.API, DiscordBot", methodName, bindingFlags)
			{
			}

			private static bool TryGetType(string typeNameWithAssembly, [<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)] out Type type)
			{
				if (CachedTypes.TryGetValue(typeNameWithAssembly, out type))
				{
					return true;
				}
				Type type2 = Type.GetType(typeNameWithAssembly);
				if ((object)type2 == null)
				{
					Debug.LogWarning((object)("Failed to resolve type: '" + typeNameWithAssembly + "'. Verify the namespace, class name, and assembly name are correct. Ensure the assembly is loaded and accessible."));
					return false;
				}
				type = type2;
				CachedTypes[typeNameWithAssembly] = type2;
				return true;
			}

			public Method(string typeNameWithAssembly, string methodName, params Type[] types)
			{
				if (!TryGetType(typeNameWithAssembly, out var type))
				{
					return;
				}
				if (type == null)
				{
					Debug.LogWarning((object)("Type resolution returned null for: '" + typeNameWithAssembly + "'"));
					return;
				}
				info = type.GetMethod(methodName, types);
				if (info == null)
				{
					Debug.LogWarning((object)("Failed to find public static method '" + methodName + "' in type '" + type.FullName + "'. Verify the method name is correct, the method exists, and it is marked as public static. "));
				}
			}

			public Method(string methodName, params Type[] types)
				: this("DiscordBot.API, DiscordBot", methodName, types)
			{
			}

			[PublicAPI]
			public ParameterInfo[] GetParameters()
			{
				return info?.GetParameters() ?? Array.Empty<ParameterInfo>();
			}

			[PublicAPI]
			public static void ClearCache()
			{
				CachedTypes.Clear();
			}
		}

		private static bool _isLoaded;

		private static readonly Method _RegisterCommand = new Method("RegisterCommand");

		private static readonly Method _SendNotification = new Method("SendNotification");

		private static readonly Method _SendChat = new Method("SendChat");

		private static readonly Dictionary<string, string> Emojis = new Dictionary<string, string>
		{
			{ "smile", "\ud83d\ude0a" },
			{ "grin", "\ud83d\ude01" },
			{ "laugh", "\ud83d\ude02" },
			{ "wink", "\ud83d\ude09" },
			{ "wave", "\ud83d\udc4b" },
			{ "clap", "\ud83d\udc4f" },
			{ "thumbsup", "\ud83d\udc4d" },
			{ "thumbsdown", "\ud83d\udc4e" },
			{ "ok", "\ud83d\udc4c" },
			{ "pray", "\ud83d\ude4f" },
			{ "muscle", "\ud83d\udcaa" },
			{ "facepalm", "\ud83e\udd26" },
			{ "dog", "\ud83d\udc36" },
			{ "cat", "\ud83d\udc31" },
			{ "mouse", "\ud83d\udc2d" },
			{ "fox", "\ud83e\udd8a" },
			{ "bear", "\ud83d\udc3b" },
			{ "panda", "\ud83d\udc3c" },
			{ "koala", "\ud83d\udc28" },
			{ "lion", "\ud83e\udd81" },
			{ "tiger", "\ud83d\udc2f" },
			{ "monkey", "\ud83d\udc35" },
			{ "unicorn", "\ud83e\udd84" },
			{ "dragon", "\ud83d\udc09" },
			{ "tree", "\ud83c\udf33" },
			{ "palm", "\ud83c\udf34" },
			{ "flower", "\ud83c\udf38" },
			{ "rose", "\ud83c\udf39" },
			{ "sun", "☀\ufe0f" },
			{ "moon", "\ud83c\udf19" },
			{ "star", "⭐" },
			{ "rain", "\ud83c\udf27\ufe0f" },
			{ "snow", "❄\ufe0f" },
			{ "fire", "\ud83d\udd25" },
			{ "lightning", "⚡" },
			{ "pizza", "\ud83c\udf55" },
			{ "burger", "\ud83c\udf54" },
			{ "fries", "\ud83c\udf5f" },
			{ "taco", "\ud83c\udf2e" },
			{ "cake", "\ud83c\udf70" },
			{ "donut", "\ud83c\udf69" },
			{ "coffee", "☕" },
			{ "tea", "\ud83c\udf75" },
			{ "beer", "\ud83c\udf7a" },
			{ "wine", "\ud83c\udf77" },
			{ "rocket", "\ud83d\ude80" },
			{ "car", "\ud83d\ude97" },
			{ "bike", "\ud83d\udeb2" },
			{ "airplane", "✈\ufe0f" },
			{ "train", "\ud83d\ude86" },
			{ "bus", "\ud83d\ude8c" },
			{ "ship", "\ud83d\udea2" },
			{ "book", "\ud83d\udcd6" },
			{ "pencil", "✏\ufe0f" },
			{ "pen", "\ud83d\udd8a\ufe0f" },
			{ "paint", "\ud83c\udfa8" },
			{ "camera", "\ud83d\udcf7" },
			{ "phone", "\ud83d\udcf1" },
			{ "computer", "\ud83d\udcbb" },
			{ "gift", "\ud83c\udf81" },
			{ "balloon", "\ud83c\udf88" },
			{ "key", "\ud83d\udd11" },
			{ "lock", "\ud83d\udd12" },
			{ "soccer", "⚽" },
			{ "basketball", "\ud83c\udfc0" },
			{ "football", "\ud83c\udfc8" },
			{ "tennis", "\ud83c\udfbe" },
			{ "golf", "⛳" },
			{ "run", "\ud83c\udfc3" },
			{ "swim", "\ud83c\udfca" },
			{ "ski", "⛷\ufe0f" },
			{ "game", "\ud83c\udfae" },
			{ "music", "\ud83c\udfb5" },
			{ "guitar", "\ud83c\udfb8" },
			{ "drum", "\ud83e\udd41" },
			{ "check", "✅" },
			{ "x", "❌" },
			{ "warning", "⚠\ufe0f" },
			{ "question", "❓" },
			{ "exclamation", "❗" },
			{ "infinity", "♾\ufe0f" },
			{ "heart", "❤\ufe0f" },
			{ "brokenheart", "\ud83d\udc94" },
			{ "sparkle", "✨" },
			{ "starstruck", "\ud83e\udd29" },
			{ "plus", "✚" },
			{ "minus", "━" },
			{ "tornado", "\ud83c\udf2a\ufe0f" },
			{ "storm", "⛈\ufe0f" },
			{ "save", "\ud83d\udcbe" },
			{ "stop", "\ud83d\udd34" }
		};

		private static bool isLoaded
		{
			get
			{
				if (_isLoaded)
				{
					return true;
				}
				_isLoaded = Type.GetType("DiscordBot.API, DiscordBot") != null;
				return _isLoaded;
			}
		}

		public static bool IsLoaded()
		{
			return isLoaded;
		}

		public static void SendNotification(string message)
		{
			_SendNotification.Invoke(message);
		}

		public static void SendChat(string message)
		{
			_SendChat.Invoke(message);
		}

		public static void RegisterCommand(string command, string description, Action<string[]> action, [<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })] Action<ZPackage> reaction = null, bool adminOnly = false, bool isSecret = false, string emoji = "")
		{
			_RegisterCommand.Invoke(command, description, action, reaction, adminOnly, isSecret, emoji);
		}
	}
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	public static class Extensions
	{
		public static string ToURL(this Webhook type)
		{
			if (1 == 0)
			{
			}
			string result = type switch
			{
				Webhook.Chat => DiscordBotPlugin.ChatWebhookURL, 
				Webhook.Notifications => DiscordBotPlugin.NoticeWebhookURL, 
				Webhook.Commands => DiscordBotPlugin.CommandWebhookURL, 
				Webhook.DeathFeed => DiscordBotPlugin.DeathFeedWebhookURL, 
				_ => DiscordBotPlugin.ChatWebhookURL, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		public static string ToID(this Channel type)
		{
			if (1 == 0)
			{
			}
			string result = type switch
			{
				Channel.Chat => DiscordBotPlugin.ChatChannelID, 
				Channel.Commands => DiscordBotPlugin.CommandChannelID, 
				_ => DiscordBotPlugin.ChatChannelID, 
			};
			if (1 == 0)
			{
			}
			return result;
		}
	}
	public enum Toggle
	{
		On = 1,
		Off = 0
	}
	public enum Webhook
	{
		Notifications,
		Chat,
		Commands,
		DeathFeed
	}
	public enum Channel
	{
		Chat,
		Commands
	}
	public enum ChatDisplay
	{
		Player,
		Bot
	}
	[BepInPlugin("RustyMods.DiscordBot", "DiscordBot", "1.1.2")]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	public class DiscordBotPlugin : BaseUnityPlugin
	{
		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
		public class StringListConfig
		{
			public readonly List<string> list;

			public StringListConfig(List<string> items)
			{
				list = items;
			}

			public StringListConfig(string items)
			{
				list = items.Split(new char[1] { ',' }).ToList();
			}

			public static void Draw(ConfigEntryBase cfg)
			{
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Expected O, but got Unknown
				//IL_0132: 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_014d: Expected O, but got Unknown
				bool valueOrDefault = cfg.Description.Tags.Select([<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : null).FirstOrDefault((bool? v) => v.HasValue).GetValueOrDefault();
				bool flag = false;
				List<string> list = new List<string>();
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				foreach (string item2 in new StringListConfig((string)cfg.BoxedValue).list)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					string item = item2;
					string text = GUILayout.TextField(item2, Array.Empty<GUILayoutOption>());
					if (text != item2 && !valueOrDefault)
					{
						flag = true;
						item = text;
					}
					if (GUILayout.Button("x", new GUIStyle(GUI.skin.button)
					{
						fixedWidth = 21f
					}, Array.Empty<GUILayoutOption>()) && !valueOrDefault)
					{
						flag = true;
					}
					else
					{
						list.Add(item);
					}
					if (GUILayout.Button("+", new GUIStyle(GUI.skin.button)
					{
						fixedWidth = 21f
					}, Array.Empty<GUILayoutOption>()) && !valueOrDefault)
					{
						list.Add("");
						flag = true;
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.EndVertical();
				if (flag)
				{
					cfg.BoxedValue = new StringListConfig(list).ToString();
				}
			}

			public override string ToString()
			{
				return string.Join(",", list);
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)]
		public class Resolution
		{
			public readonly int width;

			public readonly int height;

			public Resolution(int width, int height)
			{
				this.width = width;
				this.height = height;
				resolutions[ToString()] = this;
			}

			[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
			public sealed override string ToString()
			{
				return $"{width}x{height}";
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)]
		public class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order = null;

			[UsedImplicitly]
			public bool? Browsable = null;

			[UsedImplicitly]
			[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
			public string Category = null;

			[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
			[UsedImplicitly]
			public Action<ConfigEntryBase> CustomDrawer = null;
		}

		internal const string ModName = "DiscordBot";

		internal const string ModVersion = "1.1.2";

		internal const string Author = "RustyMods";

		private const string ModGUID = "RustyMods.DiscordBot";

		private static readonly string ConfigFileName = "RustyMods.DiscordBot.cfg";

		private static readonly string ConfigFileFullPath;

		internal static string ConnectionError;

		private readonly Harmony _harmony = new Harmony("RustyMods.DiscordBot");

		public static readonly ManualLogSource DiscordBotLogger;

		private static readonly ConfigSync ConfigSync;

		private static ConfigEntry<Toggle> _serverConfigLocked;

		public static readonly Dir directory;

		public static DiscordBotPlugin m_instance;

		private static ConfigEntry<string> m_notificationWebhookURL;

		private static ConfigEntry<Toggle> m_serverStartNotice;

		private static ConfigEntry<Toggle> m_serverStopNotice;

		private static ConfigEntry<Toggle> m_serverSaveNotice;

		private static ConfigEntry<Toggle> m_deathNotice;

		private static ConfigEntry<Toggle> m_loginNotice;

		private static ConfigEntry<Toggle> m_logoutNotice;

		private static ConfigEntry<string> m_chatWebhookURL;

		private static ConfigEntry<string> m_chatChannelID;

		private static ConfigEntry<Toggle> m_chatEnabled;

		private static ConfigEntry<ChatDisplay> m_chatType;

		private static ConfigEntry<string> m_commandWebhookURL;

		private static ConfigEntry<string> m_commandChannelID;

		private static ConfigEntry<string> m_deathFeedURL;

		private static ConfigEntry<string> m_discordAdmins;

		private static ConfigEntry<Toggle> m_logErrors;

		private static ConfigEntry<string> m_botToken;

		private static ConfigEntry<Toggle> m_screenshotDeath;

		private static ConfigEntry<float> m_screenshotDelay;

		private static ConfigEntry<string> m_screenshotResolution;

		private static ConfigEntry<int> m_screenshotDepth;

		private static ConfigEntry<Toggle> m_screenshotGif;

		private static ConfigEntry<int> m_gifFPS;

		private static ConfigEntry<float> m_gifDuration;

		private static ConfigEntry<string> m_gifResolution;

		private static readonly Dictionary<string, Resolution> resolutions;

		public static bool ShowServerStart => m_serverStartNotice.Value == Toggle.On;

		public static bool ShowChat => m_chatEnabled.Value == Toggle.On;

		public static bool LogErrors => m_logErrors.Value == Toggle.On;

		public static bool ShowServerStop => m_serverStopNotice.Value == Toggle.On;

		public static bool ShowServerSave => m_serverSaveNotice.Value == Toggle.On;

		public static bool ShowOnDeath => m_deathNotice.Value == Toggle.On;

		public static bool ShowOnLogin => m_loginNotice.Value == Toggle.On;

		public static bool ShowOnLogout => m_logoutNotice.Value == Toggle.On;

		public static ChatDisplay ChatType => m_chatType.Value;

		public static string DiscordAdmins => m_discordAdmins.Value;

		public static string BOT_TOKEN => m_botToken.Value;

		public static string ChatChannelID => m_chatChannelID.Value;

		public static string CommandChannelID => m_commandChannelID.Value;

		public static string ChatWebhookURL => m_chatWebhookURL.Value;

		public static string CommandWebhookURL => m_commandWebhookURL.Value;

		public static string NoticeWebhookURL => m_notificationWebhookURL.Value;

		public static string DeathFeedWebhookURL => m_deathFeedURL.Value;

		public static bool ScreenshotDeath => m_screenshotDeath.Value == Toggle.On;

		public static bool ScreenshotGif => m_screenshotGif.Value == Toggle.On;

		public static float ScreenshotDelay => m_screenshotDelay.Value;

		public static int GIF_FPS => m_gifFPS.Value;

		public static float GIF_DURATION => m_gifDuration.Value;

		public static Resolution ScreenshotResolution => resolutions[m_screenshotResolution.Value];

		public static Resolution GifResolution => resolutions[m_gifResolution.Value];

		public static int ScreenshotDepth => m_screenshotDepth.Value;

		public static void SetDiscordAdmins(string value)
		{
			m_discordAdmins.Value = value;
		}

		public static void LogWarning(string message)
		{
			DiscordBotLogger.LogWarning((object)message);
		}

		public static void LogDebug(string message)
		{
			DiscordBotLogger.LogDebug((object)message);
		}

		public void Awake()
		{
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Expected O, but got Unknown
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Expected O, but got Unknown
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Expected O, but got Unknown
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Expected O, but got Unknown
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Expected O, but got Unknown
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Expected O, but got Unknown
			Keys.Write();
			Localizer.Load();
			m_instance = this;
			_serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked);
			m_logErrors = config("1 - General", "Log Errors", Toggle.Off, "If on, errors will log to console as warnings");
			m_notificationWebhookURL = config("2 - Notifications", "Webhook URL", "", "Set webhook to receive notifications, like server start, stop, save etc...");
			m_serverStartNotice = config("2 - Notifications", "Startup", Toggle.On, "If on, bot will send message when server is starting");
			m_serverStopNotice = config("2 - Notifications", "Shutdown", Toggle.On, "If on, bot will send message when server is shutting down");
			m_serverSaveNotice = config("2 - Notifications", "Saving", Toggle.On, "If on, bot will send message when server is saving");
			m_loginNotice = config("2 - Notifications", "Login", Toggle.On, "If on, bot will send message when player logs in");
			m_logoutNotice = config("2 - Notifications", "Logout", Toggle.On, "If on, bot will send message when player logs out");
			m_chatWebhookURL = config("3 - Chat", "Webhook URL", "", "Set discord webhook to display chat messages");
			m_chatChannelID = config("3 - Chat", "Channel ID", "", "Set channel ID to monitor for messages");
			m_chatEnabled = config("3 - Chat", "Enabled", Toggle.On, "If on, bot will send message when player shouts and monitor discord for messages");
			m_chatType = config("3 - Chat", "Display As", ChatDisplay.Player, "Set how chat messages appear, if Player, message sent by player, else sent by bot with a prefix that player is saying");
			m_commandWebhookURL = config("4 - Commands", "Webhook URL", "", "Set discord webhook to display feedback messages from commands");
			m_commandChannelID = config("4 - Commands", "Channel ID", "", "Set channel ID to monitor for input commands");
			m_discordAdmins = config("4 - Commands", "Discord Admin", "", new ConfigDescription("List of discord admins, who can run commands", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					CustomDrawer = StringListConfig.Draw
				}
			}));
			m_botToken = config("5 - Setup", "BOT TOKEN", "", "Add bot token here, server only", synchronizedSetting: false);
			m_deathNotice = config("6 - Death Feed", "Enabled", Toggle.On, "If on, bot will send message when player dies");
			m_deathFeedURL = config("6 - Death Feed", "Webhook URL", "", "Set webhook to receive death feed messages");
			m_screenshotDeath = config("6 - Death Feed", "Screenshot", Toggle.On, "If on, bot will post screenshot of death", synchronizedSetting: false);
			m_screenshotDelay = config("6 - Death Feed", "Screenshot Delay", 0.3f, new ConfigDescription("Set delay", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()), synchronizedSetting: false);
			Resolution resolution = new Resolution(960, 540);
			Resolution resolution2 = new Resolution(800, 600);
			Resolution resolution3 = new Resolution(960, 540);
			Resolution resolution4 = new Resolution(1280, 720);
			Resolution resolution5 = new Resolution(1920, 1080);
			m_screenshotResolution = config("6 - Death Feed", "Screenshot Resolution", resolution.ToString(), new ConfigDescription("Set resolution", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5]
			{
				resolution2.ToString(),
				resolution.ToString(),
				resolution3.ToString(),
				resolution4.ToString(),
				resolution5.ToString()
			}), Array.Empty<object>()), synchronizedSetting: false);
			m_screenshotDepth = config("6 - Death Feed", "Screenshot Depth", 32, new ConfigDescription("Set depth", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[4] { 0, 16, 24, 32 }), Array.Empty<object>()), synchronizedSetting: false);
			m_screenshotResolution.SettingChanged += [<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (object _, EventArgs _) =>
			{
				Screenshot.instance?.OnResolutionChange();
			};
			m_screenshotDepth.SettingChanged += [<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (object _, EventArgs _) =>
			{
				Screenshot.instance?.OnResolutionChange();
			};
			m_screenshotGif = config("6 - Death Feed", "Screenshot GIF", Toggle.On, "If on, bot will post gif of death", synchronizedSetting: false);
			m_gifFPS = config("6 - Death Feed", "GIF FPS", 30, new ConfigDescription("Set frames per second", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), Array.Empty<object>()), synchronizedSetting: false);
			m_gifDuration = config("6 - Death Feed", "GIF Record Duration", 3f, new ConfigDescription("Set recording duration for gif, in seconds", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>()), synchronizedSetting: false);
			Resolution resolution6 = new Resolution(256, 144);
			Resolution resolution7 = new Resolution(320, 180);
			Resolution resolution8 = new Resolution(480, 270);
			Resolution resolution9 = new Resolution(640, 360);
			m_gifResolution = config("6 - Death Feed", "GIF Resolution", resolution8.ToString(), new ConfigDescription("Set resolution", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4]
			{
				resolution6.ToString(),
				resolution7.ToString(),
				resolution8.ToString(),
				resolution9.ToString()
			}), Array.Empty<object>()), synchronizedSetting: false);
			m_gifResolution.SettingChanged += [<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (object _, EventArgs _) =>
			{
				Screenshot.instance?.OnGifResolutionChange();
			};
			DiscordCommands.Setup();
			DeathQuips.Setup();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				DiscordBotLogger.LogDebug((object)"ReadConfigValues called");
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				DiscordBotLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
				DiscordBotLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		private ConfigEntry<T> config<[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
			SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2);
			syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		public ConfigEntry<T> config<[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		static DiscordBotPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ConnectionError = "";
			DiscordBotLogger = Logger.CreateLogSource("DiscordBot");
			ConfigSync = new ConfigSync("RustyMods.DiscordBot")
			{
				DisplayName = "DiscordBot",
				CurrentVersion = "1.1.2",
				MinimumRequiredVersion = "1.1.2"
			};
			_serverConfigLocked = null;
			directory = new Dir(Paths.ConfigPath, "DiscordBot");
			m_instance = null;
			m_notificationWebhookURL = null;
			m_serverStartNotice = null;
			m_serverStopNotice = null;
			m_serverSaveNotice = null;
			m_deathNotice = null;
			m_loginNotice = null;
			m_logoutNotice = null;
			m_chatWebhookURL = null;
			m_chatChannelID = null;
			m_chatEnabled = null;
			m_chatType = null;
			m_commandWebhookURL = null;
			m_commandChannelID = null;
			m_deathFeedURL = null;
			m_discordAdmins = null;
			m_logErrors = null;
			m_botToken = null;
			m_screenshotDeath = null;
			m_screenshotDelay = null;
			m_screenshotResolution = null;
			m_screenshotDepth = null;
			m_screenshotGif = null;
			m_gifFPS = null;
			m_gifDuration = null;
			m_gifResolution = null;
			resolutions = new Dictionary<string, Resolution>();
		}
	}
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	public class Screenshot : MonoBehaviour
	{
		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		public static Screenshot instance;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		private Texture2D recordedFrame;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		private RenderTexture renderTexture;

		private bool isCapturing;

		[Header("Discord message")]
		private string playerName = string.Empty;

		private string message = string.Empty;

		private string thumbnail = string.Empty;

		[Header("GIF Settings")]
		private readonly List<Texture2D> recordedFrames = new List<Texture2D>();

		private bool isRecording;

		private float recordStartTime;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		private Coroutine recordingCoroutine;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		private RenderTexture gifTexture;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)]
		private byte[] gifBytes;

		private static Camera camera => Utils.GetMainCamera();

		[Header("Screenshot Settings")]
		private static int width => DiscordBotPlugin.ScreenshotResolution.width;

		private static int height => DiscordBotPlugin.ScreenshotResolution.height;

		private static int depth => DiscordBotPlugin.ScreenshotDepth;

		private static int gifHeight => DiscordBotPlugin.GifResolution.height;

		private static int gifWidth => DiscordBotPlugin.GifResolution.width;

		private static int fps => DiscordBotPlugin.GIF_FPS;

		private static float recordDuration => DiscordBotPlugin.GIF_DURATION;

		public void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			instance = this;
			renderTexture = new RenderTexture(width, height, depth);
			renderTexture.Create();
			gifTexture = new RenderTexture(gifWidth, gifHeight, 24);
			gifTexture.Create();
		}

		public void OnResolutionChange()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if (isCapturing)
			{
				DiscordBotPlugin.LogWarning("Bot is capturing screenshot, cannot change settings");
				return;
			}
			if ((Object)(object)renderTexture != (Object)null)
			{
				renderTexture.Release();
				Object.DestroyImmediate((Object)(object)renderTexture);
				renderTexture = null;
			}
			renderTexture = new RenderTexture(width, height, depth);
			renderTexture.Create();
		}

		public void OnGifResolutionChange()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			if (isRecording)
			{
				DiscordBotPlugin.LogWarning("Bot is recording GIF, cannot change settings");
				return;
			}
			if ((Object)(object)gifTexture != (Object)null)
			{
				gifTexture.Release();
				Object.DestroyImmediate((Object)(object)gifTexture);
				gifTexture = null;
			}
			gifTexture = new RenderTexture(gifWidth, gifHeight, 24);
			gifTexture.Create();
		}

		public void OnDestroy()
		{
			instance = null;
		}

		private IEnumerator DelayedCaptureFrame()
		{
			yield return (object)new WaitForSeconds(DiscordBotPlugin.ScreenshotDelay);
			recordedFrame = Capture();
			if (recordedFrame == null)
			{
				isCapturing = false;
				yield break;
			}
			SendToDiscord(ImageConversion.EncodeToPNG(recordedFrame));
			isCapturing = false;
		}

		private Texture2D Capture()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture targetTexture = camera.targetTexture;
			camera.targetTexture = renderTexture;
			camera.Render();
			RenderTexture.active = renderTexture;
			Texture2D val = new Texture2D(width, height, (TextureFormat)3, false);
			val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0, false);
			val.Apply();
			RenderTexture.active = null;
			camera.targetTexture = targetTexture;
			return val;
		}

		public void StartCapture(string player, string quip, string avatar)
		{
			if (!isCapturing)
			{
				playerName = player;
				message = quip;
				thumbnail = avatar;
				isCapturing = true;
				((MonoBehaviour)this).StartCoroutine(DelayedCaptureFrame());
			}
		}

		public void SendToDiscord(byte[] data)
		{
			Discord.instance?.SendImageMessage(Webhook.DeathFeed, playerName, message, data, $"{DateTime.UtcNow:yyyyMMdd_HHmmss}.png", "", thumbnail);
			Object.DestroyImmediate((Object)(object)recordedFrame);
			recordedFrame = null;
		}

		private IEnumerator DelayedSelfie()
		{
			yield return (object)new WaitForSeconds(DiscordBotPlugin.ScreenshotDelay);
			recordedFrame = Capture();
			if (recordedFrame == null)
			{
				isCapturing = false;
				yield break;
			}
			SendSelfieToDiscord();
			isCapturing = false;
		}

		public void StartSelfie()
		{
			isCapturing = true;
			((MonoBehaviour)this).StartCoroutine(DelayedSelfie());
		}

		public void SendSelfieToDiscord()
		{
			Discord.instance?.SendImageMessage(Webhook.Chat, Player.m_localPlayer.GetPlayerName(), "Selfie!", ImageConversion.EncodeToPNG(recordedFrame), $"{DateTime.UtcNow:yyyyMMdd_HHmmss}.png");
			Object.DestroyImmediate((Object)(object)recordedFrame);
			recordedFrame = null;
		}

		public void StartRecording(string player, string quip, string avatar)
		{
			if (!isRecording)
			{
				playerName = player;
				message = quip;
				thumbnail = avatar;
				isRecording = true;
				recordStartTime = Time.time;
				if (recordingCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(recordingCoroutine);
				}
				recordingCoroutine = ((MonoBehaviour)this).StartCoroutine(Record());
			}
		}

		private Texture2D CaptureFrame()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture targetTexture = camera.targetTexture;
			camera.targetTexture = gifTexture;
			camera.Render();
			RenderTexture.active = gifTexture;
			Texture2D val = new Texture2D(gifWidth, gifHeight, (TextureFormat)3, false);
			val.ReadPixels(new Rect(0f, 0f, (float)gifWidth, (float)gifHeight), 0, 0, false);
			val.Apply();
			RenderTexture.active = null;
			camera.targetTexture = targetTexture;
			return val;
		}

		private IEnumerator Record()
		{
			float interval = 1f / (float)fps;
			while (isRecording && Time.time - recordStartTime < recordDuration)
			{
				recordedFrames.Add(CaptureFrame());
				yield return (object)new WaitForSeconds(interval);
			}
			isRecording = false;
			Thread thread = new Thread(CreateGif);
			thread.Start();
			((MonoBehaviour)this).StartCoroutine(WaitForBytes());
		}

		private IEnumerator WaitForBytes()
		{
			while (gifBytes == null)
			{
				yield return null;
			}
			SendGif(gifBytes);
			gifBytes = null;
		}

		private void CreateGif()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			GIFEncoder gIFEncoder = new GIFEncoder
			{
				useGlobalColorTable = true,
				repeat = 0,
				FPS = fps,
				transparent = new Color32(byte.MaxValue, (byte)0, byte.MaxValue, byte.MaxValue),
				dispose = 1
			};
			MemoryStream memoryStream = new MemoryStream();
			gIFEncoder.Start(memoryStream);
			foreach (Texture2D recordedFrame in recordedFrames)
			{
				Image image = new Image(recordedFrame);
				image.Flip();
				gIFEncoder.AddFrame(image);
			}
			gIFEncoder.Finish();
			gifBytes = memoryStream.ToArray();
			memoryStream.Close();
			recordedFrames.Clear();
		}

		private void SendGif(byte[] bytes)
		{
			Discord.instance?.SendGifMessage(Webhook.DeathFeed, playerName, message, bytes, $"{DateTime.UtcNow:yyyyMMdd_HHmmss}.gif", "", thumbnail);
		}
	}
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	public class Dir
	{
		public readonly string Path;

		public bool Exists => Directory.Exists(Path);

		public Dir(string dir, string name)
		{
			Path = System.IO.Path.Combine(dir, name);
			EnsureDirectoryExists();
		}

		private void EnsureDirectoryExists()
		{
			if (!Directory.Exists(Path))
			{
				Directory.CreateDirectory(Path);
			}
		}

		public string[] GetFiles(string searchPattern = "*", bool includeSubDirs = false)
		{
			SearchOption searchOption = (includeSubDirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
			return ExecuteWithRetry([<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] () => Directory.GetFiles(Path, searchPattern, searchOption));
		}

		public string[] GetDirectories(string searchPattern = "*")
		{
			return ExecuteWithRetry([<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] () => Directory.GetDirectories(Path, searchPattern));
		}

		public string CreateDir(string dirName)
		{
			string text = System.IO.Path.Combine(Path, dirName);
			if (Directory.Exists(text))
			{
				return text;
			}
			Directory.CreateDirectory(text);
			return text;
		}

		public string WriteFile(string fileName, string content)
		{
			string fullPath = System.IO.Path.Combine(Path, fileName);
			ExecuteWithRetry(delegate
			{
				File.WriteAllText(fullPath, content);
			});
			return fullPath;
		}

		public string WriteAllLines(string fileName, List<string> lines)
		{
			string fullPath = System.IO.Path.Combine(Path, fileName);
			ExecuteWithRetry(delegate
			{
				File.WriteAllLines(fullPath, lines);
			});
			return fullPath;
		}

		public void WriteAllBytes(string fileName, byte[] content)
		{
			string fullPath = System.IO.Path.Combine(Path, fileName);
			ExecuteWithRetry(delegate
			{
				File.WriteAllBytes(fullPath, content);
			});
		}

		public string ReadFile(string fileName)
		{
			string fullPath = System.IO.Path.Combine(Path, fileName);
			return ExecuteWithRetry([<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] () => File.ReadAllText(fullPath));
		}

		public IEnumerable<string> ReadAllLines(string fileName)
		{
			string fullPath = System.IO.Path.Combine(Path, fileName);
			return ExecuteWithRetry([<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] () => File.ReadAllLines(fullPath));
		}

		public bool FileExists(string fileName)
		{
			string fullPath = System.IO.Path.Combine(Path, fileName);
			return ExecuteWithRetry(() => File.Exists(fullPath));
		}

		public void DeleteFile(string fileName)
		{
			string fullPath = System.IO.Path.Combine(Path, fileName);
			ExecuteWithRetry(delegate
			{
				if (File.Exists(fullPath))
				{
					File.Delete(fullPath);
				}
			});
		}

		private T ExecuteWithRetry<[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)] T>(Func<T> operation)
		{
			try
			{
				return operation();
			}
			catch (DirectoryNotFoundException)
			{
				EnsureDirectoryExists();
				return operation();
			}
		}

		private void ExecuteWithRetry(Action operation)
		{
			try
			{
				operation();
			}
			catch (DirectoryNotFoundException)
			{
				EnsureDirectoryExists();
				operation();
			}
		}
	}
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	public static class DeathQuips
	{
		private static readonly Dir QuipsDir = new Dir(DiscordBotPlugin.directory.Path, "Quips");

		private static readonly Random random = new Random();

		private static string[] Templates = new string[15]
		{
			"{player} thought they could take on {creature}{level}. They were wrong. So very wrong.", "Breaking news: {creature}{level} just turned {player} into yesterday's lunch!", "{player} has been graciously donated to the {creature}{level} retirement fund.", "RIP {player} - defeated by a {creature}{level}. We'll tell your story... if we remember it.", "{player} tried to negotiate with {creature}{level}. Negotiations failed spectacularly.", "{creature}{level}  just taught {player} a valuable lesson about mortality.", "{player} is now experiencing the afterlife, courtesy of {creature}{level}.", "Darwin Award goes to {player} for challenging a {creature}{level} to single combat!", "{creature} {level} has added {player} to their collection. How thoughtful!", "{player} became {creature}'s{level} afternoon snack. Crunchy on the outside, chewy on the inside.",
			"Weather update: It's raining {player}, thanks to {creature}{level}!", "{player} just discovered what a {creature}{level} tastes like. Spoiler: They taste like {player}.", "{creature} {level} sends their regards to {player}'s next of kin.", "{player} has been permanently relocated by {creature}{level}. New address: The Great Beyond.", "Medical examiner's report: {player} suffered from acute {creature}{level} syndrome."
		};

		private static string[] LowLevelInsults = new string[4] { "Imagine dying to a {creature}{level}. We're not angry, just disappointed.", "{player} was bested by a baby {creature}{level}. Let that sink in.", "A {creature}{level} just ended {player}'s whole career. Yikes.", "{player} got schooled by {creature}{level}. Time to go back to training wheels!" };

		private static string[] HighLevelRespect = new string[4] { "{player} faced a legendary {creature}{level} and... well, at least they tried!", "{creature}{level} shows no mercy, not even for {player}. Respect the boss fight!", "{player} challenged a god-tier {creature}{level}. Bold strategy, poor execution.", "That {creature}{level} just reminded everyone why they're the apex predator. Sorry {player}." };

		private static string[] BossDeaths = new string[3] { "{player} has been obliterated by {creature}{level}. Boss fight = Boss loss!", "{creature}{level} just demonstrated why they're called a 'boss.' {player} learned this the hard way.", "{player} thought they were ready for {creature}{level}. {creature} disagreed... violently." };

		private static readonly Dictionary<HitType, string[]> deathQuips = new Dictionary<HitType, string[]>
		{
			[(HitType)3] = new string[7] { "{player} discovered gravity works. Physics: 1, {player}: 0.", "{player} tried to fly without wings. Spoiler alert: it didn't work.", "{player} has been forcibly introduced to the ground. They're getting very acquainted.", "{player} took the express route down. No stops, no survivors.", "Gravity called, {player} answered. Permanently.", "{player} forgot the first rule of holes: stop digging... or falling.", "{player} just learned why birds have wings. Too late, unfortunately." },
			[(HitType)4] = new string[7] { "{player} tried to breathe water. Fish: 1, {player}: 0.", "{player} has become one with the ocean. How poetic. How dead.", "{player} discovered they're not actually part mermaid.", "{player} took 'sleeping with the fishes' a bit too literally.", "{player} forgot to bring their floaties. Critical error.", "{player} just proved that humans are terrible at being fish.", "{player} went for a swim and stayed for eternity." },
			[(HitType)5] = new string[7] { "{player} was cremated without prior consent.", "{player} thought they were fire-proof. They were fire-food.", "{player} is now extra crispy. Would you like fries with that?", "{player} discovered that 'stop, drop, and roll' has a time limit.", "{player} became a human torch. Not the superhero kind.", "{player} just learned why fire safety exists.", "{player} is now well-done. Chef's kiss! \ud83d\udc80" },
			[(HitType)6] = new string[7] { "{player} has been turned into a {player}-sicle.", "{player} got the ultimate brain freeze.", "{player} discovered that hypothermia isn't just a suggestion.", "{player} is now permanently chilled. Ice to meet you!", "{player} became a statue. Very artistic. Very dead.", "{player} learned that winter clothing isn't optional.", "{player} is experiencing an ice age... of one." },
			[(HitType)7] = new string[7] { "{player} failed the poison taste test. Final score: Poison wins.", "{player} discovered that not all berries are friends.", "{player} has been chemically decommissioned.", "{player} took a sip from the wrong cup. Choose wisely next time!", "{player} learned why warning labels exist the hard way.", "{player} became a cautionary tale about mysterious substances.", "{player} is now immune to everything. Because they're dead." },
			[(HitType)10] = new string[7] { "{player} found the edge of the world. It found them back.", "{player} tried to go where no one has gone before. There's a reason for that.", "{player} discovered that maps have boundaries for a reason.", "{player} took 'pushing the envelope' to the extreme.", "{player} has left the building... and the world... and existence.", "{player} went beyond the point of no return. Literally.", "{player} boldly went where they shouldn't have gone." },
			[(HitType)11] = new string[7] { "{player} had a high-velocity meeting with something solid.", "{player} discovered the true meaning of 'sudden stop.'", "{player} became a pancake. Not the breakfast kind.", "{player} experienced physics at its most brutal.", "{player} collided with reality. Reality won.", "{player} learned that momentum isn't always your friend.", "{player} just had their final impact statement." },
			[(HitType)12] = new string[7] { "{player} was run over by a cart. Talk about slow and steady losing the race.", "{player} discovered that carts have right of way. Aggressively.", "{player} became a speed bump. Permanently.", "{player} was cart-wheeled into the afterlife.", "{player} learned that carts don't brake for pedestrians.", "{player} got rolled over by the least threatening vehicle possible.", "{player} was defeated by medieval transportation. How embarrassing." },
			[(HitType)13] = new string[7] { "{player} hugged a tree. The tree hugged back... harder.", "{player} became one with nature. Very one. Very nature.", "{player} discovered that trees don't move. They don't have to.", "{player} was branched out of existence.", "{player} learned that bark is worse than bite.", "{player} got rooted. Permanently.", "{player} tried to become a lumberjack. The tree disagreed." },
			[(HitType)14] = new string[7] { "{player} was their own worst enemy. Literally.", "{player} achieved the ultimate self-own.", "{player} discovered friendly fire isn't very friendly.", "{player} was defeated by their greatest foe: themselves.", "{player} just pulled off the world's most elaborate suicide.", "{player} proved that sometimes you are your own problem.", "{player} achieved peak self-sabotage." },
			[(HitType)15] = new string[7] { "{player} was structurally readjusted. Permanently.", "{player} discovered that buildings fight back.", "{player} became part of the architecture. Very integrated.", "{player} was demolished by demolition.", "{player} learned that load-bearing walls are serious business.", "{player} got constructed into the afterlife.", "{player} experienced aggressive urban planning." },
			[(HitType)16] = new string[7] { "{player} was auto-targeted and auto-eliminated.", "{player} discovered that turrets have excellent aim.", "{player} became target practice. Final score: Turret wins.", "{player} was precision-eliminated by automated defense.", "{player} learned that turrets don't take breaks.", "{player} got schooled by a machine with no emotions.", "{player} was mechanically removed from existence." },
			[(HitType)17] = new string[7] { "{player} was hit by a boat. On land. Somehow.", "{player} discovered that boats have right of way everywhere.", "{player} was sailed into the afterlife.", "{player} got boated. That's apparently a thing now.", "{player} learned that boats don't brake for pedestrians either.", "{player} was run down by the nautical express.", "{player} experienced aggressive maritime law." },
			[(HitType)18] = new string[7] { "{player} was stabbed by the ceiling. Caves are rude.", "{player} discovered that nature has pointy bits.", "{player} was cave-shanked by limestone.", "{player} learned to look up the hard way.", "{player} became a geological casualty.", "{player} was speared by a very patient rock.", "{player} got the point. Literally." },
			[(HitType)19] = new string[7] { "{player} was launched into the stratosphere. One-way ticket.", "{player} discovered medieval ballistics the hard way.", "{player} was trebucheted out of existence.", "{player} experienced the superior siege weapon personally.", "{player} got yeeted by ancient engineering.", "{player} was catapulted into legend. And death.", "{player} learned why catapults were weapons of war." },
			[(HitType)9] = new string[7] { "{player} couldn't see through the smoke screen. Permanently.", "{player} was smoked out of existence.", "{player} discovered that smoke inhalation isn't a joke.", "{player} got lost in the smoke and never found their way back.", "{player} was fog-banked into the afterlife.", "{player} couldn't clear the air in time.", "{player} became a smokehouse casualty." },
			[(HitType)8] = new string[7] { "{player} was hydro-pressured into submission.", "{player} discovered that water can be violent.", "{player} was liquidated. Literally.", "{player} learned that H2O can be H2-NO.", "{player} was swept away by aquatic aggression.", "{player} experienced water pressure personally.", "{player} got tide-rolled into oblivion." },
			[(HitType)20] = new string[7] { "{player} was cinder-blocked from life.", "{player} discovered that cinder fire burns differently. Deadlier.", "{player} was ash-ified by superior flames.", "{player} learned about advanced pyrotechnics the hard way.", "{player} was upgraded from regular fire to premium fire.", "{player} experienced fire 2.0. It's an improvement. For the fire.", "{player} was incinerated by artisanal flames." },
			[(HitType)21] = new string[7] { "{player} discovered that Ashlands water isn't refreshing.", "{player} went for a swim in liquid doom.", "{player} learned that not all oceans are created equal.", "{player} was dissolved by the most unfriendly sea.", "{player} took a bath in liquid nightmares.", "{player} discovered the ocean of nope.", "{player} went swimming and became soup." },
			[(HitType)0] = new string[7] { "{player} died to... something. We're not quite sure what.", "{player} was eliminated by mysterious circumstances.", "{player} discovered an unknown way to die. Congratulations?", "{player} was removed from existence by undefined means.", "{player} achieved death through unknown methods. Innovative!", "{player} died in a way that defies classification.", "{player} was killed by the universe's debugging process." }
		};

		public static string GenerateDeathQuip(string playerName, string creatureName, int creatureLevel, bool isBoss = false)
		{
			string[] array = (isBoss ? BossDeaths : ((creatureLevel <= 5) ? LowLevelInsults : ((creatureLevel < 50) ? Templates : HighLevelRespect)));
			string text = array[random.Next(array.Length)];
			string newValue = ((creatureLevel > 1) ? (" " + new string('★', creatureLevel - 1)) : "");
			return text.Replace("{player}", playerName).Replace("{creature}", creatureName).Replace("{level}", newValue);
		}

		public static string GenerateContextualQuip(string playerName, string creatureName, int creatureLevel, string prefabID = "")
		{
			string text = GenerateDeathQuip(playerName, creatureName, creatureLevel);
			if (1 == 0)
			{
			}
			string text2 = prefabID switch
			{
				"Blob" => " At least it was squishy!", 
				"Dragon" => " Well, that escalated quickly.", 
				"Skeleton" => " Bone-chilling performance!", 
				"Draugr" => " Braaaaains... or lack thereof.", 
				"Wolf" => " Should've brought a bigger stick.", 
				"Bjorn" => " Hibernation is over, apparently.", 
				"Goblin" => " Size doesn't matter, apparently.", 
				_ => "", 
			};
			if (1 == 0)
			{
			}
			string text3 = text2;
			return text + text3;
		}

		public static string GenerateEnvironmentalQuip(string playerName, HitType hitType)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!deathQuips.TryGetValue(hitType, out var value))
			{
				return playerName + " died in a way that words cannot describe. How mysterious...";
			}
			string text = value[random.Next(value.Length)];
			return text.Replace("{player}", playerName);
		}

		public static void Setup()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			string[] files = QuipsDir.GetFiles(".txt", includeSubDirs: true);
			if (files.Length == 0)
			{
				Write();
			}
			else
			{
				string[] array = files;
				foreach (string path in array)
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
					string[] array2 = File.ReadAllLines(path);
					switch (fileNameWithoutExtension)
					{
					case "Templates":
						Templates = array2;
						continue;
					case "LowLevelInsults":
						LowLevelInsults = array2;
						continue;
					case "HighLevelRespect":
						HighLevelRespect = array2;
						continue;
					case "BossDeaths":
						BossDeaths = array2;
						continue;
					}
					if (Enum.TryParse<HitType>(fileNameWithoutExtension, ignoreCase: true, out HitType result))
					{
						deathQuips[result] = array2;
					}
				}
			}
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(QuipsDir.Path, "*.txt");
			fileSystemWatcher.EnableRaisingEvents = true;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.Changed += OnChanged;
			fileSystemWatcher.Created += OnChanged;
		}

		private static void OnChanged(object sender, FileSystemEventArgs e)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(e.FullPath);
			string[] array = File.ReadAllLines(e.FullPath);
			switch (fileNameWithoutExtension)
			{
			case "Templates":
				Templates = array;
				return;
			case "LowLevelInsults":
				LowLevelInsults = array;
				return;
			case "HighLevelRespect":
				HighLevelRespect = array;
				return;
			case "BossDeaths":
				BossDeaths = array;
				return;
			}
			if (Enum.TryParse<HitType>(fileNameWithoutExtension, ignoreCase: true, out HitType result))
			{
				deathQuips[result] = array;
			}
		}

		private static void Write()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			QuipsDir.WriteAllLines("Templates.txt", Templates.ToList());
			QuipsDir.WriteAllLines("LowLevelInsults.txt", LowLevelInsults.ToList());
			QuipsDir.WriteAllLines("HighLevelRespect.txt", HighLevelRespect.ToList());
			QuipsDir.WriteAllLines("BossDeaths.txt", BossDeaths.ToList());
			foreach (KeyValuePair<HitType, string[]> deathQuip in deathQuips)
			{
				Dir quipsDir = QuipsDir;
				HitType key = deathQuip.Key;
				quipsDir.WriteAllLines(((object)(HitType)(ref key)).ToString() + ".txt", deathQuip.Value.ToList());
			}
		}
	}
	[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
	[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(2)]
	public class DiscordGatewayClient : MonoBehaviour
	{
		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)]
		[HarmonyPatch(typeof(ZNet), "Awake")]
		private static class ZNet_Awake_Patch
		{
			[UsedImplicitly]
			[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
			private static void Postfix(ZNet __instance)
			{
				if (__instance.IsServer())
				{
					((Component)DiscordBotPlugin.m_instance).gameObject.AddComponent<DiscordGatewayClient>();
				}
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
		private class PriorityQueue<[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(2)] T>
		{
			private readonly Queue<T> highPriority = new Queue<T>();

			private readonly Queue<T> normalPriority = new Queue<T>();

			public int Count => highPriority.Count + normalPriority.Count;

			public void Enqueue(T item, bool priority = false)
			{
				DiscordGatewayClient instance = DiscordGatewayClient.instance;
				if (instance == null || instance.isConnected)
				{
					if (priority)
					{
						highPriority.Enqueue(item);
					}
					else
					{
						normalPriority.Enqueue(item);
					}
					DiscordGatewayClient.instance?.TriggerProcessing();
				}
			}

			public T Dequeue()
			{
				return (highPriority.Count > 0) ? highPriority.Dequeue() : normalPriority.Dequeue();
			}

			public void Clear()
			{
				highPriority.Clear();
				normalPriority.Clear();
			}
		}

		[Serializable]
		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(0)]
		public class GatewayEvent
		{
			public int op;

			public JObject d;

			public int? s;

			public string t;
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)]
		[UsedImplicitly]
		public enum Opcodes
		{
			Dispatch = 0,
			Heartbeat = 1,
			Identify = 2,
			PresenceUpdate = 3,
			VoiceStateUpdate = 4,
			Resume = 6,
			Reconnect = 7,
			RequestGuildMembers = 8,
			InvalidSession = 9,
			Hello = 10,
			HeartbeatOK = 11,
			RequestSoundboardSounds = 31
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)]
		[UsedImplicitly]
		public enum Intent
		{
			Guilds = 1,
			GuildMessages = 0x200,
			MessageContent = 0x8000
		}

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(1)]
		private static readonly JsonSerializerSettings settings = new JsonSerializerSettings
		{
			MissingMemberHandling = (MissingMemberHandling)0,
			NullValueHandling = (NullValueHandling)1,
			Error = [<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(0)] (object _, [<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(1)] ErrorEventArgs args) =>
			{
				args.ErrorContext.Handled = true;
			}
		};

		public static DiscordGatewayClient instance;

		private const int BUFFER_SIZE = 16384;

		private ClientWebSocket websocket;

		private CancellationTokenSource cancellationTokenSource;

		private string gatewayUrl;

		private int sequenceNumber;

		private string sessionId;

		private bool heartbeatAcknowledged = true;

		private Coroutine heartbeatCoroutine;

		private bool isConnecting;

		private bool isConnected;

		private bool shouldReconnect = true;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(1)]
		private readonly PriorityQueue<object> messageQueue = new PriorityQueue<object>();

		private bool isSending;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(1)]
		private static readonly WaitForSeconds processMessageRate = new WaitForSeconds(0.1f);

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(1)]
		private static readonly WaitForSeconds retryConnectionDelay = new WaitForSeconds(5f);

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[method: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[field: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		public event Action<Message> OnChatReceived;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[method: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[field: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		public event Action<Message> OnCommandReceived;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[method: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[field: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		public event Action<string> OnError;

		public event Action OnConnected;

		public event Action OnDisconnected;

		[<79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[method: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		[field: <79c465b9-e19a-45b2-b8d4-89f0bda71d86>Nullable(new byte[] { 2, 1 })]
		public event Action<string> OnClosed;

		public void Awake()
		{
			instance = this;
			OnChatReceived += HandleChatMessage;
			OnCommandReceived += HandleCommands;
			OnError += HandleError;
			OnClosed += DiscordBotPlugin.LogDebug;
			OnConnected += delegate
			{
				DiscordBotPlugin.LogDebug("Connected to discord gateway");
			};
			OnDisconnected += delegate
			{
				DiscordBotPlugin.LogDebug("Disconnected from discord gateway");
			};
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		private static void HandleError(string message)
		{
			if (DiscordBotPlugin.LogErrors)
			{
				DiscordBotPlugin.LogWarning(message);
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		private static void HandleChatMessage(Message message)
		{
			Discord.instance?.BroadcastMessage(message.author?.GetDisplayName() ?? "", message.content ?? "");
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				Discord.DisplayChatMessage(message.author?.GetDisplayName() ?? "", message?.content ?? "");
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		private static void HandleCommands(Message message)
		{
			if (message.content != null)
			{
				string[] array = message.content.Split(new char[1] { ' ' });
				string text = array[0].Trim();
				if (!DiscordCommands.m_commands.TryGetValue(text, out var value))
				{
					Discord.instance?.SendMessage(Webhook.Commands, ZNet.instance.GetWorldName(), "Failed to find command: " + text);
				}
				else if (!value.IsAllowed(message.author?.GetFullUsername() ?? ""))
				{
					Discord.instance?.SendMessage(Webhook.Commands, ZNet.instance.GetWorldName(), message.author?.GetFullUsername() + " not allowed to use command: " + text);
				}
				else
				{
					value.Run(array);
				}
			}
		}

		public void TriggerProcessing()
		{
			if (!isSending && messageQueue.Count > 0)
			{
				isSending = true;
				((MonoBehaviour)this).StartCoroutine(ProcessMessageQueue());
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		private IEnumerator ProcessMessageQueue()
		{
			while (messageQueue.Count > 0 && isConnected)
			{
				object message = messageQueue.Dequeue();
				yield return SendGatewayMessage(message);
				yield return processMessageRate;
			}
			isSending = false;
		}

		private void Start()
		{
			if (string.IsNullOrEmpty(DiscordBotPlugin.BOT_TOKEN))
			{
				DiscordBotPlugin.LogWarning("Bot token not set");
			}
			else
			{
				((MonoBehaviour)this).StartCoroutine(InitializeGateway());
			}
		}

		private void OnDestroy()
		{
			shouldReconnect = false;
			DisconnectWebSocket();
			instance = null;
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		private IEnumerator InitializeGateway()
		{
			if (isConnecting || isConnected)
			{
				yield break;
			}
			isConnecting = true;
			UnityWebRequest request = UnityWebRequest.Get("https://discord.com/api/v10/gateway/bot");
			try
			{
				request.SetRequestHeader("Authorization", "Bot " + DiscordBotPlugin.BOT_TOKEN);
				request.SetRequestHeader("Content-Type", "application/json");
				yield return request.SendWebRequest();
				if ((int)request.result == 1)
				{
					JObject response = JObject.Parse(request.downloadHandler.text);
					gatewayUrl = ((object)response["url"])?.ToString() ?? string.Empty;
					if (!string.IsNullOrEmpty(gatewayUrl))
					{
						gatewayUrl += "/?v=10&encoding=json";
						yield return ((MonoBehaviour)this).StartCoroutine(ConnectToGateway());
					}
					else
					{
						this.OnError?.Invoke("Failed to get gateway URL");
						isConnecting = false;
					}
				}
				else
				{
					this.OnError?.Invoke("Failed to get gateway URL: " + request.error);
					isConnecting = false;
					yield return retryConnectionDelay;
					if (shouldReconnect)
					{
						((MonoBehaviour)this).StartCoroutine(InitializeGateway());
					}
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		private IEnumerator ConnectToGateway()
		{
			websocket = new ClientWebSocket();
			cancellationTokenSource = new CancellationTokenSource();
			Task connectTask = websocket.ConnectAsync(new Uri(gatewayUrl ?? ""), cancellationTokenSource.Token);
			yield return (object)new WaitUntil((Func<bool>)(() => connectTask.IsCompleted));
			if (connectTask.Status == TaskStatus.RanToCompletion)
			{
				isConnected = true;
				isConnecting = false;
				((MonoBehaviour)this).StartCoroutine(ListenForMessages());
			}
			else if (connectTask.Status == TaskStatus.Canceled)
			{
				this.OnClosed?.Invoke("Connection task canceled");
				isConnecting = false;
			}
			else if (connectTask.Status == TaskStatus.Faulted)
			{
				this.OnError?.Invoke("Failed to connect: " + connectTask.Exception?.GetBaseException().Message);
				isConnecting = false;
				if (shouldReconnect)
				{
					((MonoBehaviour)this).StartCoroutine(ReconnectAfterDelay());
				}
			}
			else
			{
				this.OnError?.Invoke("Failed to connect: " + connectTask.Exception?.GetBaseException().Message);
				isConnecting = false;
			}
		}

		[<a3c84666-66ef-4ed1-accf-6c30be1c4e69>NullableContext(1)]
		private IEnumerator ListenForMessages()
		{
			byte[] buffer =