Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VogsBingoMod v1.4.5
VogsBingoMod.dll
Decompiled a week 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.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using VogsBingoMod.Automarking; using VogsBingoMod.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("VogsBingoMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.4.5.0")] [assembly: AssemblyInformationalVersion("1.4.5+9954ca22630ead0cf920fe4dd8eecc349d919847")] [assembly: AssemblyProduct("VogsBingoMod")] [assembly: AssemblyTitle("VogsBingoMod")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/AtlasOfSouls/VogsBingoMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace VogsBingoMod { internal class AudioHelper : MonoBehaviour { private const int wavHeaderSize = 46; private const int wavSampleRate = 44100; private const int wavLengthToPlayInSeconds = 1; private const int wavChannels = 2; private AudioClip? _teamMarkClip; private AudioClip? _opponentMarkClip; private AudioSource audioSource; private static AudioHelper? _instance; private AudioClip? TeamMarkClip => _teamMarkClip ?? (_teamMarkClip = GetAudioClip("TeamMark.wav")); private AudioClip? OpponentMarkClip => _opponentMarkClip ?? (_opponentMarkClip = GetAudioClip("OpponentMark.wav")); internal static AudioHelper Instance => _instance ?? new AudioHelper(); internal AudioHelper() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown GameObject val = new GameObject(); Object.DontDestroyOnLoad((Object)(object)val); audioSource = val.AddComponent<AudioSource>(); _instance = this; } internal void PlayTeamMarkSound(bool isOneShot = false) { if ((Object)(object)TeamMarkClip != (Object)null) { if (VogsBingoModPlugin.instance.teamMarkSoundsVolume.Value != AudioVolume.Off) { audioSource.volume = (float)VogsBingoModPlugin.instance.teamMarkSoundsVolume.Value / 10f; if (isOneShot) { audioSource.PlayOneShot(TeamMarkClip); } else if ((!audioSource.isPlaying || (Object)(object)audioSource.clip != (Object)(object)TeamMarkClip) && UIHelper.CanPlayGoalMarkSounds) { audioSource.clip = TeamMarkClip; audioSource.Play(); } } } else { VogsBingoModPlugin.LogError("Could not find the audio clip \"TeamMark.wav\"."); } } internal void PlayOpponentMarkSound(bool isOneShot = false) { if ((Object)(object)OpponentMarkClip != (Object)null) { if (VogsBingoModPlugin.instance.opponentMarkSoundsVolume.Value != AudioVolume.Off) { audioSource.volume = (float)VogsBingoModPlugin.instance.opponentMarkSoundsVolume.Value / 10f; if (isOneShot) { audioSource.PlayOneShot(OpponentMarkClip); } else if ((!audioSource.isPlaying || (Object)(object)audioSource.clip != (Object)(object)OpponentMarkClip) && UIHelper.CanPlayGoalMarkSounds) { audioSource.clip = OpponentMarkClip; audioSource.Play(); } } } else { VogsBingoModPlugin.LogError("Could not find the audio clip \"OpponentMark.wav\"."); } } private static AudioClip? GetAudioClip(string fileName) { VogsBingoModPlugin.LogInfo("getting audio clip " + fileName); byte[] resourceAsByteArray = Resources.GetResourceAsByteArray("VogsBingoMod.Assets." + fileName); if (resourceAsByteArray == null) { return null; } float[] array = new float[(resourceAsByteArray.Length - 46) / 4]; int num = 0; for (int i = 46; i < resourceAsByteArray.Length; i += 4) { byte[] array2 = new byte[4] { resourceAsByteArray[i], resourceAsByteArray[i + 1], resourceAsByteArray[i + 2], resourceAsByteArray[i + 3] }; array[num] = BitConverter.ToSingle(array2); num++; } AudioClip val = AudioClip.Create(fileName + "AudioClip", 44100, 2, 44100, false); val.SetData(array, 0); return val; } } internal enum AudioVolume { Off = 0, Low = 3, Medium = 5, High = 7, Max = 10 } internal enum ConnectionState { NotConnected, Connecting, Connected, Disconnecting } internal class Coroutiner : MonoBehaviour { private static GameObject? coroutineObj; private static Coroutiner? coroutineComponent; internal static void CreateCoroutine(IEnumerator enumerator) { if ((Object)(object)coroutineComponent != (Object)null) { ((MonoBehaviour)coroutineComponent).StartCoroutine(enumerator); } else { VogsBingoModPlugin.LogError("Failed to start coroutine."); } } internal static void Initialize() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown coroutineObj = new GameObject("BingoModCoroutineObject"); Object.DontDestroyOnLoad((Object)(object)coroutineObj); coroutineComponent = coroutineObj.AddComponent<Coroutiner>(); } } internal static class JsonHelper { internal static string[] GetNamesFromBoard(string boardJson) { JsonGoal[] array = JsonConvert.DeserializeObject<JsonGoal[]>(boardJson); if (array == null) { return Array.Empty<string>(); } string[] array2 = new string[array.Length]; for (int i = 0; i < array.Length; i++) { int num = int.Parse(array[i].slot.Substring(4)) - 1; array2[num] = array[i].name; } return array2; } internal static int[][] GetColorsFromBoard(string boardJson) { JsonGoal[] array = JsonConvert.DeserializeObject<JsonGoal[]>(boardJson); if (array == null) { return Array.Empty<int[]>(); } int[][] array2 = new int[array.Length][]; for (int i = 0; i < array.Length; i++) { string[] array3 = array[i].colors.Split(" "); if (array3.Length == 1 && array3[0].Equals("blank")) { array2[i] = Array.Empty<int>(); } else { array2[i] = new int[array3.Length]; } for (int j = 0; j < array2[i].Length; j++) { array2[i][j] = GoalColors.NameToID(array3[j]); } } return array2; } internal static string CreateGoalMarkJson(int slotIndex, string roomCode, string color, bool remove, RoomType roomType) { return $"{{\"slot\": {slotIndex}, \"color\": \"{color}\", \"remove_color\": {remove.ToString().ToLower()}, \"room\": \"{roomCode}\"}}"; } internal static string CreateColorSwitchJson(int colorID, string roomCode, RoomType roomType) { return "{\"room\": \"" + roomCode + "\", \"color\": \"" + GoalColors.IDToName(colorID) + "\"}"; } internal static string CreateRevealCardJson(string roomCode) { return "{\"room\": \"" + roomCode + "\"}"; } internal static List<string> GetGoalNamesFromJson(string json) { List<string> list = GetNativeSupportedGoals(json).Keys.ToList(); for (int i = 0; i < list.Count; i++) { list[i] = list[i].ToLower(); } return list; } internal static Dictionary<string, bool> GetNativeSupportedGoals(string json) { Dictionary<string, bool> dictionary = new Dictionary<string, bool>(); JsonSupportedGoal[] array = JsonConvert.DeserializeObject<JsonSupportedGoal[]>(json); for (int i = 0; i < array?.Length; i++) { string key = array[i].name.ToLower(); dictionary.Add(key, array[i].automarking_support); } return dictionary; } } internal class JsonGoalMarkedMessage { public string type = ""; public JsonPlayer player = new JsonPlayer(); public JsonSquare square = new JsonSquare(); public string player_color = ""; public string color = ""; public bool remove = false; public double timestamp = 0.0; public string room = ""; } internal class JsonPlayer { public string uuid = ""; public string name = ""; public string color = ""; public bool is_spectator = false; } internal class JsonSquare { public string name = ""; public string slot = ""; public string colors = ""; } internal class JsonSupportedGoal { public string name = ""; public bool automarking_support = false; } internal class JsonMessageType { public string type = ""; } internal class JsonGoal { public string name = ""; public string slot = ""; public string colors = ""; } internal static class NetworkHandler { private class HttpTaskList : Dictionary<Task<HttpResponseMessage>, CancellationTokenSource> { private bool isExitingRoom = false; internal new void Add(Task<HttpResponseMessage> task, CancellationTokenSource tokenSource) { base.Add(task, tokenSource); Coroutiner.CreateCoroutine(UIHelper.SetConnectionPendingActive_Main(setActive: true)); } internal new bool Remove(Task<HttpResponseMessage> task) { if (ContainsKey(task)) { base[task].Cancel(); base[task].Dispose(); task.Dispose(); bool result = base.Remove(task); Coroutiner.CreateCoroutine(UIHelper.SetConnectionPendingActive_Main(base.Count > 0 || isExitingRoom)); return result; } return false; } internal new void Clear() { using (Dictionary<Task<HttpResponseMessage>, CancellationTokenSource>.Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { KeyValuePair<Task<HttpResponseMessage>, CancellationTokenSource> current = enumerator.Current; current.Value.Cancel(); current.Value.Dispose(); current.Key.Dispose(); } } base.Clear(); Coroutiner.CreateCoroutine(UIHelper.SetConnectionPendingActive_Main(isExitingRoom)); } internal void SetIsExitingRoom(bool isExitingRoom) { this.isExitingRoom = isExitingRoom; if (isExitingRoom) { Coroutiner.CreateCoroutine(UIHelper.SetConnectionPendingActive_Main(setActive: true)); } else { Coroutiner.CreateCoroutine(UIHelper.SetConnectionPendingActive_Main(base.Count > 0)); } } internal void CheckForTimeout() { bool flag = false; foreach (CancellationTokenSource value in base.Values) { if (value.IsCancellationRequested) { flag = true; } } if (flag || (webSocketClient != null && connectState == ConnectionState.Connected && webSocketClient.State != WebSocketState.Open)) { VogsBingoModPlugin.LogInfo("CANCEL REQUESTED"); ForceExitRoomWithDisconnectError(1); } } } private const string startOfBingosyncRoomLink = "https://bingosync.com/room/"; private const string startOfCaravanRoomLink = "https://caravan.kobold60.com/room/"; private const float WSCheckInterval = 5f; private const int defaultTimeout = 15000; private static HttpClient httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(15.0) }; private static ClientWebSocket? webSocketClient; private static string socketKeyJson = string.Empty; private static string roomCode = string.Empty; private static byte[] receivedWebSocketMessage = new byte[1024]; private static UTF8Encoding utf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); private static string domainName = ""; private static string socketDomainName = ""; private static HttpTaskList CurrentHttpTasks = new HttpTaskList(); private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); private static float timer = 0f; private static Task<WebSocketReceiveResult>? testWSTask = null; internal static ConnectionState connectState { get; private set; } = ConnectionState.NotConnected; internal static bool CanConnectToRoom => connectState == ConnectionState.NotConnected; internal static bool CanDisconnectFromRoom => connectState == ConnectionState.Connected; internal static RoomType roomType { get; private set; } = RoomType.Bingosync; internal static void Update() { if (timer <= 0f) { timer = 5f; CurrentHttpTasks.CheckForTimeout(); } else { timer -= Time.unscaledDeltaTime; } } internal static void SendRevealCardMessage() { if (connectState == ConnectionState.Connected) { string content = JsonHelper.CreateRevealCardJson(roomCode); StringContent content2 = new StringContent(content, Encoding.UTF8, "application/json"); SendPostRequest("https://" + domainName + ".com/api/revealed", content2, requiresWS: true)?.ContinueWith(VerifyReveal); } } private static void VerifyReveal(Task<HttpResponseMessage> revealCardTask) { HttpResponseMessage result = revealCardTask.Result; CurrentHttpTasks.Remove(revealCardTask); try { result.EnsureSuccessStatusCode(); } catch (Exception ex) { VogsBingoModPlugin.LogError(ex.Message ?? ""); Coroutiner.CreateCoroutine(UIHelper.TriggerErrorText_Main()); } Task<string> task = result.Content.ReadAsStringAsync(); task.ContinueWith(LogComplete); } internal static void SetMyColor(int newColorID) { if (connectState == ConnectionState.Connected) { string content = JsonHelper.CreateColorSwitchJson(newColorID, roomCode, roomType); StringContent content2 = new StringContent(content, Encoding.UTF8, "application/json"); SendPostRequest("https://" + domainName + ".com/api/color", content2, requiresWS: true)?.ContinueWith(PostColorSwitch); } } private static void PostColorSwitch(Task<HttpResponseMessage> switchColorTask) { HttpResponseMessage result = switchColorTask.Result; CurrentHttpTasks.Remove(switchColorTask); try { result.EnsureSuccessStatusCode(); } catch (Exception ex) { VogsBingoModPlugin.LogError(ex.Message ?? ""); Coroutiner.CreateCoroutine(UIHelper.TriggerErrorText_Main()); } Task<string> task = result.Content.ReadAsStringAsync(); task.ContinueWith(LogComplete); } internal static void MarkGoal(int slotIndex, bool remove, string color) { if (connectState == ConnectionState.Connected) { string content = JsonHelper.CreateGoalMarkJson(slotIndex + 1, roomCode, color, remove, roomType); StringContent content2 = new StringContent(content, Encoding.UTF8, "application/json"); try { VogsBingoModPlugin.LogInfo("Sending a mark post request"); SendPostRequest("https://" + domainName + ".com/api/select", content2, requiresWS: true)?.ContinueWith(PostMark); } catch (Exception e) { VogsBingoModPlugin.LogError(e); } } } private static void PostMark(Task<HttpResponseMessage> markTask) { HttpResponseMessage result = markTask.Result; CurrentHttpTasks.Remove(markTask); Task<string> task = result.Content.ReadAsStringAsync(); try { result.EnsureSuccessStatusCode(); VogsBingoModPlugin.LogInfo("Mark completed successfully."); task.ContinueWith(LogComplete); } catch (Exception) { task.ContinueWith(CheckForLockoutBlock); } } private static void CheckForLockoutBlock(Task<string> task) { string result = task.Result; task.Dispose(); if (!result.Equals("Blocked by Lockout")) { Coroutiner.CreateCoroutine(UIHelper.TriggerErrorText_Main()); } else { VogsBingoModPlugin.LogInfo("Mark was blocked by lockout."); } } private static void LogComplete(Task<string> task) { task.Dispose(); } internal static void JoinRoom(string roomUrl, string nicknameInput, string passwordInput) { if (connectState != ConnectionState.NotConnected) { return; } if (roomUrl.Length > "https://bingosync.com/room/".Length && roomUrl.Substring(0, "https://bingosync.com/room/".Length).Equals("https://bingosync.com/room/")) { VogsBingoModPlugin.LogInfo("Attempting to connect to bingosync room..."); roomCode = roomUrl.Substring("https://bingosync.com/room/".Length); domainName = "www.bingosync"; socketDomainName = "bingosync"; roomType = RoomType.Bingosync; } else { if (roomUrl.Length <= "https://caravan.kobold60.com/room/".Length || !roomUrl.Substring(0, "https://caravan.kobold60.com/room/".Length).Equals("https://caravan.kobold60.com/room/")) { VogsBingoModPlugin.LogInfo("The room link that was entered could not be recognized."); Coroutiner.CreateCoroutine(UIHelper.NotifyOfConnectingToRoomCancel_Main()); return; } VogsBingoModPlugin.LogInfo("Attempting to connect to caravan room..."); roomCode = roomUrl.Substring("https://caravan.kobold60.com/room/".Length); domainName = "caravan.kobold60"; socketDomainName = "kobold60"; roomType = RoomType.Caravan; } connectState = ConnectionState.Connecting; Coroutiner.CreateCoroutine(UIHelper.NotifyOfConnectingToRoom_Main()); string content = "{\"room\": \"" + roomCode + "\",\n\"nickname\": \"" + nicknameInput + "\",\n\"password\": \"" + passwordInput + "\"}"; StringContent content2 = new StringContent(content, Encoding.UTF8, "application/json"); try { SendPostRequest("https://" + domainName + ".com/api/join-room", content2, requiresWS: false)?.ContinueWith(ReadSocketKey); } catch (Exception e) { VogsBingoModPlugin.LogError(e); } } private static void ReadSocketKey(Task<HttpResponseMessage> httpPostReqTask) { HttpResponseMessage result = httpPostReqTask.Result; CurrentHttpTasks.Remove(httpPostReqTask); try { result.EnsureSuccessStatusCode(); } catch (Exception) { connectState = ConnectionState.NotConnected; Coroutiner.CreateCoroutine(UIHelper.NotifyOfConnectingToRoomCancel_Main()); return; } try { Task<string> task = result.Content.ReadAsStringAsync(); task.ContinueWith(StartWebSocket); } catch (Exception e) { VogsBingoModPlugin.LogError(e); } } private static void StartWebSocket(Task<string> readSocketKeyTask) { VogsBingoModPlugin.LogInfo("Starting WS..."); socketKeyJson = readSocketKeyTask.Result; readSocketKeyTask.Dispose(); webSocketClient = new ClientWebSocket(); Uri uri = new Uri("wss://sockets." + socketDomainName + ".com/broadcast"); try { Task task = webSocketClient.ConnectAsync(uri, cancellationTokenSource.Token); task.ContinueWith(SendJoinViaWebSocket); } catch (Exception e) { VogsBingoModPlugin.LogError(e); Coroutiner.CreateCoroutine(UIHelper.NotifyOfConnectingToRoomCancel_Main(1)); } } private static void SendJoinViaWebSocket(Task wsTask) { byte[] bytes = utf8.GetBytes(socketKeyJson); if (webSocketClient != null) { try { wsTask = webSocketClient.SendAsync(bytes, WebSocketMessageType.Text, endOfMessage: true, cancellationTokenSource.Token); } catch (Exception e) { VogsBingoModPlugin.LogError(e); } socketKeyJson = string.Empty; } wsTask.ContinueWith(PostJoin); } private static void PostJoin(Task wsTask) { wsTask.Dispose(); StartListeningForMessages(); connectState = ConnectionState.Connected; Coroutiner.CreateCoroutine(UIHelper.NotifyOfRoomEnter_Main(roomType)); RequestBoardViaHttp(); } internal static void ExitRoom() { if (connectState == ConnectionState.Connected && webSocketClient != null) { roomCode = string.Empty; domainName = string.Empty; socketDomainName = string.Empty; VogsBingoModPlugin.LogInfo("Starting the process of leaving the room..."); connectState = ConnectionState.Disconnecting; try { Task task = webSocketClient.CloseAsync(WebSocketCloseStatus.NormalClosure, "Exit Room button", CancellationToken.None); CurrentHttpTasks.SetIsExitingRoom(isExitingRoom: true); task.ContinueWith(PostExit); } catch (Exception e) { VogsBingoModPlugin.LogError(e); ForceExitRoomWithDisconnectError(2); } } } private static void PostExit(Task wsTask) { CurrentHttpTasks.SetIsExitingRoom(isExitingRoom: false); wsTask.Dispose(); CancelHttpTasks(); if (webSocketClient != null) { webSocketClient.Dispose(); } webSocketClient = null; connectState = ConnectionState.NotConnected; Coroutiner.CreateCoroutine(UIHelper.NotifyOfRoomExit_Main()); VogsBingoModPlugin.LogInfo("The room has been exited."); } internal static void RequestBoardViaHttp() { try { SendGetRequest("https://" + domainName + ".com/room/" + roomCode + "/board", requiresWS: true)?.ContinueWith(ReadBoard); } catch (Exception e) { VogsBingoModPlugin.LogError(e); } } private static void ReadBoard(Task<HttpResponseMessage> httpGetReqTask) { HttpResponseMessage result = httpGetReqTask.Result; CurrentHttpTasks.Remove(httpGetReqTask); try { result.EnsureSuccessStatusCode(); } catch (Exception ex) { VogsBingoModPlugin.LogError("Error requesting the board: " + ex.Message); } Task<string> task = result.Content.ReadAsStringAsync(); task.ContinueWith(SendBoardToUI); } private static void SendBoardToUI(Task<string> readBoardTask) { string result = readBoardTask.Result; readBoardTask.Dispose(); Coroutiner.CreateCoroutine(UIHelper.SetBoard_Main(result, roomType)); } private static void StartListeningForMessages() { if (webSocketClient != null) { try { Task<WebSocketReceiveResult> task = webSocketClient.ReceiveAsync(receivedWebSocketMessage, cancellationTokenSource.Token); task.ContinueWith(ReceiveWSMessage); } catch (Exception e) { VogsBingoModPlugin.LogError(e); } } } private static void ReceiveWSMessage(Task<WebSocketReceiveResult> wsTask) { VogsBingoModPlugin.LogInfo($"Received a WS message, status: {wsTask.Status}"); WebSocketReceiveResult result = wsTask.Result; if (result.MessageType == WebSocketMessageType.Text) { string text = Encoding.UTF8.GetString(receivedWebSocketMessage); string text2 = JsonConvert.DeserializeObject<JsonMessageType>(text)?.type; string text3 = text2; if (!(text3 == "goal")) { if (text3 == "new-card") { HandleNewCardMessage(); } } else { HandleGoalMessage(text); } } Array.Clear(receivedWebSocketMessage, 0, receivedWebSocketMessage.Length); if (webSocketClient != null) { try { wsTask = webSocketClient.ReceiveAsync(receivedWebSocketMessage, cancellationTokenSource.Token); testWSTask = wsTask; wsTask.ContinueWith(ReceiveWSMessage); return; } catch (Exception e) { VogsBingoModPlugin.LogError(e); return; } } wsTask.Dispose(); } private static void HandleGoalMessage(string jsonStr) { JsonGoalMarkedMessage jsonGoalMarkedMessage = JsonConvert.DeserializeObject<JsonGoalMarkedMessage>(jsonStr); if (jsonGoalMarkedMessage == null) { VogsBingoModPlugin.LogError("Could not read the JSON when receiving goal mark"); return; } int colorID = GoalColors.NameToID(jsonGoalMarkedMessage.color); bool remove = jsonGoalMarkedMessage.remove; int slotIndex = int.Parse(jsonGoalMarkedMessage.square.slot.Substring(4)) - 1; try { Coroutiner.CreateCoroutine(UIHelper.UpdateGoal_Main(colorID, remove, slotIndex)); } catch (Exception e) { VogsBingoModPlugin.LogError(e); } VogsBingoModPlugin.LogInfo("Done handling goal mark message. UI updates will happen next frame."); } private static void HandleNewCardMessage() { Coroutiner.CreateCoroutine(UIHelper.UnrevealCard_Main()); Coroutiner.CreateCoroutine(RequestNewBoardAfterWaiting()); } private static IEnumerator RequestNewBoardAfterWaiting() { yield return (object)new WaitForSecondsRealtime(1f); RequestBoardViaHttp(); } internal static void Dispose() { httpClient.Dispose(); cancellationTokenSource.Dispose(); if (webSocketClient != null) { webSocketClient.Dispose(); } } private static Task<HttpResponseMessage>? SendPostRequest(string uri, HttpContent content, bool requiresWS) { if (!requiresWS || (webSocketClient != null && webSocketClient.State == WebSocketState.Open)) { try { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); if (!requiresWS) { cancellationTokenSource.CancelAfter(15000); } Task<HttpResponseMessage> task = httpClient.PostAsync(uri, content, cancellationTokenSource.Token); CurrentHttpTasks.Add(task, cancellationTokenSource); return task; } catch (Exception e) { VogsBingoModPlugin.LogError(e); } } ForceExitRoomWithDisconnectError(3); return null; } private static void ForceExitRoomWithDisconnectError(int errorCode) { cancellationTokenSource.Dispose(); cancellationTokenSource = new CancellationTokenSource(); VogsBingoModPlugin.LogInfo("Forcing disconnect"); if (webSocketClient != null) { webSocketClient.Dispose(); webSocketClient = null; } CancelHttpTasks(); connectState = ConnectionState.NotConnected; CurrentHttpTasks.SetIsExitingRoom(isExitingRoom: false); Coroutiner.CreateCoroutine(UIHelper.NotifyOfRoomExit_Main(errorCode)); } private static void CancelHttpTasks() { httpClient.CancelPendingRequests(); CurrentHttpTasks.Clear(); } private static Task<HttpResponseMessage>? SendGetRequest(string uri, bool requiresWS) { if (!requiresWS || (webSocketClient != null && webSocketClient.State == WebSocketState.Open)) { try { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); if (!requiresWS) { cancellationTokenSource.CancelAfter(15000); } Task<HttpResponseMessage> async = httpClient.GetAsync(uri, cancellationTokenSource.Token); CurrentHttpTasks.Add(async, cancellationTokenSource); return async; } catch (Exception e) { VogsBingoModPlugin.LogError(e); } } ForceExitRoomWithDisconnectError(4); return null; } } internal static class Resources { internal static byte[]? GetResourceAsByteArray(string fileName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); Stream manifestResourceStream = executingAssembly.GetManifestResourceStream(fileName ?? ""); if (manifestResourceStream == null) { VogsBingoModPlugin.LogError("Could not find the resource \"" + fileName + "\"."); return null; } MemoryStream memoryStream = new MemoryStream(); manifestResourceStream.CopyTo(memoryStream); manifestResourceStream.Dispose(); byte[] result = memoryStream.ToArray(); memoryStream.Dispose(); return result; } } internal enum RoomType { Bingosync, Caravan } [BepInPlugin("io.github.atlasofsouls.VogsBingoMod", "VogsBingoMod", "1.4.5")] public class VogsBingoModPlugin : BaseUnityPlugin { internal enum UIScaleOptions { Default, Small, Tiny } internal const string PersistentName = "VogsBingoMod"; internal static VogsBingoModPlugin instance; private ManualLogSource logger; private ConfigEntry<KeyCode> toggleUIVisibility; private ConfigEntry<KeyCode> toggleUIOpacity; private ConfigEntry<KeyCode> revealBoardKeybind; internal ConfigEntry<string> nameAutofill; internal ConfigEntry<string> passwordAutofill; internal ConfigEntry<UIScaleOptions> uiScaleConfig; internal ConfigEntry<AudioVolume> teamMarkSoundsVolume; internal ConfigEntry<AudioVolume> opponentMarkSoundsVolume; public const string Id = "io.github.atlasofsouls.VogsBingoMod"; public static string Name => "VogsBingoMod"; public static string Version => "1.4.5"; internal static void LogInfo(string str) { try { instance.logger.LogInfo((object)str); } catch (Exception) { } } internal static void LogError(string str) { instance.logger.LogError((object)str); } internal static void LogError(Exception e) { instance.logger.LogError((object)(e.Message + ", " + e.StackTrace)); } private void Update() { //IL_001a: 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_0052: Unknown result type (might be due to invalid IL or missing references) Automarker.RunFrameChecks(); if (!UIHelper.IsTyping()) { if (Input.GetKeyDown(toggleUIVisibility.Value)) { UIHelper.CycleVisibility(); } if (Input.GetKeyDown(toggleUIOpacity.Value)) { UIHelper.CycleOpacity(); } if (Input.GetKeyDown(revealBoardKeybind.Value)) { UIHelper.RevealCardPressed(); } } NetworkHandler.Update(); } private void Awake() { //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown instance = this; logger = ((BaseUnityPlugin)this).Logger; toggleUIVisibility = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "6: Toggle UI", (KeyCode)98, "Cycles the currently active UI elements, allowing the user to show or hide the board as necessary."); toggleUIOpacity = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "7: Toggle Opacity", (KeyCode)111, "Changes how transparent the UI is over the game."); revealBoardKeybind = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "8: Reveal Card", (KeyCode)0, "Reveals the current bingo card."); uiScaleConfig = ((BaseUnityPlugin)this).Config.Bind<UIScaleOptions>("UI Settings", "5: UI Scale", UIScaleOptions.Default, "Change the size of the UI, such as the Bingo board."); nameAutofill = ((BaseUnityPlugin)this).Config.Bind<string>("Autofill Options", "1: Default Name", "", "The nickname field for entering rooms will default to this value, helpful for reusing names."); passwordAutofill = ((BaseUnityPlugin)this).Config.Bind<string>("Autofill Options", "2: Default Password", "fast", "The password field for entering rooms will default to this value. The default is \"fast\"."); teamMarkSoundsVolume = ((BaseUnityPlugin)this).Config.Bind<AudioVolume>("Audio Options", "3: Team Mark Sound Volume", AudioVolume.Medium, "Plays a sound when your color marks a goal."); opponentMarkSoundsVolume = ((BaseUnityPlugin)this).Config.Bind<AudioVolume>("Audio Options", "4: Opponent Mark Sound Volume", AudioVolume.Medium, "Plays a sound when any color other than yours marks a goal."); uiScaleConfig.SettingChanged += UIScaleChanged; nameAutofill.SettingChanged += NameAutofillChanged; passwordAutofill.SettingChanged += PasswordAutofillChanged; teamMarkSoundsVolume.SettingChanged += TeamMarkVolumeChanged; opponentMarkSoundsVolume.SettingChanged += OpponentMarkVolumeChanged; Harmony val = new Harmony("io.github.atlasofsouls.VogsBingoMod"); val.PatchAll(); UIHelper.uiCanvas.FirstAwake(); Coroutiner.Initialize(); } private void OnDisable() { NetworkHandler.Dispose(); } private void UIScaleChanged(object sender, EventArgs args) { UIHelper.UpdateUIScale(); } private void NameAutofillChanged(object sender, EventArgs args) { UICanvas uICanvas = UICanvas.GetInstance(); if ((Object)(object)uICanvas.nicknameInputField != (Object)null) { uICanvas.nicknameInputField.InputComponent.text = nameAutofill.Value; } } private void PasswordAutofillChanged(object sender, EventArgs args) { UICanvas uICanvas = UICanvas.GetInstance(); if ((Object)(object)uICanvas.passwordInputField != (Object)null) { uICanvas.passwordInputField.InputComponent.text = passwordAutofill.Value; } } private void TeamMarkVolumeChanged(object sender, EventArgs args) { AudioHelper.Instance.PlayTeamMarkSound(isOneShot: true); } private void OpponentMarkVolumeChanged(object sender, EventArgs args) { AudioHelper.Instance.PlayOpponentMarkSound(isOneShot: true); } } } namespace VogsBingoMod.UI { internal static class FontHandler { internal static Font? GetFont(string fontName) { return Resources.GetBuiltinResource<Font>(fontName + ".ttf"); } } internal enum GoalColorID { none, pink, red, orange, brown, yellow, green, teal, blue, navy, purple, beastling, hornet, vespa, scrounge, sherma, huntress, gilly, magnetite, plasmium, architect } internal static class GoalColors { internal const int BingosyncColorsFirstID = 1; internal const int CaravanColorsFirstID = 11; internal static int _myColorID = 2; internal static Color[] colorsList = (Color[])(object)new Color[21] { new Color(0f, 0f, 0f, 0f), new Color(1f, 0.7f, 1f, 0.7f), new Color(1f, 0f, 0f, 0.7f), new Color(1f, 0.4f, 0f, 0.7f), new Color(0.5f, 0.3f, 0f, 0.7f), new Color(1f, 1f, 0f, 0.7f), new Color(0f, 1f, 0f, 0.7f), new Color(0.2f, 0.5f, 0.5f, 0.7f), new Color(0f, 0.8f, 1f, 0.7f), new Color(0f, 0f, 1f, 0.7f), new Color(0.7f, 0.3f, 1f, 0.7f), new Color(1f, 0.5f, 0.6f, 0.7f), new Color(0.7f, 0.1f, 0.2f, 0.7f), new Color(0.7f, 0.3f, 0f, 0.7f), new Color(0.9f, 0.7f, 0.4f, 0.7f), new Color(0.9f, 0.8f, 0.1f, 0.7f), new Color(0.5f, 0.8f, 0.5f, 0.7f), new Color(0.1f, 0.5f, 0.2f, 0.7f), new Color(0.5f, 0.7f, 0.9f, 0.7f), new Color(0f, 0.3f, 0.7f, 0.7f), new Color(0.3f, 0.1f, 0.4f, 0.7f) }; internal static int myColorID { get { return _myColorID; } set { _myColorID = value; UIHelper.UpdateGoalTextColor(); } } internal static string MyColorName => IDToName(myColorID); internal static string[] ColorOptions => new string[21] { "none", "pink", "red", "orange", "brown", "yellow", "green", "teal", "blue", "navy", "purple", "beastling", "hornet", "vespa", "scrounge", "sherma", "huntress", "gilly", "magnetite", "plasmium", "architect" }; internal static int NameToID(string colorName) { string text = colorName.ToLower(); if (1 == 0) { } int result = text switch { "pink" => 1, "red" => 2, "orange" => 3, "brown" => 4, "yellow" => 5, "green" => 6, "teal" => 7, "blue" => 8, "navy" => 9, "purple" => 10, "beastling" => 11, "hornet" => 12, "vespa" => 13, "scrounge" => 14, "sherma" => 15, "huntress" => 16, "gilly" => 17, "magnetite" => 18, "plasmium" => 19, "architect" => 20, _ => 0, }; if (1 == 0) { } return result; } internal static string IDToName(int colorID) { return ColorOptions[colorID]; } internal static void SetMyColorToDefault(RoomType roomType) { if (roomType == RoomType.Bingosync) { myColorID = 2; } else { myColorID = 12; } } } internal static class TextureHandler { private const int goalPngWidth = 100; private const int goalPngHeight = 100; internal const string standardBackgroundName = "StandardBackground"; internal const string standardBackgroundHighlightName = "StandardBackgroundHighlight"; private static Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>(); private static Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>(); internal static Texture2D GetTexture(string imgName) { imgName = "VogsBingoMod.Assets." + imgName + ".png"; if (textures.Count <= 0) { LoadTextures(); } if (!textures.ContainsKey(imgName)) { VogsBingoModPlugin.LogError("could not find sprite \"" + imgName + "\""); } return textures[imgName]; } internal static void SetSprite(string spriteName, Image imgComponent) { imgComponent.sprite = GetSprite(spriteName); } internal static Sprite CreateGoalColorsSprite() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(95, 95); ClearTexture(val); return Sprite.Create(val, new Rect(0f, 0f, 95f, 95f), Vector2.one * 0.5f); } internal static void ClearTexture(Texture2D texture) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < ((Texture)texture).width; i++) { for (int j = 0; j < ((Texture)texture).height; j++) { texture.SetPixel(i, j, GoalColors.colorsList[0]); } } texture.Apply(); } internal static bool ShouldSliceSprite(string imgName) { return imgName.Equals("StandardBackground") || imgName.Equals("StandardBackgroundHighlight"); } internal static void LoadTextures() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.StartsWith("VogsBingoMod.Assets.")) { Texture2D val = new Texture2D(1, 1); byte[] resourceAsByteArray = Resources.GetResourceAsByteArray(text); if (resourceAsByteArray == null) { VogsBingoModPlugin.LogError("Could not load image \"" + text + "\""); continue; } ImageConversion.LoadImage(val, resourceAsByteArray); textures.Add(text, val); } } } private static Sprite GetSprite(string spriteName) { //IL_0034: 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_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) if (!sprites.ContainsKey(spriteName)) { Texture2D texture = GetTexture(spriteName); Sprite value = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), Vector2.one * 0.5f, 100f, 0u, (SpriteMeshType)0, Vector4.one * 5f); sprites.Add(spriteName, value); } return sprites[spriteName]; } } internal enum UIAnchor { MiddleCenter, TopRight } internal class UIButton : MonoBehaviour, IPointerClickHandler, IEventSystemHandler { internal Action? leftClickCallback { get; private set; } internal Action? rightClickCallback { get; private set; } public void OnPointerClick(PointerEventData eventData) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 if ((int)eventData.button == 0) { LeftClick(); } else if ((int)eventData.button == 1) { RightClick(); } } internal void SetupCallbacks(Action? leftClickAction, Action? rightClickAction) { leftClickCallback = leftClickAction; rightClickCallback = rightClickAction; } internal void LeftClick(string value = "") { if (leftClickCallback != null) { leftClickCallback(); } } internal void RightClick() { if (rightClickCallback != null) { rightClickCallback(); } } } internal class UICanvas : MonoBehaviour { private const string infoTextString = "How to Use VOG'S BINGO MOD\n\nTo use the bingo mod, you need to create a bingo room. There is a brief guide to using BingyFlea (a discord bot that makes rooms for you) on youtube titled \"How to Set up Silksong Bingo\".\n\nOnce you have the room link, you put it the room link field as well as your nickname and password (The default password is \"fast\").\n\nYou can change the board opacity, show/hide this mod's UI, and reveal the board with keybinds that can be set in options->mods->Vogs Bingo Mod. If you don't have that menu, you may need to install the ModMenu mod or use a different way of changing BepInEx configs.\nThe config also has options for sound cues and UI size, so make sure to check those out as well.\n\nLastly, when you've revealed a bingo board, if a goal doesn't mark automatically, you can click the goal to manually mark it. Goals that end with \"(M)\" will always need to be marked manually.\n\nHave fun playing Bingo!\n\n(Click this box or the \"How to Use\" button to close the How to Use information)"; private const int goalSpacing = 110; private const int goalsXOffset = 90; private const int goalsYOffset = -10; private const int sortOrder = 10000; private const int defaultBoardSize = 5; private const int defaultcolorOptions = 10; private const float defaultUIScale = 1f; private const float smallUIScale = 0.8f; private const float tinyUIScale = 0.6f; internal GameObject boardObj; internal UIButton? revealCardButton; internal UIButton? revealHandModeButton; internal UIButton? joinRoomButton; internal UIButton? exitRoomButton; internal UIButton? infoButton; internal UITextInput? roomUrlInputField; internal UITextInput? nicknameInputField; internal UITextInput? passwordInputField; internal UIDropdown? teamColorsDropdown; internal UIText? loadingCardText; internal UIText? errorText; internal UIText? connectingErrorText; internal UIButton? infoText; internal GameObject? connectionPendingIcon; internal List<OptionData> bingosyncColorOptions; internal List<OptionData> caravanColorOptions; private static UICanvas? instance; private float[] opacityOptions = new float[5] { 1f, 0.8f, 0.5f, 0.3f, 0.1f }; private float[] textOpacityOptions = new float[5] { 1f, 1f, 0.9f, 0.7f, 0.5f }; private int currentOpacityIndex = 0; private UIGoal[] uiGoals; internal float currentScale { get; private set; } internal float CurrentOpacity => opacityOptions[currentOpacityIndex]; internal float CurrentTextOpacity => textOpacityOptions[currentOpacityIndex]; internal bool CanMarkGoals => ((Object)(object)revealCardButton != (Object)null && !((Component)revealCardButton).gameObject.activeSelf) || ((Object)(object)revealHandModeButton != (Object)null && !((Component)revealHandModeButton).gameObject.activeSelf); internal static UICanvas GetInstance() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null) { instance = new GameObject("BingoCanvas").AddComponent<UICanvas>(); } return instance; } internal void FirstAwake() { Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); boardObj = UIHelper.CreateUIObject(((Component)this).transform, "BoardContainer", 0f, 0f, 100f, 100f, UIAnchor.TopRight); SceneManager.activeSceneChanged += OnSceneChange; ((Component)this).gameObject.SetActive(false); } internal void Initialize() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Expected O, but got Unknown //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Expected O, but got Unknown Canvas val = ((Component)this).gameObject.AddComponent<Canvas>(); CanvasScaler val2 = ((Component)this).gameObject.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = Vector2.right * 1920f + Vector2.up * 1080f; val2.matchWidthOrHeight = 1f; GraphicRaycaster val3 = ((Component)this).gameObject.AddComponent<GraphicRaycaster>(); val.sortingOrder = 10000; val.renderMode = (RenderMode)0; val3.blockingMask = LayerMask.op_Implicit(0); revealCardButton = UIHelper.CreateUIButton(boardObj.transform, "RevealCardButton", RevealCard, null, "Reveal Card", -230f, -200f); ((Component)revealCardButton).gameObject.SetActive(false); revealHandModeButton = UIHelper.CreateUIButton(((Component)revealCardButton).transform, "RevealCardInHandModeButton", RevealCardInHandMode, null, "Automark With Card Hidden", 0f, -110f); loadingCardText = UIHelper.CreateUIText(boardObj.transform, "LoadingCardText", "Loading Card...", 30, -230f, -200f, 300f, 100f, supportRichText: true, (TextAnchor)4); ((Component)loadingCardText).gameObject.SetActive(false); errorText = UIHelper.CreateUIText(((Component)this).transform, "ErrorText", "An error occurred while communicating with the room.", 30, -20f, -760f, 420f, 100f, supportRichText: true, (TextAnchor)4, Color.red, UIAnchor.TopRight); ((Component)errorText).gameObject.SetActive(false); connectionPendingIcon = UIHelper.CreateUIImage(boardObj.transform, "ConnectionPendingIcon", "ConnectionPendingIcon"); connectionPendingIcon.SetActive(false); SetupGoals(5); HideGoals(); joinRoomButton = UIHelper.CreateUIButton(((Component)this).transform, "JoinRoomButton", JoinRoomButtonClicked, null, "Join Room", -20f, -655f, UIAnchor.TopRight); connectingErrorText = UIHelper.CreateUIText(((Component)joinRoomButton).transform, "ConnectionErrorText", "An error occurred while connecting to the room. Check that the room link and password are correct.", 30, 0f, 160f, 420f, 200f, supportRichText: true, (TextAnchor)4, Color.red); ((Component)connectingErrorText).gameObject.SetActive(false); exitRoomButton = UIHelper.CreateUIButton(((Component)this).transform, "ExitRoomButton", ExitRoomButtonClicked, null, "Exit Room", -20f, -675f, UIAnchor.TopRight); ((Component)exitRoomButton).gameObject.SetActive(false); roomUrlInputField = UIHelper.CreateUITextInput(((Component)joinRoomButton).gameObject.transform, "RoomLinkInput", "Enter the room link...", 0f, -100f); nicknameInputField = UIHelper.CreateUITextInput(((Component)joinRoomButton).gameObject.transform, "NicknameInput", "Enter your nickname...", 0f, -180f, isPassword: false, VogsBingoModPlugin.instance.nameAutofill.Value); passwordInputField = UIHelper.CreateUITextInput(((Component)joinRoomButton).gameObject.transform, "PasswordInput", "Enter the room password...", 0f, -260f, isPassword: true, VogsBingoModPlugin.instance.passwordAutofill.Value); UIHelper.SetupJoinRoomFieldNavigation(); infoButton = UIHelper.CreateUIButton(((Component)joinRoomButton).gameObject.transform, "InfoButton", ToggleInfoText, null, "How to Use", 59f, -325f, UIAnchor.MiddleCenter, 300f, 50f); infoText = UIHelper.CreateUIButton(((Component)GetInstance()).transform, "InformationText", ToggleInfoText, null, "How to Use VOG'S BINGO MOD\n\nTo use the bingo mod, you need to create a bingo room. There is a brief guide to using BingyFlea (a discord bot that makes rooms for you) on youtube titled \"How to Set up Silksong Bingo\".\n\nOnce you have the room link, you put it the room link field as well as your nickname and password (The default password is \"fast\").\n\nYou can change the board opacity, show/hide this mod's UI, and reveal the board with keybinds that can be set in options->mods->Vogs Bingo Mod. If you don't have that menu, you may need to install the ModMenu mod or use a different way of changing BepInEx configs.\nThe config also has options for sound cues and UI size, so make sure to check those out as well.\n\nLastly, when you've revealed a bingo board, if a goal doesn't mark automatically, you can click the goal to manually mark it. Goals that end with \"(M)\" will always need to be marked manually.\n\nHave fun playing Bingo!\n\n(Click this box or the \"How to Use\" button to close the How to Use information)", 0f, 0f, UIAnchor.MiddleCenter, 1000f, 1000f); ((Component)((Component)infoText).transform.GetChild(0)).gameObject.GetComponent<Text>().alignment = (TextAnchor)3; ToggleInfoText(); bingosyncColorOptions = new List<OptionData>(); caravanColorOptions = new List<OptionData>(); for (int i = 0; i < 10; i++) { bingosyncColorOptions.Add(new OptionData(" " + GoalColors.ColorOptions[i + 1])); caravanColorOptions.Add(new OptionData(" " + GoalColors.ColorOptions[i + 11])); } teamColorsDropdown = UIHelper.CreateUIDropdown(((Component)exitRoomButton).transform, "TeamSelector", TeamChanged, bingosyncColorOptions, -325f, 30f); UpdateUIScale(); } internal void FixedUpdate() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)connectionPendingIcon != (Object)null && connectionPendingIcon.activeInHierarchy) { connectionPendingIcon.transform.Rotate(Vector3.forward * 3f, (Space)1); } } internal void ShowGoals() { UIButton? uIButton = revealCardButton; if (uIButton != null) { ((Component)uIButton).gameObject.SetActive(false); } for (int i = 0; i < uiGoals.Length; i++) { ((Component)uiGoals[i]).gameObject.SetActive(true); } } internal void HideGoals() { for (int i = 0; i < uiGoals.Length; i++) { ((Component)uiGoals[i]).gameObject.SetActive(false); } } internal void OnSceneChange(Scene oldScene, Scene newScene) { if (((Scene)(ref newScene)).name.Equals("Menu_Title")) { Initialize(); ((Component)this).gameObject.SetActive(true); SceneManager.activeSceneChanged -= OnSceneChange; } } internal void JoinRoomButtonClicked() { VogsBingoModPlugin.LogInfo("The room link that was entered was: " + roomUrlInputField?.GetText()); if (NetworkHandler.CanConnectToRoom && (Object)(object)roomUrlInputField != (Object)null && (Object)(object)nicknameInputField != (Object)null && (Object)(object)passwordInputField != (Object)null) { NetworkHandler.JoinRoom(roomUrlInputField.GetText().Trim(), nicknameInputField.GetText().Trim(), passwordInputField.GetText()); } } internal void ExitRoomButtonClicked() { if (NetworkHandler.CanDisconnectFromRoom) { UIButton? uIButton = exitRoomButton; if (uIButton != null) { ((Component)uIButton).gameObject.SetActive(false); } UIButton? uIButton2 = revealCardButton; if (uIButton2 != null) { ((Component)uIButton2).gameObject.SetActive(false); } HideGoals(); NetworkHandler.ExitRoom(); } } internal void SetGoalNames(string[] goalNames, int boardSize) { SetupGoals(boardSize); for (int i = 0; i < goalNames.Length; i++) { uiGoals[i].SetGoalName(goalNames[i]); } } internal void SetBoardColors(int[][] colorIDs) { for (int i = 0; i < colorIDs.Length; i++) { uiGoals[i].SetColors(colorIDs[i]); uiGoals[i].isHighlighted = false; } } internal void MarkGoal(int colorID, int slotIndex) { uiGoals[slotIndex].MarkGoal(colorID); } internal void UnmarkGoal(int colorID, int slotIndex) { uiGoals[slotIndex].UnmarkGoal(colorID); } internal void ResetBoard() { for (int i = 0; i < uiGoals.Length; i++) { uiGoals[i].ResetColors(); } } internal void TeamChanged(int newColorID) { newColorID = ((NetworkHandler.roomType != RoomType.Bingosync) ? (newColorID + 11) : (newColorID + 1)); GoalColors.myColorID = newColorID; VogsBingoModPlugin.LogInfo($"Switched color to {newColorID}, AKA {GoalColors.IDToName(newColorID)}"); NetworkHandler.SetMyColor(newColorID); } internal void RevealCard() { NetworkHandler.SendRevealCardMessage(); HideRevealCardButton(); ShowGoals(); } internal void RevealCardInHandMode() { UIButton? uIButton = revealHandModeButton; if (uIButton != null) { ((Component)uIButton).gameObject.SetActive(false); } UIHelper.CycleVisibility(UIHelper.VisibilityState.Nothing); } internal void UnrevealCard() { ShowRevealCardButton(); HideGoals(); } internal void ShowRevealCardButton() { UIButton? uIButton = revealCardButton; if (uIButton != null) { ((Component)uIButton).gameObject.SetActive(true); } UIButton? uIButton2 = revealHandModeButton; if (uIButton2 != null) { ((Component)uIButton2).gameObject.SetActive(true); } } internal void HideRevealCardButton() { UIButton? uIButton = revealCardButton; if (uIButton != null) { ((Component)uIButton).gameObject.SetActive(false); } } internal void ShowCardLoadingText() { UIText? uIText = loadingCardText; if (uIText != null) { ((Component)uIText).gameObject.SetActive(true); } HideRevealCardButton(); } internal void HideCardLoadingText() { UIText? uIText = loadingCardText; if (uIText != null) { ((Component)uIText).gameObject.SetActive(false); } } internal void CycleOpacity() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) currentOpacityIndex++; if (currentOpacityIndex >= opacityOptions.Length) { currentOpacityIndex = 0; } Image[] componentsInChildren = ((Component)this).gameObject.GetComponentsInChildren<Image>(true); Image[] array = componentsInChildren; foreach (Image val in array) { if (((Object)((Component)val).gameObject).name != "Blocker") { ((Graphic)val).color = new Color(((Graphic)val).color.r, ((Graphic)val).color.g, ((Graphic)val).color.b, CurrentOpacity); } } Text[] componentsInChildren2 = ((Component)this).gameObject.GetComponentsInChildren<Text>(true); Text[] array2 = componentsInChildren2; foreach (Text val2 in array2) { ((Graphic)val2).color = new Color(((Graphic)val2).color.r, ((Graphic)val2).color.g, ((Graphic)val2).color.b, CurrentTextOpacity); } } internal bool HasColor(int slotIndex, int colorID) { return uiGoals[slotIndex].HasColor(colorID); } internal void SetDropdownOptions(RoomType roomType) { if (roomType == RoomType.Bingosync) { teamColorsDropdown?.SetOptions(bingosyncColorOptions); } else { teamColorsDropdown?.SetOptions(caravanColorOptions); } } internal void UpdateUIScale() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) float uIScaleFromConfig = GetUIScaleFromConfig(); boardObj.transform.localScale = Vector3.one * uIScaleFromConfig; UIButton? uIButton = joinRoomButton; if (uIButton != null) { ((Component)uIButton).gameObject.transform.localScale = Vector3.one * uIScaleFromConfig; } UIButton? uIButton2 = exitRoomButton; if (uIButton2 != null) { ((Component)uIButton2).gameObject.transform.localScale = Vector3.one * uIScaleFromConfig; } currentScale = uIScaleFromConfig; } internal void UpdateGoalTextColor() { UIGoal[] array = uiGoals; foreach (UIGoal uIGoal in array) { uIGoal.UpdateTextColor(); } } internal void CloseInfoTextIfOpen() { if ((Object)(object)infoText != (Object)null && ((Component)infoText).gameObject.activeSelf) { ((Component)infoText).gameObject.SetActive(false); } } private float GetUIScaleFromConfig() { VogsBingoModPlugin.UIScaleOptions uIScaleOptions = (VogsBingoModPlugin.UIScaleOptions)((ConfigEntryBase)VogsBingoModPlugin.instance.uiScaleConfig).BoxedValue; if (1 == 0) { } float result = uIScaleOptions switch { VogsBingoModPlugin.UIScaleOptions.Default => 1f, VogsBingoModPlugin.UIScaleOptions.Small => 0.8f, VogsBingoModPlugin.UIScaleOptions.Tiny => 0.6f, _ => 1f, }; if (1 == 0) { } return result; } private void SetupGoals(int boardSize) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) UIGoal[] array = new UIGoal[boardSize * boardSize]; int i = 0; if (uiGoals != null) { for (; i < array.Length && i < uiGoals.Length; i++) { int xPos = i % boardSize * 110 + 90 - 110 * boardSize; int yPos = i / boardSize * -110 + -10; array[i] = uiGoals[i]; array[i].SetPosition(xPos, yPos); } } for (; i < array.Length; i++) { int num = i % boardSize * 110 + 90 - 110 * boardSize; int num2 = i / boardSize * -110 + -10; array[i] = UIHelper.CreateUIGoal(boardObj.transform, $"Goal{i}", num, num2, i); } uiGoals = array; GameObject? obj = connectionPendingIcon; if (obj != null) { obj.GetComponent<RectTransform>().anchoredPosition = Vector2.right * (float)(-110 * boardSize) + Vector2.up * 25f; } HideGoals(); } private void ToggleInfoText() { if ((Object)(object)infoText != (Object)null) { ((Component)infoText).gameObject.SetActive(!((Component)infoText).gameObject.activeSelf); } } } internal class UIDropdown : Dropdown { private const int defaultValue = 1; internal void SetOptions(List<OptionData> options) { ((Dropdown)this).ClearOptions(); ((Dropdown)this).AddOptions(options); ((Dropdown)this).SetValueWithoutNotify(1); } internal int IsOpen() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected I4, but got Unknown return (int)((Selectable)this).currentSelectionState; } } internal class UIGoal : MonoBehaviour { internal UIGoalColors goalColors; internal int slotIndex = -1; private UIText? goalText; private bool _isHighlighted = false; internal bool isHighlighted { get { return _isHighlighted; } set { if (value != _isHighlighted) { _isHighlighted = value; UpdateHighlightStatus(); } } } private Image imageComponent => ((Component)this).gameObject.GetComponent<Image>(); internal void SetGoalName(string goalName) { if ((Object)(object)goalText == (Object)null) { goalText = ((Component)this).gameObject.GetComponentInChildren<UIText>(true); } goalText.SetText(goalName); } internal void MarkGoal(int colorID) { if (colorID == GoalColors.myColorID) { AudioHelper.Instance.PlayTeamMarkSound(); } else { AudioHelper.Instance.PlayOpponentMarkSound(); } goalColors.AddColor(colorID); UpdateTextColor(); } internal void UnmarkGoal(int colorID) { goalColors.RemoveColor(colorID); UpdateTextColor(); } internal void SetColors(int[] colorIDs) { goalColors.SetColors(colorIDs); UpdateTextColor(); } internal void ResetColors() { goalColors.ResetColors(); UpdateTextColor(); } internal bool HasColor(int colorID) { return goalColors.HasColor(colorID); } internal void OnLeftClick() { UIHelper.MarkGoal(slotIndex, HasColor(GoalColors.myColorID)); } internal void OnRightClick() { isHighlighted = !isHighlighted; } private void UpdateHighlightStatus() { if (isHighlighted) { TextureHandler.SetSprite("StandardBackgroundHighlight", imageComponent); } else { TextureHandler.SetSprite("StandardBackground", imageComponent); } } internal void SetPosition(int xPos, int yPos) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_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_0024: Unknown result type (might be due to invalid IL or missing references) ((Component)this).gameObject.GetComponent<RectTransform>().anchoredPosition = Vector2.right * (float)xPos + Vector2.up * (float)yPos; } internal void UpdateTextColor() { //IL_003e: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)goalText == (Object)null)) { Color white = default(Color); if (HasColor(GoalColors.myColorID)) { ((Color)(ref white))..ctor(0f, 1f, 0f); } else { white = Color.white; } ((Graphic)goalText.textComponent).color = new Color(white.r, white.g, white.b, UICanvas.GetInstance().CurrentTextOpacity); } } } internal class UIGoalColors : MonoBehaviour { private Texture2D? texture; private List<int> currentColorIDs = new List<int>(); private Texture2D Texture => ((Object)(object)texture != (Object)null) ? texture : (texture = ((Component)this).gameObject.GetComponent<Image>().sprite.texture); internal void AddColor(int colorID) { if (currentColorIDs.BinarySearch(colorID) < 0) { currentColorIDs.Add(colorID); currentColorIDs.Sort(); VogsBingoModPlugin.LogInfo("Refreshing colors for a goal"); RefreshColors(); } } internal void RemoveColor(int colorID) { currentColorIDs.Remove(colorID); RefreshColors(); } internal void SetColors(int[] colorIDs) { currentColorIDs.Clear(); foreach (int item in colorIDs) { currentColorIDs.Add(item); currentColorIDs.Sort(); } RefreshColors(); } internal bool HasColor(int colorID) { return currentColorIDs.Contains(colorID); } internal void ResetColors() { currentColorIDs.Clear(); TextureHandler.ClearTexture(Texture); } private void RefreshColors() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if (currentColorIDs.Count <= 0) { ResetColors(); return; } int num = (((Texture)Texture).width + ((Texture)Texture).height) / currentColorIDs.Count; for (int i = 0; i < ((Texture)Texture).width; i++) { for (int j = 0; j < ((Texture)Texture).height; j++) { int num2 = (i + ((Texture)Texture).height - 1 - j) / num; if (num2 >= currentColorIDs.Count) { num2 = currentColorIDs.Count - 1; } Texture.SetPixel(i, j, GoalColors.colorsList[currentColorIDs[num2]]); } } VogsBingoModPlugin.LogInfo("About to apply the texture change."); Texture.Apply(false); VogsBingoModPlugin.LogInfo("Done applying the texture change."); } } internal static class UIHelper { internal enum VisibilityState { Everything, JustBoard, Nothing } private const int defaultDropdownOptionWidth = 200; private const int defaultDropdownOptionHeight = 35; private const int defaultDropdownFontSize = 25; private const int defaultButtonFontSize = 30; private const int defaultTextInputFontSize = 30; private const int defaultMaxTextResize = 25; private const int defaultMinTextResize = 14; private const int defaultButtonHeight = 100; private const int defaultButtonWidth = 418; private const int defaultTextInputHeight = 66; private const int defaultTextInputWidth = 418; private const int defaultGoalWidth = 100; private const int defaultGoalHeight = 100; internal static UICanvas uiCanvas = UICanvas.GetInstance(); private static VisibilityState visibilityState = VisibilityState.Everything; internal static bool CanPlayGoalMarkSounds => (Object)(object)uiCanvas.revealCardButton != (Object)null && !((Component)uiCanvas.revealCardButton).gameObject.activeSelf; internal static IEnumerator NotifyOfRoomEnter_Main(RoomType roomType) { yield return null; UIButton? exitRoomButton = uiCanvas.exitRoomButton; if (exitRoomButton != null) { ((Component)exitRoomButton).gameObject.SetActive(true); } uiCanvas.SetDropdownOptions(roomType); GoalColors.SetMyColorToDefault(roomType); } internal static IEnumerator SetBoard_Main(string boardJson, RoomType roomType) { yield return null; string[] goalNames = JsonHelper.GetNamesFromBoard(boardJson); try { Automarker.SetGoalNames(goalNames); uiCanvas.SetGoalNames(Automarker.AddSupportNotations(goalNames), (roomType == RoomType.Bingosync) ? 5 : 6); new Texture2D(1, 1); } catch (Exception ex) { Exception e = ex; VogsBingoModPlugin.LogError(e); } uiCanvas.SetBoardColors(JsonHelper.GetColorsFromBoard(boardJson)); uiCanvas.HideGoals(); uiCanvas.HideCardLoadingText(); uiCanvas.ShowRevealCardButton(); } internal static IEnumerator NotifyOfConnectingToRoom_Main() { yield return null; UIButton? joinRoomButton = uiCanvas.joinRoomButton; if (joinRoomButton != null) { ((Component)joinRoomButton).gameObject.SetActive(false); } uiCanvas.CloseInfoTextIfOpen(); } internal static IEnumerator NotifyOfConnectingToRoomCancel_Main(int errorCode = 0) { yield return null; UIButton? joinRoomButton = uiCanvas.joinRoomButton; if (joinRoomButton != null) { ((Component)joinRoomButton).gameObject.SetActive(true); } string errorText = "An error occurred while connecting to the room "; TriggerErrorText(textToDisplay: (errorCode != 0 && errorCode == 1) ? (errorText + "(1). Check that your internet connection is working.") : (errorText + "(0). Check that the room link and password are correct."), errorText: uiCanvas.connectingErrorText); } internal static IEnumerator NotifyOfRoomExit_Main(int errorCode = 0) { yield return null; UIButton? joinRoomButton = uiCanvas.joinRoomButton; if (joinRoomButton != null) { ((Component)joinRoomButton).gameObject.SetActive(true); } uiCanvas.HideGoals(); UIButton? exitRoomButton = uiCanvas.exitRoomButton; if (exitRoomButton != null) { ((Component)exitRoomButton).gameObject.SetActive(false); } uiCanvas.HideRevealCardButton(); if (errorCode > 0) { TriggerErrorText(uiCanvas.connectingErrorText, $"An error occurred while trying to communicate with the room. ({errorCode})"); } } internal static IEnumerator UpdateGoal_Main(int colorID, bool shouldRemoveColor, int slotIndex) { yield return null; if (shouldRemoveColor) { uiCanvas.UnmarkGoal(colorID, slotIndex); yield break; } VogsBingoModPlugin.LogInfo($"Updating goal UI for slot {slotIndex} with color number {colorID}"); uiCanvas.MarkGoal(colorID, slotIndex); } internal static IEnumerator UnrevealCard_Main() { yield return null; uiCanvas.HideGoals(); uiCanvas.ShowCardLoadingText(); } internal static IEnumerator TriggerErrorText_Main() { yield return null; UIText? errorText = uiCanvas.errorText; if (errorText != null) { ((Component)errorText).gameObject.SetActive(true); } UIText? errorText2 = uiCanvas.errorText; Coroutiner.CreateCoroutine(DisableErrorText((errorText2 != null) ? ((Component)errorText2).gameObject : null)); } internal static IEnumerator SetConnectionPendingActive_Main(bool setActive) { yield return null; GameObject? connectionPendingIcon = uiCanvas.connectionPendingIcon; if (connectionPendingIcon != null) { connectionPendingIcon.SetActive(setActive); } } internal static IEnumerator DisableErrorText(GameObject? errorObject) { yield return (object)new WaitForSecondsRealtime(3f); if (errorObject != null) { errorObject.SetActive(false); } } internal static void CycleVisibility() { switch (visibilityState) { case VisibilityState.Everything: if (NetworkHandler.connectState == ConnectionState.Connected) { UIButton? exitRoomButton2 = uiCanvas.exitRoomButton; if (exitRoomButton2 != null) { ((Component)exitRoomButton2).gameObject.SetActive(false); } visibilityState = VisibilityState.JustBoard; } else if (NetworkHandler.connectState == ConnectionState.NotConnected) { UIButton? joinRoomButton2 = uiCanvas.joinRoomButton; if (joinRoomButton2 != null) { ((Component)joinRoomButton2).gameObject.SetActive(false); } visibilityState = VisibilityState.Nothing; } break; case VisibilityState.JustBoard: uiCanvas.boardObj.SetActive(false); visibilityState = VisibilityState.Nothing; break; case VisibilityState.Nothing: if (NetworkHandler.connectState == ConnectionState.Connected) { uiCanvas.boardObj.SetActive(true); UIButton? exitRoomButton = uiCanvas.exitRoomButton; if (exitRoomButton != null) { ((Component)exitRoomButton).gameObject.SetActive(true); } visibilityState = VisibilityState.Everything; } else { uiCanvas.boardObj.SetActive(true); UIButton? joinRoomButton = uiCanvas.joinRoomButton; if (joinRoomButton != null) { ((Component)joinRoomButton).gameObject.SetActive(true); } visibilityState = VisibilityState.Everything; } break; } } internal static void CycleVisibility(VisibilityState stateToCycleTo) { VisibilityState visibilityState = UIHelper.visibilityState; while (UIHelper.visibilityState != stateToCycleTo) { CycleVisibility(); if (UIHelper.visibilityState == visibilityState) { break; } } } internal static UIGoal CreateUIGoal(Transform parent, string objName, float xOffset, float yOffset, int slotIndex, float width = 100f, float height = 100f) { GameObject val = CreateUIObject(parent, objName, xOffset, yOffset, 100f, 100f, UIAnchor.TopRight); val.AddComponent<CanvasRenderer>(); Image val2 = SetupImageComponent(val, "StandardBackground", width, height); UIGoal uIGoal = val.AddComponent<UIGoal>(); uIGoal.slotIndex = slotIndex; uIGoal.goalColors = CreateUIGoalColorsObject(val.transform, objName + "Colors"); try { Text textComponent = CreateUIText(val.transform, objName + "Text", "Talk to Forge Daughter and Twelfth Architect", 14, 0f, 0f, width - 10f, height - 10f, supportRichText: true, (TextAnchor)4).textComponent; textComponent.resizeTextForBestFit = true; textComponent.resizeTextMaxSize = 25; textComponent.resizeTextMinSize = 14; } catch (Exception e) { VogsBingoModPlugin.LogError(e); } val.AddComponent<UIButton>().SetupCallbacks(uIGoal.OnLeftClick, uIGoal.OnRightClick); return uIGoal; } internal static UIText CreateUIText(Transform parent, string objName, string text = "", int fontSize = 14, float xOffset = 0f, float yOffset = 0f, float width = 100f, float height = 100f, bool supportRichText = true, TextAnchor anchor = (TextAnchor)4, Color? color = null, UIAnchor canvasAnchor = UIAnchor.MiddleCenter) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateUIObject(parent, objName, xOffset, yOffset, width, height, canvasAnchor); val.AddComponent<CanvasRenderer>(); Text val2 = val.AddComponent<Text>(); val2.text = text; val2.font = FontHandler.GetFont("LegacyRuntime"); val2.alignment = anchor; val2.fontSize = fontSize; val2.supportRichText = supportRichText; if (!color.HasValue) { color = Color.white; } Color value = color.Value; ((Graphic)val2).color = new Color(value.r, value.g, value.b, uiCanvas.CurrentTextOpacity); UIText uIText = val.AddComponent<UIText>(); uIText.textComponent = val2; return uIText; } internal static GameObject CreateUIObject(Transform parent, string objName, float xOffset = 0f, float yOffset = 0f, float width = 100f, float height = 100f, UIAnchor anchor = UIAnchor.MiddleCenter) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_003f: 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) GameObject val = new GameObject(objName); RectTransform val2 = val.AddComponent<RectTransform>(); val.transform.SetParent(parent); ((Transform)val2).localScale = Vector3.one; if (anchor == UIAnchor.TopRight) { val2.anchorMin = Vector2.one; val2.anchorMax = Vector2.one; val2.pivot = Vector2.one; } val2.SetSizeWithCurrentAnchors((Axis)0, width); val2.SetSizeWithCurrentAnchors((Axis)1, height); val2.anchoredPosition = Vector2.right * xOffset + Vector2.up * yOffset; return val; } internal static UIButton CreateUIButton(Transform parent, string objName, Action? leftClickCallback, Action? rightClickCallback, string displayText, float xOffset = 0f, float yOffset = 0f, UIAnchor anchor = UIAnchor.MiddleCenter, float width = 418f, float height = 100f) { GameObject val = CreateUIObject(parent, objName, xOffset, yOffset, 100f, 100f, anchor); val.AddComponent<CanvasRenderer>(); SetupImageComponent(val, "StandardBackground", width, height); UIButton uIButton = val.AddComponent<UIButton>(); uIButton.SetupCallbacks(leftClickCallback, rightClickCallback); CreateUIText(val.transform, objName + "Text", displayText, 30, 0f, 0f, width - 20f, height, supportRichText: true, (TextAnchor)4); return uIButton; } internal static UITextInput CreateUITextInput(Transform parent, string objName, string textWhenEmpty, float xOffset = 0f, float yOffset = 0f, bool isPassword = false, string startingText = "") { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateUIObject(parent, objName, xOffset, yOffset); SetupImageComponent(val, "StandardBackground", 418f, 66f); Transform transform = val.transform; string objName2 = objName + "Text"; string empty = string.Empty; Rect rect = val.GetComponent<RectTransform>().rect; CreateUIText(transform, objName2, empty, 30, 0f, 0f, ((Rect)(ref rect)).width, 100f, supportRichText: true, (TextAnchor)4); UITextInput uITextInput = val.AddComponent<UITextInput>(); InputField val2 = val.AddComponent<InputField>(); if (isPassword) { val2.contentType = (ContentType)7; } val2.textComponent = val.GetComponentInChildren<Text>(true); ((UnityEvent<string>)(object)val2.onValueChanged).AddListener((UnityAction<string>)uITextInput.UpdatePlaceholder); uITextInput.placeholderObj = ((Component)CreateUIText(val.transform, objName + "Placeholder", textWhenEmpty, 30, 0f, 0f, 418f, 66f, supportRichText: true, (TextAnchor)4, Color.grey)).gameObject; val2.text = startingText; return uITextInput; } internal static void SetupJoinRoomFieldNavigation() { if ((Object)(object)uiCanvas.roomUrlInputField != (Object)null && (Object)(object)uiCanvas.nicknameInputField != (Object)null && (Object)(object)uiCanvas.passwordInputField != (Object)null && (Object)(object)uiCanvas.joinRoomButton != (Object)null) { ((UnityEvent<string>)(object)uiCanvas.roomUrlInputField.InputComponent.onSubmit).AddListener((UnityAction<string>)uiCanvas.nicknameInputField.Select); ((UnityEvent<string>)(object)uiCanvas.nicknameInputField.InputComponent.onSubmit).AddListener((UnityAction<string>)uiCanvas.passwordInputField.Select); ((UnityEvent<string>)(object)uiCanvas.passwordInputField.InputComponent.onSubmit).AddListener((UnityAction<string>)uiCanvas.joinRoomButton.LeftClick); } } internal static UIDropdown CreateUIDropdown(Transform parent, string objName, UnityAction<int> callbackOnValueChanged, List<OptionData> optionData, float xOffset = 0f, float yOffset = 0f) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) int count = optionData.Count; float width = 200f; float num = 35f; GameObject val = CreateUIObject(parent, objName, xOffset, yOffset); val.AddComponent<CanvasRenderer>(); Image val2 = SetupImageComponent(val, "StandardBackground", 200f, 35f); UIDropdown uIDropdown = val.AddComponent<UIDropdown>(); UIText uIText = CreateUIText(val.transform, "Label", " red", 25, 0f, 0f, width, num, supportRichText: true, (TextAnchor)3); ((Dropdown)uIDropdown).captionText = uIText.textComponent; GameObject val3 = CreateUIObject(val.transform, "Template", 0f, (float)(-(count + 1)) * num / 2f, width, num); val3.SetActive(false); val3.AddComponent<CanvasRenderer>(); Image imgComponent = val3.AddComponent<Image>(); TextureHandler.SetSprite("DropdownFullPanel", imgComponent); ((Dropdown)uIDropdown).template = val3.GetComponent<RectTransform>(); GameObject val4 = new GameObject("Toggle"); RectTransform val5 = val4.AddComponent<RectTransform>(); val4.transform.SetParent(val3.transform); val5.anchoredPosition = Vector2.zero; val5.SetSizeWithCurrentAnchors((Axis)1, num); val4.AddComponent<Toggle>(); UIText uIText2 = CreateUIText(val4.transform, "Item Text", "Placeholder Option", 25, 0f, 0f, width, num, supportRichText: true, (TextAnchor)3); ((Dropdown)uIDropdown).itemText = uIText2.textComponent; uIDropdown.SetOptions(optionData); ((UnityEvent<int>)(object)((Dropdown)uIDropdown).onValueChanged).AddListener(callbackOnValueChanged); return uIDropdown; } internal static GameObject CreateUIImage(Transform parent, string objName, string imgName, float xOffset = 0f, float yOffset = 0f, float width = -1f, float height = -1f, UIAnchor anchor = UIAnchor.MiddleCenter) { GameObject val = CreateUIObject(parent, objName, xOffset, yOffset, 100f, 100f, anchor); SetupImageComponent(val, imgName, width, height); return val; } internal static void RevealCardPressed() { if ((Object)(object)uiCanvas.revealCardButton != (Object)null && ((Component)uiCanvas.revealCardButton).gameObject.activeInHierarchy) { uiCanvas.revealCardButton.LeftClick(); } } internal static void CycleOpacity() { if (!IsTyping()) { uiCanvas.CycleOpacity(); } } internal static void MarkGoal(int slotIndex, bool remove) { NetworkHandler.MarkGoal(slotIndex, remove, GoalColors.MyColorName); } internal static bool MarkIfUnmarkedGoal(int slotIndex, bool debug = false) { if (uiCanvas.CanMarkGoals && !uiCanvas.HasColor(slotIndex, GoalColors.myColorID)) { if (debug) { VogsBingoModPlugin.LogInfo($"Slot number {slotIndex} is marking as color {GoalColors.IDToName(GoalColors.myColorID)}."); } MarkGoal(slotIndex, remove: false); return true; } if (debug) { VogsBingoModPlugin.LogInfo($"Slot number {slotIndex} could not be marked, either due to marking being disabled or the player's color is already present."); } return false; } internal static void UpdateUIScale() { uiCanvas.UpdateUIScale(); } private static Image SetupImageComponent(GameObject objToAttachTo, string imageName = "", float width = -1f, float height = -1f) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) RectTransform component = objToAttachTo.GetComponent<RectTransform>(); Image val = objToAttachTo.AddComponent<Image>(); TextureHandler.SetSprite(imageName, val); Rect rect = val.sprite.rect; float num = ((Rect)(ref rect)).width; rect = val.sprite.rect; float num2 = ((Rect)(ref rect)).height; if (width >= 0f) { num = width; } if (height >= 0f) { num2 = height; } component.SetSizeWithCurrentAnchors((Axis)0, num); component.SetSizeWithCurrentAnchors((Axis)1, num2); if (TextureHandler.ShouldSliceSprite(imageName)) { val.type = (Type)1; val.fillCenter = true; } ((Graphic)val).color = new Color(((Graphic)val).color.r, ((Graphic)val).color.g, ((Graphic)val).color.b, uiCanvas.CurrentOpacity); return val; } private static UIGoalColors CreateUIGoalColorsObject(Transform parent, string objName) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateUIObject(parent, objName); val.AddComponent<CanvasRenderer>(); Image val2 = val.AddComponent<Image>(); Sprite val3 = TextureHandler.CreateGoalColorsSprite(); ((Graphic)val2).color = new Color(((Graphic)val2).color.r, ((Graphic)val2).color.g, ((Graphic)val2).color.b, uiCanvas.CurrentOpacity); val2.sprite = val3; RectTransform component = val.GetComponent<RectTransform>(); Rect rect = val3.rect; component.SetSizeWithCurrentAnchors((Axis)0, ((Rect)(ref rect)).width); rect = val3.rect; component.SetSizeWithCurrentAnchors((Axis)1, ((Rect)(ref rect)).height); return val.AddComponent<UIGoalColors>(); } internal static bool IsTyping() { if ((Object)(object)uiCanvas.roomUrlInputField != (Object)null && (Object)(object)uiCanvas.nicknameInputField != (Object)null && (Object)(object)uiCanvas.passwordInputField != (Object)null) { return uiCanvas.roomUrlInputField.IsFocused() || uiCanvas.nicknameInputField.IsFocused() || uiCanvas.passwordInputField.IsFocused(); } return true; } internal static void TriggerErrorText(UIText? errorText, string textToDisplay) { errorText?.SetText(textToDisplay); if (errorText != null) { ((Component)errorText).gameObject.SetActive(true); } Coroutiner.CreateCoroutine(DisableErrorText((errorText != null) ? ((Component)errorText).gameObject : null)); } internal static void UpdateGoalTextColor() { uiCanvas.UpdateGoalTextColor(); } } internal class UIText : MonoBehaviour { internal Text textComponent; internal void SetText(string text) { if ((Object)(object)textComponent == (Object)null) { textComponent = ((Component)this).gameObject.GetComponentInChildren<Text>(true); } textComponent.text = text; } private void Update() { if ((Object)(object)textComponent != (Object)null && (Object)(object)textComponent.font == (Object)null) { textComponent.font = FontHandler.GetFont("LegacyRuntime"); } } } internal class UITextInput : MonoBehaviour { internal GameObject placeholderObj; private InputField? inputComponent; internal InputField InputComponent => ((Object)(object)inputComponent != (Object)null) ? inputComponent : (inputComponent = ((Component)this).gameObject.GetComponent<InputField>()); internal string GetText() { return InputComponent.text; } internal void UpdatePlaceholder(string currentText) { if (currentText.Equals("")) { placeholderObj.SetActive(true); } else { placeholderObj.SetActive(false); } } internal bool IsFocused() { return InputComponent.isFocused; } internal void Select(string value) { ((Selectable)InputComponent).Select(); } } } namespace VogsBingoMod.Automarking { internal class Automarker : MonoBehaviour { private static float currentTimer = 1f; private static Dictionary<string, bool> nativeSupportedGoals = GetNativeSupportedGoals(); private static Dictionary<int, List<int>> currentGoals = new Dictionary<int, List<int>>(); internal static void SetGoalNames(string[] goalNames) { currentGoals.Clear(); for (int i = 0; i < goalNames.Length; i++) { int num = GoalHelper.NameToID(goalNames[i].ToLower()); if (num < 0) { num = -i - 1; } if (currentGoals.ContainsKey(num)) { currentGoals[num].Add(i); continue; } currentGoals.Add(num, new List<int>(1) { i }); } } internal static string[] AddSupportNotations(string[] goalNames) { for (int i = 0; i < goalNames.Length; i++) { string text = goalNames[i].ToLower(); if (nativeSupportedGoals.TryGetValue(text, out var value)) { if (!value) { goalNames[i] += " (U)"; } } else if (GoalHelper.HasRegisteredGoal(text)) { goalNames[i] += "*"; } else { goalNames[i] += " (M)"; } } return goalNames; } internal static bool BoardHasGoal(int goalID) { return currentGoals.ContainsKey(goalID); } internal static bool BoardHasGoal(GoalID goalID) { return BoardHasGoal((int)goalID); } internal static bool MarkIfAvailable(int goalID, bool debug = false) { if ((Object)(object)UICanvas.GetInstance().revealCardButton == (Object)null) { VogsBingoModPlugin.LogError("Failed to mark a goal because the reveal card button does not exist."); return false; } if (BoardHasGoal(goalID)) { if (debug) { VogsBingoModPlugin.LogInfo($"Goal ID {goalID} was found on the board at slot number {currentGoals[goalID]} (0 indexed)."); } bool result = true; foreach (int item in currentGoals[goalID]) { if (!UIHelper.MarkIfUnmarkedGoal(item, debug)) { result = false; } } return result; } if (debug) { VogsBingoModPlugin.LogInfo($"Goal ID {goalID} was not found on the board."); } return false; } internal static void MarkIfAvailable(GoalID goalID) { MarkIfAvailable((int)goalID); } internal static string GetGoalsJson() { byte[] resourceAsByteArray = Resources.GetResourceAsByteArray("VogsBingoMod.Automarking.Goals.json"); if (resourceAsByteArray == null) { VogsBingoModPlugin.LogError("Could not retrieve the goal support json."); } return Encoding.UTF8.GetString(resourceAsByteArray); } private static Dictionary<string, bool> GetNativeSupportedGoals() { string goalsJson = GetGoalsJson(); return JsonHelper.GetNativeSupportedGoals(goalsJson); } internal static void UpdateSilkSkills() { int num = 0; if (PlayerData.instance.hasNeedleThrow) { num++; } if (PlayerData.instance.hasThreadSphere) { num++; MarkIfAvailable(GoalID.ThreadStorm); } if (PlayerData.instance.hasSilkCharge) { num++; MarkIfAvailable(GoalID.Sharpdart); } if (PlayerData.instance.hasParry) { num++; } if (PlayerData.instance.hasSilkBomb) { num++; } if (PlayerData.instance.hasSilkBossNeedle) { num++; MarkIfAvailable(GoalID.PaleNails); } if (num >= 3) { MarkIfAvailable(GoalID.ThreeSilkSkills); if (num >= 4) { MarkIfAvailable(GoalID.FourSilkSkills); } } } internal static void CheckIfGoalCompleted(GoalID goalID, string context = "") { bool flag = false; switch (goalID) { case GoalID.CompassPendantBrooch: flag = CheckIfToolsObtained(context, "Compass", "Bone Necklace", "Rosary Magnet"); break; case GoalID.StraightThreefoldandLongPin: flag = CheckIfToolsObtained(context, "Straight Pin", "Tri Pin", "Harpoon"); break; case GoalID.DeadBugsPurseaSilkeater: flag = CheckIfToolsObtained(context, "Dead Mans Purse") && (int)SaveData.Silkeaters > 0; break; case GoalID.BarbedBraceletFracturedMask: flag = CheckIfToolsObtained(context, "Fractured Mask", "Barbed Wire"); break; case GoalID.MagnetiteDiceMagnetiteBrooch: flag = CheckIfToolsObtained(context, "Rosary Magnet", "Magnetite Dice"); break; case GoalID.WardingBellClawMirror: flag = CheckIfToolsObtained(context, "Bell Bind", "Dazzle Bind"); break; case GoalID.WardingBellSawtoothCirclet: flag = CheckIfToolsObtained(context, "Bell Bind", "Brolly Spike"); break; case GoalID.MagmaBellCurveclaw: flag = CheckIfToolsObtained(context, "Lava Charm", "Curve Claws"); break; case GoalID.WeightedBeltAscendantsGrip: flag = CheckIfToolsObtained(context, "Weighted Anklet", "Wallcling"); break; case GoalID.ScuttlebraceSilkspeed: flag = CheckIfToolsObtained(context, "Scuttlebrace", "Sprintmaster"); break; case GoalID.PimpilloVoltvessels: flag = CheckIfToolsObtained(context, "Lightning Rod", "Pimpilo"); break; case GoalID.PollipPouchStingShard: flag = CheckIfToolsObtained(context, "Sting Shard", "Poison Pouch"); break; case GoalID.WeavelightInjectorBand: flag = CheckIfToolsObtained(context, "White Ring", "Quickbind"); break; case GoalID.BlastedStepsSilkeaterCraftmetal: try { flag = (bool)SaveData.BlastedSilkeater && (context.Equals("craftmetal") || ((PersistentItemDataCollection<bool, SerializableBoolData>)(object)SceneData.instance.persistentBools).scenes["Coral_32"]["Collectable Item Pickup - Tool Metal"].Value); } catch (Exception) { } break; case GoalID.BothFreeSimpleKeys: flag = (bool)SaveData.SinnersKey && (bool)SaveData.KarakKey; break; case GoalID.ShellwoodVaultsMaskShards: flag = (bool)SaveData.ShellwoodMaskShard && (bool)SaveData.VaultsMaskShard; break; case GoalID.CogworkClapperJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.CogworkClapperKilled; break; case GoalID.ImobaJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.ImobaKilled; break; case GoalID.SquirrmJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.SquirrmKilled; break; case GoalID.GromlingJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.GromlingKilled; break; case GoalID.CraggliteJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.CraggliteKilled; break; case GoalID.DeepDiverJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.DeepDiverKilled; break; case GoalID.SkullwingJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.SkullwingKilled; break; case GoalID.MiteMotherJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.MiteMotherKilled; break; case GoalID.UnravelledJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.UnravelledKilled; break; case GoalID.ShadowChargerJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.ShadowChargerKilled; break; case GoalID.CovetousPilgrimJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.CovetousPilgrimKilled; break; case GoalID.MassiveMossgrubJournalEntry: flag = (bool)SaveData.HasJournal && (bool)SaveData.MassiveMossgrubKilled; break; case GoalID.TalktoStyxHuntress: flag = (bool)SaveData.HuntressSpokenTo && (bool)SaveData.StyxSpokenTo; break; case GoalID.TalktoForgeDaughterandTwelfthArchitect: flag = (bool)SaveData.TwelfthArchitectSpokenTo && (bool)SaveData.ForgeDaughterSpokenTo; break; case GoalID.BreakBothofStyxsOneways: flag = (bool)SaveData.SinnersStyxWallBroken && (bool)SaveData.GreymoorStyxWallBroken; break; case GoalID.BothVendorSimpleKeys: flag = (bool)SaveData.JubilanaKeyBought && (bool)SaveData.PebbKeyBought; break; case GoalID.GreymoorFleasTwoKratt: flag = (bool)SaveData.FleaCrawLake && (bool)SaveData.FleaGreymoorTower && (bool)SaveData.FleaKratt; break; case GoalID.FarFieldsFleasTwo: flag = (bool)SaveData.FleaFarFieldsCage && (bool)SaveData.FleaPilgrimsRest; break; case GoalID.ShellwoodBellhartFleasTwo: flag = (bool)SaveData.FleaShellwood && (bool)SaveData.FleaBellvein; break; case GoalID.DeepDocksFleasThree: flag = (bool)SaveData.FleaSwiftStep && (bool)SaveData.FleaDeeperDocks && (bool)SaveData.FleaDeepDocksBellway; break; case GoalID.WormwaysBlastedStepsFleasTwo: flag = (bool)SaveData.FleaWormways && (bool)SaveData.FleaBlastedSteps; break; case GoalID.UnderworksFleasTwo: flag = (bool)SaveData.FleaUnderworksCauldron && (bool)SaveData.FleaUnderworksWispThicket; break; case GoalID.LowerBilewaterHuntersMarchFleasTwo: flag = (bool)SaveData.FleaBilewaterThieves && (bool)SaveData.FleaHuntersMarch; break; case GoalID.SinnersRoadVaultsFleasTwo: flag = (bool)SaveData.FleaSinnersRoad && (bool)SaveData.FleaVaults; break; case GoalID.DeepDocksSpoolFragmentsTwo: flag = (bool)SaveData.DeepDocksSpoolFragNearSpa && (bool)SaveData.DeeperDocksSpoolFrag; break; case GoalID.UnderworksSpoolFragmentsTwo: flag = (bool)SaveData.UnderworksArenaSpoolFrag && (bool)SaveData.UnderworksLibrary_11bSpoolFrag; break; case GoalID.HaveSixRosaryStringsnopurchasing: flag = SaveData.automarkRosaryStringHandler.GetNonPurchasedStringsCurrentlyHeld() + SaveData.automarkRosaryStringHandler.GetFrayedStringsCurrentlyHeld() >= 6; break; case GoalID.BreakEightRosaryStringsnopurchasing: flag = SaveData.automarkRosaryStringHandler.GetNonPurchasedStringsBroken() + SaveData.automarkRosaryStringHandler.GetFrayedStringsBroken() >= 8; break; case GoalID.TalktoGrishkinandGilly: flag = (bool)SaveData.GillySpokenTo && (bool)SaveData.GrishkinSpokenTo; break; default: VogsBingoModPlugin.LogError($"There isn't a check for goalID {goalID}"); break; } if (flag) { MarkIfAvailable(goalID); } } internal static void CheckIfGoalsCompleted(GoalID[] goalIDs) { foreach (GoalID goalID in goalIDs) { CheckIfGoalCompleted(goalID); } } internal static void CheckIfGoalsCompleted(AutomarkIntValue[] values, int currentValue) { foreach (AutomarkIntValue markValue in values) { CheckIfGoalCompleted(markValue, currentValue); } } internal static void CheckIfGoalCompleted(AutomarkIntValue markValue, int currentValue) { VogsBingoModPlugin.LogInfo($"Checking if goal {markValue.goalToMark} is finished"); if (currentValue >= markValue.markValue) { VogsBingoModPlugin.LogInfo($"Goal {markValue.goalToMark} is finished, checking if the goal is on the board..."); MarkIfAvailable(markValue.goalToMark); } } internal static void RunFrameChecks() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 currentTimer -= Time.unscaledDeltaTime; if (!(currentTimer < 0f)) { return; } currentTimer = 1f; if (PlayerData.instance != null) { if ((int)PlayerData.instance.CaravanTroupeLocation == 2) { MarkIfAvailable(GoalID.MeetCaravanattheGrandGateTwelve); } else if ((int)PlayerData.instance.CaravanTroupeLocation == 1) { MarkIfAvailable(GoalID.MeettheCaravaninGreymoor); } if (PlayerData.instance.HasMelodyArchitect) { MarkIfAvailable(GoalID.ArchitectsMelody); } if (PlayerData.instance.HasMelodyConductor) { MarkIfAvailable(GoalID.ConductorsMelody); } if (PlayerData.instance.HasMelodyLibrarian) { MarkIfAvailable(GoalID.VaultkeepersMelody); } if (PlayerData.instance.act3_wokeUp) { MarkIfAvailable(GoalID.EnterActThree); } if (PlayerData.instance.mapBoolList != null && SaveData.MapCount.Value != PlayerData.instance.mapBoolList.HasCount) { SaveData.MapCount.Value = PlayerData.instance.mapBoolList.HasCount; } } } internal static void UpdateFleas(boo