Decompiled source of TootTallyMultiplayer v1.0.3
plugins/TootTallyMultiplayer.dll
Decompiled 2 weeks 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.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BaboonAPI.Hooks.Initializer; using BaboonAPI.Hooks.Tracks; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Microsoft.FSharp.Core; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using TMPro; using TootTallyAccounts; using TootTallyCore; using TootTallyCore.APIServices; using TootTallyCore.Graphics; using TootTallyCore.Graphics.Animations; using TootTallyCore.Utils.Assets; using TootTallyCore.Utils.Helpers; using TootTallyCore.Utils.TootTallyGlobals; using TootTallyCore.Utils.TootTallyModules; using TootTallyCore.Utils.TootTallyNotifs; using TootTallyGameModifiers; using TootTallyLeaderboard; using TootTallyLeaderboard.Replays; using TootTallyMultiplayer.APIService; using TootTallyMultiplayer.MultiplayerCore; using TootTallyMultiplayer.MultiplayerCore.InputPrompts; using TootTallyMultiplayer.MultiplayerCore.PointScore; using TootTallyMultiplayer.MultiplayerPanels; using TootTallySettings; using TootTallySpectator; using TootTallyWebsocketLibs; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Localization.Components; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; using WebSocketSharp; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("TootTallyMultiplayer")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("TootTally Multiplayer Module")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("TootTallyMultiplayer")] [assembly: AssemblyTitle("TootTallyMultiplayer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.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 TootTallyMultiplayer { public class MultiplayerCard : MonoBehaviour { public MultSerializableClasses.MultiplayerUserInfo user; public TMP_Text textName; public TMP_Text textState; public TMP_Text textRank; public Image image; public Image containerImage; public Transform container; private Color _defaultColor; private Color _defaultContainerColor; public void InitTexts() { //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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) container = ((Component)this).transform.GetChild(0); textName = ((Component)container.Find("Name")).GetComponent<TMP_Text>(); textState = ((Component)container.Find("State")).GetComponent<TMP_Text>(); textRank = ((Component)container.Find("Rank")).GetComponent<TMP_Text>(); image = ((Component)this).gameObject.GetComponent<Image>(); _defaultColor = ((Graphic)image).color; containerImage = ((Component)container).GetComponent<Image>(); _defaultContainerColor = ((Graphic)containerImage).color; } public void ResetImageColor() { //IL_0007: 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) ((Graphic)image).color = _defaultColor; ((Graphic)containerImage).color = _defaultContainerColor; } public void UpdateUserInfo(MultSerializableClasses.MultiplayerUserInfo user, string state = null) { this.user = user; ResetImageColor(); SetTexts(user.username, state ?? user.state, user.rank); } public void SetTexts(string username, string state, int rank) { textName.text = username; textState.text = state; textRank.text = $"#{rank}"; } } public class MultiplayerController { public enum MultiplayerState { None, Home, CreatingLobby, Lobby, Hosting, SelectSong, ExitScene, Playing, PointScene, Quitting } public enum MultiplayerUserState { Spectating = -1, NotReady, Ready, Loading, Playing } private static List<MultSerializableClasses.MultiplayerLobbyInfo> _lobbyInfoList; private static List<string> _newLobbyCodeList; private static MultSerializableClasses.MultiplayerLobbyInfo _currentLobby; private static MultiplayerSystem _multiConnection; private static MultiplayerLiveScoreController _multiLiveScoreController; private MultiplayerPanelBase _currentActivePanel; private MultiplayerPanelBase _lastPanel; public bool IsTransitioning; private bool _hasSong; private MultSerializableClasses.UserState _currentUserState; private static string _savedDownloadLink; private static string _savedTrackRef; private string _searchFilter; private MultiplayerMainPanel _multMainPanel; private MultiplayerLobbyPanel _multLobbyPanel; private MultiplayerCreatePanel _multCreatePanel; private float _startGameTimer; private float _startGameTimerMaxTime; private float _nextStartTimerTick; public bool IsUpdating; public bool IsConnectionPending; public bool IsDownloadPending; public bool IsTimerStarted; public static MultSerializableClasses.MultiplayerSongInfo savedSongInfo; public static SingleTrackData savedTrackData; public PlaytestAnims GetInstance => CurrentInstance; public static PlaytestAnims CurrentInstance { get; private set; } public bool IsConnected { get { if (_multiConnection != null) { return ((WebsocketManager)_multiConnection).IsConnected; } return false; } } public bool IsAnybodyLoading => _currentLobby.players.Where((MultSerializableClasses.MultiplayerUserInfo x) => x.id != TootTallyUser.userInfo.id).Any((MultSerializableClasses.MultiplayerUserInfo x) => x.state == "Loading"); public bool IsRequestPending { get { if (!_multCreatePanel.IsRequestPending) { return IsConnectionPending; } return true; } } public bool IsDevMode { get { if (!TootTallyUser.userInfo.dev) { return TootTallyUser.userInfo.moderator; } return true; } } public MultiplayerController(PlaytestAnims __instance) { //IL_0160: Unknown result type (might be due to invalid IL or missing references) CurrentInstance = __instance; ((Component)CurrentInstance.factpanel).gameObject.SetActive(false); GameObject gameObject = GameObject.Find("Canvas-Window").gameObject; Transform val = gameObject.transform.Find("Panel"); GameObject canvas = Object.Instantiate<GameObject>(AssetBundleManager.GetPrefab("multiplayercanvas")); try { _multMainPanel = new MultiplayerMainPanel(canvas, this); } catch (Exception ex) { Plugin.LogError(ex.Message); Plugin.LogError(ex.StackTrace); } try { _multLobbyPanel = new MultiplayerLobbyPanel(canvas, this); } catch (Exception ex2) { Plugin.LogError(ex2.Message); Plugin.LogError(ex2.StackTrace); } try { _multCreatePanel = new MultiplayerCreatePanel(canvas, this); } catch (Exception ex3) { Plugin.LogError(ex3.Message); Plugin.LogError(ex3.StackTrace); } if (_lobbyInfoList == null) { _lobbyInfoList = new List<MultSerializableClasses.MultiplayerLobbyInfo>(); } _currentActivePanel = _multMainPanel; _searchFilter = ""; if (IsConnected) { UpdateLobbySongDetails(); _multiConnection.OnSocketOptionReceived = OnOptionInfoReceived; _multiConnection.OnSocketSongInfoReceived = OnSongInfoReceived; _multiConnection.OnSocketLobbyInfoReceived = OnLobbyInfoReceived; OnLobbyInfoReceived(_currentLobby); } TootTallyAnimationManager.AddNewScaleAnimation(_multMainPanel.panel, Vector3.one, 0.8f, GetSecondDegreeAnimation(1.5f), (Action<GameObject>)delegate { RefreshAllLobbyInfo(); MultiplayerManager.AllowExit = true; }); } public void OnGameControllerStartSetup() { _multiLiveScoreController = GameObject.Find("GameplayCanvas/UIHolder").AddComponent<MultiplayerLiveScoreController>(); MultiplayerPointScoreController.ClearSavedScores(); } public void OnGameControllerStartSongSendReadyState() { SendUserState(MultSerializableClasses.UserState.Playing); } public void OnSongQuit() { _multiConnection.SendUserState(MultSerializableClasses.UserState.NotReady); } public void InitializePointScore() { GameObject.Find("Canvas/FullPanel").AddComponent<MultiplayerPointScoreController>(); } private IEnumerator<WaitForSeconds> DelayDisplayLobbyInfo(float delay, MultSerializableClasses.MultiplayerLobbyInfo lobby, Action<MultSerializableClasses.MultiplayerLobbyInfo> callback) { yield return new WaitForSeconds(delay); callback(lobby); } public void UpdateLobbyInfo() { List<MultSerializableClasses.MultiplayerLobbyInfo> list = _lobbyInfoList.Where((MultSerializableClasses.MultiplayerLobbyInfo x) => x.title.Contains(_searchFilter)).ToList(); if (list.Count == 0) { _multMainPanel.ShowNoLobbyText(); _multMainPanel.FinalizeLobbyDisplay(); return; } _multMainPanel.SetupForLobbyDisplay(); for (int i = 0; i < list.Count; i++) { if (_newLobbyCodeList.Contains(list[i].id)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine((IEnumerator)DelayDisplayLobbyInfo((float)i * 0.1f, list[i], _multMainPanel.DisplayLobby)); } else { _multMainPanel.DisplayLobby(list[i], shouldAnimate: false); } } _multMainPanel.FinalizeLobbyDisplay(); _newLobbyCodeList.Clear(); _multMainPanel.UpdateScrolling(list.Count); } public void ConnectToLobby(string code, string password = "", bool forceEntry = false) { RefreshAllLobbyInfo(); if (_multiConnection == null || !((WebsocketManager)_multiConnection).ConnectionPending) { _multiConnection?.Disconnect(); Plugin.LogInfo("Connecting to " + code); IsConnectionPending = true; if (forceEntry) { code += "?ForceEntry=true"; } else if (password != "") { code = code + "?Password=" + password; } _multiConnection = new MultiplayerSystem(code, isHost: false) { OnWebSocketOpenCallback = delegate { _multMainPanel.OnLobbyConnectSuccess(); _multiConnection.OnWebSocketCloseCallback = null; _multiConnection.OnSocketSongInfoReceived = OnSongInfoReceived; _multiConnection.OnSocketOptionReceived = OnOptionInfoReceived; _multiConnection.OnSocketLobbyInfoReceived = OnLobbyInfoReceived; }, OnWebSocketCloseCallback = DisconnectFromLobby }; } } public void DisconnectFromLobby() { if (((WebsocketManager)_multiConnection).IsConnected) { _multiConnection.Disconnect(); _multLobbyPanel.ResetData(); } else { _multMainPanel.OnLobbyDisconnectError(); } StopTimer(); _currentLobby.code = ""; IsConnectionPending = false; MultiplayerManager.UpdateMultiplayerStateIfChanged(MultiplayerState.Home); MoveToMain(); RefreshAllLobbyInfo(); } public void Update() { if (!IsConnected || _multiConnection == null) { return; } if (IsConnectionPending) { UpdateConnection(); return; } _multiConnection.UpdateStacks(); if (IsTimerStarted) { UpdateTimer(); } } public void UpdateConnection() { IsConnectionPending = false; string text = _multiConnection.GetServerID.Split(new char[1] { '?' })[0]; TootTallyNotifManager.DisplayNotif("Connected to " + text, 6f); MultiplayerLogger.ClearLogs(); MultiplayerLogger.ServerLog("Connected to " + text); MultiplayerManager.UpdateMultiplayerState(MultiplayerState.Lobby); OnLobbyConnectionSuccess(); } public void OnLobbyConnectionSuccess() { MoveToLobby(); } public void MoveToCreate() { TransitionToPanel(_multCreatePanel); } public void MoveToLobby() { TransitionToPanel(_multLobbyPanel); } public void MoveToMain() { TransitionToPanel(_multMainPanel); } public void ReturnToLastPanel() { TransitionToPanel(_lastPanel); } public void HidePanel() { _currentActivePanel.panel.SetActive(false); } public void ShowPanel() { _currentActivePanel.panel.SetActive(true); } public void RefreshAllLobbyInfo() { if (IsUpdating || (Object)(object)CurrentInstance == (Object)null) { return; } IsUpdating = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine((IEnumerator)MultiplayerAPIService.GetLobbyList(delegate(List<MultSerializableClasses.MultiplayerLobbyInfo> lobbyList) { _multMainPanel.ClearAllLobby(); IEnumerable<string> idList = _lobbyInfoList.Select((MultSerializableClasses.MultiplayerLobbyInfo x) => x.id); _newLobbyCodeList = (from x in lobbyList select x.id into x where !idList.Contains(x) select x).ToList(); _lobbyInfoList = lobbyList; UpdateLobbyInfo(); IsUpdating = false; _multMainPanel.ShowRefreshLobbyButton(); })); } public void RefreshCurrentLobbyInfo() { if (_currentLobby.code != "") { OnLobbyInfoReceived(_currentLobby); } } public void OnLobbyInfoReceived(MultSerializableClasses.MultiplayerLobbyInfo lobbyInfo) { _currentLobby = lobbyInfo; if ((Object)(object)CurrentInstance != (Object)null) { _currentUserState = (MultSerializableClasses.UserState)Enum.Parse(typeof(MultSerializableClasses.UserState), _currentLobby.players.Find((MultSerializableClasses.MultiplayerUserInfo x) => x.id == TootTallyUser.userInfo.id).state); _multLobbyPanel.DisplayAllUserInfo(_currentLobby.players); _multLobbyPanel.OnLobbyInfoReceived(lobbyInfo.title, lobbyInfo.players.Count, lobbyInfo.maxPlayerCount); OnSongInfoReceived(_currentLobby.songInfo); } } public void OnLobbyInfoReceived(MultiplayerSystem.SocketLobbyInfo socketLobbyInfo) { OnLobbyInfoReceived(socketLobbyInfo.lobbyInfo); } public void OnUserInfoReceived(MultSerializableClasses.MultiplayerUserInfo userInfo) { if (userInfo.id != 0) { int index = _currentLobby.players.FindIndex((MultSerializableClasses.MultiplayerUserInfo x) => x.id == userInfo.id); _currentLobby.players[index] = userInfo; if ((Object)(object)CurrentInstance != (Object)null) { _multLobbyPanel?.UpdateUserInfo(userInfo); } } } public void TransitionToPanel(MultiplayerPanelBase nextPanel) { //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_003e: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown if (_currentActivePanel != nextPanel && !IsTransitioning) { IsTransitioning = true; _lastPanel = _currentActivePanel; Vector2 positionOut = -nextPanel.GetPanelPosition; TootTallyAnimationManager.AddNewPositionAnimation(_currentActivePanel.panel, Vector2.op_Implicit(positionOut), 0.9f, new SecondDegreeDynamicsAnimation(1.5f, 0.89f, 1.1f), (Action<GameObject>)delegate { //IL_002c: Unknown result type (might be due to invalid IL or missing references) _lastPanel.panel.SetActive(false); _lastPanel.panel.GetComponent<RectTransform>().anchoredPosition = positionOut; }); nextPanel.panel.SetActive(true); _currentActivePanel = nextPanel; TootTallyAnimationManager.AddNewPositionAnimation(nextPanel.panel, Vector2.op_Implicit(Vector2.zero), 0.9f, new SecondDegreeDynamicsAnimation(1.5f, 0.89f, 1.1f), (Action<GameObject>)delegate { IsTransitioning = false; }); } } public void OnSongInfoReceived(MultiplayerSystem.SocketSongInfo socketSongInfo) { OnSongInfoReceived(socketSongInfo.songInfo); } public void OnSongInfoReceived(MultSerializableClasses.MultiplayerSongInfo songInfo) { //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown if ((savedSongInfo.trackRef == "" || savedSongInfo.trackRef != songInfo.trackRef) && songInfo.trackRef != "") { MultiplayerLogger.HostLog(_currentLobby.players[0].username, "Song \"" + songInfo.songName + "\" was selected."); } savedSongInfo = songInfo; TootTallyGlobalVariables.gameSpeedMultiplier = songInfo.gameSpeed; GameModifierManager.LoadModifiersFromString(songInfo.modifiers); float num = (int)((songInfo.gameSpeed - 0.5f) / 0.25f); float difficulty; if (num != 6f) { float num2 = num * 0.25f + 0.5f; float num3 = (num + 1f) * 0.25f + 0.5f; float num4 = (songInfo.gameSpeed - num2) / (num3 - num2); difficulty = EasingHelper.Lerp(songInfo.speed_diffs[(int)num], songInfo.speed_diffs[(int)num + 1], num4); } else { difficulty = songInfo.speed_diffs[(int)num]; } UpdateLobbySongInfo(songInfo.songName, songInfo.gameSpeed, songInfo.modifiers, difficulty); FSharpOption<TromboneTrack> val = TrackLookup.tryLookup(songInfo.trackRef); _hasSong = songInfo.trackRef != "" && OptionModule.IsSome<TromboneTrack>(val); if (_hasSong) { SelectSongFromTrackref(val.Value.trackref); if (_currentUserState == MultSerializableClasses.UserState.NoSong) { SendUserState(MultSerializableClasses.UserState.NotReady); } _savedDownloadLink = null; _savedTrackRef = ""; } else { _savedDownloadLink = FileHelper.GetDownloadLinkFromSongData(new SongDataFromDB { mirror = songInfo.mirror, download = songInfo.download }); _savedTrackRef = songInfo.trackRef; SendUserState(MultSerializableClasses.UserState.NoSong); _multLobbyPanel.SetNullTrackDataDetails(_savedDownloadLink != null); } } public void DownloadSavedChart(ProgressBar bar) { if (_savedDownloadLink == null || IsDownloadPending) { return; } IsDownloadPending = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine((IEnumerator)TootTallyAPIService.DownloadZipFromServer(_savedDownloadLink, bar, (Action<byte[]>)delegate(byte[] data) { IsDownloadPending = false; if (data != null) { try { string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location), "Downloads/"); string text2 = _savedDownloadLink.Split(new char[1] { '/' }).Last() ?? ""; if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } FileHelper.WriteBytesToFile(text, text2, data); string text3 = Path.Combine(text, text2); string text4 = Path.Combine(Paths.BepInExRootPath, "CustomSongs/"); FileHelper.ExtractZipToDirectory(text3, text4); FileHelper.DeleteFile(text, text2); Plugin.Instance.ReloadTracks(); SelectSongFromTrackref(_savedTrackRef); SendUserState(MultSerializableClasses.UserState.NotReady); return; } catch (Exception) { _multLobbyPanel.OnUserStateChange(_currentUserState); TootTallyNotifManager.DisplayNotif("Download failed. Unexpected error occured.", 6f); return; } } _multLobbyPanel.OnUserStateChange(_currentUserState); TootTallyNotifManager.DisplayNotif("Download failed.", 6f); })); } public void SelectSongFromTrackref(string trackref) { FSharpOption<TromboneTrack> val = TrackLookup.tryLookup(trackref); savedTrackData = TrackLookup.toTrackData(val.Value); UpdateLobbySongDetails(); GlobalVariables.levelselect_index = savedTrackData.trackindex; GlobalVariables.chosen_track = savedTrackData.trackref; GlobalVariables.chosen_track_data = savedTrackData; _hasSong = true; _savedDownloadLink = null; _savedTrackRef = null; Plugin.LogInfo("Selected: " + savedTrackData.trackref); } public void UpdateLobbySongInfo(string songName, float gamespeed, string modifiers, float difficulty) { _multLobbyPanel?.OnSongInfoChanged(songName, gamespeed, modifiers, difficulty); } public void UpdateLobbySongDetails() { if (!((Object)(object)CurrentInstance == (Object)null)) { if (savedTrackData != null) { _multLobbyPanel?.SetTrackDataDetails(savedTrackData); } if (savedSongInfo.trackRef != "") { _multLobbyPanel?.OnSongInfoChanged(savedSongInfo); } } } public void StartLobbyGame() { if (IsTimerStarted) { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.AbortGame); return; } _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.StartTimer, new object[1] { 5 }); } public void SendStartGame() { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.StartGame); } public void StartGame() { if (_hasSong && (Object)(object)CurrentInstance != (Object)null && !IsTransitioning) { MultiplayerManager.UpdateMultiplayerState(MultiplayerState.Playing); Plugin.LogInfo("Starting Multiplayer for " + GlobalVariables.chosen_track_data.trackname_short + " - " + GlobalVariables.chosen_track_data.trackref); MultiplayerLogger.ServerLog("Song starting now."); IsTransitioning = true; CurrentInstance.sfx_ok.Play(); ((Component)CurrentInstance.fadepanel).gameObject.SetActive(true); MultiAudioController.PauseMusicSoft(); LeanTween.alphaCanvas(CurrentInstance.fadepanel, 1f, 0.65f).setOnComplete((Action)LoadLoaderScene); } else { TootTallyNotifManager.DisplayNotif("Cannot start the game. " + ((!_hasSong) ? "Chart not owned." : ""), 6f); } } public void AbortTimer() { StopTimer(); MultiplayerLogger.ServerLog("Song start aborted."); } public void StopTimer() { IsTimerStarted = false; _startGameTimer = (_startGameTimerMaxTime = _nextStartTimerTick); _multLobbyPanel.OnTimerAbort(); } public void StartTimer(float time) { _startGameTimer = (_startGameTimerMaxTime = (_startGameTimer = (_nextStartTimerTick = time))); _multLobbyPanel.OnTimerStart(); IsTimerStarted = true; } public void UpdateTimer() { _startGameTimer -= Time.deltaTime; if (_startGameTimer <= 0f) { StopTimer(); if (_multLobbyPanel.IsHost) { SendStartGame(); } } else if (_startGameTimer < _nextStartTimerTick) { MultiplayerLogger.ServerLog($"Song starting in {Mathf.RoundToInt(_startGameTimer)}s"); _nextStartTimerTick -= 1f; CurrentInstance.sfx_hover.Play(); } } public void UpdateSearchFilter(string filter) { _searchFilter = filter; RefreshAllLobbyInfo(); } public void KickUserFromLobby(int userID) { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.KickFromLobby, new object[1] { userID }); } public void GiveHostUser(int userID) { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.GiveHost, new object[1] { userID }); _currentUserState = MultSerializableClasses.UserState.NoSong; } public void SendQuickChat(MultiplayerSystem.QuickChat chat) { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.QuickChat, new object[1] { (int)chat }); } public void SendQuickChat(int chatId) { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.QuickChat, new object[1] { chatId }); } public void OnQuickChatReceived(int userID, MultiplayerSystem.QuickChat chat) { _multLobbyPanel?.OnQuickChatReceived(userID, chat); } public void SendSetLobbySettings(string name, string description, string password, int maxPlayer) { _multiConnection.SendSetLobbyInfo(name, description, password, maxPlayer); } public void OpenSongLink() { if (!(savedSongInfo.trackRef == "") && savedSongInfo.songID != 0) { Application.OpenURL($"https://toottally.com/song/{savedSongInfo.songID}/"); } } public void LoadLoaderScene() { CurrentInstance = null; _multLobbyPanel = null; IsTransitioning = false; SceneManager.LoadScene("loader"); } public void TransitionToSongSelection() { MultiplayerManager.UpdateMultiplayerState(MultiplayerState.SelectSong); } public void OnOptionInfoReceived(MultiplayerSystem.SocketOptionInfo optionInfo) { object obj = Enum.Parse(typeof(MultiplayerSystem.OptionInfoType), optionInfo.optionType); if (!(obj is MultiplayerSystem.OptionInfoType)) { return; } switch ((MultiplayerSystem.OptionInfoType)obj) { case MultiplayerSystem.OptionInfoType.StartGame: StartGame(); break; case MultiplayerSystem.OptionInfoType.StartTimer: StartTimer((float)optionInfo.values[0]); break; case MultiplayerSystem.OptionInfoType.AbortGame: AbortTimer(); break; case MultiplayerSystem.OptionInfoType.KickFromLobby: if (TootTallyUser.userInfo.id == (int)optionInfo.values[0]) { DisconnectFromLobby(); } break; case MultiplayerSystem.OptionInfoType.QuickChat: OnQuickChatReceived((int)optionInfo.values[0], (MultiplayerSystem.QuickChat)optionInfo.values[1]); break; case MultiplayerSystem.OptionInfoType.Refresh: case MultiplayerSystem.OptionInfoType.UpdateUserState: case MultiplayerSystem.OptionInfoType.GiveHost: RefreshAllLobbyInfo(); break; case MultiplayerSystem.OptionInfoType.UpdateUserInfo: OnUserInfoReceived(optionInfo.values[0].ToObject<MultSerializableClasses.MultiplayerUserInfo>()); break; case MultiplayerSystem.OptionInfoType.UpdateScore: _multiLiveScoreController?.UpdateLiveScore((int)optionInfo.values[0], (int)optionInfo.values[1], (int)optionInfo.values[2], (int)optionInfo.values[3]); break; case MultiplayerSystem.OptionInfoType.FinalScore: MultiplayerPointScoreController.AddScore((int)optionInfo.values[0], (int)optionInfo.values[1], (float)optionInfo.values[2], (int)optionInfo.values[3], optionInfo.values[4].ToObject<int[]>()); break; case MultiplayerSystem.OptionInfoType.Quit: _multiLiveScoreController?.OnUserQuit((int)optionInfo.values[0]); break; case MultiplayerSystem.OptionInfoType.SongFinished: break; } } public static MultSerializableClasses.MultiplayerUserInfo GetUserFromLobby(int id) { return _currentLobby.players.Find((MultSerializableClasses.MultiplayerUserInfo x) => x.id == id); } public void SendSongFinishedToLobby() { _multiConnection?.SendOptionInfo(MultiplayerSystem.OptionInfoType.SongFinished); } public void SendQuitFlag() { _multiConnection?.SendOptionInfo(MultiplayerSystem.OptionInfoType.Quit); } public void SendSongHashToLobby(string songHash, float gamespeed, string modifiers) { _multiConnection?.SendSongHash(songHash, gamespeed, modifiers); } public void SendScoreDataToLobby(int score, int combo, int health, int tally) { _multiConnection?.SendUpdateScore(score, combo, health, tally); _multiLiveScoreController?.UpdateLiveScore(TootTallyUser.userInfo.id, score, combo, health); } public void SendUserState(MultSerializableClasses.UserState state) { if (_currentUserState != state) { _currentUserState = state; _multLobbyPanel?.OnUserStateChange(state); _multiConnection?.SendUserState(state); } } public static SecondDegreeDynamicsAnimation GetSecondDegreeAnimation(float speedMult = 1f) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new SecondDegreeDynamicsAnimation(speedMult, 0.75f, 1.15f); } public static SecondDegreeDynamicsAnimation GetSecondDegreeAnimationNoBounce(float speedMult = 1f) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new SecondDegreeDynamicsAnimation(speedMult, 1f, 1f); } public void Dispose() { CurrentInstance = null; _lobbyInfoList?.Clear(); _multiConnection?.Disconnect(); } public void DebugFakeLobby() { _multMainPanel?.DisplayLobbyDebug(); } public void DebugFakeUser() { _multLobbyPanel?.DisplayUserInfoDebug(); } } public static class MultiplayerGameObjectFactory { private static TMP_InputField _inputFieldPrefab; private static GameObject _userCardPrefab; private static GameObject _liveScorePrefab; private static GameObject _pointScorePrefab; private static bool _isInitialized; public static void Initialize() { if (!_isInitialized) { SetUserCardPrefab(); SetInputFieldPrefab(); SetLiveScorePrefab(); SetPointScorePrefab(); _isInitialized = true; } } private static void SetUserCardPrefab() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) _userCardPrefab = Object.Instantiate<GameObject>(GetBorderedHorizontalBox(new Vector2(700f, 72f), 3)); GameObject gameObject = ((Component)_userCardPrefab.transform.GetChild(0)).gameObject; HorizontalLayoutGroup component = gameObject.GetComponent<HorizontalLayoutGroup>(); ((LayoutGroup)component).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = false; bool childForceExpandHeight = (((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false); ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = childForceExpandHeight; TMP_Text val = GameObjectFactory.CreateSingleText(gameObject.transform, "Name", "", Vector2.one / 2f, new Vector2(190f, 75f), Theme.colors.leaderboard.text, (TextFont)0); val.alignment = (TextAlignmentOptions)513; TMP_Text val2 = GameObjectFactory.CreateSingleText(gameObject.transform, "State", "", Vector2.one / 2f, new Vector2(190f, 75f), Theme.colors.leaderboard.text, (TextFont)0); val2.alignment = (TextAlignmentOptions)516; TMP_Text val3 = GameObjectFactory.CreateSingleText(gameObject.transform, "Rank", "", Vector2.one / 2f, new Vector2(190f, 75f), Theme.colors.leaderboard.text, (TextFont)0); val3.alignment = (TextAlignmentOptions)516; Object.DontDestroyOnLoad((Object)(object)_userCardPrefab); } private static void SetLiveScorePrefab() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) _liveScorePrefab = GetBorderedHorizontalBox(new Vector2(160f, 28f), 2); CanvasGroup val = _liveScorePrefab.AddComponent<CanvasGroup>(); val.alpha = 0.75f; GameObject gameObject = ((Component)_liveScorePrefab.transform.GetChild(0)).gameObject; HorizontalLayoutGroup component = gameObject.GetComponent<HorizontalLayoutGroup>(); bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false); ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = childControlWidth; RectTransform component2 = _liveScorePrefab.GetComponent<RectTransform>(); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(1f, 0f); component2.anchorMin = val2; Vector2 pivot = (component2.anchorMax = val2); component2.pivot = pivot; GameObject val4 = Object.Instantiate<GameObject>(gameObject, gameObject.transform); ((Object)val4).name = "Mask"; val4.AddComponent<LayoutElement>().ignoreLayout = true; val4.AddComponent<Mask>().showMaskGraphic = false; _liveScorePrefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_liveScorePrefab); } private static void SetPointScorePrefab() { //IL_000a: 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_0082: Unknown result type (might be due to invalid IL or missing references) _pointScorePrefab = GetBorderedHorizontalBox(new Vector2(200f, 28f), 2); GameObject gameObject = ((Component)_pointScorePrefab.transform.GetChild(0)).gameObject; HorizontalLayoutGroup component = gameObject.GetComponent<HorizontalLayoutGroup>(); bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false); ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = childControlWidth; RectTransform component2 = _pointScorePrefab.GetComponent<RectTransform>(); component2.pivot = new Vector2(0f, 1f); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.04f, 0.926f); component2.anchorMin = val; component2.anchorMax = val; _pointScorePrefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_pointScorePrefab); } private static void SetInputFieldPrefab() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("InputFieldHolder"); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchoredPosition = Vector2.zero; val2.sizeDelta = new Vector2(350f, 50f); GameObject val3 = Object.Instantiate<GameObject>(val, val.transform); GameObject val4 = Object.Instantiate<GameObject>(val3, val.transform); ((Object)val3).name = "Image"; ((Object)val4).name = "Text"; _inputFieldPrefab = val.AddComponent<TMP_InputField>(); Vector2 anchorMax = (val2.anchorMin = Vector2.zero); val2.anchorMax = anchorMax; ((Selectable)_inputFieldPrefab).image = val3.AddComponent<Image>(); RectTransform component = val3.GetComponent<RectTransform>(); Vector2 val5 = (component.pivot = Vector2.zero); anchorMax = (component.anchorMax = val5); component.anchorMin = anchorMax; component.anchoredPosition = new Vector2(0f, 4f); component.sizeDelta = new Vector2(350f, 2f); RectTransform component2 = val4.GetComponent<RectTransform>(); Vector2 val7 = (component2.pivot = Vector2.zero); val5 = (component2.anchorMax = val7); anchorMax = (component2.anchorMin = val5); component2.anchoredPosition = anchorMax; component2.sizeDelta = new Vector2(350f, 50f); _inputFieldPrefab.textComponent = GameObjectFactory.CreateSingleText(val4.transform, "TextLabel", "", Theme.colors.leaderboard.text, (TextFont)0); _inputFieldPrefab.textComponent.rectTransform.pivot = new Vector2(0f, 0.5f); _inputFieldPrefab.textComponent.alignment = (TextAlignmentOptions)513; _inputFieldPrefab.textComponent.margin = new Vector4(5f, 0f, 0f, 0f); _inputFieldPrefab.textComponent.enableWordWrapping = true; _inputFieldPrefab.textViewport = _inputFieldPrefab.textComponent.rectTransform; Object.DontDestroyOnLoad((Object)(object)_inputFieldPrefab); } public static TMP_InputField CreateInputField(Transform canvasTransform, string name, Vector2 size, float fontSize, string text, bool isPassword) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) TMP_InputField val = Object.Instantiate<TMP_InputField>(_inputFieldPrefab, canvasTransform); ((Object)val).name = name; ((Component)val).GetComponent<RectTransform>().sizeDelta = size; ((Component)((Component)val).transform.Find("Image")).GetComponent<RectTransform>().sizeDelta = new Vector2(size.x, 2f); ((Component)((Component)val).transform.Find("Text")).GetComponent<RectTransform>().sizeDelta = size; ((Component)val.textComponent).GetComponent<RectTransform>().sizeDelta = size; val.textComponent.fontSize = fontSize; val.textComponent.overflowMode = (TextOverflowModes)1; val.text = text; val.inputType = (InputType)(isPassword ? 2 : 0); return val; } public static GameObject CreateLiveScoreCard(Transform canvasTransform, Vector2 position, string name) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(_liveScorePrefab, canvasTransform); val.SetActive(true); val.GetComponent<RectTransform>().anchoredPosition = position; ((Object)val).name = name; return val; } public static GameObject CreatePointScoreCard(Transform canvasTransform, Vector2 position, string name) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(_pointScorePrefab, canvasTransform); val.SetActive(true); val.GetComponent<RectTransform>().anchoredPosition = position; ((Object)val).name = name; return val; } public static MultiplayerCard CreateUserCard(Transform canvasTransform) { MultiplayerCard multiplayerCard = Object.Instantiate<GameObject>(_userCardPrefab, canvasTransform).AddComponent<MultiplayerCard>(); multiplayerCard.InitTexts(); return multiplayerCard; } public static GameObject CreatePasswordInputPrompt(Transform canvasTransform, string titleText, Action<string> OnConfirm, Action OnCancel) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) GameObject borderedVerticalBox = GetBorderedVerticalBox(new Vector2(520f, 235f), 4, canvasTransform); RectTransform component = borderedVerticalBox.GetComponent<RectTransform>(); Vector2 val2 = (component.pivot = Vector2.one / 2f); Vector2 anchorMin = (component.anchorMax = val2); component.anchorMin = anchorMin; GameObject gameObject = ((Component)borderedVerticalBox.transform.GetChild(0)).gameObject; VerticalLayoutGroup component2 = gameObject.GetComponent<VerticalLayoutGroup>(); ((LayoutGroup)component2).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)component2).spacing = 21f; ((LayoutGroup)component2).padding = new RectOffset(5, 5, 35, 5); TMP_Text val4 = GameObjectFactory.CreateSingleText(gameObject.transform, "TitleText", titleText, (TextFont)0); val4.fontSize = 26f; val4.fontStyle = (FontStyles)1; val4.rectTransform.sizeDelta = new Vector2(0f, 32f); GameObject horizontalBox = GetHorizontalBox(new Vector2(0f, 30f), gameObject.transform); HorizontalLayoutGroup component3 = horizontalBox.GetComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component3).spacing = 8f; ((LayoutGroup)component3).padding = new RectOffset(0, 0, 3, 0); TMP_Text val5 = GameObjectFactory.CreateSingleText(horizontalBox.transform, "InputFieldLabel", "Password:", (TextFont)0); val5.rectTransform.sizeDelta = new Vector2(115f, 30f); val5.alignment = (TextAlignmentOptions)1028; TMP_InputField inputField = CreateInputField(horizontalBox.transform, "InputField", new Vector2(275f, 30f), 24f, "", isPassword: true); GameObject horizontalBox2 = GetHorizontalBox(new Vector2(0f, 66f), gameObject.transform); HorizontalLayoutGroup component4 = horizontalBox2.GetComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component4).spacing = 100f; bool childControlHeight = (((HorizontalOrVerticalLayoutGroup)component4).childForceExpandHeight = false); ((HorizontalOrVerticalLayoutGroup)component4).childControlHeight = childControlHeight; CustomButton val6 = GameObjectFactory.CreateCustomButton(horizontalBox2.transform, Vector2.zero, new Vector2(170f, 65f), "Confirm", "ConfirmButton", (Action)delegate { OnConfirm?.Invoke(inputField.text); }); CustomButton val7 = GameObjectFactory.CreateCustomButton(horizontalBox2.transform, Vector2.zero, new Vector2(170f, 65f), "Cancel", "CancelButton", OnCancel); return borderedVerticalBox; } public static LobbySettingsInputPrompt CreateLobbySettingsInputPrompt(Transform canvasTransform, Action<string, string, string, string> OnConfirm) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) LobbySettingsInputPrompt lobbySettingsInputPrompt = new LobbySettingsInputPrompt(canvasTransform, OnConfirm); lobbySettingsInputPrompt.gameObject.transform.localScale = new Vector3(0f, 0f, 1f); return lobbySettingsInputPrompt; } public static GameObject CreateQuickChatPopup(Transform canvasTransform, Action<MultiplayerSystem.QuickChat> OnBtnClickCallback, Action OnCloseBtnClick) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) GameObject borderedVerticalBox = GetBorderedVerticalBox(new Vector2(450f, 700f), 4, canvasTransform); borderedVerticalBox.transform.localScale = Vector2.op_Implicit(Vector2.zero); GameObject gameObject = ((Component)borderedVerticalBox.transform.GetChild(0)).gameObject; ((Graphic)gameObject.GetComponent<Image>()).color = (TMPro_ExtensionMethods.CompareRGB(Theme.colors.leaderboard.text, Color.black) ? new Color(1f, 1f, 1f, 1f) : new Color(0f, 0f, 0f, 1f)); RectTransform component = borderedVerticalBox.GetComponent<RectTransform>(); Vector2 val2 = (component.pivot = Vector2.one / 2f); Vector2 anchorMin = (component.anchorMax = val2); component.anchorMin = anchorMin; TMP_Text val4 = GameObjectFactory.CreateSingleText(gameObject.transform, "QuickChatTitle", "Quick Chat", (TextFont)0); val4.fontSize = 38f; val4.fontStyle = (FontStyles)1; val4.alignment = (TextAlignmentOptions)1026; val4.rectTransform.sizeDelta = new Vector2(450f, 60f); ((Component)GameObjectFactory.CreateCustomButton(gameObject.transform, Vector2.one * -5f, new Vector2(32f, 32f), AssetManager.GetSprite("Close64.png"), "CloseQuickChatButton", OnCloseBtnClick)).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; Color normalColor = default(Color); ((Color)(ref normalColor))..ctor(0f, 0f, 0f, 0f); for (int i = 0; i < 3; i++) { GameObject horizontalBox = GetHorizontalBox(new Vector2(0f, 205f), gameObject.transform); ((HorizontalOrVerticalLayoutGroup)horizontalBox.GetComponent<HorizontalLayoutGroup>()).spacing = 20f; for (int j = 0; j < 2; j++) { GameObject verticalBox = GetVerticalBox(new Vector2(190f, 0f), horizontalBox.transform); VerticalLayoutGroup component2 = verticalBox.GetComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component2).spacing = 1f; for (int k = 0; k < 4; k++) { int index = i * 8 + j * 4 + k; MultiplayerSystem.QuickChat quickChatOption = MultiplayerSystem.QuickChatToTextDic.ElementAt(index).Key; string text = string.Concat(from x in quickChatOption.ToString() select (!char.IsUpper(x)) ? x.ToString() : (" " + x)).TrimStart(new char[1] { ' ' }); CustomButton val5 = GameObjectFactory.CreateCustomButton(verticalBox.transform, Vector2.zero, new Vector2(0f, 36f), text, $"QCButton{quickChatOption}", (Action)delegate { OnBtnClickCallback(quickChatOption); }); ColorBlock colors = ((Selectable)val5.button).colors; ((ColorBlock)(ref colors)).normalColor = normalColor; ((Selectable)val5.button).colors = colors; } } } return borderedVerticalBox; } public static GameObject GetVerticalBox(Vector2 size, Transform parent = null) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(AssetBundleManager.GetPrefab("verticalbox"), parent); val.GetComponent<RectTransform>().sizeDelta = size; return val; } public static GameObject GetHorizontalBox(Vector2 size, Transform parent = null) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(AssetBundleManager.GetPrefab("horizontalbox"), parent); val.GetComponent<RectTransform>().sizeDelta = size; return val; } public static GameObject GetBorderedVerticalBox(Vector2 size, int bordersize, Transform parent = null) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_002b: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(AssetBundleManager.GetPrefab("borderedverticalbox"), parent); ((LayoutGroup)val.GetComponent<VerticalLayoutGroup>()).padding = new RectOffset(bordersize, bordersize, bordersize, bordersize); val.GetComponent<RectTransform>().sizeDelta = size + Vector2.one * 2f * (float)bordersize; return val; } public static GameObject GetBorderedHorizontalBox(Vector2 size, int bordersize, Transform parent = null) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_002b: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(AssetBundleManager.GetPrefab("borderedhorizontalbox"), parent); ((LayoutGroup)val.GetComponent<HorizontalLayoutGroup>()).padding = new RectOffset(bordersize, bordersize, bordersize, bordersize); val.GetComponent<RectTransform>().sizeDelta = size + Vector2.one * 2f * (float)bordersize; return val; } } public static class MultiplayerManager { public enum HomeScreenButtonIndexes { Play, Collect, Quit, Improv, Baboon, Credit, Settings, Advanced } public static readonly WaitForSeconds WAIT_TIME = new WaitForSeconds(5f); public static bool AllowExit; public const string PLAYTEST_SCENE_NAME = "zzz_playtest"; public const string LEVELSELECT_SCENE_NAME = "levelselect"; private static readonly string[] LETTER_GRADES = new string[7] { "F", "D", "C", "B", "A", "S", "SS" }; private static PlaytestAnims _currentInstance; private static PointSceneController _currentPointSceneInstance; private static RectTransform _multiButtonOutlineRectTransform; private static TootTallyAnimation _multiBtnAnimation; private static TootTallyAnimation _multiTextAnimation; private static MultiplayerController.MultiplayerState _state; private static MultiplayerController.MultiplayerState _previousState; private static MultiplayerController _multiController; private static bool _isSceneActive; private static bool _multiButtonLoaded; private static bool _isLevelSelectInit; private static bool _attemptedInitLevelSelect; private static bool _isRecursiveRefreshRunning; private static bool _wasAutotootUsed; private static bool _isSyncing = true; private static float _syncTimeoutTimer; public static MultiplayerController GetMultiplayerController => _multiController; public static bool IsConnectedToMultiplayer { get { if (_multiController != null) { return _multiController.IsConnected; } return false; } } public static bool IsPlayingMultiplayer { get { if (_multiController != null) { return _state == MultiplayerController.MultiplayerState.Playing; } return false; } } [HarmonyPatch(typeof(PlaytestAnims), "Start")] [HarmonyPrefix] public static bool OnStartPrefixLoadLevelSelectIfNotInit(PlaytestAnims __instance) { GlobalVariables.scene_destination = "levelselect"; if (SpectatingManager.IsSpectating) { SpectatingManager.StopAllSpectator(); } _currentInstance = __instance; if (!_isLevelSelectInit) { _attemptedInitLevelSelect = true; __instance.fadepanel.alpha = 1f; ((Component)__instance.fadepanel).gameObject.SetActive(true); SceneManager.LoadScene("levelselect", (LoadSceneMode)1); return false; } return true; } [HarmonyPatch(typeof(PlaytestAnims), "Start")] [HarmonyPostfix] public static void ChangePlayTestToMultiplayerScreen(PlaytestAnims __instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!_isLevelSelectInit) { return; } ((Component)Camera.main).transform.localPosition = Vector3.zero; ((Component)__instance.logo_trect).gameObject.SetActive(false); ((Component)__instance.logo_crect).gameObject.SetActive(false); GameModifierManager.ClearAllModifiers(); MultiplayerGameObjectFactory.Initialize(); MultiAudioController.InitMusic(); if (!MultiAudioController.IsMusicLoaded) { MultiAudioController.LoadMusic("MultiplayerMusic.mp3", delegate { MultiAudioController.PlayMusicSoft(); }); } else if (MultiAudioController.IsPaused) { MultiAudioController.ResumeMusicSoft(); } else { MultiAudioController.PlayMusicSoft(); } _multiController = new MultiplayerController(__instance); _isSceneActive = true; AllowExit = false; if ((_multiController.IsConnected && _state == MultiplayerController.MultiplayerState.SelectSong) || _state == MultiplayerController.MultiplayerState.PointScene || _state == MultiplayerController.MultiplayerState.Quitting) { UpdateMultiplayerState(MultiplayerController.MultiplayerState.Lobby); _multiController.UpdateLobbySongDetails(); } else { _previousState = MultiplayerController.MultiplayerState.None; UpdateMultiplayerState(MultiplayerController.MultiplayerState.Home); StartRecursiveRefresh(); } } [HarmonyPatch(typeof(Plugin), "Update")] [HarmonyPostfix] public static void Update() { if (!_isSceneActive) { return; } if (Input.GetKeyDown((KeyCode)27) && CanPressEscape()) { if (_state == MultiplayerController.MultiplayerState.Home) { ExitMultiplayer(); } else if (_state == MultiplayerController.MultiplayerState.Lobby) { _multiController.DisconnectFromLobby(); } else { _multiController.ReturnToLastPanel(); RollbackMultiplayerState(); } } else if (Input.GetKeyDown((KeyCode)45) && _state != MultiplayerController.MultiplayerState.Playing) { MultiAudioController.ChangeVolume(-0.01f); } else if (Input.GetKeyDown((KeyCode)61) && _state != MultiplayerController.MultiplayerState.Playing) { MultiAudioController.ChangeVolume(0.01f); } _multiController?.Update(); } private static bool CanPressEscape() { if (!_multiController.IsTransitioning && !_multiController.IsRequestPending && _state != MultiplayerController.MultiplayerState.ExitScene && _state != MultiplayerController.MultiplayerState.SelectSong && _state != MultiplayerController.MultiplayerState.Playing && _state != MultiplayerController.MultiplayerState.PointScene) { return _state != MultiplayerController.MultiplayerState.Quitting; } return false; } [HarmonyPatch(typeof(PlaytestAnims), "nextScene")] [HarmonyPrefix] public static bool OverwriteNextScene() { Plugin.LogInfo("exiting multi"); _isSceneActive = false; SceneManager.LoadScene("saveslot"); return false; } [HarmonyPatch(typeof(HomeController), "Start")] [HarmonyPostfix] public static void OnHomeControllerStartPostFixAddMultiplayerButton(HomeController __instance) { //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Expected O, but got Unknown //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04da: Unknown result type (might be due to invalid IL or missing references) //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0566: Unknown result type (might be due to invalid IL or missing references) //IL_057c: Unknown result type (might be due to invalid IL or missing references) //IL_05c8: Unknown result type (might be due to invalid IL or missing references) //IL_05de: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = GameObject.Find("MainCanvas").gameObject; GameObject gameObject2 = ((Component)gameObject.transform.Find("MainMenu")).gameObject; GameObject multiplayerButton = Object.Instantiate<GameObject>(__instance.btncontainers[1], gameObject2.transform); GameObject val = Object.Instantiate<GameObject>(((Component)gameObject2.transform.Find("Button1Collect")).gameObject, gameObject2.transform); GameObject multiplayerText = Object.Instantiate<GameObject>(__instance.paneltxts[1], gameObject2.transform); ((Object)multiplayerButton).name = "MULTIContainer"; ((Object)val).name = "MULTIButton"; ((Object)multiplayerText).name = "MULTIText"; Object.DestroyImmediate((Object)(object)((Component)multiplayerText.transform.GetChild(1)).GetComponent<LocalizeStringEvent>()); Text component = ((Component)multiplayerText.transform.GetChild(1)).GetComponent<Text>(); string text2 = (((Component)multiplayerText.transform.GetChild(1).GetChild(0)).GetComponent<Text>().text = "<i>MULTI</i>"); component.text = text2; ThemeManager.OverwriteGameObjectSpriteAndColor(((Component)multiplayerButton.transform.Find("FG")).gameObject, "MultiplayerButtonV2.png", Color.white); multiplayerButton.transform.SetSiblingIndex(0); multiplayerText.transform.SetSiblingIndex(21); val.transform.SetSiblingIndex(22); RectTransform component2 = multiplayerText.GetComponent<RectTransform>(); component2.anchoredPosition = new Vector2(100f, 100f); component2.sizeDelta = new Vector2(334f, 87f); _multiButtonOutlineRectTransform = ((Component)multiplayerButton.transform.Find("outline")).GetComponent<RectTransform>(); ((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (__instance.waitforclick == 0f) { __instance.addWaitForClick(); __instance.playSfx(3); if (TootTallyUser.userInfo == null || TootTallyUser.userInfo.id == 0) { TootTallyNotifManager.DisplayError("Please login on TootTally to play online.", 6f); } else { Plugin.LogInfo("Entering Multiplayer..."); __instance.musobj.Stop(); __instance.quickFlash(2); LeanTween.scale(__instance.fullcanvas, new Vector3(0.001f, 0.001f, 1f), 0.5f).setEaseInQuart(); __instance.screenfade.alpha = 0f; LeanTween.alphaCanvas(__instance.screenfade, 1f, 0.45f).setDelay(0.25f).setOnComplete((Action)LoadPlayTestScene); } } }); EventTrigger component3 = val.GetComponent<EventTrigger>(); component3.triggers.Clear(); Entry val2 = new Entry(); val2.eventID = (EventTriggerType)0; ((UnityEvent<BaseEventData>)(object)val2.callback).AddListener((UnityAction<BaseEventData>)delegate { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0067: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) TootTallyAnimation multiBtnAnimation2 = _multiBtnAnimation; if (multiBtnAnimation2 != null) { multiBtnAnimation2.Dispose(); } _multiBtnAnimation = TootTallyAnimationManager.AddNewScaleAnimation(((Component)multiplayerButton.transform.Find("outline")).gameObject, new Vector2(1.01f, 1.01f), 0.5f, new SecondDegreeDynamicsAnimation(3.75f, 0.8f, 1.05f), (Action<GameObject>)null); _multiBtnAnimation.SetStartVector(((Transform)_multiButtonOutlineRectTransform).localScale); TootTallyAnimation multiTextAnimation2 = _multiTextAnimation; if (multiTextAnimation2 != null) { multiTextAnimation2.Dispose(); } _multiTextAnimation = TootTallyAnimationManager.AddNewScaleAnimation(multiplayerText, new Vector2(1f, 1f), 0.5f, new SecondDegreeDynamicsAnimation(3.5f, 0.65f, 1.15f), (Action<GameObject>)null); _multiTextAnimation.SetStartVector(((Transform)multiplayerText.GetComponent<RectTransform>()).localScale); __instance.playSfx(2); RectTransform component11 = multiplayerButton.GetComponent<RectTransform>(); component11.anchoredPosition += new Vector2(-2f, 0f); }); component3.triggers.Add(val2); Entry val3 = new Entry(); val3.eventID = (EventTriggerType)1; ((UnityEvent<BaseEventData>)(object)val3.callback).AddListener((UnityAction<BaseEventData>)delegate { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0067: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) TootTallyAnimation multiBtnAnimation = _multiBtnAnimation; if (multiBtnAnimation != null) { multiBtnAnimation.Dispose(); } _multiBtnAnimation = TootTallyAnimationManager.AddNewScaleAnimation(((Component)multiplayerButton.transform.Find("outline")).gameObject, new Vector2(0.4f, 0.4f), 0.5f, new SecondDegreeDynamicsAnimation(1.5f, 0.8f, 1f), (Action<GameObject>)null); _multiBtnAnimation.SetStartVector(((Transform)_multiButtonOutlineRectTransform).localScale); TootTallyAnimation multiTextAnimation = _multiTextAnimation; if (multiTextAnimation != null) { multiTextAnimation.Dispose(); } _multiTextAnimation = TootTallyAnimationManager.AddNewScaleAnimation(multiplayerText, new Vector2(0.8f, 0.8f), 0.5f, new SecondDegreeDynamicsAnimation(3.5f, 0.65f, 1.15f), (Action<GameObject>)null); _multiTextAnimation.SetStartVector(((Transform)multiplayerText.GetComponent<RectTransform>()).localScale); RectTransform component10 = multiplayerButton.GetComponent<RectTransform>(); component10.anchoredPosition += new Vector2(2f, 0f); }); component3.triggers.Add(val3); _multiButtonLoaded = true; GameObject val4 = __instance.btncontainers[1]; ThemeManager.OverwriteGameObjectSpriteAndColor(((Component)val4.transform.Find("FG")).gameObject, "CollectButtonV2.png", Color.white); GameObject gameObject3 = ((Component)val4.transform.Find("FG")).gameObject; RectTransform component4 = gameObject3.GetComponent<RectTransform>(); val4.GetComponent<RectTransform>().anchoredPosition = new Vector2(900f, 475.2f); val4.GetComponent<RectTransform>().sizeDelta = new Vector2(320f, 190f); component4.sizeDelta = new Vector2(320f, 190f); GameObject val5 = __instance.allbtnoutlines[1]; ThemeManager.OverwriteGameObjectSpriteAndColor(val5, "CollectButtonOutline.png", Color.white); RectTransform component5 = val5.GetComponent<RectTransform>(); component5.sizeDelta = new Vector2(351f, 217.2f); GameObject val6 = __instance.paneltxts[1]; val6.transform.GetChild(1).localScale = Vector3.one * 0.6f; val6.GetComponent<RectTransform>().anchoredPosition = new Vector2(790f, 430f); val6.GetComponent<RectTransform>().sizeDelta = new Vector2(285f, 48f); val6.GetComponent<RectTransform>().pivot = Vector2.one / 2f; GameObject val7 = __instance.btncontainers[3]; GameObject gameObject4 = ((Component)val7.transform.Find("FG")).gameObject; ThemeManager.OverwriteGameObjectSpriteAndColor(gameObject4, "ImprovButtonV2.png", Color.white); RectTransform component6 = gameObject4.GetComponent<RectTransform>(); val7.GetComponent<RectTransform>().anchoredPosition = new Vector2(-150f, 156f); component6.sizeDelta = new Vector2(450f, 190f); GameObject val8 = __instance.allbtnoutlines[3]; ThemeManager.OverwriteGameObjectSpriteAndColor(val8, "ImprovButtonOutline.png", Color.white); RectTransform component7 = val8.GetComponent<RectTransform>(); component7.sizeDelta = new Vector2(480f, 220f); GameObject val9 = __instance.paneltxts[3]; Transform child = val9.transform.GetChild(0); Transform child2 = val9.transform.GetChild(1); Vector3 localScale = (child2.localScale = Vector3.one * 0.6f); child.localScale = localScale; child.localPosition = Vector2.op_Implicit(new Vector2(-196f, 0f)); child2.localPosition = Vector2.op_Implicit(new Vector2(42f, 25f)); val9.GetComponent<RectTransform>().anchoredPosition = new Vector2(305f, 385f); val9.GetComponent<RectTransform>().sizeDelta = new Vector2(426f, 54f); GameObject gameObject5 = ((Component)gameObject2.transform.Find("Button1Collect")).gameObject; RectTransform component8 = gameObject5.GetComponent<RectTransform>(); component8.anchoredPosition = new Vector2(739f, 380f); component8.sizeDelta = new Vector2(320f, 190f); ((Transform)component8).Rotate(0f, 0f, 15f); GameObject gameObject6 = ((Component)gameObject2.transform.Find("Button3")).gameObject; RectTransform component9 = gameObject6.GetComponent<RectTransform>(); component9.anchoredPosition = new Vector2(310f, 383f); component9.sizeDelta = new Vector2(450f, 195f); } private static void LoadPlayTestScene() { SceneManager.LoadScene("zzz_playtest"); } [HarmonyPatch(typeof(HomeController), "Update")] [HarmonyPostfix] public static void AnimateMultiButton(HomeController __instance) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (_multiButtonLoaded) { ((Component)((Component)((Component)_multiButtonOutlineRectTransform).transform.parent).transform.Find("FG/texholder")).GetComponent<CanvasGroup>().alpha = (((Transform)_multiButtonOutlineRectTransform).localScale.y - 0.4f) / 1.5f; } } [HarmonyPatch(typeof(GlobalLeaderboardManager), "OnLevelSelectControllerStartPostfix")] [HarmonyPrefix] public static bool PreventGlobalLeaderboardFromLoadingWhenInitMulti() { if (_attemptedInitLevelSelect) { _attemptedInitLevelSelect = false; return false; } return true; } [HarmonyPatch(typeof(GameObjectFactory), "OnLevelSelectControllerInitialize")] [HarmonyPostfix] public static void ArtificiallyInitLevelSelectOnFirstMultiplayerEnter(LevelSelectController levelSelectController) { if (!_isLevelSelectInit) { Plugin.LogInfo("levelselect init success"); _isLevelSelectInit = true; if ((Object)(object)_currentInstance != (Object)null) { LeanTween.cancelAll(); SceneManager.UnloadSceneAsync("levelselect"); _currentInstance.Start(); } } } [HarmonyPatch(typeof(ReplaySystemManager), "ResolveLoadReplay")] [HarmonyPrefix] public static bool SkipResolveReplayIfInMulti() { if (_state != MultiplayerController.MultiplayerState.SelectSong) { return true; } TootTallyNotifManager.DisplayNotif("Cannot watch replays in multiplayer.", 6f); return false; } [HarmonyPatch(typeof(LevelSelectController), "Start")] [HarmonyPostfix] public static void HideBackButton(LevelSelectController __instance) { if (IsConnectedToMultiplayer) { _currentInstance.hidefade(); _multiController.SendUserState(MultSerializableClasses.UserState.SelectingSong); } } [HarmonyPatch(typeof(LevelSelectController), "clickBack")] [HarmonyPrefix] public static bool ClickBackButtonMultiplayerSelectSong(LevelSelectController __instance) { if (!IsConnectedToMultiplayer) { return true; } OnMultiplayerSelectSongExit(__instance); return false; } [HarmonyPatch(typeof(LevelSelectController), "clickPlay")] [HarmonyPrefix] public static bool ClickPlayButtonMultiplayerSelectSong(LevelSelectController __instance) { if (__instance.back_clicked) { return false; } if (!IsConnectedToMultiplayer) { return true; } SingleTrackData val = (MultiplayerController.savedTrackData = __instance.alltrackslist[__instance.songindex]); string trackref = val.trackref; TromboneTrack val2 = TrackLookup.lookup(trackref); string songHash = SongDataHelper.GetSongHash(val2); GlobalVariables.levelselect_index = val.trackindex; GlobalVariables.chosen_track = val.trackref; GlobalVariables.chosen_track_data = val; _multiController.SendSongHashToLobby(songHash, TootTallyGlobalVariables.gameSpeedMultiplier, GameModifierManager.GetModifiersString()); OnMultiplayerSelectSongExit(__instance); return false; } private static void OnMultiplayerSelectSongExit(LevelSelectController __instance) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) _multiController.SendUserState(MultSerializableClasses.UserState.Ready); UpdateMultiplayerState(MultiplayerController.MultiplayerState.Lobby); __instance.back_clicked = true; __instance.bgmus.Stop(); __instance.doSfx(__instance.sfx_click); __instance.fader.SetActive(true); __instance.fader.transform.localScale = new Vector3(9.9f, 0.001f, 1f); LeanTween.cancelAll(); LeanTween.scaleY(__instance.fader, 9.75f, 0.25f).setEaseInQuart().setOnComplete((Action)delegate { //IL_009a: Unknown result type (might be due to invalid IL or missing references) _multiController.ShowPanel(); SceneManager.UnloadSceneAsync("levelselect"); MultiAudioController.ResumeMusicSoft(); _currentInstance.startBGAnims(); _currentInstance.fadepanel.alpha = 1f; ((Component)_currentInstance.fadepanel).gameObject.SetActive(true); LeanTween.alphaCanvas(_currentInstance.fadepanel, 0f, 1f).setOnComplete((Action)_currentInstance.hidefade); _currentInstance.factpanel.anchoredPosition3D = new Vector3(0f, -600f, 0f); }); } [HarmonyPatch(typeof(LevelSelectController), "hoverPlay")] [HarmonyPrefix] public static bool PreventHoverPlayLeanTweenWhenTransitioning(LevelSelectController __instance) { if (IsConnectedToMultiplayer) { return !__instance.back_clicked; } return false; } [HarmonyPatch(typeof(LevelSelectController), "unHoverPlay")] [HarmonyPrefix] public static bool PreventUnhoverPlayLeanTweenWhenTransitioning(LevelSelectController __instance) { if (IsConnectedToMultiplayer) { return !__instance.back_clicked; } return false; } [HarmonyPatch(typeof(PointSceneController), "Start")] [HarmonyPostfix] private static void OnPointSceneControllerStart(PointSceneController __instance) { if (_state == MultiplayerController.MultiplayerState.Playing) { _currentPointSceneInstance = __instance; _multiController.SendSongFinishedToLobby(); _multiController.InitializePointScore(); UpdateMultiplayerState(MultiplayerController.MultiplayerState.PointScene); __instance.btn_retry_obj.SetActive(false); __instance.btn_nav_cards.SetActive(false); __instance.btn_nav_baboon.SetActive(false); __instance.btn_leaderboard.SetActive(false); } } public static void OnMultiplayerPointScoreClick(int score, float percent, int maxCombo, int[] noteTally) { if (!((Object)(object)_currentPointSceneInstance == (Object)null)) { _currentPointSceneInstance.txt_score.text = $"{score}:n0 {percent:0.00}%"; _currentPointSceneInstance.txt_perfectos.text = noteTally[4].ToString("n0"); _currentPointSceneInstance.txt_nices.text = noteTally[3].ToString("n0"); _currentPointSceneInstance.txt_okays.text = noteTally[2].ToString("n0"); _currentPointSceneInstance.txt_mehs.text = noteTally[1].ToString("n0"); _currentPointSceneInstance.txt_nasties.text = noteTally[0].ToString("n0"); _currentPointSceneInstance.scorepercentage = Mathf.Max((float)(score / GlobalVariables.gameplay_absolute_max_score), 0.01f); _currentPointSceneInstance.scoreindex = (int)Mathf.Clamp(_currentPointSceneInstance.scorepercentage / 0.2f - 1f, -1f, 5f); _currentPointSceneInstance.letterscore = LETTER_GRADES[_currentPointSceneInstance.scoreindex + 1]; _currentPointSceneInstance.popScoreAnim(_currentPointSceneInstance.scoreindex + 1); } } [HarmonyPatch(typeof(PointSceneController), "clickCont")] [HarmonyPostfix] private static void OnClickContReturnToMulti(PointSceneController __instance) { if (_state == MultiplayerController.MultiplayerState.PointScene) { __instance.scenetarget = "zzz_playtest"; } } [HarmonyPatch(typeof(PointSceneController), "clickRetry")] [HarmonyPrefix] private static bool OnRetryClickPreventRetry() { if (_state == MultiplayerController.MultiplayerState.PointScene) { TootTallyNotifManager.DisplayNotif("Can't retry in multiplayer.", 6f); return false; } return true; } [HarmonyPatch(typeof(GameController), "pauseRetryLevel")] [HarmonyPrefix] private static bool PreventRetryInMultiplayer() { if (_multiController != null && _state == MultiplayerController.MultiplayerState.Quitting) { TootTallyNotifManager.DisplayNotif("Can't quick retry in multiplayer.", 6f); return false; } return true; } [HarmonyPatch(typeof(GameController), "pauseQuitLevel")] [HarmonyPrefix] private static bool PreventQuickQuittingInMultiplayer() { if (_multiController != null && _state == MultiplayerController.MultiplayerState.Quitting) { TootTallyNotifManager.DisplayNotif("Can't fast quit in multiplayer.", 6f); return false; } return true; } [HarmonyPatch(typeof(GameController), "doScoreText")] [HarmonyPostfix] private static void OnDoScoreTextSendScoreToLobby(int whichtext, GameController __instance) { if (IsPlayingMultiplayer && IsConnectedToMultiplayer && !_wasAutotootUsed) { if (!_wasAutotootUsed && __instance.controllermode) { _wasAutotootUsed = true; _multiController.SendQuitFlag(); } else { _multiController.SendScoreDataToLobby(__instance.totalscore, __instance.highestcombocounter, (int)__instance.currenthealth, whichtext); } } } [HarmonyPatch(typeof(GameController), "Start")] [HarmonyPostfix] private static void OnMultiplayerGameStart(GameController __instance) { _wasAutotootUsed = false; if (IsPlayingMultiplayer) { _multiController.OnGameControllerStartSetup(); } } [HarmonyPatch(typeof(GameController), "Update")] [HarmonyPostfix] private static void OnMultiplayerUpdateWaitForSync(GameController __instance) { if (_isSyncing) { if (IsPlayingMultiplayer && (!_multiController.IsAnybodyLoading || _syncTimeoutTimer > 10f)) { __instance.startSong(true); } else { _syncTimeoutTimer += Time.deltaTime; } } if (IsPlayingMultiplayer) { __instance.restarttimer = 0.01f; } } [HarmonyPatch(typeof(GameController), "startSong")] [HarmonyPrefix] private static bool OnMultiplayerWaitForSync() { if (IsPlayingMultiplayer && _multiController.IsAnybodyLoading && _syncTimeoutTimer < 10f) { _isSyncing = true; _syncTimeoutTimer = 0f; _multiController.OnGameControllerStartSongSendReadyState(); TootTallyNotifManager.DisplayNotif("Waiting for all players to load...", 6f); return false; } _syncTimeoutTimer = 0f; _isSyncing = false; return true; } [HarmonyPatch(typeof(PauseCanvasController), "showPausePanel")] [HarmonyPrefix] public static bool OnGamePause(PauseCanvasController __instance) { if (!IsPlayingMultiplayer) { return true; } UpdateMultiplayerState(MultiplayerController.MultiplayerState.Quitting); GameController gc = __instance.gc; gc.paused = true; gc.quitting = true; gc.sfxrefs.backfromfreeplay.Play(); gc.pausecanvas.SetActive(false); gc.curtainc.closeCurtain(false); LeanTween.alphaCanvas(__instance.curtaincontroller.fullfadeblack, 1f, 0.5f).setDelay(0.6f).setEaseInOutQuint() .setOnComplete((Action)delegate { __instance.curtaincontroller.unloadAssets(); SceneManager.LoadScene("zzz_playtest"); }); return false; } [HarmonyPatch(typeof(SpectatingManager), "OnSpectateButtonPress")] [HarmonyPrefix] public static bool PreventSpectatingWhileInMultiplayer() { if (IsPlayingMultiplayer || IsConnectedToMultiplayer || _isSceneActive) { TootTallyNotifManager.DisplayNotif("Cannot spectate someone while in multiplayer.", 6f); return false; } return true; } [HarmonyPatch(typeof(GameModifierManager), "Toggle")] [HarmonyPrefix] public static bool PreventBrutalAndInstaFailToggles(ModifierType modifierType) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 if (IsPlayingMultiplayer || IsConnectedToMultiplayer || _isSceneActive) { if ((int)modifierType == 2) { TootTallyNotifManager.DisplayNotif("Cannot enable Brutal Mode in multiplayer.", 6f); return false; } if ((int)modifierType == 3) { TootTallyNotifManager.DisplayNotif("Cannot enable InstaFail in multiplayer.", 6f); return false; } } return true; } public static void ExitMultiplayer() { if (AllowExit) { UpdateMultiplayerState(MultiplayerController.MultiplayerState.ExitScene); } } public static void UpdateMultiplayerStateIfChanged(MultiplayerController.MultiplayerState newState) { if (_state != newState) { _previousState = _state; _state = newState; ResolveMultiplayerState(); } } public static void UpdateMultiplayerState(MultiplayerController.MultiplayerState newState) { _previousState = _state; _state = newState; ResolveMultiplayerState(); } private static void ResolveMultiplayerState() { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) Plugin.LogInfo($"Multiplayer state changed from {_previousState} to {_state}"); switch (_state) { case MultiplayerController.MultiplayerState.Lobby: _multiController.OnLobbyConnectionSuccess(); break; case MultiplayerController.MultiplayerState.SelectSong: _currentInstance.fadepanel.alpha = 0f; ((Component)_currentInstance.fadepanel).gameObject.SetActive(true); MultiAudioController.PauseMusicSoft(); LeanTween.alphaCanvas(_currentInstance.fadepanel, 1f, 0.25f).setOnComplete((Action)delegate { SceneManager.LoadScene("levelselect", (LoadSceneMode)1); _multiController.HidePanel(); }); _currentInstance.factpanel.anchoredPosition3D = new Vector3(0f, -600f, 0f); break; case MultiplayerController.MultiplayerState.ExitScene: LeanTween.cancel(((Component)_currentInstance.fadepanel).gameObject); MultiAudioController.StopMusicSoft(); StopRecursiveRefresh(); _multiController.Dispose(); LeaveScene(); break; case MultiplayerController.MultiplayerState.Playing: StopRecursiveRefresh(); break; case MultiplayerController.MultiplayerState.Quitting: if (!_wasAutotootUsed) { _multiController.SendQuitFlag(); } _multiController.OnSongQuit(); break; case MultiplayerController.MultiplayerState.Home: case MultiplayerController.MultiplayerState.CreatingLobby: case MultiplayerController.MultiplayerState.Hosting: case MultiplayerController.MultiplayerState.PointScene: break; } } private static void LeaveScene() { if (TootTallyUser.userInfo.id == 8) { _currentInstance.nextScene(); return; } _currentInstance.sfx_ok.Play(); ((Component)_currentInstance.fadepanel).gameObject.SetActive(true); LeanTween.alphaCanvas(_currentInstance.fadepanel, 1f, 0.4f).setOnComplete((Action)_currentInstance.nextScene); } public static void RollbackMultiplayerState() { MultiplayerController.MultiplayerState state = _state; _state = _previousState; _previousState = state; ResolveMultiplayerState(); } public static void StartRecursiveRefresh() { _isRecursiveRefreshRunning = true; ((MonoBehaviour)_currentInstance).StartCoroutine((IEnumerator)RecursiveLobbyRefresh()); } public static void StopRecursiveRefresh() { _isRecursiveRefreshRunning = false; ((MonoBehaviour)_currentInstance).StopCoroutine((IEnumerator)RecursiveLobbyRefresh()); } private static IEnumerator<WaitForSeconds> RecursiveLobbyRefresh() { yield return WAIT_TIME; if ((Object)(object)_currentInstance != (Object)null && _isRecursiveRefreshRunning) { _multiController.RefreshAllLobbyInfo(); ((MonoBehaviour)_currentInstance).StartCoroutine((IEnumerator)RecursiveLobbyRefresh()); } } public static void DebugFakeLobby() { _multiController?.DebugFakeLobby(); } public static void DebugFakeUser() { _multiController?.DebugFakeUser(); } } [BepInPlugin("TootTallyMultiplayer", "TootTallyMultiplayer", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("Tooter")] public class Plugin : BaseUnityPlugin, ITootTallyModule { public static Plugin Instance; private const string CONFIG_NAME = "Multiplayer.cfg"; private Harmony _harmony; public static TootTallySettingPage settingPage; public bool IsConfigInitialized { get; set; } public string Name { get { return "TootTallyMultiplayer"; } set { Name = value; } } public ConfigEntry<bool> ModuleConfigEnabled { get; set; } public ConfigEntry<bool> ShowLiveScore { get; set; } public ConfigEntry<string> SavedLobbyTitle { get; set; } public ConfigEntry<string> SavedLobbyDesc { get; set; } public ConfigEntry<int> SavedLobbyMaxPlayer { get; set; } public static void LogInfo(string msg) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg); } public static void LogError(string msg) { ((BaseUnityPlugin)Instance).Logger.LogError((object)msg); } private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown if (!((Object)(object)Instance != (Object)null)) { Instance = this; _harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); GameInitializationEvent.Register(((BaseUnityPlugin)this).Info, (Action)TryInitialize); } } public void Update() { } private void TryInitialize() { ModuleConfigEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Modules", "Multiplayer", true, "Enable TootTally's Multiplayer module"); TootTallyModuleManager.AddModule((ITootTallyModule)(object)this); Plugin.Instance.AddModuleToSettingPage((ITootTallyModule)(object)this); } public void LoadModule() { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ShowLiveScore = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "ShowLiveScore", true, "Show the live score while playing in multiplayer."); SavedLobbyTitle = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SavedLobbyTitle", "", "Last lobby creation name used."); SavedLobbyDesc = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SavedLobbyDesc", "Welcome to my lobby!", "Last lobby creation description used."); SavedLobbyMaxPlayer = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SavedLobbyMaxPlayer", 16, "Last lobby creation lobby max player used."); string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), "multiplayerassetbundle"); AssetBundleManager.LoadAssets(text); string text2 = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), "Assets"); AssetManager.LoadAssets(text2); _harmony.PatchAll(typeof(MultiplayerManager)); LogInfo("Module loaded!"); } public void UnloadModule() { _harmony.UnpatchSelf(); LogInfo("Module unloaded!"); } } public class MultiplayerSystem : WebsocketManager { public enum DataType { SongInfo, LobbyInfo, OptionInfo, SetSong, SetLobbyInfo } public enum QuickChat { Hello, Welcome, Bye, Leave, Wait, ImReady, ReadyUp, GoodLuck, GoodChart, BadChart, Yes, No, TooFast, TooSlow, TooHard, TooEasy, NicePlay, GoodGame, CloseOne, Rematch, Laugh, Enjoy, WantHost, GiveHost } public enum OptionInfoType { Refresh, UpdateUserInfo, UpdateUserState, UpdateScore, SongFinished, FinalScore, QuickChat, Quit, GiveHost, KickFromLobby, StartTimer, StartGame, AbortGame, LobbyInfoChanged } public interface ISocketMessage { string dataType { get; } } public struct SocketSetSongByHash : ISocketMessage { public string filehash { get; set; } public float gamespeed { get; set; } public string modifiers { get; set; } public string dataType => DataType.SetSong.ToString(); } public struct SocketSetLobbyInfo : ISocketMessage { public string name; public string description; public string password; public int maxPlayer; public string dataType => DataType.SetSong.ToString(); } public struct SocketOptionInfo : ISocketMessage { public string optionType { get; set; } public dynamic[] values { get; set; } public string dataType => DataType.OptionInfo.ToString(); } public struct SocketLobbyInfo : ISocketMessage { public MultSerializableClasses.MultiplayerLobbyInfo lobbyInfo { get; set; } public string dataType => DataType.LobbyInfo.ToString(); } public struct SocketSongInfo : ISocketMessage { public MultSerializableClasses.MultiplayerSongInfo songInfo { get; set; } public string dataType => DataType.SongInfo.ToString(); } public class SocketDataConverter : JsonConverter { public override bool CanWrite => false; public override bool CanConvert(Type objectType) { return objectType == typeof(ISocketMessage); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); object obj = Enum.Parse(typeof(DataType), Extensions.Value<string>((IEnumerable<JToken>)val["dataType"])); if (obj is DataType) { switch ((DataType)obj) { case DataType.SongInfo: return ((JToken)val).ToObject<SocketSongInfo>(serializer); case DataType.LobbyInfo: return ((JToken)val).ToObject<SocketLobbyInfo>(serializer); case DataType.OptionInfo: return ((JToken)val).ToObject<SocketOptionInfo>(serializer); } } return null; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } public Action OnWebSocketOpenCallback; public Action OnWebSocketCloseCallback; public static JsonConverter[] _dataConverter = (JsonConverter[])(object)new JsonConverter[1] { new SocketDataConverter() }; public ConcurrentQueue<SocketSongInfo> _receivedSongInfo; public ConcurrentQueue<SocketLobbyInfo> _receivedLobbyInfo; public ConcurrentQueue<SocketOptionInfo> _receivedSocketOptionInfo; public Action<SocketSongInfo> OnSocketSongInfoReceived; public Action<SocketLobbyInfo> OnSocketLobbyInfoReceived; public Action<SocketOptionInfo> OnSocketOptionReceived; public static readonly Dictionary<QuickChat, string> QuickChatToTextDic = new Dictionary<QuickChat, string> { { QuickChat.Hello, "Hello!" }, { QuickChat.Welcome, "Welcome!" }, { QuickChat.Bye, "Bye bye!" }, { QuickChat.Leave, "I have to leave." }, { QuickChat.Wait, "Wait for me." }, { QuickChat.ImReady, "I'm ready!" }, { QuickChat.ReadyUp, "Ready up!" }, { QuickChat.GoodLuck, "Good luck!" }, { QuickChat.GoodChart, "I like this chart." }, { QuickChat.BadChart, "I don't like this chart." }, { QuickChat.Yes, "Yes." }, { QuickChat.No, "No." }, { QuickChat.TooFast, "I think the game speed is too fast." }, { QuickChat.TooSlow, "I think the game speed is too slow." }, { QuickChat.TooHard, "I think the song is too hard." }, { QuickChat.TooEasy, "I think the song is too easy." }, { QuickChat.NicePlay, "Nice play!" }, { QuickChat.GoodGame, "Good game." }, { QuickChat.CloseOne, "That was a close match!" }, { QuickChat.Rematch, "Rematch!" }, { QuickChat.Laugh, "Ahah!" }, { QuickChat.Enjoy, "Im enjoying this lobby!" }, { QuickChat.WantHost, "Can I have host?" }, { QuickChat.GiveHost, "Who want to be host?" } }; public string GetServerID => ((WebsocketManager)this)._id; public MultiplayerSystem(string serverID, bool isHost) : base(serverID, "wss://spec.toottally.com/mp/join/", "1.0.3") { ((WebsocketManager)this).ConnectionPending = true; _receivedSongInfo = new ConcurrentQueue<SocketSongInfo>(); _receivedLobbyInfo = new ConcurrentQueue<SocketLobbyInfo>(); _receivedSocketOptionInfo = new ConcurrentQueue<SocketOptionInfo>(); ((WebsocketManager)this).ConnectToWebSocketServer(((WebsocketManager)this)._url + serverID, Plugin.GetAPIKey, isHost); } public void SendSongHash(string filehash, float gamespeed, string modifiers) { SocketSetSongByHash socketSetSongByHash = default(SocketSetSongByHash); socketSetSongByHash.filehash = filehash; socketSetSongByHash.gamespeed = gamespeed; socketSetSongByHash.modifiers = modifiers; SocketSetSongByHash socketSetSongByHash2 = socketSetSongByHash; SendSongHash(socketSetSongByHash2); } public void SendSetLobbyInfo(string name, string description, string password, int maxPlayer) { SocketSetLobbyInfo socketSetLobbyInfo = default(SocketSetLobbyInfo); socketSetLobbyInfo.name = name; socketSetLobbyInfo.description = description; socketSetLobbyInfo.password = password; socketSetLobbyInfo.maxPlayer = maxPlayer; SocketSetLobbyInfo socketSetLobbyInfo2 = socketSetLobbyInfo; string text = JsonConvert.SerializeObject((object)socketSetLobbyInfo2); ((WebsocketManager)this).SendToSocket(text); } public void SendSongHash(SocketSetSongByHash socketSetSongByHash) { string text = JsonConvert.SerializeObject((object)socketSetSongByHash); ((WebsocketManager)this).SendToSocket(text); } public void SendOptionInfo(OptionInfoType optionType, dynamic[] values = null) { SocketOptionInfo socketOptionInfo = default(SocketOptionInfo); socketOptionInfo.optionType = optionType.ToString(); socketOptionInfo.values = values; SocketOptionInfo socketOptionInfo2 = socketOptionInfo; string text = JsonConvert.SerializeObject((object)socketOptionInfo2); ((WebsocketManager)this).SendToSocket(text); } public void SendUserState(MultSerializableClasses.UserState state) { SendOptionInfo(OptionInfoType.UpdateUserState, new object[1] { state.ToString() }); } public void SendUpdateScore(int score, int combo, int health, int tally) { SendOptionInfo(OptionInfoType.UpdateScore, new object[4] { score, combo, health, tally }); } public void UpdateStacks() { if (OnSocketSongInfoReceived != null && _receivedSongInfo.TryDequeue(out var result)) { OnSocketSongInfoReceived(result); } if (OnSocketLobbyInfoReceived != null && _receivedLobbyInfo.TryDequeue(out var result2)) { OnSocketLobbyInfoReceived(result2); } if (OnSocketOptionReceived != null && _receivedSocketOptionInfo.TryDequeue(out var result3)) { OnSocketOptionReceived(result3); } } protected override void OnDataReceived(object sender, MessageEventArgs e) { if (e.IsText) { ISocketMessage socketMessage; try { socketMessage = JsonConvert.DeserializeObject<ISocketMessage>(e.Data, _dataConverter); } catch (Exception) { return; } if (socketMessage is SocketSongInfo item && !((WebsocketManager)this).IsHost) { _receivedSongInfo.Enqueue(item); } else if (socketMessage is SocketOptionInfo item2) { _receivedSocketOptionInfo.Enqueue(item2); } else if (socketMessage is SocketLobbyInfo) { SocketLobbyInfo item3 = (SocketLobbyInfo)(object)socketMessage; _receivedLobbyInfo.Enqueue(item3); } } } protected override void OnWebSocketOpen(object sender, EventArgs e) { TootTallyNotifManager.DisplayNotif("Connected to multiplayer server.", 6f); OnWebSocketOpenCallback?.Invoke(); ((WebsocketManager)this).OnWebSocketOpen(sender, e); } protected overr