Decompiled source of SBGL UnifiedMod v0.1.1
SBGL.UnifiedMod.dll
Decompiled a day 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using FMODUnity; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SBGL.UnifiedMod.Core; using SBGL.UnifiedMod.Features; using SBGL.UnifiedMod.Features.CompetitivePluginCheck; using SBGL.UnifiedMod.Patches; using SBGL.UnifiedMod.Utils; using SBGLLiveLeaderboard; using SBGLeagueAutomation; using Steamworks; using Steamworks.Data; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("GameAssembly")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SBGL.UnifiedMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.0.1.0")] [assembly: AssemblyInformationalVersion("0.0.1+c3f052b0dea59e1a22071a28f40a279b9dc1c3e3")] [assembly: AssemblyProduct("Super Battle Golf League Unified Mod")] [assembly: AssemblyTitle("SBGL.UnifiedMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 SBGLeagueAutomation { public class SBGLPlugin : MonoBehaviour { [HarmonyPatch] private static class CourseManager_RpcInformEndingCourse_Patch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("CourseManager"); if (type == null) { return null; } return AccessTools.Method(type, "UserCode_RpcInformEndingCourse", (Type[])null, (Type[])null); } private static void Postfix() { try { SBGLPlugin sBGLPlugin = Object.FindAnyObjectByType<SBGLPlugin>((FindObjectsInactive)1); if ((Object)(object)sBGLPlugin != (Object)null) { sBGLPlugin.OnCourseRpcInformEndingCourse(); } } catch (Exception arg) { Debug.Log((object)$"[SBGL.Matchmaking] CourseManager.RpcInformEndingCourse postfix error: {arg}"); } } } public class PlayerProfile { public string id; public string display_name; public string region; public string state_province; public float current_mmr; } public class MatchmakingSession { public string id; public string lobby_name; public string lobby_password; public string host_player_id; public string status; public string match_id; public string lobby_id; public string host_steam_id; public string steam_lobby_link; public List<string> player_ids; public List<string> accepted_player_ids; public string match_type; public string selected_course; public int season; } public class MatchStats { public string matchmaking_session_id; public string match_id; public string player_id; public string player_name; public string match_date; public int duration_seconds; public bool is_host; public string status; public string course_name; public string match_type; public int season; } private class CachedLeaderboardPlayer { public string Name; public int BaseScore; public string RawStrokes; public string MMR; public int ProjectedDelta; } public struct PlayerData { public string name; public string mmr; } [CompilerGenerated] private sealed class <>c__DisplayClass132_0 { public string playerId; public string resolvedDisplayName; public int casualMatchesPlayed; public bool updated; public SBGLPlugin <>4__this; internal void <IncrementCasualMatchesPlayedForActivePlayers>b__2(string id) { playerId = id; } internal void <IncrementCasualMatchesPlayedForActivePlayers>b__3(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { resolvedDisplayName = ((string)val["display_name"]) ?? resolvedDisplayName; int.TryParse(((object)val["casual_matches_played"])?.ToString() ?? "0", out casualMatchesPlayed); } } internal void <IncrementCasualMatchesPlayedForActivePlayers>b__4(string res) { if (<>4__this.ParseApiSingleObject(res) != null) { updated = true; } } } [CompilerGenerated] private sealed class <>c__DisplayClass148_0 { public bool readSucceeded; public string existingScreenshotUrl; public bool uploadSucceeded; public SBGLPlugin <>4__this; internal void <UploadCapturedMatchScreenshotIfNeeded>b__0(string res) { readSucceeded = true; JObject val = <>4__this.ParseApiSingleObject(res); existingScreenshotUrl = (string)((val != null) ? val["screenshot_url"] : null); } internal void <UploadCapturedMatchScreenshotIfNeeded>b__1(string res) { JObject val = <>4__this.ParseApiSingleObject(res); uploadSucceeded = val != null; } } [CompilerGenerated] private sealed class <>c__DisplayClass148_1 { public string uploadedFileUrl; internal void <UploadCapturedMatchScreenshotIfNeeded>b__2(string url) { uploadedFileUrl = url; } } [CompilerGenerated] private sealed class <>c__DisplayClass165_0 { public string existingMatchId; internal void <WaitForExistingMatchBeforeFallback>b__0(string id) { existingMatchId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass167_0 { public SBGLPlugin <>4__this; public string resolvedId; internal void <ResolveExistingMatchEntryId>b__0(string res) { JObject val = <>4__this.ParseApiObjectList(res).FirstOrDefault(); if (val != null) { resolvedId = (string)val["id"]; } } } [CompilerGenerated] private sealed class <>c__DisplayClass169_0 { public SBGLPlugin <>4__this; public string sourceTag; } [CompilerGenerated] private sealed class <>c__DisplayClass169_1 { public string existingEntryId; public string createdEntryId; public <>c__DisplayClass169_0 CS$<>8__locals1; internal void <EnsureMatchEntryForPlayer>b__0(string id) { existingEntryId = id; } internal void <EnsureMatchEntryForPlayer>b__1(string res) { try { JObject val = CS$<>8__locals1.<>4__this.ParseApiSingleObject(res); if (val != null) { createdEntryId = (string)val["id"]; } } catch (Exception ex) { CS$<>8__locals1.<>4__this.Log("<color=yellow>[" + CS$<>8__locals1.sourceTag + "] Could not parse MatchEntry response: " + ex.Message + "</color>"); } } } [CompilerGenerated] private sealed class <>c__DisplayClass182_0 { public SBGLPlugin <>4__this; public string existingId; internal void <MatchmakingLoop>b__0(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { <>4__this._currentQueueId = existingId; <>4__this._webStatus = "QUEUED"; <>4__this.Log("<color=green>[Queue] ✓ Updated existing entry " + existingId + " with has_mod:true.</color>"); } else { <>4__this.Log("<color=red>[Queue] Failed to update existing entry " + existingId + ".</color>"); } } internal void <MatchmakingLoop>b__1(string res) { JObject val = <>4__this.ParseApiSingleObject(res); <>4__this._currentQueueId = ((string)((val != null) ? val["id"] : null)) ?? <>4__this._currentQueueId; <>4__this._webStatus = "QUEUED"; <>4__this.Log("<color=green>[Queue] ✓ Created new entry " + <>4__this._currentQueueId + " with has_mod:true.</color>"); } } [CompilerGenerated] private sealed class <>c__DisplayClass183_0 { public SBGLPlugin <>4__this; public bool leaveSuccess; internal void <LeaveQueue>b__0(string res) { if (<>4__this.ParseApiSingleObject(res) != null) { <>4__this.ResetPluginState(); <>4__this.Log("✓ Left Queue."); leaveSuccess = true; } } } [CompilerGenerated] private sealed class <>c__DisplayClass195_0 { public string existingMatchId; internal void <CreateMatchAndEntriesInternal>b__0(string id) { existingMatchId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass195_1 { public string apiMatchId; internal void <CreateMatchAndEntriesInternal>b__1(string id) { apiMatchId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass195_2 { public string fallbackFoundId; internal void <CreateMatchAndEntriesInternal>b__2(string id) { fallbackFoundId = id; } internal void <CreateMatchAndEntriesInternal>b__3(string id) { fallbackFoundId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass195_3 { public string finalCheckId; public SBGLPlugin <>4__this; internal void <CreateMatchAndEntriesInternal>b__4(string res) { JObject obj = <>4__this.SelectNewestReusableMatch(<>4__this.ParseApiObjectList(res)); finalCheckId = (string)((obj != null) ? obj["id"] : null); } } [CompilerGenerated] private sealed class <>c__DisplayClass195_4 { public string newMatchId; internal void <CreateMatchAndEntriesInternal>b__5(string id) { newMatchId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass195_5 { public string linkMatchId; public SBGLPlugin <>4__this; internal void <CreateMatchAndEntriesInternal>b__6(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { <>4__this._currentSession.match_id = linkMatchId; <>4__this.Log("<color=green>[Match Creation] ✓ MatchmakingSession " + <>4__this._currentSession.id + " linked to match: " + linkMatchId + "</color>"); } else { <>4__this.Log("<color=yellow>[Match Creation] Could not confirm MatchmakingSession update</color>"); } } } [CompilerGenerated] private sealed class <>c__DisplayClass195_6 { public string playerId; public SBGLPlugin <>4__this; } [CompilerGenerated] private sealed class <>c__DisplayClass195_7 { public string playerName; public string preMatchMmr; public string entryId; public <>c__DisplayClass195_6 CS$<>8__locals1; internal void <CreateMatchAndEntriesInternal>b__7(string res) { try { JObject val = CS$<>8__locals1.<>4__this.ParseApiSingleObject(res); if (val != null) { playerName = (string)val["display_name"]; if (string.IsNullOrEmpty(playerName)) { CS$<>8__locals1.<>4__this.Log("<color=yellow>[Match Creation] Player " + CS$<>8__locals1.playerId + " has no display_name, using ID</color>"); playerName = CS$<>8__locals1.playerId; } object obj = val["current_mmr"]; if (obj != null) { preMatchMmr = obj.ToString(); } CS$<>8__locals1.<>4__this.Log("<color=cyan>[Match Creation] Fetched player: " + playerName + " (MMR: " + preMatchMmr + ")</color>"); } else { CS$<>8__locals1.<>4__this.Log("<color=yellow>[Match Creation] Failed to fetch Player " + CS$<>8__locals1.playerId + " - response null</color>"); playerName = CS$<>8__locals1.playerId; } } catch (Exception ex) { CS$<>8__locals1.<>4__this.Log("<color=yellow>[Match Creation] Error fetching Player " + CS$<>8__locals1.playerId + ": " + ex.Message + "</color>"); playerName = CS$<>8__locals1.playerId; } } internal void <CreateMatchAndEntriesInternal>b__8(string id) { entryId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass197_0 { public bool shouldUpload; internal void <MonitorAndUpdateScores>b__3(bool ok) { shouldUpload = ok; } } [CompilerGenerated] private sealed class <>c__DisplayClass197_1 { public string playerId; public string entryId; public SBGLPlugin <>4__this; internal void <MonitorAndUpdateScores>b__4(string id) { playerId = id; } internal void <MonitorAndUpdateScores>b__6(string id) { entryId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass197_2 { public string preMatchMmr; public <>c__DisplayClass197_1 CS$<>8__locals1; internal void <MonitorAndUpdateScores>b__5(string res) { JObject val = CS$<>8__locals1.<>4__this.ParseApiSingleObject(res); object obj = ((val != null) ? val["current_mmr"] : null); if (obj != null) { preMatchMmr = obj.ToString(); } } } [CompilerGenerated] private sealed class <>c__DisplayClass198_0 { public SBGLPlugin <>4__this; public string playerName; internal void <UpdateMatchEntry>b__0(string res) { try { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { <>4__this.Log("<color=green>[Score Update] ✓ MatchEntry updated for " + playerName + "</color>"); } } catch (Exception ex) { <>4__this.Log("<color=yellow>[Score Update] Could not update MatchEntry: " + ex.Message + "</color>"); } } } [CompilerGenerated] private sealed class <>c__DisplayClass202_0 { public SBGLPlugin <>4__this; public string resolvedId; public string normalizedName; public Func<JObject, bool> <>9__3; internal void <ResolvePlayerIdByNameFromApi>b__0(string res) { JObject val = <>4__this.ParseApiObjectList(res)?.FirstOrDefault(); if (val != null) { resolvedId = (string)val["id"]; } } internal void <ResolvePlayerIdByNameFromApi>b__1(string res) { JObject val = <>4__this.ParseApiObjectList(res)?.FirstOrDefault(); if (val != null) { resolvedId = (string)val["id"]; } } internal void <ResolvePlayerIdByNameFromApi>b__2(string res) { List<JObject> list = <>4__this.ParseApiObjectList(res); if (list != null && list.Count != 0) { JObject val = ((IEnumerable<JObject>)list).FirstOrDefault((Func<JObject, bool>)((JObject r) => string.Equals((string)((r != null) ? r["display_name"] : null), normalizedName, StringComparison.OrdinalIgnoreCase) || string.Equals((string)((r != null) ? r["ign"] : null), normalizedName, StringComparison.OrdinalIgnoreCase))); JObject val2 = val ?? list.FirstOrDefault(); if (val2 != null) { resolvedId = (string)val2["id"]; } } } internal bool <ResolvePlayerIdByNameFromApi>b__3(JObject r) { return string.Equals((string)((r != null) ? r["display_name"] : null), normalizedName, StringComparison.OrdinalIgnoreCase) || string.Equals((string)((r != null) ? r["ign"] : null), normalizedName, StringComparison.OrdinalIgnoreCase); } } [CompilerGenerated] private sealed class <>c__DisplayClass203_0 { public SBGLPlugin <>4__this; public int actualPlayerCount; public string source; internal void <UpdateMatchPlayerCountIfNeeded>b__0(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { <>4__this._lastUploadedPlayerCount = actualPlayerCount; <>4__this.Log($"<color=green>[Match Count] ✓ Updated match player_count to {actualPlayerCount} ({source})</color>"); } else { <>4__this.Log($"<color=yellow>[Match Count] Could not confirm player_count update to {actualPlayerCount} ({source})</color>"); } } } [CompilerGenerated] private sealed class <>c__DisplayClass210_0 { public SBGLPlugin <>4__this; public HashSet<string> knownNames; public Action<string> <>9__3; internal void <EnrichPlayerIdsFromLeaderboard>b__3(string res) { JObject val = <>4__this.ParseApiSingleObject(res); string text = (string)((val != null) ? val["display_name"] : null); if (!string.IsNullOrWhiteSpace(text)) { knownNames.Add(text); } } } [CompilerGenerated] private sealed class <>c__DisplayClass210_1 { public string playerIdFromName; internal void <EnrichPlayerIdsFromLeaderboard>b__4(string id) { playerIdFromName = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass211_0 { public SBGLPlugin <>4__this; public Dictionary<string, float> finalPreMmrByName; } [CompilerGenerated] private sealed class <>c__DisplayClass211_1 { public CachedLeaderboardPlayer p; public <>c__DisplayClass211_0 CS$<>8__locals1; internal void <FinalizeMatchStats>b__3(string res) { JObject val = CS$<>8__locals1.<>4__this.ParseApiSingleObject(res); object obj = ((val != null) ? val["current_mmr"] : null); if (obj != null && float.TryParse(obj.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { CS$<>8__locals1.finalPreMmrByName[p.Name] = result; CS$<>8__locals1.<>4__this.Log($"<color=cyan>[Match Finalize] MMR for {p.Name} resolved from API: {result}</color>"); } } } [CompilerGenerated] private sealed class <>c__DisplayClass211_2 { public string playerId; public string entryId; public <>c__DisplayClass211_0 CS$<>8__locals2; internal void <FinalizeMatchStats>b__6(string id) { playerId = id; } internal void <FinalizeMatchStats>b__5(string id) { entryId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass211_3 { public string preMatchMmr; public <>c__DisplayClass211_2 CS$<>8__locals3; internal void <FinalizeMatchStats>b__4(string res) { JObject val = CS$<>8__locals3.CS$<>8__locals2.<>4__this.ParseApiSingleObject(res); object obj = ((val != null) ? val["current_mmr"] : null); if (obj != null) { preMatchMmr = obj.ToString(); } } } [CompilerGenerated] private sealed class <>c__DisplayClass212_0 { public SBGLPlugin <>4__this; public string playerName; public string preMatchMmr; public string entryId; internal void <CreatePlaceholderMatchEntryForMissingSessionPlayer>b__0(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { playerName = (string)val["display_name"]; object obj = val["current_mmr"]; if (obj != null) { preMatchMmr = obj.ToString(); } } } internal void <CreatePlaceholderMatchEntryForMissingSessionPlayer>b__1(string id) { entryId = id; } } [CompilerGenerated] private sealed class <>c__DisplayClass213_0 { public string matchId; public SBGLPlugin <>4__this; internal void <SubmitMatchStats>b__0(string id) { matchId = id; } internal void <SubmitMatchStats>b__1(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { <>4__this._currentSession.match_id = matchId; <>4__this.Log("<color=green>[Match Stats] ✓ MatchmakingSession " + <>4__this._currentSession.id + " linked to match: " + matchId + "</color>"); } else { <>4__this.Log("<color=yellow>[Match Stats] Could not confirm MatchmakingSession update</color>"); } } } [CompilerGenerated] private sealed class <>c__DisplayClass216_0 { public SBGLPlugin <>4__this; public Action<string> onMatchIdReceived; internal void <SubmitMatchEntry>b__0(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { string text = ((string)val["id"]) ?? "unknown"; <>4__this._lastUploadedPlayerCount = Mathf.Max(0, <>4__this._matchExpectedPlayerCount); <>4__this.Log("<color=green>[Match Stats] ✓ Match entry created (ID: " + text + ")</color>"); <>4__this.ShowUploadNotification("Upload success: match ID " + text + ".", "success"); onMatchIdReceived?.Invoke(text); } else { <>4__this.Log("<color=yellow>[Match Stats] Response received but could not parse ID</color>"); <>4__this.ShowUploadNotification("Upload failed: invalid API response.", "failure"); } } } [CompilerGenerated] private sealed class <>c__DisplayClass217_0 { public SBGLPlugin <>4__this; public string playerDisplayName; public string playerId; public Func<string, bool> <>9__2; internal void <SubmitMatchEntryForPlayer>b__0(string res) { try { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { playerDisplayName = (string)val["display_name"]; <>4__this.Log("<color=cyan>[Match Stats] Opponent display name (API): " + playerDisplayName + "</color>"); } } catch (Exception ex) { <>4__this.Log("<color=yellow>[Match Stats] Error parsing opponent profile: " + ex.Message + "</color>"); } } internal bool <SubmitMatchEntryForPlayer>b__2(string k) { return string.Equals(k?.Trim(), playerDisplayName?.Trim(), StringComparison.OrdinalIgnoreCase); } internal void <SubmitMatchEntryForPlayer>b__1(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { string text = ((string)val["id"]) ?? "unknown"; <>4__this.Log("<color=green>[Match Stats] ✓ MatchEntry created (ID: " + text + ") for player " + (playerDisplayName ?? playerId) + "</color>"); } else { <>4__this.Log("<color=yellow>[Match Stats] Could not parse MatchEntry response for player " + (playerDisplayName ?? playerId) + "</color>"); } } } [CompilerGenerated] private sealed class <AcceptMatch>d__186 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; private List<string> <acceptedIds>5__1; private string <acceptedIdsList>5__2; private string <acceptJson>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AcceptMatch>d__186(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <acceptedIds>5__1 = null; <acceptedIdsList>5__2 = null; <acceptJson>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._currentSession == null) { return false; } <>4__this._hasAccepted = true; <>4__this.Log("<color=cyan>[Accept] Refreshing session data before accepting...</color>"); <>2__current = <>4__this.PollSessionStatus(); <>1__state = 1; return true; case 1: <>1__state = -1; <acceptedIds>5__1 = new List<string>(); if (<>4__this._currentSession.accepted_player_ids != null) { <acceptedIds>5__1.AddRange(<>4__this._currentSession.accepted_player_ids); } if (!<acceptedIds>5__1.Contains(<>4__this._userProfile.id)) { <acceptedIds>5__1.Add(<>4__this._userProfile.id); } <acceptedIdsList>5__2 = string.Join("\",\"", <acceptedIds>5__1); <acceptJson>5__3 = "{\"accepted_player_ids\":[\"" + <acceptedIdsList>5__2 + "\"]}"; <>4__this.Log("<color=cyan>[Accept] Current player accepting: " + <>4__this._userProfile.id + "</color>"); <>4__this.Log($"<color=cyan>[Accept] Total accepted players: {<acceptedIds>5__1.Count}</color>"); <>4__this.Log("<color=cyan>[Accept] JSON payload: " + <acceptJson>5__3 + "</color>"); <>4__this._currentSession.accepted_player_ids = new List<string>(<acceptedIds>5__1); <>2__current = <>4__this.CallAPI("/MatchmakingSession/" + <>4__this._currentSession.id, "PUT", <acceptJson>5__3, delegate { <>4__this.Log("<color=green>✓ Match Accepted. Waiting for all players to accept before transitioning to ready...</color>"); }); <>1__state = 2; return true; case 2: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <AutoJoinMatch>d__187 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AutoJoinMatch>d__187(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { if (<>1__state != 0) { return false; } <>1__state = -1; if (<>4__this._currentSession == null || string.IsNullOrEmpty(<>4__this._currentSession.steam_lobby_link)) { return false; } <>4__this._autoJoinAttempts++; <>4__this._lastAutoJoinAttemptAt = DateTime.Now; <>4__this._lastAutoJoinSteamLink = <>4__this._currentSession.steam_lobby_link; <>4__this._hasAccepted = true; <>4__this.Log("Attempting automatic join with link: " + <>4__this._currentSession.steam_lobby_link); <>4__this.JoinBySteamLink(<>4__this._currentSession.steam_lobby_link, <>4__this._currentSession.lobby_password); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <BackgroundSyncLoop>d__179 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; private int <retryCount>5__1; private bool <isInMenuScene>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <BackgroundSyncLoop>d__179(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) Scene activeScene; switch (<>1__state) { default: return false; case 0: <>1__state = -1; <retryCount>5__1 = 0; goto IL_04f6; case 1: <>1__state = -1; if (<>4__this._userProfile != null) { <retryCount>5__1 = 0; } else { <retryCount>5__1++; if (<retryCount>5__1 == 1) { <>4__this.Log($"<color=yellow>Waiting for player profile resolution... (Attempt {<retryCount>5__1}/{10})</color>"); } if (<retryCount>5__1 % 3 == 0) { <>4__this.Log($"<color=yellow>Still waiting for player profile... (Attempt {<retryCount>5__1}/{10})</color>"); } if (<retryCount>5__1 >= 10) { <>4__this.Log("<color=orange>Player profile resolution timed out. Background sync will stop until the next reload.</color>"); return false; } } goto IL_01a0; case 2: <>1__state = -1; goto IL_01ef; case 3: <>1__state = -1; goto IL_0266; case 4: <>1__state = -1; goto IL_02af; case 5: <>1__state = -1; goto IL_0326; case 6: <>1__state = -1; goto IL_0379; case 7: <>1__state = -1; goto IL_0440; case 8: <>1__state = -1; break; case 9: { <>1__state = -1; goto IL_04f6; } IL_01a0: if (<>4__this._userProfile == null) { break; } if (!<>4__this._activeSeasonFetched) { <>2__current = <>4__this.FetchActiveSeasonId(); <>1__state = 2; return true; } goto IL_01ef; IL_0326: if (<>4__this._currentSession != null && <>4__this._currentSession.status == "pending_accept") { <>2__current = <>4__this.PollSessionStatus(); <>1__state = 6; return true; } goto IL_0379; IL_01ef: activeScene = SceneManager.GetActiveScene(); <isInMenuScene>5__2 = ((Scene)(ref activeScene)).name.ToLower().Contains("menu"); if (!<>4__this._isQueueing && <>4__this._currentSession == null && !<>4__this._isInGameplay) { <>2__current = <>4__this.CheckExistingQueueEntry(); <>1__state = 3; return true; } goto IL_0266; IL_02af: if (<>4__this._isInitializing) { <>4__this._isInitializing = false; <>4__this.Log("Initialization Complete: Queue Unlocked."); } if (<>4__this._isQueueing && <>4__this._currentSession == null) { <>2__current = <>4__this.CheckForMatch(); <>1__state = 5; return true; } goto IL_0326; IL_0379: if (<>4__this._isHost && <>4__this._hostLobbyStarted && <>4__this._currentSession != null && !<>4__this._hostCancelSent) { if (NetworkServer.active) { <>4__this._hostServerWasActive = true; } else if (<>4__this._hostServerWasActive && <>4__this._currentSession.status != "completed") { <>4__this.Log("Host lobby appears closed. Marking MatchmakingSession as completed..."); <>2__current = <>4__this.CancelSessionAsHost("host_left_lobby"); <>1__state = 7; return true; } } goto IL_0440; IL_0440: if (<>4__this._currentSession != null && !<>4__this._isHost && <>4__this._currentSession.status == "ready" && !string.IsNullOrEmpty(<>4__this._currentSession.steam_lobby_link) && !<>4__this._hasAccepted) { <>4__this.Log("Auto-joining match as non-host..."); <>2__current = <>4__this.AutoJoinMatch(); <>1__state = 8; return true; } break; IL_04f6: <>4__this._syncTickCount++; if (<>4__this._userProfile == null) { <>2__current = <>4__this.EnsureUserProfileResolved("Sync"); <>1__state = 1; return true; } goto IL_01a0; IL_0266: if (<isInMenuScene>5__2 && !IsRankedTriggered && !<>4__this._isInGameplay) { <>2__current = <>4__this.RefreshPlayerList(); <>1__state = 4; return true; } goto IL_02af; } <>2__current = _syncLoopDelay; <>1__state = 9; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CallAPI>d__223 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string endpoint; public string method; public string json; public Action<string> onSuccess; public SBGLPlugin <>4__this; private string <fullUrl>5__1; private UnityWebRequest <req>5__2; private string <errorMsg>5__3; private int <length>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CallAPI>d__223(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <fullUrl>5__1 = null; <req>5__2 = null; <errorMsg>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Invalid comparison between Unknown and I4 //IL_01da: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <fullUrl>5__1 = <>4__this.GetBaseApiUrl() + endpoint; <>4__this.Log("<color=cyan>[API] " + method + " " + endpoint + "</color>"); <>4__this.Log("<color=cyan>[API] Full URL: " + <fullUrl>5__1 + "</color>"); <req>5__2 = new UnityWebRequest(<fullUrl>5__1, method); <>1__state = -3; if (!string.IsNullOrEmpty(json)) { <req>5__2.uploadHandler = (UploadHandler)new UploadHandlerRaw(Encoding.UTF8.GetBytes(json)); } <req>5__2.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); <>4__this.ApplyApiHeaders(<req>5__2); <>2__current = <req>5__2.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -3; if ((int)<req>5__2.result == 1) { <>4__this.Log("<color=green>[API] " + method + " " + endpoint + " - Success</color>"); onSuccess?.Invoke(<req>5__2.downloadHandler.text); } else { <errorMsg>5__3 = $"[API] {method} {endpoint} failed: {<req>5__2.result}"; if (!string.IsNullOrEmpty(<req>5__2.error)) { <errorMsg>5__3 = <errorMsg>5__3 + " - " + <req>5__2.error; } if (<req>5__2.responseCode > 0) { <errorMsg>5__3 += $" (HTTP {<req>5__2.responseCode})"; } DownloadHandler downloadHandler = <req>5__2.downloadHandler; if (!string.IsNullOrEmpty((downloadHandler != null) ? downloadHandler.text : null)) { <length>5__4 = Math.Min(200, <req>5__2.downloadHandler.text.Length); <errorMsg>5__3 = <errorMsg>5__3 + " - Response: " + <req>5__2.downloadHandler.text.Substring(0, <length>5__4); } <>4__this.Log("<color=red>" + <errorMsg>5__3 + "</color>"); <errorMsg>5__3 = null; } <>m__Finally1(); <req>5__2 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__2 != null) { ((IDisposable)<req>5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CancelSessionAsHost>d__192 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string reason; public SBGLPlugin <>4__this; private string <sessionId>5__1; private string <json>5__2; private UnityWebRequest <req>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CancelSessionAsHost>d__192(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <sessionId>5__1 = null; <json>5__2 = null; <req>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Invalid comparison between Unknown and I4 //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._hostCancelSent) { return false; } if (!<>4__this._isHost || <>4__this._currentSession == null || string.IsNullOrEmpty(<>4__this._currentSession.id)) { return false; } if (<>4__this._currentSession.id == "DEBUG") { return false; } <>4__this._hostCancelSent = true; <sessionId>5__1 = <>4__this._currentSession.id; <json>5__2 = "{\"status\":\"completed\"}"; <req>5__3 = new UnityWebRequest(<>4__this.GetBaseApiUrl() + "/MatchmakingSession/" + <sessionId>5__1, "PUT"); <>1__state = -3; <req>5__3.uploadHandler = (UploadHandler)new UploadHandlerRaw(Encoding.UTF8.GetBytes(<json>5__2)); <req>5__3.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); <>4__this.ApplyApiHeaders(<req>5__3); <>2__current = <req>5__3.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -3; if ((int)<req>5__3.result == 1) { if (<>4__this._currentSession != null && <>4__this._currentSession.id == <sessionId>5__1) { <>4__this._currentSession.status = "completed"; } <>4__this.Log("Host leave update sent (" + reason + "): session marked completed."); } else { <>4__this._hostCancelSent = false; <>4__this.Log($"<color=red>Host cancel failed ({reason}): {<req>5__3.result} {<req>5__3.error}</color>"); } <>m__Finally1(); <req>5__3 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__3 != null) { ((IDisposable)<req>5__3).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CaptureAndStorePerHoleScreenshot>d__141 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string source; public SBGLPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CaptureAndStorePerHoleScreenshot>d__141(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>1__state = -3; <>2__current = <>4__this.CaptureMatchScreenshotForReview(source + " (per-hole immediate)"); <>1__state = 1; return true; case 1: <>1__state = -3; <>m__Finally1(); return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <>4__this._matchScreenshotSignalCoroutine = null; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CaptureAndUploadScreenshotFromForcedScoreboard>d__142 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string source; public SBGLPlugin <>4__this; private float <waited>5__1; private float <snapshotTimeout>5__2; private bool <gotFinalSnapshot>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CaptureAndUploadScreenshotFromForcedScoreboard>d__142(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 3u) { try { } finally { <>m__Finally1(); } } <>1__state = -2; } private bool MoveNext() { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; <>1__state = -3; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; result = true; break; case 1: <>1__state = -3; <waited>5__1 = 0f; <snapshotTimeout>5__2 = 6f; <gotFinalSnapshot>5__3 = false; goto IL_011f; case 2: <>1__state = -3; <waited>5__1 += 0.25f; goto IL_011f; case 3: <>1__state = -3; <>2__current = <>4__this.UploadCapturedMatchScreenshotIfNeeded(source); <>1__state = 4; result = true; break; case 4: { <>1__state = -3; <>m__Finally1(); result = false; break; } IL_011f: if (<waited>5__1 < <snapshotTimeout>5__2) { if (!<>4__this._matchEndedReceived) { try { if (<>4__this.TryCaptureFinalLeaderboardSnapshot(source + " (screenshot-wait)")) { <gotFinalSnapshot>5__3 = true; goto IL_0136; } } catch { } <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 2; result = true; break; } <gotFinalSnapshot>5__3 = true; } goto IL_0136; IL_0136: if (!<gotFinalSnapshot>5__3) { <>4__this.Log($"<color=yellow>[Match Screenshot] Final leaderboard snapshot not available within {<snapshotTimeout>5__2}s - skipping forced-scoreboard capture ({source})</color>"); result = false; <>m__Finally1(); } else { <>2__current = <>4__this.CaptureMatchScreenshotForReview(source); <>1__state = 3; result = true; } break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <>4__this._matchScreenshotSignalCoroutine = null; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CaptureMatchScreenshotForReview>d__147 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string source; public SBGLPlugin <>4__this; private float <waitedSeconds>5__1; private int <screenWidth>5__2; private int <screenHeight>5__3; private Texture2D <capturedTexture>5__4; private Texture2D <encodedTexture>5__5; private byte[] <imageBytes>5__6; private Exception <ex>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CaptureMatchScreenshotForReview>d__147(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <capturedTexture>5__4 = null; <encodedTexture>5__5 = null; <imageBytes>5__6 = null; <ex>5__7 = null; <>1__state = -2; } private bool MoveNext() { //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._matchScreenshotUploadCompleted || <>4__this._matchScreenshotUploadInProgress) { return false; } if (<>4__this._pendingMatchScreenshotBytes != null && <>4__this._pendingMatchScreenshotBytes.Length != 0) { <>4__this.Log("<color=cyan>[Match Screenshot] Replacing previous pending screenshot with a newer capture (" + source + ")</color>"); } <waitedSeconds>5__1 = 0f; goto IL_00db; case 1: <>1__state = -1; <waitedSeconds>5__1 += Mathf.Max(Time.unscaledDeltaTime, 0.016f); goto IL_00db; case 2: { <>1__state = -1; <screenWidth>5__2 = Screen.width; <screenHeight>5__3 = Screen.height; if (<screenWidth>5__2 <= 0 || <screenHeight>5__3 <= 0) { <>4__this.Log("<color=yellow>[Match Screenshot] Screen dimensions were invalid - skipping capture</color>"); return false; } <capturedTexture>5__4 = null; <encodedTexture>5__5 = null; try { <capturedTexture>5__4 = new Texture2D(<screenWidth>5__2, <screenHeight>5__3, (TextureFormat)3, false); <capturedTexture>5__4.ReadPixels(new Rect(0f, 0f, (float)<screenWidth>5__2, (float)<screenHeight>5__3), 0, 0, false); <capturedTexture>5__4.Apply(false, false); <encodedTexture>5__5 = <>4__this.ResizeTextureToFit(<capturedTexture>5__4, 1920, 1080); <imageBytes>5__6 = <>4__this.EncodeScreenshotBytes(<encodedTexture>5__5); if (<imageBytes>5__6 == null || <imageBytes>5__6.Length == 0) { <>4__this.Log("<color=yellow>[Match Screenshot] JPEG encoding returned no data - skipping capture</color>"); return false; } <>4__this._pendingMatchScreenshotBytes = <imageBytes>5__6; <>4__this._pendingMatchScreenshotFileName = <>4__this.BuildMatchScreenshotFileName(); <>4__this._pendingUploadedScreenshotUrl = null; <>4__this.Log($"<color=green>[Match Screenshot] ✓ Captured final scoreboard screenshot from {source} ({((Texture)<encodedTexture>5__5).width}x{((Texture)<encodedTexture>5__5).height}, {(float)<imageBytes>5__6.Length / 1024f:0.#} KB)</color>"); <imageBytes>5__6 = null; } catch (Exception ex) { <ex>5__7 = ex; <>4__this.Log("<color=yellow>[Match Screenshot] Could not capture screenshot from " + source + ": " + <ex>5__7.Message + "</color>"); } finally { if ((Object)(object)<encodedTexture>5__5 != (Object)null && <encodedTexture>5__5 != <capturedTexture>5__4) { Object.Destroy((Object)(object)<encodedTexture>5__5); } if ((Object)(object)<capturedTexture>5__4 != (Object)null) { Object.Destroy((Object)(object)<capturedTexture>5__4); } } return false; } IL_00db: if (!CourseManager.ForceDisplayScoreboard && <waitedSeconds>5__1 < 4f) { <>2__current = null; <>1__state = 1; return true; } if (!CourseManager.ForceDisplayScoreboard) { <>4__this.Log("<color=yellow>[Match Screenshot] Forced scoreboard was not visible in time for " + source + " - skipping capture for now</color>"); return false; } <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CheckAndSubmitMatchStats>d__160 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; private string <query>5__1; private string <fullUrl>5__2; private UnityWebRequest <req>5__3; private List<JObject> <existingMatches>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckAndSubmitMatchStats>d__160(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } <query>5__1 = null; <fullUrl>5__2 = null; <req>5__3 = null; <existingMatches>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Invalid comparison between Unknown and I4 //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; if (<>4__this._userProfile == null || <>4__this._currentSession == null) { <>4__this.Log("<color=red>[Match Stats] Failed: Missing profile or session</color>"); result = false; break; } <>4__this.Log("<color=cyan>[Match Stats] Waiting for leaderboard to populate...</color>"); <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 1; result = true; break; case 1: <>1__state = -1; <query>5__1 = "{\"matchmaking_session_id\":\"" + <>4__this._currentSession.id + "\"}"; <fullUrl>5__2 = <>4__this.GetBaseApiUrl() + "/Match?q=" + UnityWebRequest.EscapeURL(<query>5__1); <>4__this.Log("<color=cyan>[Match Stats] Checking for existing match entry...</color>"); <>4__this.Log("<color=cyan>[Match Stats] Query URL: " + <fullUrl>5__2.Substring(0, Math.Min(150, <fullUrl>5__2.Length)) + "...</color>"); <req>5__3 = UnityWebRequest.Get(<fullUrl>5__2); <>1__state = -3; <>4__this.ApplyApiHeaders(<req>5__3); <>2__current = <req>5__3.SendWebRequest(); <>1__state = 2; result = true; break; case 2: <>1__state = -3; if ((int)<req>5__3.result == 1) { <existingMatches>5__4 = <>4__this.ParseApiObjectList(<req>5__3.downloadHandler.text); if (<existingMatches>5__4.Count > 0) { <>4__this.Log($"<color=orange>[Match Stats] Match already exists for this session (found {<existingMatches>5__4.Count} entries)</color>"); <>4__this._matchStatsSubmitted = true; result = false; <>m__Finally1(); break; } <>4__this.Log("<color=cyan>[Match Stats] No existing match found - proceeding with submission</color>"); <existingMatches>5__4 = null; } else { <>4__this.Log($"<color=yellow>[Match Stats] Could not query existing matches: {<req>5__3.result} - proceeding anyway</color>"); } <>m__Finally1(); <req>5__3 = null; <>2__current = <>4__this.SubmitMatchStats(); <>1__state = 3; result = true; break; case 3: <>1__state = -1; result = false; break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__3 != null) { ((IDisposable)<req>5__3).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CheckExistingQueueEntry>d__181 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; private string <checkQuery>5__1; private string <checkUrl>5__2; private UnityWebRequest <req>5__3; private List<JObject> <existing>5__4; private string <patchJson>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckExistingQueueEntry>d__181(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <checkQuery>5__1 = null; <checkUrl>5__2 = null; <req>5__3 = null; <existing>5__4 = null; <patchJson>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Invalid comparison between Unknown and I4 try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <checkQuery>5__1 = "{\"player_id\":\"" + <>4__this._userProfile.id + "\",\"status\":\"queued\"}"; <checkUrl>5__2 = <>4__this.GetBaseApiUrl() + "/MatchmakingQueue?q=" + UnityWebRequest.EscapeURL(<checkQuery>5__1); <req>5__3 = UnityWebRequest.Get(<checkUrl>5__2); <>1__state = -3; <>4__this.ApplyApiHeaders(<req>5__3); <>2__current = <req>5__3.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -3; if ((int)<req>5__3.result != 1) { break; } <existing>5__4 = <>4__this.ParseApiObjectList(<req>5__3.downloadHandler.text); if (<existing>5__4 != null && <existing>5__4.Count > 0) { <>4__this._currentQueueId = (string)<existing>5__4[0]["id"]; <>4__this._isQueueing = true; <>4__this._webStatus = "QUEUED"; <>4__this._queueStartTime = DateTime.Now; <>4__this.Log("<color=yellow>[Queue] Detected existing queue entry " + <>4__this._currentQueueId + " from website — rejoining.</color>"); <patchJson>5__5 = "{\"has_mod\":true,\"created_by\":\"SBGL_UnifiedMod\",\"match_type\":\"" + <>4__this.GetQueueMatchTypePayload() + "\"}"; <>2__current = <>4__this.CallAPI("/MatchmakingQueue/" + <>4__this._currentQueueId, "PUT", <patchJson>5__5, delegate(string res) { if (<>4__this.ParseApiSingleObject(res) != null) { <>4__this.Log("<color=green>[Queue] ✓ Patched has_mod:true onto existing entry " + <>4__this._currentQueueId + ".</color>"); } }); <>1__state = 2; return true; } goto IL_0226; case 2: { <>1__state = -3; <patchJson>5__5 = null; goto IL_0226; } IL_0226: <existing>5__4 = null; break; } <>m__Finally1(); <req>5__3 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__3 != null) { ((IDisposable)<req>5__3).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CheckForMatch>d__184 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; private string <query>5__1; private string <fullUrl>5__2; private UnityWebRequest <req>5__3; private List<JObject> <sessions>5__4; private JObject <activeSession>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckForMatch>d__184(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <query>5__1 = null; <fullUrl>5__2 = null; <req>5__3 = null; <sessions>5__4 = null; <activeSession>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Invalid comparison between Unknown and I4 //IL_01f7: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <query>5__1 = "{\"$or\":[{\"host_player_id\":\"" + <>4__this._userProfile.id + "\"},{\"player_ids\":{\"$in\":[\"" + <>4__this._userProfile.id + "\"]}}],\"status\":\"pending_accept\"}"; <fullUrl>5__2 = <>4__this.GetBaseApiUrl() + "/MatchmakingSession?q=" + UnityWebRequest.EscapeURL(<query>5__1); <>4__this.Log("<color=cyan>[Sync] GET /MatchmakingSession (checking for pending matches)</color>"); <>4__this.Log("<color=cyan>[Sync] Full URL: " + <fullUrl>5__2.Substring(0, Math.Min(150, <fullUrl>5__2.Length)) + "...</color>"); <req>5__3 = UnityWebRequest.Get(<fullUrl>5__2); <>1__state = -3; <>4__this.ApplyApiHeaders(<req>5__3); <>2__current = <req>5__3.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -3; if ((int)<req>5__3.result == 1) { <sessions>5__4 = <>4__this.ParseApiObjectList(<req>5__3.downloadHandler.text); <activeSession>5__5 = ((IEnumerable<JObject>)<sessions>5__4).FirstOrDefault((Func<JObject, bool>)((JObject session) => !string.IsNullOrEmpty((string)session["lobby_name"]))); if (<activeSession>5__5 != null) { <>4__this._webStatus = "MATCH FOUND: PENDING"; <>4__this.Log("Match Found! Accept needed."); } <sessions>5__4 = null; <activeSession>5__5 = null; } else { <>4__this.Log($"<color=red>[Sync] CheckForMatch failed: {<req>5__3.result} - {<req>5__3.error}</color>"); } <>m__Finally1(); <req>5__3 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__3 != null) { ((IDisposable)<req>5__3).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ClaimHostRoleCoroutine>d__107 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; private string <json>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ClaimHostRoleCoroutine>d__107(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <json>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._currentSession == null || <>4__this._userProfile == null) { return false; } if (<>4__this._isHost) { return false; } <>4__this.Log("<color=cyan>[PDS] Claiming host role for session " + <>4__this._currentSession.id + "...</color>"); <json>5__1 = "{\"host_player_id\":\"" + <>4__this._userProfile.id + "\"}"; <>2__current = <>4__this.CallAPI("/MatchmakingSession/" + <>4__this._currentSession.id, "PUT", <json>5__1, delegate(string res) { JObject val = <>4__this.ParseApiSingleObject(res); if (val != null) { <>4__this._currentSession.host_player_id = <>4__this._userProfile.id; <>4__this._isHost = true; <>4__this.Log("<color=green>[PDS] ✓ Host role claimed — session host_player_id set to our player ID.</color>"); } else { <>4__this.Log("<color=red>[PDS] Failed to claim host role — API response was null.</color>"); } }); <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CreateMatchAndEntries>d__194 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CreateMatchAndEntries>d__194(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._matchCreationInProgress) { <>4__this.Log("<color=orange>[Match Creation] Already in progress - skipping duplicate call</color>"); return false; } <>4__this._matchCreationInProgress = true; <>2__current = <>4__this.CreateMatchAndEntriesInternal(); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this._matchCreationInProgress = false; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CreateMatchAndEntriesInternal>d__195 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SBGLPlugin <>4__this; private bool <isManualLocalLobby>5__1; private string <currentMatchType>5__2; private bool <isCasualMatch>5__3; private string <activeSessionId>5__4; private Dictionary<string, int> <playerScores>5__5; private Dictionary<string, int> <playerScoresVsPar>5__6; private List<LiveLeaderboardPlugin.SBGLPlayer> <startingLeaderboard>5__7; private Dictionary<string, int> <startingPositionMap>5__8; private bool <isEffectiveHost>5__9; private List<string> <playerIds>5__10; private LiveLeaderboardPlugin <liveLeaderboard>5__11; private List<LiveLeaderboardPlugin.SBGLPlayer> <allLeaderboardPlayers>5__12; private List<LiveLeaderboardPlugin.SBGLPlayer>.Enumerator <>s__13; private LiveLeaderboardPlugin.SBGLPlayer <player>5__14; private string <strokeStr>5__15; private int <vsPar>5__16; private Exception <ex>5__17; private <>c__DisplayClass195_0 <>8__18; private float <waitElapsed>5__19; private float <nextApiCheckAt>5__20; private string <p2pId>5__21; private <>c__DisplayClass195_1 <>8__22; private <>c__DisplayClass195_2 <>8__23; private float <fallbackDelay>5__24; private string <prePostSessionId>5__25; private <>c__DisplayClass195_3 <>8__26; private string <finalCheckQuery>5__27; private <>c__DisplayClass195_4 <>8__28; private IEnumerable<ulong> <peers>5__29; private <>c__DisplayClass195_5 <>8__30; private List<string>.Enumerator <>s__31; private <>c__DisplayClass195_6 <>8__32; private <>c__DisplayClass195_7 <>8__33; private int <gamePoints>5__34; private int <scoreVsPar>5__35; private int <startingPosition>5__36; private int <score>5__37; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CreateMatchAndEntriesInternal>d__195(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 11) <= 1u) { try { } finally { <>m__Finally1(); } } <currentMatchType>5__2 = null; <activeSessionId>5__4 = null; <playerScores>5__5 = null; <playerScoresVsPar>5__6 = null; <startingLeaderboard>5__7 = null; <startingPositionMap>5__8 = null; <playerIds>5__10 = null; <liveLeaderboard>5__11 = null; <allLeaderboardPlayers>5__12 = null; <>s__13 = default(List<LiveLeaderboardPlugin.SBGLPlayer>.Enumerator); <player>5__14 = null; <strokeStr>5__15 = null; <ex>5__17 = null; <>8__18 = null; <p2pId>5__21 = null; <>8__22 = null; <>8__23 = null; <prePostSessionId>5__25 = null; <>8__26 = null; <finalCheckQuery>5__27 = null; <>8__28 = null; <peers>5__29 = null; <>8__30 = null; <>s__31 = default(List<string>.Enumerator); <>8__32 = null; <>8__33 = null; <>1__state = -2; } private bool MoveNext() { //IL_0864: Unknown result type (might be due to invalid IL or missing references) //IL_086e: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._userProfile == null) { <>4__this.Log("<color=red>[Match Creation] Failed: Missing player profile</color>"); return false; } <isManualLocalLobby>5__1 = <>4__this._currentSession == null; if (<isManualLocalLobby>5__1) { if (string.IsNullOrWhiteSpace(<>4__this._localManualSessionId)) { <>4__this._localManualSessionId = <>4__this.BuildStableManualLocalSessionId(); } <>4__this.Log("<color=cyan>[Match Creation] Manual local lobby detected. Session surrogate: " + <>4__this._localManualSessionId + "</color>"); } <currentMatchType>5__2 = <>4__this._currentSession?.match_type ?? PlayerPrefs.GetString("MatchType", ""); <isCasualMatch>5__3 = <>4__this.IsCurrentMatchCasual(); if (IsProSeriesMatchType(<currentMatchType>5__2) || IsProSeriesMatchType(PlayerPrefs.GetString("MatchType", ""))) { if (!<>4__this._proSeriesSkipLogged) { <>4__this.Log("<color=yellow>[Match] Pro Series match — automated upload skipped</color>"); <>4__this._proSeriesSkipLogged = true; } <>4__this._matchEntriesCreated = true; return false; } <activeSessionId>5__4 = ((<>4__this._currentSession != null) ? <>4__this._currentSession.id : <>4__this._localManualSessionId); <>4__this.Log("<color=cyan>[Match Creation] Starting new match for session " + <activeSessionId>5__4 + "</color>"); <>4__this._matchStartTime = DateTime.UtcNow; <playerScores>5__5 = new Dictionary<string, int>(); <playerScoresVsPar>5__6 = new Dictionary<string, int>(); <startingLeaderboard>5__7 = null; try { <liveLeaderboard>5__11 = Object.FindAnyObjectByType<LiveLeaderboardPlugin>((FindObjectsInactive)1); if ((Object)(object)<liveLeaderboard>5__11 != (Object)null) { <allLeaderboardPlayers>5__12 = <liveLeaderboard>5__11.GetCurrentLeaderboard(); <startingLeaderboard>5__7 = new List<LiveLeaderboardPlugin.SBGLPlayer>(<allLeaderboardPlayers>5__12); <>4__this.Log($"<color=cyan>[Match Creation] Found {<allLeaderboardPlayers>5__12.Count} players on leaderboard</color>"); <>s__13 = <allLeaderboardPlayers>5__12.GetEnumerator(); try { while (<>s__13.MoveNext()) { <player>5__14 = <>s__13.Current; if (<player>5__14 != null) { <playerScores>5__5[<player>5__14.Name] = <player>5__14.BaseScore; if (!string.IsNullOrEmpty(<player>5__14.RawStrokes)) { <strokeStr>5__15 = <player>5__14.RawStrokes.Replace("±", "").Trim(); int.TryParse(<strokeStr>5__15, out <vsPar>5__16); <playerScoresVsPar>5__6[<player>5__14.Name] = <vsPar>5__16; <strokeStr>5__15 = null; } <player>5__14 = null; } } } finally { ((IDisposable)<>s__13).Dispose(); } <>s__13 = default(List<LiveLeaderboardPlugin.SBGLPlayer>.Enumerator); <allLeaderboardPlayers>5__12 = null; } <liveLeaderboard>5__11 = null; } catch (Exception ex) { <ex>5__17 = ex; <>4__this.Log("<color=yellow>[Match Creation] Error prefetching leaderboard: " + <ex>5__17.Message + "</color>"); } <>4__this._cachedLeaderboardScores = <playerScores>5__5; <>4__this._cachedLeaderboardScoresVsPar = <playerScoresVsPar>5__6; <>4__this._matchExpectedPlayerCount = <startingLeaderboard>5__7?.Count ?? 0; <startingPositionMap>5__8 = ((<startingLeaderboard>5__7 != null) ? <>4__this.BuildFinishPositionMap(<startingLeaderboard>5__7) : new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)); if (<isCasualMatch>5__3) { if (<startingLeaderboard>5__7 == null || <startingLeaderboard>5__7.Count == 0) { <>4__this.Log("<color=yellow>[Casual] Leaderboard is empty - deferring casual stat update until players appear</color>"); if (<>4__this._monitorCoroutine == null) { <>4__this._monitorCoroutine = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.MonitorAndUpdateScores()); } return false; } <>4__this.Log("<color=cyan>[Casual] Casual match detected - skipping Match/MatchEntry upload and incrementing player stats instead</color>"); <>2__current = <>4__this.IncrementCasualMatchesPlayedForActivePlayers(<startingLeaderboard>5__7); <>1__state = 1; return true; } <isEffectiveHost>5__9 = <>4__this._isHost || NetworkServer.active; if (<isEffectiveHost>5__9) { <>4__this.Log("<color=cyan>[Match Creation] We are the host — creating Match record with priority</color>"); if (<>4__this._currentSession != null) { <>8__18 = new <>c__DisplayClass195_0(); <>8__18.existingMatchId = null; <>2__current = <>4__this.ResolveExistingMatchIdForCurrentSession(delegate(string id) { <>8__18.existingMatchId = id; }); <>1__state = 2; return true; } goto IL_0a1e; } MatchResultSubmissionService.ReceivedP2PMatchId = null; <>4__this.Log("<color=cyan>[Match Creation] We are a client — waiting up to 12s for host to upload the match...</color>"); <waitElapsed>5__19 = 0f; <nextApiCheckAt>5__20 = 2f; goto IL_089d; case 1: <>1__state = -1; if (<>4__this._monitorCoroutine != null) { ((MonoBehaviour)<>4__this).StopCoroutine(<>4__this._monitorCoroutine); <>4__this._monitorCoroutine = null; } return false; case 2: <>1__state = -1; if (!string.IsNullOrEmpty(<>8__18.existingMatchId)) { <>4__this._currentMatchId = <>8__18.existingMatchId; <>4__this.ShowUploadNotification("Match record already exists; reusing existing upload."); goto IL_0cf9; } <>8__18 = null; goto IL_0a1e; case 3: <>1__state = -1; if (!string.IsNullOrEmpty(<>8__22.apiMatchId)) { <>4__this.Log($"<color=green>[Match Creation] ✓ Found host match via API at {<waitElapsed>5__19:0.#}s: {<>8__22.apiMatchId}</color>"); <>4__this._currentMatchId = <>8__22.apiMatchId; <>4__this.ShowUploadNotification("Match record adopted from host."); goto IL_0cf9; } <>8__22 = null; goto IL_085e; case 4: <>1__state = -1; <waitElapsed>5__19 += 0.5f; <p2pId>5__21 = null; goto IL_089d; case 5: <>1__state = -1; goto IL_0992; case 6: <>1__state = -1; goto IL_0992; case 7: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__26.finalCheckId)) { <>4__this.Log("<color=green>[Match Creation] ✓ Final pre-POST check found existing active match: " + <>8__26.finalCheckId + " — skipping duplicate POST</color>"); <>4__this._currentMatchId = <>8__26.finalCheckId; if (<>4__this._currentSession != null) { <>4__this._currentSession.match_id = <>8__26.finalCheckId; } <>4__this.ShowUploadNotification("Match record already exists; reusing existing upload."); goto IL_0cf9; } <>8__26 = null; <finalCheckQuery>5__27 = null; goto IL_0bc9; case 8: <>1__state = -1; if (string.IsNullOrEmpty(<>8__28.newMatchId)) { <>4__this.Log("<color=red>[Match Creation] Failed to create Match record</color>"); <>4__this.ShowUploadNotification("Upload failed: could not create match record.", "failure"); return false; } <>4__this._currentMatchId = <>8__28.newMatchId; <>4__this.Log("<color=green>[Match Creation] ✓ Match created: " + <>8__28.newMatchId + "</color>"); <>4__this.ShowUploadNotification("Upload success: match record created.", "success"); <peers>5__29 = CompetitivePluginCheck.GetKnownPeers(); MatchResultSubmissionService.BroadcastMatchId(<>8__28.newMatchId, <peers>5__29); <>8__28 = null; <peers>5__29 = null; goto IL_0cf9; case 9: <>1__state = -1; <>8__30 = null; goto IL_0dd2; case 10: <>1__state = -1; <>4__this._matchExpectedPlayerCount = <playerIds>5__10.Count; <>s__31 = <playerIds>5__10.GetEnumerator(); <>1__state = -3; goto IL_12ef; case 11: <>1__state = -3; goto IL_10e4; case 12: { <>1__state = -3; if (string.IsNullOrWhiteSpace(<>8__33.entryId)) { <>4__this.Log("<color=yellow>[Match Creation] MatchEntry not ready yet for " + (<>8__33.playerName ?? <>8__33.CS$<>8__locals1.playerId) + "; gameplay monitor will retry if needed</color>"); } <>8__33 = null; <>8__32 = null; goto IL_12ef; } IL_0cf9: if (<>4__this._currentSession != null) { <>8__30 = new <>c__DisplayClass195_5(); <>8__30.<>4__this = <>4__this; <>8__30.linkMatchId = <>4__this._currentMatchId; <>2__current = <>4__this.CallAPI("/MatchmakingSession/" + <>4__this._currentSession.id, "PUT", "{\"match_id\":\"" + <>8__30.linkMatchId + "\"}", delegate(string res) { JObject val2 = <>8__30.<>4__this.ParseApiSingleObject(res); if (val2 != null) { <>8__30.<>4__this._currentSession.match_id = <>8__30.linkMatchId; <>8__30.<>4__this.Log("<color=green>[Match Creation] ✓ MatchmakingSession " + <>8__30.<>4__this._currentSession.id + " linked to match: " + <>8__30.linkMatchId + "</color>"); } else { <>8__30.<>4__this.Log("<color=yellow>[Match Creation] Could not confirm MatchmakingSession update</color>"); } }); <>1__state = 9; return true; } <>4__this.Log("<color=cyan>[Match Creation] Local lobby mode: skipping MatchmakingSession link</color>"); goto IL_0dd2; IL_12ef: if (<>s__31.MoveNext()) { <>8__32 = new <>c__DisplayClass195_6(); <>8__32.<>4__this = <>4__this; <>8__32.playerId = <>s__31.Current; <>8__33 = new <>c__DisplayClass195_7(); <>8__33.CS$<>8__locals1 = <>8__32; <>8__33.playerName = null; <>8__33.preMatchMmr = null; <gamePoints>5__34 = 0; <scoreVsPar>5__35 = 0; if (<>8__33.CS$<>8__locals1.playerId == <>4__this._userProfile.id) { <>8__33.playerName = <>4__this._userProfile.display_name; <>8__33.preMatchMmr = <>4__this._userProfile.current_mmr.ToString(); <>4__this.Log("<color=cyan>[Match Creation] Current player: " + <>8__33.playerName + " (MMR: " + <>8__33.preMatchMmr + ")</color>"); goto IL_10e4; } <>2__current = <>4__this.CallAPI("/Player/" + <>8__33.CS$<>8__locals1.playerId, "GET", "", delegate(string res) { try { JObject val = <>8__33.CS$<>8__locals1.<>4__this.ParseApiSingleObject(res); if (val != null) { <>8__33.playerName = (string)val["display_name"]; if (string.IsNullOrEmpty(<>8__33.playerName)) { <>8__33.CS$<>8__locals1.<>4__this.Log("<color=yellow>[Match Creation] Player " + <>8__33.CS$<>8__locals1.playerId + " has no display_name, using ID</color>"); <>8__33.playerName = <>8__33.CS$<>8__locals1.playerId; } object obj2 = val["current_mmr"]; if (obj2 != null) { <>8__33.preMatchMmr = obj2.ToString(); } <>8__33.CS$<>8__locals1.<>4__this.Log("<color=cyan>[Match Creation] Fetched player: " + <>8__33.playerName + " (MMR: " + <>8__33.preMatchMmr + ")</color>"); } else { <>8__33.CS$<>8__locals1.<>4__this.Log("<color=yellow>[Match Creation] Failed to fetch Player " + <>8__33.CS$<>8__locals1.playerId + " - response null</color>"); <>8__33.playerName = <>8__33.CS$<>8__locals1.playerId; } } catch (Exception ex2) { <>8__33.CS$<>8__locals1.<>4__this.Log("<color=yellow>[Match Creation] Error fetching Player " + <>8__33.CS$<>8__locals1.playerId + ": " + ex2.Message + "</color>"); <>8__33.playerName = <>8__33.CS$<>8__locals1.playerId; } }); <>1__state = 11; return true; } <>m__Finally1(); <>s__31 = default(List<string>.Enumerator); <>4__this._matchEntriesCreated = true; <>4__this.Log("<color=green>[Match Creation] ✓ Match and entries initialized. Starting score monitoring...</color>"); if (<>4__this._monitorCoroutine == null) { <>4__this._monitorCoroutine = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.MonitorAndUpdateScores()); } return false; IL_0a1e: <>4__this.Log("<color=cyan>[Match Creation] No existing Match found — proceeding with POST</color>"); <prePostSessionId>5__25 = ((<>4__this._currentSession != null) ? <>4__this._currentSession.id : <>4__this._localManualSessionId); if (!string.IsNullOrWhiteSpace(<prePostSessionId>5__25)) { <>8__26 = new <>c__DisplayClass195_3(); <>8__26.<>4__this = <>4__this; <>8__26.finalCheckId = null; <finalCheckQuery>5__27 = UnityWebRequest.EscapeURL("{\"matchmaking_session_id\":\"" + <prePostSessionId>5__25 + "\"}"); <>2__current = <>4__this.CallAPI("/Match?q=" + <finalCheckQuery>5__27 + "&sort_by=created_date", "GET", "", delegate(string res) { JObject obj = <>8__26.<>4__this.SelectNewestReusableMatch(<>8__26.<>4__this.ParseApiObjectList(res)); <>8__26.finalCheckId = (string)((obj != null) ? obj["id"] : null); }); <>1__state = 7; return true; } goto IL_0bc9; IL_089d: if (<waitElapsed>5__19 < 12f) { <p2pId>5__21 = MatchResultSubmissionService.ReceivedP2PMatchId; if (!string.IsNullOrEmpty(<p2pId>5__21)) { <>4__this.Log("<color=green>[Match Creation] ✓ Received P2P Match ID from host: " + <p2pId>5__21 + "</color>"); <>4__this._currentMatchId = <p2pId>5__21; if (<>4__this._currentSession != null) { <>4__this._currentSession.match_id = <p2pId>5__21; } <>4__this.ShowUploadNotification("Match record adopted from host via P2P."); goto IL_0cf9; } if (<>4__this._currentSession != null && <waitElapsed>5__19 >= <nextApiCheckAt>5__20) { <>8__22 = new <>c__DisplayClass195_1(); <nextApiCheckAt>5__20 += 2f; <>8__22.apiMatchId = null; <>2__current = <>4__this.ResolveExistingMatchIdForCurrentSession(delegate(string id) { <>8__22.apiMatchId = id; }, logMisses: false); <>1__state = 3; return true; } goto IL_085e; } <>4__this.Log("<color=yellow>[Match Creation] Host did not upload within 12s — non-host fallback slot ordering...</color>"); if (<>4__this._currentSession != null) { <>8__23 = new <>c__DisplayClass195_2(); <fallbackDelay>5__24 = <>4__this.GetCurrentPlayerMatchUploadDelaySeconds(); <>8__23.fallbackFoundId = null; if (<fallbackDelay>5__24 > 0f) { <>2__current = <>4__this.WaitForExistingMatchBeforeFallback(<fallbackDelay>5__24, delegate(string id) { <>8__23.fallbackFoundId = id; }); <>1__state = 5; return true; } <>2__current = <>4__this.ResolveExistingMatchIdForCurrentSession(delegate(string id) { <>8__23.fallbackFoundId = id; }, logMisses: false); <>1__state = 6; return true; } goto IL_0a0c; IL_0992: if (!string.IsNullOrEmpty(<>8__23.fallbackFoundId)) { <>4__this.Log("<color=green>[Match Creation] ✓ Match adopted in non-host fallback: " + <>8__23.fallbackFoundId + "</color>"); <>4__this._currentMatchId = <>8__23.fallbackFoundId; <>4__this.ShowUploadNotification("Match record adopted from another player."); goto IL_0cf9; } <>8__23 = null; goto IL_0a0c; IL_10e4: if (!string.IsNullOrEmpty(<>8__33.playerName)) { <>4__this._playerIdsByName[<>8__33.playerName] = <>8__33.CS$<>8__locals1.playerId; if (<>4__this._cachedLeaderboardScores.TryGetValue(<>8__33.playerName, out <score>5__37)) { <gamePoints>5__34 = <score>5__37; <>4__this._cachedLeaderboardScoresVsPar.TryGetValue(<>8__33.playerName, out <scoreVsPar>5__35); } <>4__this._lastSubmittedScores[<>8__33.playerName] = <gamePoints>5__34; <>4__this._lastSubmittedScoresVsPar[<>8__33.playerName] = <scoreVsPar>5__35; } <startingPosition>5__36 = 0; if (!string.IsNullOrWhiteSpace(<>8__33.playerName)) { <startingPositionMap>5__8.TryGetValue(<>8__33.playerName, out <startingPosition>5__36); } <>8__33.entryId = null; <>2__current = <>4__this.EnsureMatchEntryForPlayer("Match Creation", <>8__33.CS$<>8__locals1.playerId, <>8__33.playerName, <>8__33.preMatchMmr, null, <gamePoints>5__34, <scoreVsPar>5__35, <startingPosition>5__36, "Progressive match tracking - created at round start", delegate(string id) { <>8__33.entryId = id; }); <>1__state = 12; return true; IL_0bc9: <prePostSessionId>5__25 = null; <>8__28 = new <>c__DisplayClass195_4(); <>8__28.newMatchId = null; <>2__current = <>4__this.SubmitMatchEntry(<>4__this.CollectMatchStats(0f), delegate(string id) { <>8__28.newMatchId = id; }); <>1__state = 8; return true; IL_0dd2: <>4__this._playerMatchEntryIds.Clear(); <>4__this._playerIdsByName.Clear(); <>4__this._lastSubmittedScores.Clear(); <>4__this._lastSubmittedScoresVsPar.Clear(); if (<startingLeaderboard>5__7 == null || <startingLeaderboard>5__7.Count == 0) { <>4__this.Log("<color=yellow>[Match Creation] Leaderboard empty at round start — deferring MatchEntry creation until the gameplay monitor sees players</color>"); if (<>4__this._monitorCoroutine == null) { <>4__this._monitorCoroutine = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.MonitorAndUpdateScores()); } return false; } <playerIds>5__10 = ((<>4__this._currentSession != null && <>4__this._currentSession.player_ids != null && <>4__this._currentSession.player_ids.Count > 0) ? <>4__this._currentSession.player_ids : new List<string> { <>4__this._userProfile.id }); <>2__current = <>4__this.EnrichPlayerIdsFromLeaderboard(<startingLeaderboard>5__7, <playerIds>5__10); <>1__state = 10; return true; IL_085e: <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 4; return true; IL_0a0c: <>4__this.Log("<color=cyan>[Match Creation] No match found in non-host fallback — posting as fallback creator</color>"); goto IL_0a1e; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__31).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CreatePlaceholderMatchEntryForMissingSessionPlayer>d__212 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string playerId; public SBGLPlugin <>4__this; private <>c__DisplayClass212_0 <>8__1; private int <gamePoints>5__2; private int <scoreVsPar>5__3; private int <lastScore>5__4; private int <lastVsPar>5__5; private int <cachedScore>5__6; private int <cachedVsPar>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CreatePlaceholderMatchEntryForMissingSessionPlayer>d__212(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass212_0(); <>8__1.<>4__this = <>4__this; if (string.IsNullOrWhiteSpace(playerId) || string.IsNullOrWhiteSpace(<>4__this._currentMatchId)) { return false; } <>8__1.playerName = null; <>8__1.preMatchMmr = null; if (<>4__this._userProfile != null && string.Equals(playerId, <>4__this._userProfile.id, StringComparison.OrdinalIgnoreCase)) { <>8__1.playerName = <>4__this._userProfile.display_name; <>8__1.preMatchMmr = <>4__this._userProfile.current_mmr.ToString(); goto IL_0149; } <>2__current = <>4__this.CallAPI("/Player/" + playerId, "GET", "", delegate(string res) { JObject val = <>8__1.<>4__this.ParseApiSingleObject(res); if (val != null) { <>8__1.playerName = (string)val["display_name"]; object obj = val["current_mmr"]; if (obj != null) { <>8__1.preMatchMmr = obj.ToString(); } } }); <>1__state = 1; return true; case 1: <>1__state = -1; goto IL_0149; case 2: { <>1__state = -1; if (!string.IsNullOrEmpty(<>8__1.entryId)) { <>4__this._playerMatchEntryIds[playerId] = <>8__1.entryId; <>4__this._playerIdsByName[<>8__1.playerName.Trim()] = playerId; <>4__this._lastSubmittedScores[<>8__1.playerName] = <gamePoints>5__2; <>4__this._lastSubmittedScoresVsPar[<>8__1.playerName] = <scoreVsPar>5__3; } else { <>4__this.Log("<color=yellow>[Match Finalize] Could not create placeholder MatchEntry for missing session player " + <>8__1.playerName + "</color>"); } return false; } IL_0149: if (string.IsNullOrWhiteSpace(<>8__1.playerName)) { <>8__1.playerName = playerId; } <gamePoints>5__2 = 0; <scoreVsPar>5__3 = 0; if (<>4__this._lastSubmittedScores.TryGetValue(<>8__1.playerName, out <lastScore>5__4)) { <gamePoints>5__2 = <lastScore>5__4; } else if (<>4__this._cachedLeaderboardScores.TryGetValue(<>8__1.playerName, out <cachedScore>5__6)) { <gamePoints>5__2 = <cachedScore>5__6; } if (<>4__this._lastSubmittedScoresVsPar.TryGetValue(<>8__1.playerName, out <lastVsPar>5__5)) { <scoreVsPar>5__3 = <lastVsPar>5__5; } else if (<>4__this._cachedLeaderboardScoresVsPar.TryGetValue(<>8__1.playerName, out <cachedVsPar>5__7)) { <scoreVsPar>5__3 = <cachedVsPar>5__7; } if (<gamePoints>5__2 == 0) { <>4__this.Log("<color=yellow>[Match Finalize] Skipping placeholder for session player " + <>8__1.playerName + " — game points is 0</color>"); return false; } <>8__1.entryId = null; <>2__current = <>4__this.EnsureMatchEntryForPlayer("Match Finalize", playerId, <>8__1.playerName, <>8__1.preMatchMmr, null, <gamePoints>5__2, <scoreVsPar>5__3, 0, "Placeholder entry created because player was in the session but missing from the final leaderboard snapshot", delegate(string id) { <>8__1.entryId = id; }); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DownloadProfilePic>d__228 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string url; public SBGLPlugin <>4__this; private UnityWebRequest <req>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DownloadProfilePic>d__228(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <req>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <req>5__1 = UnityWebRequestTexture.GetTexture(url.Replace("http://", "https://")); <>1__state = -3; <>2__current = <req>5__1.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -3; if ((int)<req>5__1.result == 1) { <>4__this._profileTexture = DownloadHandlerTexture.GetContent(<req>5__1); } <>4__this._hasFetchedProfilePic = true; <>m__Finally1(); <req>5__1 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__1 != null) { ((IDisposable)<req>5__1).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <EnrichPlayerIdsFromLeaderboard>d__210 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public List<LiveLeaderboardPlugin.SBGLPlayer> startingLeaderboard; public List<string> playerIds; public SBGLPlugin <>4__this; private <>c__DisplayClass210_0 <>8__1; private List<string> <leaderboardNames>5__2; private Dictionary<string, string> <testOverrides>5__3; private HashSet<string> <knownIds>5__4; private List<string>.Enumerator <>s__5; private string <existingId>5__6; private List<LiveLeaderboardPlugin.SBGLPlayer>.Enumerator <>s__7; private LiveLeaderboardPlugin.SBGLPlayer <lbPlayer>5__8; private <>c__DisplayClass210_1 <>8__9; private string <lookupName>5__10; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EnrichPlayerIdsFromLeaderboard>d__210(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { switch (<>1__state) { case -3: case 1: try { } finally { <>m__Finally1(); } break; case -4: case 2: try { } finally { <>m__Finally2(); } break; } <>8__1 = null; <leaderboardNames>5__2 = null; <testOverrides>5__3 = null; <knownIds>5__4 = null; <>s__5 = default(List<string>.Enumerator); <existingId>5__6 = null; <>s__7 = default(List<LiveLeaderboardPlugin.SBGLPlayer>.Enumerator); <lbPlayer>5__8 = null; <>8__9 = null; <lookupName>5__10 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass210_0(); <>8__1.<>4__this = <>4__this; if (startingLeaderboard == null || startingLeaderboard.Count == 0 || playerIds == null) { return false; } <leaderboardNames>5__2 = (from p in startingLeaderboard?.Where((LiveLeaderboardPlugin.SBGLPlayer p) => p != null && !string.IsNullOrWhiteSpace(p.Name)) select p.Name).ToList() ?? new List<string>(); <testOverrides>5__3 = <>4__this.GetTestPlayerOverrides(<leaderboardNames>5__2); if (<testOverrides>5__3.Count > 0) { <>4__this.Log($"<color=magenta>[Test Override] {<testOverrides>5__3.Count} player override(s) active for this match</color>"); } <knownIds>5__4 = new HashSet<string>(playerIds.Where((string id) => !string.IsNullOrWhiteSpace(id)), StringComparer.OrdinalIgnoreCase); <>8__1.knownNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (<>4__this._userProfile != null && !string.IsNullOrWhiteSpace(<>4__this._userProfile.display_name) && !string.IsNullOrWhiteSpace(<>4__this._userProfile.id)) { <>8__1.knownNames.Add(<>4__this._userProfile.display_name); <knownIds>5__4.Add(<>4__this._userProfile.id); if (!playerIds.Contains(<>4__this._userProfile.id)) { playerIds.Add(<>4__this._userProfile.id); } } <>s__5 = <knownIds>5__4.ToList().GetEnumerator(); <>1__state = -3; goto IL_032e; case 1: <>1__state = -3; <existingId>5__6 = null; goto IL_032e; case 2: { <>1__state = -4; if (!string.IsNullOrWhiteSpace(<>8__9.playerIdFromName)) { <>8__1.knownNames.Add(<lbPlayer>5__8.Name); if (<knownIds>5__4.Add(<>8__9.playerIdFromName)) { playerIds.Add(<>8__9.playerIdFromName); <>4__this.Log("<color=cyan>[Match Creation] Resolved leaderboard player " + <lbPlayer>5__8.Name + " -> " + <>8__9.playerIdFromName + "</color>"); } } else { <>4__this.Log("<color=yellow>[Match Creation] Could not resolve leaderboard player '" + <lbPlayer>5__8.Name + "' to a Player ID</color>"); } <>8__9 = null; <lookupName>5__10 = null; <lbPlayer>5__8 = null; break; } IL_032e: while (<>s__5.MoveNext()) { <existingId>5__6 = <>s__5.Current; if (<>4__this._userProfile != null && string.Equals(<existingId>5__6, <>4__this._userProfile.id, StringComparison.OrdinalIgnoreCase)) { continue; } <>2__current = <>4__this.CallAPI("/Player/" + <existingId>5__6, "GET", "", delegate(string res) { JObject val = <>8__1.<>4__this.ParseApiSingleObject(res); string text = (string)((val != null) ? val["display_name"] : null); if (!string.IsNullOrWhiteSpace(text)) { <>8__1.knownNames.Add(text); } }); <>1__state = 1; return true; } <>m__Finally1(); <>s__5 = default(List<string>.Enumerator); <>s__7 = startingLeaderboard.GetEnumerator(); <>1__state = -4; break; } while (<>s__7.MoveNext()) { <lbPlayer>5__8 = <>s__7.Current; <>8__9 = new <>c__DisplayClass210_1(); if (<lbPlayer>5__8 == null || string.IsNullOrWhiteSpace(<lbPlayer>5__8.Name) || <>8__1.knownNames.Contains(<lbPlayer>5__8.Name)) { continue; } <lookupName>5__10 = <>4__this.ApplyTestPlayerOverride(<lbPlayer>5__8.Name, <testOverrides>5__3); <>8__9.playerIdFromName = null; <>2__current = <>4__this.ResolvePlayerIdByNameFromApi(<lookupName>5__10, delegate(string id) { <>8__9.playerIdFromName = id; }); <>1__state = 2; return true; } <>m__Finally2(); <>s__7 = default(List<LiveLeaderboardPlugin.SBGLPlayer>.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__5).Dispose(); } private void <>m__Finally2() { <>1__state = -1; ((IDi