Skip to content
This repository has been archived by the owner on Nov 19, 2021. It is now read-only.

Commit

Permalink
New Mod: PrivateInstanceIcon!
Browse files Browse the repository at this point in the history
  • Loading branch information
loukylor committed Aug 13, 2021
1 parent 87874e6 commit 15fd970
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 1 deletion.
36 changes: 36 additions & 0 deletions PrivateInstanceIcon/PrivateInstanceIcon.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<AssemblyName>PrivateInstanceIcon</AssemblyName>
<RootNamespace>PrivateInstanceIcon</RootNamespace>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath></OutputPath>
</PropertyGroup>

<ItemGroup>
<None Remove="icon.png" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="icon.png" />
</ItemGroup>

<ItemGroup>
<Reference Include="UnityEngine.ImageConversionModule">
<HintPath>$(VRChatPath)MelonLoader\Managed\UnityEngine.ImageConversionModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>$(VRChatPath)MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
</Reference>
<Reference Include="VRCCore-Standalone">
<HintPath>$(VRChatPath)MelonLoader\Managed\VRCCore-Standalone.dll</HintPath>
</Reference>
</ItemGroup>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="move &quot;bin\Release\net472\PrivateInstanceIcon.dll&quot; &quot;$(VRChatPath)Mods&quot;" />
</Target>

</Project>
114 changes: 114 additions & 0 deletions PrivateInstanceIcon/PrivateInstanceIconMod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Reflection;
using MelonLoader;
using UnityEngine;
using UnityEngine.UI;
using VRC.Core;

[assembly: MelonInfo(typeof(PrivateInstanceIcon.PrivateInstanceIconMod), "PrivateInstanceIcon", "1.0.0", "loukylor", "https://github.com/loukylor/VRC-Mods")]
[assembly: MelonGame("VRChat", "VRChat")]

namespace PrivateInstanceIcon
{
public class PrivateInstanceIconMod : MelonMod
{
private static PropertyInfo listEnum;
private static PropertyInfo pickerPrefabProp;
private static Sprite iconSprite;

public static MelonPreferences_Entry<bool> excludeJoinMe;
public static MelonPreferences_Entry<bool> hidePrivateInstances;
public override void OnApplicationStart()
{
listEnum = typeof(UiUserList).GetProperties().First(pi => pi.Name.StartsWith("field_Public_Enum"));
pickerPrefabProp = typeof(UiUserList).GetProperties().First(pi => pi.PropertyType == typeof(GameObject));

Texture2D iconTex = new Texture2D(2, 2);
using (Stream iconStream = Assembly.GetManifestResourceStream("PrivateInstanceIcon.icon.png"))
{
var buffer = new byte[iconStream.Length];
iconStream.Read(buffer, 0, buffer.Length);
ImageConversion.LoadImage(iconTex, buffer);
}

Rect rect = new Rect(0, 0, iconTex.width, iconTex.height);
Vector2 pivot = new Vector2(0.5f, 0.5f);
Vector4 border = Vector4.zero;
iconSprite = Sprite.CreateSprite_Injected(iconTex, ref rect, ref pivot, 50, 0, SpriteMeshType.Tight, ref border, false);
iconSprite.hideFlags = HideFlags.DontUnloadUnusedAsset;

foreach (MethodInfo method in typeof(UiUserList).GetMethods().Where(mi => mi.Name.StartsWith("Method_Protected_Virtual_Void_VRCUiContentButton_Object_")))
HarmonyInstance.Patch(method, null, typeof(PrivateInstanceIconMod).GetMethod(nameof(OnSetPickerContentFromApiModel), BindingFlags.NonPublic | BindingFlags.Static).ToNewHarmonyMethod());
HarmonyInstance.Patch(typeof(UiUserList).GetMethod("Awake"), postfix: typeof(PrivateInstanceIconMod).GetMethod(nameof(OnUiUserListAwake), BindingFlags.NonPublic | BindingFlags.Static).ToNewHarmonyMethod(), finalizer: typeof(PrivateInstanceIconMod).GetMethod(nameof(OnSetPickerContentFromApiModelErrored), BindingFlags.NonPublic | BindingFlags.Static).ToNewHarmonyMethod());

MelonPreferences_Category category = MelonPreferences.CreateCategory("PrivateInstanceIcon Config");
excludeJoinMe = category.CreateEntry(nameof(excludeJoinMe), true, "Whether to hide the icon when people are on join me, and in private instances.");
hidePrivateInstances = category.CreateEntry(nameof(hidePrivateInstances), false, "Whether to just not show people who are in private instances.");
}

private static void OnUiUserListAwake(UiUserList __instance)
{
if ((int)listEnum.GetValue(__instance) != 3)
return;

GameObject pickerPrefab = (GameObject)pickerPrefabProp.GetValue(__instance);
VRCUiContentButton picker = pickerPrefab.GetComponent<VRCUiContentButton>();

GameObject[] newArr = new GameObject[picker.field_Public_VRCUiDynamicOverlayIcons_0.field_Public_ArrayOf_GameObject_0.Length + 1];
picker.field_Public_VRCUiDynamicOverlayIcons_0.field_Public_ArrayOf_GameObject_0.CopyTo(newArr, 0);

GameObject icon = GameObject.Instantiate(picker.transform.Find("Icons/OverlayIcons/iconUserOnPC").gameObject);
icon.name = "PrivateInstanceIcon";
icon.transform.SetParent(picker.transform.Find("Icons/OverlayIcons"));
icon.GetComponent<Image>().sprite = iconSprite;
icon.SetActive(false);

newArr[newArr.Length - 1] = icon;

picker.field_Public_VRCUiDynamicOverlayIcons_0.field_Public_ArrayOf_GameObject_0 = newArr;
}

private static void OnSetPickerContentFromApiModel(UiUserList __instance, VRCUiContentButton __0, Il2CppSystem.Object __1)
{
if ((int)listEnum.GetValue(__instance) != 3)
return;

APIUser user = __1.TryCast<APIUser>();
if (user == null)
return;

GameObject icon = __0.field_Public_VRCUiDynamicOverlayIcons_0.field_Public_ArrayOf_GameObject_0.First(gameObject => gameObject.name == "PrivateInstanceIcon");
if (user.location == "private" && !(excludeJoinMe.Value && __0.field_Public_UiStatusIcon_0.field_Public_UserStatus_0 == APIUser.UserStatus.JoinMe))
{
if (hidePrivateInstances.Value)
MelonCoroutines.Start(SetInactiveCoroutine(__0.gameObject));
else
icon.SetActive(true);
}
else
{
icon.SetActive(false);
}
}

private static IEnumerator SetInactiveCoroutine(GameObject go)
{
// This was necessary. fuck you unity
go.SetActive(false);
yield return null;
go.SetActive(false);
}

private static Exception OnSetPickerContentFromApiModelErrored(Exception __exception)
{
// There's actually no better way to do this https://github.com/knah/Il2CppAssemblyUnhollower/blob/master/UnhollowerBaseLib/Il2CppException.cs
if (__exception is NullReferenceException || __exception.Message.Contains("System.NullReferenceException"))
return null;
else
return __exception;
}
}
}
Binary file added PrivateInstanceIcon/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ More detailed instructions and more mods can be found in the [VRChat Modding Gro
- [InstanceHistory](#instancehistory)
- [PlayerList](#playerlist)
- [PreviewScroller](#previewscroller)
- [PrivateInstanceIcon](#privateinstanceicon)
- [ReloadAvatars](#reloadavatars)
- [RememberMe](#rememberme)
- [SelectYourself](#selectyourself)
Expand Down Expand Up @@ -172,6 +173,16 @@ A mod that let's you sort of scroll the avatar preview so you can control where
## Requirements
- [VRChatUtilityKit](https://github.com/loukylor/VRC-Mods/releases)

# PrivateInstanceIcon
Adds an icon to the social menu that shows if you can join a person or not.

## Features
Let's you configure whether you want the icon on people that are on join me, but in privates.<br>
You can also just straight up hide users from the list that you cant join. Note that when the list refreshes, the hidden users might pop up for a frame.

## Picture of the Icon
![Picture of me with the icon on it](https://i.imgur.com/bLgOC5R.png)

# ReloadAvatars
Adds buttons to reload a single user's avatar or all users' avatar.

Expand Down
16 changes: 15 additions & 1 deletion VRC-Mods.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SelectYourself", "SelectYou
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChairExitController", "ChairExitController\ChairExitController.csproj", "{C44CEA6D-AAAC-4C6F-B231-C9E6040583E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserHistory", "UserHistory\UserHistory.csproj", "{805A672C-8C37-4240-9F03-0F5371708E04}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserHistory", "UserHistory\UserHistory.csproj", "{805A672C-8C37-4240-9F03-0F5371708E04}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrivateInstanceIcon", "PrivateInstanceIcon\PrivateInstanceIcon.csproj", "{D7A475B6-D116-4800-A433-02329F460640}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -245,6 +247,18 @@ Global
{805A672C-8C37-4240-9F03-0F5371708E04}.Release|x64.Build.0 = Release|Any CPU
{805A672C-8C37-4240-9F03-0F5371708E04}.Release|x86.ActiveCfg = Release|Any CPU
{805A672C-8C37-4240-9F03-0F5371708E04}.Release|x86.Build.0 = Release|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Debug|x64.ActiveCfg = Debug|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Debug|x64.Build.0 = Debug|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Debug|x86.ActiveCfg = Debug|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Debug|x86.Build.0 = Debug|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Release|Any CPU.Build.0 = Release|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Release|x64.ActiveCfg = Release|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Release|x64.Build.0 = Release|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Release|x86.ActiveCfg = Release|Any CPU
{D7A475B6-D116-4800-A433-02329F460640}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down

0 comments on commit 15fd970

Please sign in to comment.