Decompiled source of TootTallyMultiplayer v1.0.9
plugins/TootTallyMultiplayer.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.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 TrombLoader.CustomTracks; 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.9.0")] [assembly: AssemblyInformationalVersion("1.0.9")] [assembly: AssemblyProduct("TootTallyMultiplayer")] [assembly: AssemblyTitle("TootTallyMultiplayer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.9.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 TMP_Text textModifiers; public GameObject teamChanger; public Image image; public Image containerImage; public Transform container; private Button _teamChangerButton; private Text _teamChangerText; private Color _defaultColor; private Color _defaultContainerColor; private MultiplayerController _controller; public static readonly int TEAM_COUNT = Enum.GetNames(typeof(MultSerializableClasses.MultiplayerTeamState)).Length; public void Init(MultiplayerController controller) { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0144: 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) _controller = controller; container = ((Component)this).transform.GetChild(1); textName = ((Component)container.Find("Name")).GetComponent<TMP_Text>(); textState = ((Component)container.Find("State")).GetComponent<TMP_Text>(); textRank = ((Component)container.Find("Rank")).GetComponent<TMP_Text>(); textModifiers = ((Component)((Component)this).transform.GetChild(2).Find("Container/Modifiers")).GetComponent<TMP_Text>(); textModifiers.enableAutoSizing = true; teamChanger = ((Component)((Component)this).transform.GetChild(0)).gameObject; _teamChangerText = teamChanger.gameObject.GetComponentInChildren<Text>(); _teamChangerButton = teamChanger.GetComponent<Button>(); ((UnityEvent)_teamChangerButton.onClick).AddListener((UnityAction)delegate { controller.ChangeTeam(new object[2] { (user.team + 1) % TEAM_COUNT, user.id }); }); image = ((Component)this).gameObject.GetComponent<Image>(); _defaultColor = ((Graphic)image).color; containerImage = ((Component)container).GetComponent<Image>(); _defaultContainerColor = ((Graphic)containerImage).color; } public void UpdateTeamColor(int team) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) user.team = team; switch (team) { case 0: UpdateTeamColor(new Color(1f, 0f, 0f), "R"); break; case 1: UpdateTeamColor(new Color(0f, 0f, 1f), "B"); break; } } private void UpdateTeamColor(Color mainColor, string text) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Button teamChangerButton = _teamChangerButton; ColorBlock colors = default(ColorBlock); ((ColorBlock)(ref colors)).normalColor = mainColor; ((ColorBlock)(ref colors)).highlightedColor = new Color(mainColor.r + 0.3f, mainColor.g + 0.3f, mainColor.b + 0.3f); ((ColorBlock)(ref colors)).pressedColor = mainColor; ((ColorBlock)(ref colors)).disabledColor = mainColor; ((ColorBlock)(ref colors)).colorMultiplier = 1f; ((Selectable)teamChangerButton).colors = colors; _teamChangerText.text = text; } public void UpdateUserCard(MultSerializableClasses.MultiplayerUserInfo user, string state) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) this.user = user; ((Graphic)image).color = _defaultColor; ((Graphic)containerImage).color = _defaultContainerColor; textName.text = user.username; textState.text = state ?? user.state; textRank.text = $"#{user.rank}"; UpdateMods(user.mods); UpdateTeamColor(user.team); } public void UpdateMods(string mods) { user.mods = mods; textModifiers.text = mods; } } 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 GameObject _muteButton; private Sprite _mutedBtnSprite; private Sprite _unmutedBtnSprite; 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 string LobbyCode; public static MultSerializableClasses.MultiplayerSongInfo savedSongInfo; public static SingleTrackData savedTrackData; public PlaytestAnims GetInstance => CurrentInstance; public static PlaytestAnims CurrentInstance { get; private set; } public bool IsFreemod => _currentLobby.freemod; 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00ce: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: 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 val2 = Object.Instantiate<GameObject>(AssetBundleManager.GetPrefab("multiplayercanvas")); _mutedBtnSprite = AssetManager.GetSprite("MuteBtnOff.png"); _unmutedBtnSprite = AssetManager.GetSprite("MuteBtnOn.png"); _muteButton = GameObjectFactory.CreateClickableImageHolder(val2.transform, Vector2.zero, Vector2.one * 64f, GetCurrentMuteSprite(), "MuteButton", (Action)OnToggleMuteButtonClick); RectTransform component = _muteButton.GetComponent<RectTransform>(); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.99f, 0f); component.pivot = val3; component.anchorMax = (component.anchorMin = val3); try { _multMainPanel = new MultiplayerMainPanel(val2, this); } catch (Exception ex) { Plugin.LogError(ex.Message); Plugin.LogError(ex.StackTrace); } try { _multLobbyPanel = new MultiplayerLobbyPanel(val2, this); } catch (Exception ex2) { Plugin.LogError(ex2.Message); Plugin.LogError(ex2.StackTrace); } try { _multCreatePanel = new MultiplayerCreatePanel(val2, 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 OnToggleMuteButtonClick() { Plugin.Instance.MuteMusic.Value = !Plugin.Instance.MuteMusic.Value; if (Plugin.Instance.MuteMusic.Value) { MultiAudioController.PauseMusicHard(); } else { MultiAudioController.PlayMusicHard(); } _muteButton.GetComponent<Image>().sprite = GetCurrentMuteSprite(); } public Sprite GetCurrentMuteSprite() { if (!Plugin.Instance.MuteMusic.Value) { return _unmutedBtnSprite; } return _mutedBtnSprite; } public void OnGameControllerStartSetup() { _multiLiveScoreController = GameObject.Find("GameplayCanvas/UIHolder").AddComponent<MultiplayerLiveScoreController>(); MultiAudioController.PauseMusicSoft(); 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 ShowMute() { GameObject muteButton = _muteButton; if (muteButton != null) { muteButton.SetActive(true); } } public void HideMute() { GameObject muteButton = _muteButton; if (muteButton != null) { muteButton.SetActive(false); } } 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.UpdateLobbyInfo(_currentLobby.players, lobbyInfo); 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_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: 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_01b5: 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; if (songInfo.modifiers != "FM") { 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); if (val != null) { TromboneTrack value = val.Value; CustomTrack val2 = (CustomTrack)(object)((value is CustomTrack) ? value : null); if (val2 != null && File.Exists(Path.Combine(val2.folderPath, "song.ogg"))) { PlayClipPlaybackFromTrack(val2); goto IL_003f; } } PlayDefaultSong(); goto IL_003f; IL_003f: 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 PlayClipPlaybackFromTrack(CustomTrack ct) { MultiAudioController.PauseMusicSoft(0.3f, delegate { MultiAudioController.LoadClip(Path.Combine(ct.folderPath, "song.ogg"), delegate { MultiAudioController.PlayMusicSoft(); }); }); } public void PlayDefaultSong() { MultiAudioController.PauseMusicSoft(0.3f, delegate { MultiAudioController.SetSongToDefault(); MultiAudioController.PlayMusicSoft(); }); } 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) { TootTallyGlobalVariables.isPracticing = false; 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 ChangeTeam(dynamic[] values) { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.ChangeTeam, values); } public void SetModifiers(string values) { _multiConnection.SendOptionInfo(MultiplayerSystem.OptionInfoType.SetModifiers, new object[1] { values }); } public void OnQuickChatReceived(int userID, MultiplayerSystem.QuickChat chat) { _multLobbyPanel?.OnQuickChatReceived(userID, chat); } public void SendSetLobbySettings(MultiplayerSystem.SocketSetLobbyInfo lobbyInfo) { _multiConnection.SendSetLobbyInfo(lobbyInfo); } 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() { HideMute(); 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.ChangeTeam: _multLobbyPanel.UpdateTeam((int)optionInfo.values[1], (int)optionInfo.values[0]); break; case MultiplayerSystem.OptionInfoType.SetModifiers: _multLobbyPanel.UpdateMods((int)optionInfo.values[0], optionInfo.values[1]); 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) { modifiers = (_currentLobby.freemod ? "FM" : 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 Toggle _togglePrefab; 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_002a: 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_009c: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) _userCardPrefab = Object.Instantiate<GameObject>(GameModifierFactory.GetBorderedHorizontalBox(new Vector2(800f, 72f), 3, (Transform)null)); CustomButton val = GameObjectFactory.CreateCustomButton(_userCardPrefab.transform, Vector2.zero, new Vector2(25f, 65f), "R", "TeamChanger", (Action)null); 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 val2 = GameObjectFactory.CreateSingleText(gameObject.transform, "Name", "", Vector2.one / 2f, new Vector2(240f, 75f), Theme.colors.leaderboard.text, (TextFont)0); val2.alignment = (TextAlignmentOptions)513; TMP_Text val3 = GameObjectFactory.CreateSingleText(gameObject.transform, "State", "", Vector2.one / 2f, new Vector2(240f, 75f), Theme.colors.leaderboard.text, (TextFont)0); val3.alignment = (TextAlignmentOptions)516; TMP_Text val4 = GameObjectFactory.CreateSingleText(gameObject.transform, "Rank", "", Vector2.one / 2f, new Vector2(100f, 75f), Theme.colors.leaderboard.text, (TextFont)0); val4.alignment = (TextAlignmentOptions)516; GameObject borderedHorizontalBox = GameModifierFactory.GetBorderedHorizontalBox(new Vector2(70f, 72f), 0, _userCardPrefab.transform); GameObject gameObject2 = ((Component)borderedHorizontalBox.transform.GetChild(0)).gameObject; TMP_Text val5 = GameObjectFactory.CreateSingleText(gameObject2.transform, "Modifiers", "", Vector2.one / 2f, new Vector2(70f, 75f), Theme.colors.leaderboard.text, (TextFont)0); val5.alignment = (TextAlignmentOptions)514; ((Component)val).transform.SetAsFirstSibling(); 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 = GameModifierFactory.GetBorderedHorizontalBox(new Vector2(160f, 28f), 2, (Transform)null); 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 = GameModifierFactory.GetBorderedHorizontalBox(new Vector2(200f, 28f), 2, (Transform)null); 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 void SetTogglePrefab(HomeController __instance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown _togglePrefab = Object.Instantiate<Toggle>(__instance.set_tog_accessb_jumpscare); ((Object)_togglePrefab).name = "MultiplayerTogglePrefab"; _togglePrefab.onValueChanged = new ToggleEvent(); Object.DontDestroyOnLoad((Object)(object)_togglePrefab); } 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, MultiplayerController controller) { MultiplayerCard multiplayerCard = Object.Instantiate<GameObject>(_userCardPrefab, canvasTransform).AddComponent<MultiplayerCard>(); multiplayerCard.Init(controller); 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 = GameModifierFactory.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 = GameModifierFactory.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 = GameModifierFactory.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, MultiplayerController controller) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) LobbySettingsInputPrompt lobbySettingsInputPrompt = new LobbySettingsInputPrompt(canvasTransform, controller); lobbySettingsInputPrompt.gameObject.transform.localScale = new Vector3(0f, 0f, 1f); return lobbySettingsInputPrompt; } public static CustomPopup CreateQuickChatPopup(Transform buttonTransform, Transform popupTransform, Action<MultiplayerSystem.QuickChat> OnBtnClickCallback) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_019d: 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_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) CustomPopup val = new CustomPopup("Quick Chat", buttonTransform, Vector2.zero, new Vector2(64f, 64f), AssetManager.GetSprite("Bubble.png"), popupTransform, new Vector2(450f, 700f), 38, new Vector2(32f, 32f)); GameObject gameObject = ((Component)val.popupBox.transform.GetChild(0)).gameObject; Color normalColor = default(Color); ((Color)(ref normalColor))..ctor(0f, 0f, 0f, 0f); for (int i = 0; i < 3; i++) { GameObject horizontalBox = GameModifierFactory.GetHorizontalBox(new Vector2(0f, 205f), gameObject.transform); ((HorizontalOrVerticalLayoutGroup)horizontalBox.GetComponent<HorizontalLayoutGroup>()).spacing = 20f; for (int j = 0; j < 2; j++) { GameObject verticalBox = GameModifierFactory.GetVerticalBox(new Vector2(190f, 0f), horizontalBox.transform); VerticalLayoutGroup component = verticalBox.GetComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component).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 val2 = GameObjectFactory.CreateCustomButton(verticalBox.transform, Vector2.zero, new Vector2(0f, 36f), text, $"QCButton{quickChatOption}", (Action)delegate { OnBtnClickCallback(quickChatOption); }); ColorBlock colors = ((Selectable)val2.button).colors; ((ColorBlock)(ref colors)).normalColor = normalColor; ((Selectable)val2.button).colors = colors; } } } return val; } public static Toggle CreateToggle(Transform canvasTransform, string name, Vector2 size, string text) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_004c: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00cc: Unknown result type (might be due to invalid IL or missing references) Toggle val = Object.Instantiate<Toggle>(_togglePrefab, canvasTransform); RectTransform component = ((Component)val).GetComponent<RectTransform>(); component.pivot = Vector2.op_Implicit(Vector3.zero); component.anchoredPosition = Vector2.op_Implicit(Vector3.zero); component.sizeDelta = size; TMP_Text val2 = GameObjectFactory.CreateSingleText(((Component)val).transform, name + "Label", text, Vector2.zero, new Vector2(250f, 0f), Theme.colors.leaderboard.text, (TextFont)1); val2.alignment = (TextAlignmentOptions)513; val2.fontStyle = (FontStyles)4; val2.enableWordWrapping = false; val2.rectTransform.anchoredPosition = new Vector2(20f, 0f); RectTransform rectTransform = val2.rectTransform; RectTransform rectTransform2 = val2.rectTransform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(1f, 0.5f); rectTransform2.anchorMin = val3; rectTransform.anchorMax = val3; val2.fontSize = 28f; val2.text = text; ((Object)val).name = name; val.isOn = false; 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.IsDefaultMusicLoaded) { 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_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: 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_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c5: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Unknown result type (might be due to invalid IL or missing references) //IL_05d3: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: 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; MultiplayerGameObjectFactory.SetTogglePrefab(__instance); 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("Button3FreeImprov")).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_00a4: Unknown result type (might be due to invalid IL or missing references) _multiController.ShowPanel(); _multiController.ShowMute(); 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(LoadController), "Start")] [HarmonyPostfix] public static void StopMusicForWhateverFuckingReasons() { if (IsConnectedToMultiplayer) { MultiAudioController.StopMusicHard(); } } [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 PreventToggles(ModifierType modifierType) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 if (!IsPlayingMultiplayer && !IsConnectedToMultiplayer && !_isSceneActive) { return true; } if ((int)modifierType == 0 && _multiController.IsFreemod) { TootTallyNotifManager.DisplayNotif("Cannot enable Hidden with freemod.", 6f); return false; } if ((int)modifierType == 1 && _multiController.IsFreemod) { TootTallyNotifManager.DisplayNotif("Cannot enable Flashlight with freemod.", 6f); return false; } 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.9")] [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 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> MuteMusic { 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."); MuteMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "MuteMusic", false, "Mute the multiplayer menu music and song preview"); 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."); AssetManager.LoadAssets(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), "Assets")); _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, ChangeTeam, SetModifiers, 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 bool autorotate; public bool teams; public bool freemod; public string dataType => DataType.SetLobbyInfo.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, JsonSe