private void AddAvatar(string id) { bool changed = true; if (!favoriteAvatarList.Contains(id)) { favoriteAvatarList.Add(id); changed = true; } if (!savedFavoriteAvatars.ContainsKey(id)) { savedFavoriteAvatars[id] = new SerializableApiAvatar() { id = id }; changed = true; } if (changed) { Save(); } if (useNetwork && !waitingForServer) { new Thread(() => { VRCModNetworkManager.SendRPC("slaynash.avatarfav.addavatar", id, null, (error) => { addError = "Unable to favorite avatar: " + error; favButton.GetComponent <Button>().interactable = true; }); }).Start(); } }
private void SearchForAvatars(string text) { VRCUiPopupManagerUtils.ShowPopup("AvatarFav", "Looking for avatars"); VRCModNetworkManager.SendRPC("slaynash.avatarfav.search", text.Trim(), () => { }, (error) => { VRCUiPopupManagerUtils.ShowPopup("AvatarFav", "Unable to fetch avatars:\nVRVCModNetwork returned error:\n" + error, "Close", () => VRCUiPopupManagerUtils.GetVRCUiPopupManager().HideCurrentPopup()); }); }
private void RemoveAvatar(string id) { var changed = false; if (savedFavoriteAvatars.ContainsKey(id)) { savedFavoriteAvatars.Remove(id); changed = true; } if (favoriteAvatarList.Contains(id)) { favoriteAvatarList.Remove(id); changed = true; } if (changed) { Save(); } if (useNetwork && !waitingForServer) { new Thread(() => { VRCModNetworkManager.SendRPC("slaynash.avatarfav.removeavatar", id, null, (error) => { addError = "Unable to unfavorite avatar: " + error; favButton.GetComponent <Button>().interactable = true; }); }).Start(); } }
private void OnUpdate() { if (!Initialised) { return; } VRCModNetworkManager.Update(); VRCModNetworkStatus.Update(); ModdedUsersManager.Update(); }
private IEnumerator VRCToolsSetup() { VRCModLogger.Log("[VRCTools] Initialising VRCTools"); yield return(VRCUiManagerUtils.WaitForUiManagerInit()); VRCModLogger.Log("[VRCTools] Overwriting login button event"); VRCUiPageAuthentication loginPage = Resources.FindObjectsOfTypeAll <VRCUiPageAuthentication>().FirstOrDefault((page) => page.gameObject.name == "LoginUserPass"); if (loginPage != null) { Button loginButton = loginPage.transform.Find("ButtonDone (1)")?.GetComponent <Button>(); if (loginButton != null) { ButtonClickedEvent bce = loginButton.onClick; loginButton.onClick = new ButtonClickedEvent(); loginButton.onClick.AddListener(() => { VRCModNetworkManager.SetCredentials(GetTextFromUiInputField(loginPage.loginUserName) + ":" + GetTextFromUiInputField(loginPage.loginPassword)); bce?.Invoke(); }); } else { VRCModLogger.Log("[VRCTools] Unable to find login button in login page"); } } else { VRCModLogger.Log("[VRCTools] Unable to find login page"); } yield return(VRCModLoaderUpdater.CheckVRCModLoaderHash()); try { VRCModNetworkStatus.Setup(); ModConfigPage.Setup(); ModdedUsersManager.Init(); } catch (Exception ex) { VRCModLogger.Log("[VRCTools]" + ex.ToString()); } VRCModLogger.Log("[VRCTools] Init done !"); VRCUiPopupManagerUtils.GetVRCUiPopupManager().HideCurrentPopup(); Initialised = true; if (!usingVRCMenuUtils) { VRCFlowManagerUtils.EnableVRCFlowManager(); } VRCModNetworkManager.ConnectAsync(); }
private void RequestAvatars() { new Thread(() => VRCModNetworkManager.SendRPC("slaynash.avatarfav.getavatars", "", null, (error) => { VRCModLogger.Log("[AvatarFav] Unable to fetch avatars: Server returned " + error); if (error.Equals("SERVER_DISCONNECTED")) { waitingForServer = true; } })).Start(); }
private void RemoveAvatar(string id) { new Thread(() => { VRCModNetworkManager.SendRPC("slaynash.avatarfav.removeavatar", id, null, (error) => { addError = "Unable to unfavorite avatar: " + error; favButton.GetComponent <Button>().interactable = true; }); }).Start(); }
public override void RemoteError(string error) { base.RemoteError(error); if (id != null) { VRCModNetworkManager.SheduleForMainThread(() => { SecurePlayerPrefs.DeleteKey("vrcmnw_token_" + id); }); } }
public override void Handle(string parts) { Destroy(); if (!parts.Equals("OK")) { string[] rpcparts = parts.Split(new char[] { ' ' }, 3); VRCModNetworkManager.HandleRpc(rpcparts[0], rpcparts[1], rpcparts[2]); WriteLine("OK"); } else { onSuccess?.Invoke(); } }
public override void Handle(string parts) { Destroy(); if (parts.StartsWith("OK")) { VRCModNetworkManager.SheduleForMainThread(() => { onSuccess?.Invoke(); }); } else { onError(parts); } }
public override void Handle(string parts) { if (parts.StartsWith("OK")) { VRCModNetworkManager.SheduleForMainThread(() => { VRCModNetworkManager.IsAuthenticated = true; if (!parts.Equals("OK")) { string token = parts.Substring(3); SecurePlayerPrefs.SetString("vrcmnw_token_" + id, token, "vl9u1grTnvXA"); } }); } Destroy(); }
private void OnUpdate() { if (!Initialized) { return; } VRCModNetworkManager.Update(); VRCModNetworkStatus.Update(); ModdedUsersManager.Update(); /* * if(Input.GetKeyDown(KeyCode.F2)) * { * VRCModLogger.Log(SteamUtils.GetSteamTicket()); * } */ }
public override void RemoteError(string error) { base.RemoteError(error); if (id != null) { VRCModNetworkManager.SheduleForMainThread(() => { if (SecurePlayerPrefs.HasKey("vrcmnw_token_" + id)) { SecurePlayerPrefs.DeleteKey("vrcmnw_token_" + id); VRCModNetworkManager.userUuid = ""; } }); } VRCModNetworkManager.authError = error; }
internal static void Init() { if (Environment.CommandLine.Contains("--vrctools.enablenameplateicons")) { enableNameplateIcons = true; } VRCModNetworkManager.SetRPCListener("slaynash.vrctools.moddedplayerlistonjoin", OnModdedplayerlistonjoinReceived); VRCModNetworkManager.SetRPCListener("slaynash.vrctools.moddedplayerjoined", OnModdedplayerjoinReceived); VRCModNetworkManager.SetRPCListener("slaynash.vrctools.moddedplayerleft", OnModdedplayerleftReceived); userProperty = typeof(Player).GetProperties(BindingFlags.Public | BindingFlags.Instance).First((pi) => pi.PropertyType == typeof(APIUser)); Texture2D tex = new Texture2D(2, 2); Texture2DUtils.LoadImage(tex, Convert.FromBase64String(ImageDatas.VRCTOOLS_LOGO)); vrctoolsSprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f)); }
private static IEnumerator AddAvatar(string id, string name) { bool done = false; VRCModNetworkManager.SendRPC("slaynash.avatarfav.addavatar", id, () => { VRCModLogger.Log("[VRCheatAvatarfileImporter] Avatar " + name + " successfully added"); importedAvatars++; done = true; }, (error) => { VRCModLogger.Log("[VRCheatAvatarfileImporter] Unable to add the avatar " + name + ": VRCMNW Server returned error: " + error); done = true; }); while (!done) { yield return(null); } }
public override void Handle(string parts) { Destroy(); if (parts.StartsWith("OK")) { VRCModNetworkManager.SheduleForMainThread(() => { int returnValue = int.Parse(parts.Split(new[] { ' ' }, 2)[1]); VRCModNetworkManager.IsAuthenticated = true; VRCModNetworkManager.VRCAuthStatus = returnValue; onSuccess?.Invoke(); }); } else { onError(parts); } }
private static IEnumerator CheckForPermissions() { if (!ModPrefs.GetBool("vrctools", "remoteauthcheckasked")) { VRCModLogger.Log("[VRCTools] Asking for auth"); yield return(ShowAuthAgreePopup()); ModPrefs.SetBool("vrctools", "remoteauthcheckasked", true); } if (ModPrefs.GetBool("vrctools", "remoteauthcheck")) { VRCModNetworkManager.ConnectAsync(); VRCModLogger.Log("[VRCTools] Key remoteauthcheck found (true)"); yield return(AvatarFavUpdater.CheckForAvatarFavUpdate()); } else { VRCModLogger.Log("[VRCTools] Key remoteauthcheck found (false)"); } }
public void OnUpdate() { if (!initialised) { return; } lock (actions) { foreach (Action a in actions) { try { a(); } catch (Exception e) { VRCModLogger.Log("[AvatarFav] Error while calling action from main thread: " + e); } } actions.Clear(); } try { //Update list if element is active if (favList.gameObject.activeInHierarchy) { lock (favoriteAvatarList) { if (avatarAvailables) { avatarAvailables = false; favList.ClearSpecificList(); if (newAvatarsFirst) { List <string> favReversed = favoriteAvatarList.ToList(); favReversed.Reverse(); favList.specificListIds = favReversed.ToArray(); } else { favList.specificListIds = favoriteAvatarList.ToArray(); } favList.Refresh(); freshUpdate = true; } } } if (pageAvatar.avatar != null && pageAvatar.avatar.apiAvatar != null && CurrentUserUtils.GetGetCurrentUser().GetValue(null) != null && !currentUiAvatarId.Equals(pageAvatar.avatar.apiAvatar.id) || freshUpdate) { currentUiAvatarId = pageAvatar.avatar.apiAvatar.id; bool favorited = favoriteAvatarList.Contains(currentUiAvatarId); if (favorited) { favButtonText.text = "Unfavorite"; } else { favButtonText.text = "Favorite"; } if ((!pageAvatar.avatar.apiAvatar.releaseStatus.Equals("public") && !favorited) || pageAvatar.avatar.apiAvatar.authorId == APIUser.CurrentUser.id) { favButton.gameObject.SetActive(false); avatarModel.localPosition = baseAvatarModelPosition; } else { favButton.gameObject.SetActive(true); avatarModel.localPosition = baseAvatarModelPosition + new Vector3(0, 60, 0); } } //Show returned error if exists if (addError != null) { VRCUiPopupManagerUtils.ShowPopup("Error", addError, "Close", () => VRCUiPopupManagerUtils.GetVRCUiPopupManager().HideCurrentPopup()); addError = null; } if (RoomManager.currentRoom != null && RoomManager.currentRoom.id != null && RoomManager.currentRoom.currentInstanceIdOnly != null) { if (currentRoom == null) { currentRoom = RoomManager.currentRoom; if (currentRoom.releaseStatus != "public") { VRCModLogger.Log("[AvatarFav] Current world release status isn't public. Pedestal scan disabled."); } else { VRC_AvatarPedestal[] pedestalsInWorld = GameObject.FindObjectsOfType <VRC_AvatarPedestal>(); VRCModLogger.Log("[AvatarFav] Found " + pedestalsInWorld.Length + " VRC_AvatarPedestal in current world"); string dataToSend = currentRoom.id; foreach (VRC_AvatarPedestal p in pedestalsInWorld) { if (p.blueprintId == null || p.blueprintId == "") { continue; } dataToSend += ";" + p.blueprintId; } VRCModNetworkManager.SendRPC("slaynash.avatarfav.avatarsinworld", dataToSend); } } } else { currentRoom = null; } } catch (Exception e) { VRCModLogger.Log("[AvatarFav] [ERROR] " + e.ToString()); } freshUpdate = false; }
private IEnumerator VRCToolsSetup() { VRCModLogger.Log("[VRCTools] Initialising VRCTools"); VRCModLogger.Log("[VRCTools] Current scene: " + SceneManager.GetActiveScene().name + "(index: " + SceneManager.GetActiveScene().buildIndex + ", path: " + SceneManager.GetActiveScene().path + ")"); VRCModLogger.Log("[VRCTools] ModComponent Sibling index: " + ModComponent.Instance.transform.GetSiblingIndex()); VRCModLogger.Log("[VRCTools] Root gameobjects:"); foreach (GameObject g in SceneManager.GetActiveScene().GetRootGameObjects()) { VRCModLogger.Log(" - " + g); } VRCModLogger.Log("[VRCTools] Call trace - THIS IS NOT AN ERROR:"); VRCModLogger.Log(new System.Diagnostics.StackTrace().ToString()); initializing = true; yield return(VRCUiManagerUtils.WaitForUiManagerInit()); if (!HarmonyLoaded()) { bool waitforpopup = true; VRCUiPopupManagerUtils.ShowPopup("VRCTools", "Missing library: Harmony. Please install it using the VRChat Mod Manager (see #how-to on discord.gg/rCqKSvR)", "Close game", () => Application.Quit(), "Ignore", () => waitforpopup = false); while (waitforpopup) { yield return(null); } Initialized = true; if (!usingVRCMenuUtils) { VRCFlowManagerUtils.EnableVRCFlowManager(); } yield break; } VRCModLogger.Log("[VRCTools] Overwriting login button event"); VRCUiPageAuthentication loginPage = Resources.FindObjectsOfTypeAll <VRCUiPageAuthentication>().FirstOrDefault((page) => page.gameObject.name == "LoginUserPass"); if (loginPage != null) { Button loginButton = loginPage.transform.Find("ButtonDone (1)")?.GetComponent <Button>(); if (loginButton != null) { ButtonClickedEvent bce = loginButton.onClick; loginButton.onClick = new ButtonClickedEvent(); loginButton.onClick.AddListener(() => { VRCModNetworkManager.SetCredentials(Uri.EscapeDataString(GetTextFromUiInputField(loginPage.loginUserName)) + ":" + Uri.EscapeDataString(GetTextFromUiInputField(loginPage.loginPassword))); bce?.Invoke(); }); } else { VRCModLogger.Log("[VRCTools] Unable to find login button in login page"); } } else { VRCModLogger.Log("[VRCTools] Unable to find login page"); } yield return(VRCModLoaderUpdater.CheckVRCModLoaderHash()); yield return(VRCToolsAutoUpdater.CheckAndUpdate()); try { VRCModNetworkStatus.Setup(); VRCModNetworkLogin.SetupVRCModNetworkLoginPage(); ModConfigPage.Setup(); ModdedUsersManager.Init(); } catch (Exception ex) { VRCModLogger.Log("[VRCTools]" + ex.ToString()); } VRCModLogger.Log("[VRCTools] Injecting VRCModNetwork login page"); VRCModNetworkLogin.InjectVRCModNetworkLoginPage(); yield return(VRCModNetworkManager.ConnectInit()); VRCUiPopupManagerUtils.GetVRCUiPopupManager().HideCurrentPopup(); Initialized = true; initializing = false; if (!usingVRCMenuUtils) { VRCFlowManagerUtils.EnableVRCFlowManager(); } }
private IEnumerator VRCToolsSetup() { initialising = true; VRCModLogger.Log("[VRCTools] Initialising VRCTools"); try { OculusUtils.ApplyPatches(); } catch (Exception e) { VRCModLogger.Log("[VRCTools] Error while applying Oculus patches: " + e); } yield return(VRCUiManagerUtils.WaitForUiManagerInit()); VRCModLogger.Log("[VRCTools] Overwriting login button event"); VRCUiPageAuthentication[] authpages = Resources.FindObjectsOfTypeAll <VRCUiPageAuthentication>(); VRCUiPageAuthentication loginPage = authpages.First((page) => page.gameObject.name == "LoginUserPass"); if (loginPage != null) { Button loginButton = loginPage.transform.Find("ButtonDone (1)")?.GetComponent <Button>(); if (loginButton != null) { ButtonClickedEvent bce = loginButton.onClick; loginButton.onClick = new ButtonClickedEvent(); loginButton.onClick.AddListener(() => { VRCModNetworkManager.SetCredentials(GetTextFromUiInputField(loginPage.loginUserName) + ":" + GetTextFromUiInputField(loginPage.loginPassword)); bce?.Invoke(); }); } else { VRCModLogger.Log("[VRCTools] Unable to find login button in login page"); } } else { VRCModLogger.Log("[VRCTools] Unable to find login page"); } yield return(DependenciesDownloader.CheckDownloadFiles()); yield return(VRCModLoaderUpdater.CheckVRCModLoaderHash()); if (ModPrefs.GetBool("vrctools", "enablediscordrichpresence")) { DiscordManager.Init(); } yield return(AvatarFavUpdater.CheckForAvatarFavUpdate()); VRCModNetworkStatus.Setup(); ModConfigPage.Setup(); ModdedUsersManager.Init(); /* * if (ApiCredentials.Load()) * { * VRCModLogger.Log("ApiCredentials.GetAuthTokenProviderUserId() => " + ApiCredentials.()); * if (!SecurePlayerPrefs.HasKey("vrcmnw_token_" + ApiCredentials.GetAuthTokenProviderUserId())) * { * ApiCredentials.Clear(); * } * } */ ApiCredentials.Clear(); VRCModLogger.Log("[VRCTools] Init done !"); VRCUiPopupManagerUtils.GetVRCUiPopupManager().HideCurrentPopup(); VRCFlowManagerUtils.EnableVRCFlowManager(); initialising = false; Initialised = true; VRCModNetworkManager.ConnectAsync(); }
private IEnumerator VRCToolsSetup() { VRCModLogger.Log("[VRCTools] Waiting for UI Manager..."); yield return(VRCUiManagerUtils.WaitForUiManagerInit()); VRCModLogger.Log("[VRCTools] UIManager initialised ! Resuming setup"); VRCModLogger.Log("[VRCTools] Overwriting login button event"); VRCUiPageAuthentication[] authpages = Resources.FindObjectsOfTypeAll <VRCUiPageAuthentication>(); VRCUiPageAuthentication loginPage = authpages.First((page) => page.gameObject.name == "LoginUserPass"); if (loginPage != null) { Button loginButton = loginPage.transform.Find("ButtonDone (1)")?.GetComponent <Button>(); if (loginButton != null) { ButtonClickedEvent bce = loginButton.onClick; loginButton.onClick = new ButtonClickedEvent(); loginButton.onClick.AddListener(() => { VRCModNetworkManager.SetCredentials(GetTextFromUiInputField(loginPage.loginUserName) + ":" + GetTextFromUiInputField(loginPage.loginPassword)); bce?.Invoke(); }); } else { VRCModLogger.Log("[VRCTools] Unable to find login button in login page"); } } else { VRCModLogger.Log("[VRCTools] Unable to find login page"); } VRCModLogger.Log("[VRCTools] CheckDownloadFiles"); yield return(DependenciesDownloader.CheckDownloadFiles()); VRCModLogger.Log("[VRCTools] CheckVRCModLoaderHash"); yield return(VRCModLoaderUpdater.CheckVRCModLoaderHash()); if (ModPrefs.GetBool("vrctools", "enablediscordrichpresence")) { VRCModLogger.Log("[VRCTools] DiscordManager Init"); DiscordManager.Init(); } VRCModLogger.Log("[VRCTools] CheckForPermissions"); yield return(CheckForPermissions()); VRCModLogger.Log("[VRCTools] VRCModNetworkStatus Setup"); VRCModNetworkStatus.Setup(); VRCModLogger.Log("[VRCTools] ModConfigPage Setup"); ModConfigPage.Setup(); VRCModLogger.Log("[VRCTools] ModdedUsersManager Init"); ModdedUsersManager.Init(); VRCUiManagerUtils.OnPageShown += (page) => { VRCModLogger.Log("[VRCTools] OnPageShown: " + page.screenType + " " + (string.IsNullOrEmpty(page.displayName) ? "" : page.displayName + " ") + "(" + page.GetType() + ")"); }; VRCModLogger.Log("[VRCTools] Init done !"); VRCFlowManagerUtils.EnableVRCFlowManager(); initialising = false; Initialised = true; //DebugUtils.PrintHierarchy(VRCUiManagerUtils.GetVRCUiManager().transform.root, 0); }
void OnLevelWasLoaded(int level) { VRCModLogger.Log("[AvatarFav] OnLevelWasLoaded (" + level + ")"); if (level == (Application.platform == RuntimePlatform.WindowsPlayer ? 1 : 2) && !alreadyLoaded) { alreadyLoaded = true; if (instance != null) { Debug.LogWarning("[AvatarFav] Trying to load the same plugin two time !"); return; } instance = this; VRCModLogger.Log("[AvatarFav] Adding button to UI - Looking up for Change Button"); // Add a "Favorite" / "Unfavorite" button over the "Choose" button of the AvatarPage Transform changeButton = null; pageAvatar = Resources.FindObjectsOfTypeAll <PageAvatar>().First(p => (changeButton = p.transform.Find("Change Button")) != null); VRCModLogger.Log("[AvatarFav] Adding avatar check on Change button"); baseChooseEvent = changeButton.GetComponent <Button>().onClick; changeButton.GetComponent <Button>().onClick = new Button.ButtonClickedEvent(); changeButton.GetComponent <Button>().onClick.AddListener(() => { VRCModLogger.Log("[AvatarFav] Fetching avatar releaseStatus for " + pageAvatar.avatar.apiAvatar.name + " (" + pageAvatar.avatar.apiAvatar.id + ")"); ModManager.StartCoroutine(CheckAndWearAvatar()); }); VRCModLogger.Log("[AvatarFav] Adding favorite button to UI - Duplicating Button"); favButton = UnityUiUtils.DuplicateButton(changeButton, "Favorite", new Vector2(0, 80)); favButton.name = "ToggleFavorite"; favButton.gameObject.SetActive(false); favButtonText = favButton.Find("Text").GetComponent <Text>(); favButton.GetComponent <Button>().interactable = false; favButton.GetComponent <Button>().onClick.AddListener(ToggleAvatarFavorite); VRCModLogger.Log("[AvatarFav] Storing default AvatarModel position"); avatarModel = pageAvatar.transform.Find("AvatarModel"); baseAvatarModelPosition = avatarModel.localPosition; FileInfo[] files = new DirectoryInfo(Environment.CurrentDirectory).GetFiles("Avatars.txt", SearchOption.AllDirectories); VRCModLogger.Log("[AvatarFavMod] Found " + files.Length + " Avatars.txt"); if (files.Length > 0) { VRCModLogger.Log("[AvatarFav] Adding import button to UI - Duplicating Button"); Transform importButton = UnityUiUtils.DuplicateButton(changeButton, "Import Avatars", new Vector2(0, 0)); importButton.name = "ImportAvatars"; importButton.GetComponent <RectTransform>().anchoredPosition = new Vector2(560, 371); importButton.GetComponent <Button>().onClick.AddListener(() => { VRCUiPopupManagerUtils.ShowPopup("AvatarFav", "Do you want to import the public avatars from your VRCheat avatar list ?", "Yes", () => { ModManager.StartCoroutine(VRCheatAvatarfileImporter.ImportAvatarfile()); }, "No", () => { VRCUiPopupManagerUtils.GetVRCUiPopupManager().HideCurrentPopup(); }); VRCheatAvatarfileImporter.ImportAvatarfile(); }); } favList = AvatarPageHelper.AddNewList("Favorite Avatar List (Unofficial)", 1); // Get Getter of VRCUiContentButton.PressAction applyAvatarField = typeof(VRCUiContentButton).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).First((field) => field.FieldType == typeof(Action)); VRCModLogger.Log("[AvatarFav] Registering VRCModNetwork events"); VRCModNetworkManager.OnAuthenticated += () => { RequestAvatars(); }; VRCModNetworkManager.SetRPCListener("slaynash.avatarfav.serverconnected", (senderId, data) => { if (waitingForServer) { RequestAvatars(); } }); VRCModNetworkManager.SetRPCListener("slaynash.avatarfav.error", (senderId, data) => addError = data); VRCModNetworkManager.SetRPCListener("slaynash.avatarfav.avatarlistupdated", (senderId, data) => { lock (favoriteAvatarList) { // Update Ui favButton.GetComponent <Button>().interactable = true; SerializableApiAvatar[] serializedAvatars = SerializableApiAvatar.ParseJson(data); favoriteAvatarList.Clear(); foreach (SerializableApiAvatar serializedAvatar in serializedAvatars) { favoriteAvatarList.Add(serializedAvatar.id); } avatarAvailables = true; } }); VRCModLogger.Log("[AvatarFav] Adding avatar search list"); if (pageAvatar != null) { VRCUiPageHeader pageheader = VRCUiManagerUtils.GetVRCUiManager().GetComponentInChildren <VRCUiPageHeader>(true); if (pageheader != null) { searchbar = pageheader.searchBar; if (searchbar != null) { VRCModLogger.Log("[AvatarFav] creating avatar search list"); avatarSearchList = AvatarPageHelper.AddNewList("Search Results", 0); avatarSearchList.ClearAll(); avatarSearchList.gameObject.SetActive(false); avatarSearchList.collapsedCount = 50; avatarSearchList.expandedCount = 50; avatarSearchList.collapseRows = 5; avatarSearchList.extendRows = 5; avatarSearchList.contractedHeight = 850f; avatarSearchList.expandedHeight = 850f; avatarSearchList.GetComponent <LayoutElement>().minWidth = 1600f; avatarSearchList.GetComponentInChildren <GridLayoutGroup>(true).constraintCount = 5; avatarSearchList.expandButton.image.enabled = false; VRCModLogger.Log("[AvatarFav] Overwriting search button"); VRCUiManagerUtils.OnPageShown += (page) => { if (page.GetType() == typeof(PageAvatar)) { UiVRCList[] lists = page.GetComponentsInChildren <UiVRCList>(true); foreach (UiVRCList list in lists) { if (list != avatarSearchList && (list.GetType() != typeof(UiAvatarList) || ((int)categoryField.GetValue(list)) != 0)) { list.gameObject.SetActive(true); } else { list.gameObject.SetActive(false); } } VRCModLogger.Log("[AvatarFav] PageAvatar shown. Enabling searchbar next frame"); ModManager.StartCoroutine(EnableSearchbarNextFrame()); } }; VRCModNetworkManager.SetRPCListener("slaynash.avatarfav.searchresults", (senderid, data) => { AddMainAction(() => { if (data.StartsWith("ERROR")) { VRCUiPopupManagerUtils.ShowPopup("AvatarFav", "Unable to fetch avatars: Server returned error: " + data.Substring("ERROR ".Length), "Close", () => VRCUiPopupManagerUtils.GetVRCUiPopupManager().HideCurrentPopup()); } else { avatarSearchList.ClearSpecificList(); if (!avatarSearchList.gameObject.activeSelf) { UiVRCList[] lists = pageAvatar.GetComponentsInChildren <UiVRCList>(true); foreach (UiVRCList list in lists) { if (list != avatarSearchList) { list.gameObject.SetActive(false); } } } SerializableApiAvatar[] serializedAvatars = SerializableApiAvatar.ParseJson(data); string[] avatarsIds = new string[serializedAvatars.Length]; for (int i = 0; i < serializedAvatars.Length; i++) { avatarsIds[i] = serializedAvatars[i].id; } avatarSearchList.specificListIds = avatarsIds; if (avatarSearchList.gameObject.activeSelf) { avatarSearchList.Refresh(); } else { avatarSearchList.gameObject.SetActive(true); } } }); }); } else { VRCModLogger.LogError("[AvatarFav] Unable to find search bar"); } } else { VRCModLogger.LogError("[AvatarFav] Unable to find page header"); } } else { VRCModLogger.LogError("[AvatarFav] Unable to find avatar page"); } VRCModLogger.Log("[AvatarFav] AvatarFav Initialised !"); initialised = true; } }