This repository has been archived by the owner on Nov 19, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
176 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 "bin\Release\net472\PrivateInstanceIcon.dll" "$(VRChatPath)Mods"" /> | ||
</Target> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters