Decompiled source of DiscordBot v1.2.5
DiscordBot.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
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 DiscordBot.Notices; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using uGIF; [assembly: ComVisible(false)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyTrademark("")] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("DiscordBot")] [assembly: AssemblyDescription("")] [assembly: AssemblyFileVersion("1.2.5")] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyCompany("RustyMods")] [assembly: AssemblyProduct("DiscordBot")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyConfiguration("")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.5.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<96ea2e4e-1d9f-4d65-9323-a43f017d41b6>Embedded] internal sealed class <96ea2e4e-1d9f-4d65-9323-a43f017d41b6>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<96ea2e4e-1d9f-4d65-9323-a43f017d41b6>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <239e2483-84fb-4479-8c52-efd07452cd88>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <239e2483-84fb-4479-8c52-efd07452cd88>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <239e2483-84fb-4479-8c52-efd07452cd88>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [<96ea2e4e-1d9f-4d65-9323-a43f017d41b6>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContextAttribute : Attribute { public readonly byte Flag; public <8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace uGIF { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] 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]); } } } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] 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(Color32[] pixels, int width, int height) { this.pixels = pixels; this.width = width; this.height = 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)); } } [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>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); } } } [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] 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 { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [PublicAPI] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>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; [<239e2483-84fb-4479-8c52-efd07452cd88>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([<8463bf94-2e6d-4e2f-af82-7033db72bcef>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, [<8463bf94-2e6d-4e2f-af82-7033db72bcef>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, [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null) { if (convertConfigValue == null) { convertConfigValue = [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] [return: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += [<8463bf94-2e6d-4e2f-af82-7033db72bcef>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: <239e2483-84fb-4479-8c52-efd07452cd88>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; } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(2)] public static byte[] ReadEmbeddedFileBytes([<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] string resourceFileName, Assembly containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<8463bf94-2e6d-4e2f-af82-7033db72bcef>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 { [PublicAPI] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public static class API { public static List<Action> m_queue = new List<Action>(); public static void RegisterCommand(string command, string description, [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1, 1 })] Action<string[]> action, [<239e2483-84fb-4479-8c52-efd07452cd88>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); } return; } m_queue.Add(delegate { if (!DiscordCommands.m_commands.ContainsKey(command)) { new DiscordCommands.DiscordCommand(command, description, action, reaction, adminOnly, isSecret, 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); } } [PublicAPI] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] public static class DiscordBot_API { [<239e2483-84fb-4479-8c52-efd07452cd88>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>(); [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] private readonly MethodInfo info; [return: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 1, 2 })] public object[] Invoke([<239e2483-84fb-4479-8c52-efd07452cd88>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, [<239e2483-84fb-4479-8c52-efd07452cd88>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, [<239e2483-84fb-4479-8c52-efd07452cd88>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); } } [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] 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 } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [BepInPlugin("RustyMods.DiscordBot", "DiscordBot", "1.2.5")] public class DiscordBotPlugin : BaseUnityPlugin { [<239e2483-84fb-4479-8c52-efd07452cd88>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([<8463bf94-2e6d-4e2f-af82-7033db72bcef>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); } } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>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; } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] public sealed override string ToString() { return $"{width}x{height}"; } } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order = null; [UsedImplicitly] public bool? Browsable = null; [UsedImplicitly] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] public string Category = null; [UsedImplicitly] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] public Action<ConfigEntryBase> CustomDrawer = null; } internal const string ModName = "DiscordBot"; internal const string ModVersion = "1.2.5"; 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; public static readonly Dir directory; public static DiscordBotPlugin m_instance; private static ConfigEntry<Toggle> _serverConfigLocked; private static ConfigEntry<string> m_startWorldHook; private static ConfigEntry<string> m_saveWebhook; private static ConfigEntry<string> m_shutdownWebhook; private static ConfigEntry<string> m_loginWebhook; private static ConfigEntry<string> m_logoutWebhook; private static ConfigEntry<string> m_eventWebhook; private static ConfigEntry<string> m_newDayWebhook; 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<Toggle> m_eventNotice; private static ConfigEntry<Toggle> m_newDayNotice; private static ConfigEntry<Toggle> m_coordinateDetails; 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<Toggle> m_screenshotGif; private static ConfigEntry<int> m_gifFPS; private static ConfigEntry<float> m_gifDuration; private static ConfigEntry<string> m_gifResolution; private static ConfigEntry<KeyCode> m_selfieKey; private static ConfigEntry<AIService> m_aiService; private static ConfigEntry<string> m_chatGPTAPIKEY; private static ConfigEntry<string> m_geminiAPIKEY; private static ConfigEntry<string> m_deepSeekAPIKEY; private static ConfigEntry<string> m_openRouterAPIKEY; private static ConfigEntry<OpenRouterModel> m_openRouterModel; private static ConfigEntry<Toggle> m_enableJobs; 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 bool ShowEvent => m_eventNotice.Value == Toggle.On; public static bool ShowNewDay => m_newDayNotice.Value == Toggle.On; public static bool ShowCoordinates => m_coordinateDetails.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 KeyCode SelfieKey => m_selfieKey.Value; public static AIService AIService => m_aiService.Value; public static string ChatGPT_KEY => m_chatGPTAPIKEY.Value; public static string Gemini_KEY => m_geminiAPIKEY.Value; public static string DeepSeek_KEY => m_deepSeekAPIKEY.Value; public static string OpenRouter_KEY => m_openRouterAPIKEY.Value; public static OpenRouterModel OpenRouterModel => m_openRouterModel.Value; public static List<string> OnWorldStartHooks => Utility.IsNullOrWhiteSpace(m_startWorldHook.Value) ? new List<string>() : new StringListConfig(m_startWorldHook.Value).list; public static List<string> OnWorldSaveHooks => Utility.IsNullOrWhiteSpace(m_saveWebhook.Value) ? new List<string>() : new StringListConfig(m_saveWebhook.Value).list; public static List<string> OnWorldShutdownHooks => Utility.IsNullOrWhiteSpace(m_shutdownWebhook.Value) ? new List<string>() : new StringListConfig(m_shutdownWebhook.Value).list; public static List<string> OnLoginHooks => Utility.IsNullOrWhiteSpace(m_loginWebhook.Value) ? new List<string>() : new StringListConfig(m_loginWebhook.Value).list; public static List<string> OnLogoutHooks => Utility.IsNullOrWhiteSpace(m_logoutWebhook.Value) ? new List<string>() : new StringListConfig(m_logoutWebhook.Value).list; public static List<string> OnEventHooks => Utility.IsNullOrWhiteSpace(m_eventWebhook.Value) ? new List<string>() : new StringListConfig(m_eventWebhook.Value).list; public static List<string> OnNewDayHooks => Utility.IsNullOrWhiteSpace(m_newDayWebhook.Value) ? new List<string>() : new StringListConfig(m_newDayWebhook.Value).list; public static bool JobsEnabled => m_enableJobs.Value == Toggle.On; 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 static void LogError(string message) { DiscordBotLogger.LogError((object)message); } public void Awake() { //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Expected O, but got Unknown //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Expected O, but got Unknown //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Expected O, but got Unknown //IL_0400: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Expected O, but got Unknown //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Expected O, but got Unknown //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Expected O, but got Unknown //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Expected O, but got Unknown //IL_058e: Unknown result type (might be due to invalid IL or missing references) //IL_0599: Expected O, but got Unknown //IL_05d9: Unknown result type (might be due to invalid IL or missing references) //IL_05e4: Expected O, but got Unknown //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Expected O, but got Unknown //IL_066f: Unknown result type (might be due to invalid IL or missing references) //IL_067a: Expected O, but got Unknown //IL_06ba: Unknown result type (might be due to invalid IL or missing references) //IL_06c5: Expected O, but got Unknown //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_0710: 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, caught errors will log to console"); 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_eventNotice = config("2 - Notifications", "Random Events", Toggle.On, "If on, bot will send message when random event starts"); m_newDayNotice = config("2 - Notifications", "New Day", Toggle.Off, "If on, bot will send message when a new day begins"); m_coordinateDetails = config("2 - Notifications", "Show Coordinates", Toggle.On, "If on, coordinates will be added to login/logout notifications"); 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_enableJobs = config("4 - Commands", "Jobs", Toggle.On, "If on, jobs are enabled"); 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(800, 600); Resolution resolution2 = new Resolution(960, 540); Resolution resolution3 = new Resolution(1280, 720); Resolution resolution4 = new Resolution(1920, 1080); m_screenshotResolution = config("6 - Death Feed", "Screenshot Resolution", resolution2.ToString(), new ConfigDescription("Set resolution", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { resolution.ToString(), resolution2.ToString(), resolution3.ToString(), resolution4.ToString() }), Array.Empty<object>()), synchronizedSetting: false); 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 resolution5 = new Resolution(256, 144); Resolution resolution6 = new Resolution(320, 180); Resolution resolution7 = new Resolution(480, 270); Resolution resolution8 = new Resolution(640, 360); m_gifResolution = config("6 - Death Feed", "GIF Resolution", resolution7.ToString(), new ConfigDescription("Set resolution", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { resolution5.ToString(), resolution6.ToString(), resolution7.ToString(), resolution8.ToString() }), Array.Empty<object>()), synchronizedSetting: false); m_selfieKey = config<KeyCode>("1 - General", "Selfie", (KeyCode)0, "Hotkey to take selfie and send to discord", synchronizedSetting: false); m_startWorldHook = config("7 - Webhooks", "On World Start", "", new ConfigDescription("If empty, will use default notification webhook", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_saveWebhook = config("7 - Webhooks", "On World Save", "", new ConfigDescription("If empty, will use default notification webhook", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_shutdownWebhook = config("7 - Webhooks", "On World Shutdown", "", new ConfigDescription("If empty, will use default notification webhook", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_loginWebhook = config("7 - Webhooks", "On Login", "", new ConfigDescription("If empty, will use default notification webhook", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_logoutWebhook = config("7 - Webhooks", "On Logout", "", new ConfigDescription("If empty, will use default notification webhook", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_eventWebhook = config("7 - Webhooks", "On Event", "", new ConfigDescription("If empty, will use default notification webhook", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_newDayWebhook = config("7 - Webhooks", "On New Day", "", new ConfigDescription("If empty, will use default notification webhook", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_aiService = config("8 - AI", "Provider", AIService.Gemini, "Set which Artificial Intelligence API to use", synchronizedSetting: false); m_chatGPTAPIKEY = config("8 - AI", "ChatGPT", "", "Set ChatGPT key", synchronizedSetting: false); m_geminiAPIKEY = config("8 - AI", "Gemini", "", "Set Gemini key", synchronizedSetting: false); m_deepSeekAPIKEY = config("8 - AI", "DeepSeek", "", "Set DeepSeek key", synchronizedSetting: false); m_openRouterAPIKEY = config("8 - AI", "OpenRouter", "", "Set OpenRouter key", synchronizedSetting: false); m_openRouterModel = config("8 - AI", "OpenRouter Model", OpenRouterModel.Claude3_5Sonnet, "Set OpenRouter Model", synchronizedSetting: false); 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<[<239e2483-84fb-4479-8c52-efd07452cd88>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<[<239e2483-84fb-4479-8c52-efd07452cd88>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.2.5", MinimumRequiredVersion = "1.2.5" }; directory = new Dir(Paths.ConfigPath, "DiscordBot"); m_instance = null; _serverConfigLocked = null; m_startWorldHook = null; m_saveWebhook = null; m_shutdownWebhook = null; m_loginWebhook = null; m_logoutWebhook = null; m_eventWebhook = null; m_newDayWebhook = null; m_notificationWebhookURL = null; m_serverStartNotice = null; m_serverStopNotice = null; m_serverSaveNotice = null; m_deathNotice = null; m_loginNotice = null; m_logoutNotice = null; m_eventNotice = null; m_newDayNotice = null; m_coordinateDetails = 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_screenshotGif = null; m_gifFPS = null; m_gifDuration = null; m_gifResolution = null; m_selfieKey = null; m_aiService = null; m_chatGPTAPIKEY = null; m_geminiAPIKEY = null; m_deepSeekAPIKEY = null; m_openRouterAPIKEY = null; m_openRouterModel = null; m_enableJobs = null; resolutions = new Dictionary<string, Resolution>(); } } public enum AIService { ChatGPT, Gemini, DeepSeek, OpenRouter } [PublicAPI] public enum GPTModel { [InternalName("gpt-3.5-turbo")] Turbo, [InternalName("gpt-4o")] GPT4o, [InternalName("gpt-4o-mini")] GPT4oMini, [InternalName("gpt-4.1")] GPT4_1 } [PublicAPI] public enum GeminiModel { [InternalName("gemini-2.0-flash")] Flash2_0, [InternalName("gemini-2.5-flash")] Flash2_5, [InternalName("gemini-2.5-pro")] Pro2_5 } [PublicAPI] public enum DeepSeekModel { [InternalName("deepseek-chat")] Chat, [InternalName("deepseek-reasoner")] Reasoner } [PublicAPI] public enum OpenRouterModel { [InternalName("anthropic/claude-3.5-sonnet")] Claude3_5Sonnet, [InternalName("google/gemini-2.0-flash-exp:free")] GeminiFlashFree, [InternalName("meta-llama/llama-4-maverick:free")] Llama4_Maverick, [InternalName("microsoft/wizardlm-2-8x22b")] WizardLM8x22B, [InternalName("openai/gpt-4o-mini")] GPT4oMini, [InternalName("deepseek/deepseek-chat")] DeepSeekChat, [InternalName("nousresearch/hermes-3-llama-3.1-405b:free")] Hermes3_Llama31_405b } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class InternalName : Attribute { public readonly string internalName; public InternalName(string internalName) { this.internalName = internalName; } } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class ChatAI : MonoBehaviour { [HarmonyPatch(typeof(Terminal), "UpdateChat")] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] private static class Terminal_UpdateChat_Patch { [UsedImplicitly] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] private static void Postfix(Terminal __instance) { if (!((Object)(object)__instance != (Object)(object)Chat.instance) && Object.op_Implicit((Object)(object)instance)) { instance.tempChat = ((TMP_Text)__instance.m_output).text; } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] private static class ZNet_OnNewConnection_Patch { [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [UsedImplicitly] private static void Postfix(ZNetPeer peer) { peer.m_rpc.Register<string, string>("RPC_ChatAIMessage", (Action<ZRpc, string, string>)RPC_ChatAIMessage); } } [Serializable] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class GPTRequest { public string model = "gpt-4o-mini"; public List<GPTMessage> messages = new List<GPTMessage>(); } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GPTResponse { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public GPTChoice[] choices; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GPTChoice { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public GPTMessage message; } [Serializable] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class GPTMessage { public string role; public string content; public GPTMessage() { } public GPTMessage(string role, string content) { this.role = role; this.content = content; } } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GeminiRequest { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public List<GeminiContent> contents = new List<GeminiContent>(); } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GeminiContent { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public List<GeminiPart> parts; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GeminiPart { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public string text; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GeminiResponse { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public GeminiCandidate[] candidates; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] public GeminiUsageMetadata UsageMetadata; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GeminiUsageMetadata { public int promptTokenCount; public int candidatesTokenCount; public int totalTokenCount; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class GeminiCandidate { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public GeminiContent content; } [Serializable] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class DeepSeekRequest { public string model = "deepseek-chat"; public List<DeepSeekMessage> messages = new List<DeepSeekMessage>(); public bool stream = false; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class DeepSeekResponse { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public DeepSeekChoice[] choices; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class DeepSeekChoice { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public DeepSeekMessage message; } [Serializable] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class DeepSeekMessage { public string role; public string content; public DeepSeekMessage() { } public DeepSeekMessage(string role, string content) { this.role = role; this.content = content; } } [Serializable] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class OpenRouterRequest { public string model = "anthropic/claude-3.5-sonnet"; public List<OpenRouterMessage> messages = new List<OpenRouterMessage>(); public bool stream = false; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class OpenRouterResponse { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public OpenRouterChoice[] choices; } [Serializable] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] public class OpenRouterChoice { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(1)] public OpenRouterMessage message; } [Serializable] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class OpenRouterMessage { public string role; public string content; public OpenRouterMessage() { } public OpenRouterMessage(string role, string content) { this.role = role; this.content = content; } } [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] public static ChatAI instance; public bool isThinking; public int ellipsesCount; public float ellipsesTimer; public string tempChat = ""; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] [method: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] [field: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] public event Action<string> OnResponse; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] [method: <8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(2)] [field: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] public event Action<int, int, int> OnMetadata; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] [method: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] [field: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] public event Action<string> OnError; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] [method: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] [field: <239e2483-84fb-4479-8c52-efd07452cd88>Nullable(new byte[] { 2, 1 })] public event Action<string> OnDeathQuip; public void BroadcastMessage(string username, string message) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { peer.m_rpc.Invoke("RPC_ChatAIMessage", new object[2] { username, message }); } } public static void RPC_ChatAIMessage(ZRpc rpc, string username, string message) { DisplayChatMessage(username, message); } private static void DisplayChatMessage(string username, string message) { string text = "</color><color=orange>" + username + "</color>: " + message; ((Terminal)Chat.instance).AddString(text); Chat.instance.Show(); } public void Awake() { instance = this; OnResponse += HandleResponse; OnError += HandleError; OnDeathQuip += HandleDeathQuip; OnMetadata += HandleMetadata; } public void Update() { if (!Object.op_Implicit((Object)(object)Chat.instance) || !isThinking) { return; } ellipsesTimer += Time.deltaTime; if (!(ellipsesTimer < 0.5f)) { ellipsesTimer = 0f; if (ellipsesCount > 3) { ellipsesCount = 0; } ellipsesCount++; ((TMP_Text)((Terminal)Chat.instance).m_output).text = tempChat + new string('.', ellipsesCount); } } public void OnDestroy() { instance = null; } public void HandleResponse(string response) { ((Terminal)Chat.instance).AddString($"<color=orange>[{DiscordBotPlugin.AIService}]</color>: {response}"); Chat.instance.Show(); BroadcastMessage($"[{DiscordBotPlugin.AIService}]", response); Discord.instance?.SendMessage(Webhook.Chat, DiscordBotPlugin.AIService.ToString(), response); } public void HandleMetadata(int promptTokenCount, int candidatesTokenCount, int totalTokenCount) { string message = $"Prompt Token Count: {promptTokenCount}; Candidates Token Count: {candidatesTokenCount}; Total Token Count: {totalTokenCount}"; DiscordBotPlugin.LogDebug(message); } public void HandleError(string error) { DiscordBotPlugin.LogError(error); } public void HandleDeathQuip(string quip) { if (Object.op_Implicit((Object)(object)Screenshot.instance)) { Screenshot.instance.message = quip; } if (Object.op_Implicit((Object)(object)Recorder.instance)) { Recorder.instance.message = quip; } } public void Ask(string prompt, bool deathQuip = false) { switch (DiscordBotPlugin.AIService) { case AIService.ChatGPT: AskOpenAI(prompt, deathQuip); break; case AIService.Gemini: AskGemini(prompt, deathQuip); break; case AIService.DeepSeek: AskDeepSeek(prompt, deathQuip); break; case AIService.OpenRouter: AskOpenRouter(prompt, deathQuip); break; } } public static bool HasKey() { AIService aIService = DiscordBotPlugin.AIService; if (1 == 0) { } bool result = aIService switch { AIService.ChatGPT => !string.IsNullOrEmpty(DiscordBotPlugin.ChatGPT_KEY), AIService.Gemini => !string.IsNullOrEmpty(DiscordBotPlugin.Gemini_KEY), AIService.DeepSeek => !string.IsNullOrEmpty(DiscordBotPlugin.DeepSeek_KEY), AIService.OpenRouter => !string.IsNullOrEmpty(DiscordBotPlugin.OpenRouter_KEY), _ => false, }; if (1 == 0) { } return result; } public void AskOpenAI(string prompt, bool deathQuip = false) { if (string.IsNullOrEmpty(DiscordBotPlugin.ChatGPT_KEY)) { this.OnError?.Invoke("OpenAI API token not set"); } else { ((MonoBehaviour)this).StartCoroutine(PromptOpenAI(DiscordBotPlugin.ChatGPT_KEY, prompt, deathQuip)); } } public void AskGemini(string prompt, bool deathQuip = false) { if (string.IsNullOrEmpty(DiscordBotPlugin.Gemini_KEY)) { this.OnError?.Invoke("Gemini API token not set"); } else { ((MonoBehaviour)this).StartCoroutine(PromptGemini(DiscordBotPlugin.Gemini_KEY, prompt, deathQuip)); } } public void AskDeepSeek(string prompt, bool deathQuip = false) { if (string.IsNullOrEmpty(DiscordBotPlugin.DeepSeek_KEY)) { this.OnError?.Invoke("DeepSeek API token not set"); } else { ((MonoBehaviour)this).StartCoroutine(PromptDeepSeek(DiscordBotPlugin.DeepSeek_KEY, prompt, deathQuip)); } } public void AskOpenRouter(string prompt, bool deathQuip = false) { if (string.IsNullOrEmpty(DiscordBotPlugin.OpenRouter_KEY)) { this.OnError?.Invoke("OpenRouter API token not set"); } else { ((MonoBehaviour)this).StartCoroutine(PromptOpenRouter(DiscordBotPlugin.OpenRouter_KEY, prompt, deathQuip)); } } private IEnumerator PromptOpenAI(string apiKey, string prompt, bool deathQuip) { isThinking = true; string json = JsonConvert.SerializeObject((object)new GPTRequest { model = Utils.GetAttributeOfType<InternalName>((Enum)GPTModel.Turbo).internalName, messages = { new GPTMessage("user", prompt) } }); byte[] body = Encoding.UTF8.GetBytes(json); UnityWebRequest request = new UnityWebRequest("https://api.openai.com/v1/chat/completions", "POST"); try { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(body); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Authorization", "Bearer " + apiKey); yield return request.SendWebRequest(); isThinking = false; if ((int)request.result != 1) { this.OnError?.Invoke("Failed to prompt gpt: " + request.error); } else { ParseGPTResponse(request.downloadHandler.text, deathQuip); } } finally { ((IDisposable)request)?.Dispose(); } } public void ParseGPTResponse(string json, bool deathQuip) { GPTResponse gPTResponse = JsonConvert.DeserializeObject<GPTResponse>(json); if (gPTResponse == null) { this.OnError?.Invoke("Failed to parse response"); return; } string obj = gPTResponse.choices[0].message.content.Trim(); if (!deathQuip) { this.OnResponse?.Invoke(obj); } else { this.OnDeathQuip?.Invoke(obj); } } private IEnumerator PromptGemini(string apiKey, string prompt, bool deathQuip) { isThinking = true; string model = Utils.GetAttributeOfType<InternalName>((Enum)GeminiModel.Flash2_0).internalName; string url = "https://generativelanguage.googleapis.com/v1beta/models/" + model + ":generateContent?key=" + apiKey; string json = JsonConvert.SerializeObject((object)new GeminiRequest { contents = { new GeminiContent { parts = new List<GeminiPart> { new GeminiPart { text = prompt } } } } }); byte[] body = Encoding.UTF8.GetBytes(json); UnityWebRequest request = new UnityWebRequest(url, "POST"); try { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(body); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); yield return request.SendWebRequest(); isThinking = false; if ((int)request.result != 1) { this.OnError?.Invoke("Failed to prompt Gemini: " + request.error); this.OnError?.Invoke("Response: " + request.downloadHandler.text); } else { ParseGeminiResponse(request.downloadHandler.text, deathQuip); } } finally { ((IDisposable)request)?.Dispose(); } } public void ParseGeminiResponse(string json, bool deathQuip) { GeminiResponse geminiResponse = JsonConvert.DeserializeObject<GeminiResponse>(json); if (geminiResponse?.candidates == null || geminiResponse.candidates.Length == 0) { this.OnError?.Invoke("Failed to parse gemini response"); return; } string obj = geminiResponse.candidates[0].content.parts[0].text.Trim(); if (geminiResponse.UsageMetadata != null) { this.OnMetadata?.Invoke(geminiResponse.UsageMetadata.promptTokenCount, geminiResponse.UsageMetadata.candidatesTokenCount, geminiResponse.UsageMetadata.totalTokenCount); } if (deathQuip) { this.OnDeathQuip?.Invoke(obj); } else { this.OnResponse?.Invoke(obj); } } private IEnumerator PromptDeepSeek(string apiKey, string prompt, bool deathQuip) { isThinking = true; string json = JsonConvert.SerializeObject((object)new DeepSeekRequest { model = Utils.GetAttributeOfType<InternalName>((Enum)DeepSeekModel.Chat).internalName, messages = { new DeepSeekMessage("user", prompt) } }); byte[] body = Encoding.UTF8.GetBytes(json); UnityWebRequest request = new UnityWebRequest("https://api.deepseek.com/chat/completions", "POST"); try { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(body); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Authorization", "Bearer " + apiKey); yield return request.SendWebRequest(); isThinking = false; if ((int)request.result != 1) { this.OnError?.Invoke("Failed to prompt DeepSeek: " + request.error); this.OnError?.Invoke("Response: " + request.downloadHandler.text); } else { ParseDeepSeekResponse(request.downloadHandler.text, deathQuip); } } finally { ((IDisposable)request)?.Dispose(); } } public void ParseDeepSeekResponse(string json, bool deathQuip) { DeepSeekResponse deepSeekResponse = JsonConvert.DeserializeObject<DeepSeekResponse>(json); if (deepSeekResponse?.choices == null || deepSeekResponse.choices.Length == 0) { this.OnError?.Invoke("Failed to parse DeepSeek response"); return; } string obj = deepSeekResponse.choices[0].message.content.Trim(); if (deathQuip) { this.OnDeathQuip?.Invoke(obj); } else { this.OnResponse?.Invoke(obj); } } private IEnumerator PromptOpenRouter(string apiKey, string prompt, bool deathQuip) { isThinking = true; string json = JsonConvert.SerializeObject((object)new OpenRouterRequest { model = Utils.GetAttributeOfType<InternalName>((Enum)DiscordBotPlugin.OpenRouterModel).internalName, messages = { new OpenRouterMessage("user", prompt) } }); byte[] body = Encoding.UTF8.GetBytes(json); UnityWebRequest request = new UnityWebRequest("https://openrouter.ai/api/v1/chat/completions", "POST"); try { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(body); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Authorization", "Bearer " + apiKey); request.SetRequestHeader("HTTP-Referer", "https://github.com/RustyMods/DiscordBot"); request.SetRequestHeader("X-Title", "DiscordBot"); yield return request.SendWebRequest(); isThinking = false; if ((int)request.result != 1) { this.OnError?.Invoke("Failed to prompt OpenRouter: " + request.error); this.OnError?.Invoke("Response: " + request.downloadHandler.text); } else { ParseOpenRouterResponse(request.downloadHandler.text, deathQuip); } } finally { ((IDisposable)request)?.Dispose(); } } public void ParseOpenRouterResponse(string json, bool deathQuip) { OpenRouterResponse openRouterResponse = JsonConvert.DeserializeObject<OpenRouterResponse>(json); if (openRouterResponse?.choices == null || openRouterResponse.choices.Length == 0) { this.OnError?.Invoke("Failed to parse OpenRouter response"); return; } string obj = openRouterResponse.choices[0].message.content.Trim(); if (deathQuip) { this.OnDeathQuip?.Invoke(obj); } else { this.OnResponse?.Invoke(obj); } } } public static class ColorExtensions { public static Color Blurple => new Color(0.36f, 0.47f, 1f); public static Color SoftBlue => new Color(0.25f, 0.55f, 0.95f); public static Color MutedBlue => new Color(0.32f, 0.78f, 0.85f); public static Color Purple => new Color(0.64f, 0.43f, 0.95f); public static Color SlateGray => new Color(0.22f, 0.25f, 0.3f); public static Color VibrantOrange => new Color(1f, 0.55f, 0.25f); public static Color CoolGray => new Color(0.45f, 0.52f, 0.6f); } [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] public class Recorder : MonoBehaviour { [Header("Discord message")] private string playerName = string.Empty; public string message = string.Empty; private string thumbnail = string.Empty; [Header("GIF Settings")] private readonly List<Image> recordedImages = new List<Image>(); private bool isRecording; private float recordStartTime; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] private Coroutine recordingCoroutine; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] private byte[] gifBytes; [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] public static Recorder instance; private static Camera camera => Utils.GetMainCamera(); 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() { instance = this; } public void OnDestroy() { instance = 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 IEnumerator Record() { Screenshot.instance?.HideHud(); float interval = 1f / (float)fps; while (isRecording && Time.time - recordStartTime < recordDuration) { yield return (object)new WaitForEndOfFrame(); Image img = new Image(ScreenCapture.CaptureScreenshotAsTexture()); recordedImages.Add(img); yield return (object)new WaitForSeconds(interval); } isRecording = false; Screenshot.instance?.ShowHud(); Thread thread = new Thread(CreateGif); thread.Start(); ((MonoBehaviour)this).StartCoroutine(WaitForBytes()); } private IEnumerator WaitForBytes() { while (gifBytes == null) { yield return null; } SendGif(gifBytes); Cleanup(); } public void Cleanup() { recordedImages.Clear(); 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 (Image recordedImage in recordedImages) { recordedImage.ResizeBilinear(gifWidth, gifHeight); recordedImage.Flip(); gIFEncoder.AddFrame(recordedImage); } gIFEncoder.Finish(); gifBytes = memoryStream.ToArray(); memoryStream.Close(); } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(2)] private void SendGif(byte[] bytes) { if (bytes == null || bytes.Length == 0) { DiscordBotPlugin.LogWarning("GIF bytes are null or empty"); } else { Discord.instance?.SendGifMessage(Webhook.DeathFeed, playerName, message, bytes, $"{DateTime.UtcNow:yyyyMMdd_HHmmss}.gif", "", thumbnail); } } } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(0)] public class Screenshot : MonoBehaviour { [<239e2483-84fb-4479-8c52-efd07452cd88>Nullable(2)] public static Screenshot instance; private Texture2D recordedFrame = null; private bool isCapturing; [Header("Discord message")] private string playerName = string.Empty; public string message = string.Empty; private string thumbnail = string.Empty; private GameObject m_chatWindow = null; [Header("Screenshot Settings")] private static int width => DiscordBotPlugin.ScreenshotResolution.width; private static int height => DiscordBotPlugin.ScreenshotResolution.height; public void Awake() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown instance = this; recordedFrame = new Texture2D(width, height, (TextureFormat)3, false); } public void Start() { m_chatWindow = ((Component)((Transform)((Terminal)Chat.instance).m_chatWindow).Find("root")).gameObject; } public void Update() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((int)DiscordBotPlugin.SelfieKey != 0 && Input.GetKey(DiscordBotPlugin.SelfieKey) && !isCapturing) { StartSelfie(); } } public void OnDestroy() { instance = null; } private IEnumerator DelayedCaptureFrame() { HideHud(); yield return (object)new WaitForSeconds(DiscordBotPlugin.ScreenshotDelay); yield return (object)new WaitForEndOfFrame(); Texture2D frame = ScreenCapture.CaptureScreenshotAsTexture(); ShowHud(); try { Image img = new Image(frame); img.ResizeBilinear(width, height); recordedFrame.Reinitialize(width, height); recordedFrame.SetPixels32(img.pixels); recordedFrame.Apply(); } catch (Exception ex) { DiscordBotPlugin.LogWarning("Failed to resize recorded frame: " + ex.Message); isCapturing = false; yield break; } byte[] bytes = ImageConversion.EncodeToPNG(recordedFrame); if (bytes == null || bytes.Length == 0) { DiscordBotPlugin.LogWarning("Failed to encode recorded frame"); isCapturing = false; } else { SendToDiscord(bytes); isCapturing = false; } } 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 HideHud() { Hud.instance.m_userHidden = true; Hud.instance.m_hudPressed = 0f; m_chatWindow.SetActive(false); ((Component)Console.instance).gameObject.SetActive(false); } public void ShowHud() { Hud.instance.m_userHidden = false; Hud.instance.m_hudPressed = 0f; m_chatWindow.SetActive(true); ((Component)Console.instance).gameObject.SetActive(true); } private IEnumerator DelayedSelfie() { HideHud(); yield return (object)new WaitForSeconds(DiscordBotPlugin.ScreenshotDelay); yield return (object)new WaitForEndOfFrame(); Texture2D frame = ScreenCapture.CaptureScreenshotAsTexture(); ShowHud(); try { Image img = new Image(frame); img.ResizeBilinear(width, height); recordedFrame.Reinitialize(width, height); recordedFrame.SetPixels32(img.pixels); recordedFrame.Apply(); } catch (Exception ex) { DiscordBotPlugin.LogWarning("Failed to resize recorded frame: " + ex.Message); isCapturing = false; yield break; } byte[] bytes = ImageConversion.EncodeToPNG(recordedFrame); if (bytes == null || bytes.Length == 0) { DiscordBotPlugin.LogWarning("Failed to encode recorded frame"); isCapturing = false; } else { SendSelfieToDiscord(bytes); isCapturing = false; } } public void StartSelfie() { isCapturing = true; ((MonoBehaviour)this).StartCoroutine(DelayedSelfie()); } public void SendToDiscord(byte[] data) { Discord.instance?.SendImageMessage(Webhook.DeathFeed, playerName, message, data, $"{DateTime.UtcNow:yyyyMMdd_HHmmss}.png", "", thumbnail); } public void SendSelfieToDiscord(byte[] bytes) { Discord.instance?.SendImageMessage(Webhook.Chat, Player.m_localPlayer.GetPlayerName(), "Selfie!", bytes, $"{DateTime.UtcNow:yyyyMMdd_HHmmss}.png"); } } [<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(1)] [<239e2483-84fb-4479-8c52-efd07452cd88>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([<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] () => Directory.GetFiles(Path, searchPattern, searchOption)); } public string[] GetDirectories(string searchPattern = "*") { return ExecuteWithRetry([<8463bf94-2e6d-4e2f-af82-7033db72bcef>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([<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] () => File.ReadAllText(fullPath)); } public IEnumerable<string> ReadAllLines(string fileName) { string fullPath = System.IO.Path.Combine(Path, fileName); return ExecuteWithRetry([<8463bf94-2e6d-4e2f-af82-7033db72bcef>NullableContext(0)] () => File.ReadAllLines(fullPath)); } public bool FileExists(string fileName) { string fullPath = System.IO.Path.Combine(Path, fileName); return ExecuteWithRetry(() => File.Exists(f