Skip to content
This repository was archived by the owner on Jul 29, 2022. It is now read-only.

Commit c7aae7e

Browse files
committed
Initial Release of ClassicPlates. Please help me clean up this mess.
Known Issues and Quirks: > Icon only mode displays full nameplate (Awaiting Asset Revision 6) > Currently incompatible with most mods that add things to nameplates (Asset Revision 6) > Settings are somewhat incomplete > Code is a little scuffed at parts *Please don't bully me too hard
1 parent cb6557b commit c7aae7e

14 files changed

Lines changed: 2955 additions & 8 deletions

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
# Autogenerated VS/MD/Consulo solution and project files
2929
ExportedObj/
3030
.consulo/
31-
*.csproj
3231
*.unityproj
3332
*.sln
3433
*.suo

ClassicPlates/AssetManager.cs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
using System.Collections;
2+
using System.Reflection;
3+
using MelonLoader;
4+
using UnhollowerBaseLib;
5+
using UnhollowerRuntimeLib;
6+
using UnityEngine;
7+
8+
namespace ClassicPlates;
9+
10+
internal static class AssetManager
11+
{
12+
internal static GameObject? Nameplate;
13+
private static AssetBundle? _bundle;
14+
public static readonly Dictionary<string, Sprite>? SpriteDict = new Dictionary<string, Sprite>();
15+
public static Il2CppReferenceArray<Sprite>? SpeakingSprites;
16+
public static Il2CppReferenceArray<Sprite>? MutedSprites;
17+
18+
private static GameObject LoadPrefab(string @object)
19+
{
20+
if (_bundle is null)
21+
{
22+
MelonLogger.Error("Failed to load Prefab: " + @object);
23+
throw new FileLoadException();
24+
}
25+
var go = _bundle.LoadAsset_Internal(@object, Il2CppType.Of<GameObject>()).Cast<GameObject>();
26+
go.hideFlags |= HideFlags.DontUnloadUnusedAsset;
27+
go.hideFlags = HideFlags.HideAndDontSave;
28+
MelonDebug.Msg("Loaded Prefab: " + @object);
29+
return go;
30+
}
31+
32+
private static Sprite LoadSprite(string sprite)
33+
{
34+
if (_bundle is null)
35+
{
36+
MelonLogger.Error("Failed to load Sprite: " + sprite);
37+
throw new FileLoadException();
38+
}
39+
var sprite2 = _bundle.LoadAsset_Internal(sprite, Il2CppType.Of<Sprite>()).Cast<Sprite>();
40+
sprite2.hideFlags |= HideFlags.DontUnloadUnusedAsset;
41+
sprite2.hideFlags = HideFlags.HideAndDontSave;
42+
MelonDebug.Msg("Loaded Sprite: " + sprite);
43+
return sprite2;
44+
}
45+
46+
static IEnumerator LoadResources()
47+
{
48+
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ClassicPlates.Resources.classicplates");
49+
if (stream != null)
50+
{
51+
using var memoryStream = new MemoryStream((int) stream.Length);
52+
stream.CopyTo(memoryStream);
53+
_bundle = AssetBundle.LoadFromMemory_Internal(memoryStream.ToArray(), 0);
54+
try
55+
{
56+
Nameplate = LoadPrefab("Nameplate.prefab") ?? throw new Exception("AssetLoadException");
57+
58+
SpriteDict?.Add("bubble0",
59+
LoadSprite("bubble_0.png") ?? throw new Exception("AssetLoadException: bubble_0.png"));
60+
SpriteDict?.Add("bubble1",
61+
LoadSprite("bubble_1.png") ?? throw new Exception("AssetLoadException: bubble_1.png"));
62+
SpriteDict?.Add("bubble2",
63+
LoadSprite("bubble_2.png") ?? throw new Exception("AssetLoadException: bubble_2.png"));
64+
SpriteDict?.Add("bubble3",
65+
LoadSprite("bubble_3.png") ?? throw new Exception("AssetLoadException: bubble_3.png"));
66+
SpriteDict?.Add("bubblemute",
67+
LoadSprite("bubble_mute.png") ?? throw new Exception("AssetLoadException: bubble_mute.png"));
68+
69+
SpriteDict?.Add("ear",
70+
LoadSprite("ear.png") ?? throw new Exception("AssetLoadException: ear.png"));
71+
SpriteDict?.Add("earmute",
72+
LoadSprite("ear_mute.png") ?? throw new Exception("AssetLoadException: ear_mute.png"));
73+
74+
SpriteDict?.Add("defaulticon",
75+
LoadSprite("icon_default.png") ?? throw new Exception("AssetLoadException: icon_default.png"));
76+
SpriteDict?.Add("iconborder",
77+
LoadSprite("IconBorder.png") ?? throw new Exception("AssetLoadException: IconBorder.png"));
78+
SpriteDict?.Add("friend",
79+
LoadSprite("friend_icon.png") ?? throw new Exception("AssetLoadException: friend_icon.png"));
80+
SpriteDict?.Add("quest",
81+
LoadSprite("quest.png") ?? throw new Exception("AssetLoadException: quest.png"));
82+
SpriteDict?.Add("crown",
83+
LoadSprite("crown.png") ?? throw new Exception("AssetLoadException: crown.png"));
84+
85+
SpriteDict?.Add("nameplate",
86+
LoadSprite("NameplateSilent.png") ?? throw new Exception("AssetLoadException: NameplateSilent.png"));
87+
SpriteDict?.Add("nameplatetalk",
88+
LoadSprite("NameplateTalk.png") ?? throw new Exception("AssetLoadException: NameplateTalk.png"));
89+
SpriteDict?.Add("nameplatemask",
90+
LoadSprite("NameplateMask.png") ?? throw new Exception("AssetLoadException: NameplateMask.png"));
91+
92+
SpriteDict?.Add("fallback",
93+
LoadSprite("fallback_icon.png") ?? throw new Exception("AssetLoadException: fallback_icon.png"));
94+
SpriteDict?.Add("fallbackerror",
95+
LoadSprite("perf_fallback_error.png") ?? throw new Exception("AssetLoadException: perf_fallback_error.png"));
96+
SpriteDict?.Add("fallbackmissing",
97+
LoadSprite("perf_fallback_missing.png") ?? throw new Exception("AssetLoadException: perf_fallback_missing.png"));
98+
SpriteDict?.Add("fallbackgreat",
99+
LoadSprite("perf_fallback_great.png") ?? throw new Exception("AssetLoadException: perf_fallback_great.png"));
100+
SpriteDict?.Add("fallbackgood",
101+
LoadSprite("perf_fallback_good.png") ?? throw new Exception("AssetLoadException: perf_fallback_good.png"));
102+
SpriteDict?.Add("fallbackmedium",
103+
LoadSprite("perf_fallback_medium.png") ?? throw new Exception("AssetLoadException: perf_fallback_medium.png"));
104+
SpriteDict?.Add("fallbackpoor",
105+
LoadSprite("perf_fallback_poor.png") ?? throw new Exception("AssetLoadException: perf_fallback_poor.png"));
106+
SpriteDict?.Add("fallbackhorrible",
107+
LoadSprite("perf_fallback_horrible.png") ?? throw new Exception("AssetLoadException: perf_fallback_horrible.png"));
108+
109+
SpriteDict?.Add("great",
110+
LoadSprite("Perf_Great.png") ?? throw new Exception("AssetLoadException: Perf_Great.png"));
111+
SpriteDict?.Add("good",
112+
LoadSprite("Perf_Good.png") ?? throw new Exception("AssetLoadException: Perf_Good.png"));
113+
SpriteDict?.Add("medium",
114+
LoadSprite("Perf_Medium.png") ?? throw new Exception("AssetLoadException: Perf_Medium.png"));
115+
SpriteDict?.Add("poor",
116+
LoadSprite("Perf_Poor.png") ?? throw new Exception("AssetLoadException: Perf_Poor.png"));
117+
SpriteDict?.Add("horrible",
118+
LoadSprite("Perf_Horrible.png") ?? throw new Exception("AssetLoadException: Perf_Horrible.png"));
119+
SpriteDict?.Add("blocked",
120+
LoadSprite("Perf_Blocked.png") ?? throw new Exception("AssetLoadException: Perf_Blocked.png"));
121+
SpriteDict?.Add("imposter",
122+
LoadSprite("perf_impostor.png") ?? throw new Exception("AssetLoadException: perf_impostor.png"));
123+
124+
SpriteDict?.Add("physyes",
125+
LoadSprite("PhysYes.png") ?? throw new Exception("AssetLoadException: PhysYes.png"));
126+
SpriteDict?.Add("physno",
127+
LoadSprite("PhysNo.png") ?? throw new Exception("AssetLoadException: PhysNo.png"));
128+
129+
CreateSpriteArrays();
130+
}
131+
catch (Exception e)
132+
{
133+
MelonLogger.Error($"Nameplate Assets failed to load\n\n{e}");
134+
}
135+
}
136+
else
137+
{
138+
MelonLogger.Error("Stream is null, Nameplates cannot load");
139+
}
140+
141+
yield break;
142+
}
143+
public static void Init() => MelonCoroutines.Start(LoadResources());
144+
145+
146+
private static void CreateSpriteArrays()
147+
{
148+
if (SpriteDict == null) return;
149+
150+
SpeakingSprites = new Il2CppReferenceArray<Sprite>(new[]
151+
{
152+
SpriteDict["bubble0"],
153+
SpriteDict["bubble1"],
154+
SpriteDict["bubble2"],
155+
SpriteDict["bubble3"]
156+
});
157+
158+
MutedSprites = new Il2CppReferenceArray<Sprite>(new[]
159+
{
160+
SpriteDict["bubblemute"]
161+
});
162+
}
163+
}

ClassicPlates/ClassicPlates.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System.Collections;
2+
using ClassicPlates.Patching;
3+
using MelonLoader;
4+
using VRC;
5+
6+
[assembly: MelonInfo(typeof(ClassicPlates.ClassicPlates), "ClassicNameplates", "1.0.0", ".FS.#8519")]
7+
[assembly: MelonGame("VRChat", "VRChat")]
8+
[assembly: MelonOptionalDependencies("UIExpansionKit")]
9+
namespace ClassicPlates;
10+
11+
//TODO: Add Nameplates onto Cameras
12+
//TODO: Add AFK Detection
13+
//TODO: Setting Presets
14+
//TODO: Nameplate Stats Compatibility
15+
//TODO: TW/ReMod/BTK Compatibility
16+
//TODO: Hook into OnSocialRank change
17+
public class ClassicPlates : MelonMod
18+
{
19+
public static NameplateManager? NameplateManager;
20+
21+
public override void OnApplicationStart()
22+
{
23+
AssetManager.Init();
24+
Settings.Init();
25+
MelonCoroutines.Start(UIManagerInit());
26+
}
27+
28+
private static IEnumerator UIManagerInit()
29+
{
30+
while (VRCUiManager.prop_VRCUiManager_0 == null) { yield return null; }
31+
try
32+
{
33+
NameplateManager = new NameplateManager();
34+
NetworkManagerHooks.Init();
35+
Patching.Patching.Init();
36+
}
37+
catch (Exception obj)
38+
{
39+
MelonLogger.Error("Unable to Apply Patches: " + obj);
40+
}
41+
}
42+
43+
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
44+
{
45+
if (NameplateManager?.Nameplates == null) return;
46+
if (NameplateManager.Nameplates.Count <= 0) return;
47+
foreach (var plate in NameplateManager.Nameplates)
48+
{
49+
NameplateManager.Nameplates.Remove(plate.Key);
50+
}
51+
}
52+
53+
public override void OnPreferencesSaved()
54+
{
55+
if (NameplateManager?.Nameplates == null) return;
56+
57+
if (RoomManager.field_Internal_Static_ApiWorld_0 != null &&
58+
RoomManager.field_Internal_Static_ApiWorldInstance_0 != null)
59+
{
60+
foreach (var player in PlayerManager.field_Private_Static_PlayerManager_0.field_Private_List_1_Player_0)
61+
{
62+
if (player._vrcplayer != null)
63+
NameplateManager.CreateNameplate(player._vrcplayer);
64+
}
65+
66+
foreach (var plate in NameplateManager.Nameplates)
67+
{
68+
MelonDebug.Msg("Applying Settings for user: " + plate.Key);
69+
70+
if (plate.Value != null && plate.Value.Nameplate != null)
71+
{
72+
plate.Value.ApplySettings();
73+
}
74+
}
75+
}
76+
else
77+
{
78+
MelonDebug.Msg("Not in Room, clearing any straggler Nameplates");
79+
NameplateManager.ClearNameplates();
80+
}
81+
}
82+
}

ClassicPlates/ClassicPlates.csproj

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net472</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<LangVersion>10</LangVersion>
8+
<AssemblyName>ClassicPlates.dev</AssemblyName>
9+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
10+
<AssemblyOriginatorKeyFile>FS_Signed.snk</AssemblyOriginatorKeyFile>
11+
<PublicSign>false</PublicSign>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<Reference Include="0Harmony, Version=2.9.0.0, Culture=neutral, PublicKeyToken=null">
16+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\0Harmony.dll</HintPath>
17+
</Reference>
18+
<Reference Include="Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
19+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\Assembly-CSharp.dll</HintPath>
20+
</Reference>
21+
<Reference Include="DataModel">
22+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat_ML6\MelonLoader\Managed\DataModel.dll</HintPath>
23+
</Reference>
24+
<Reference Include="DataModel, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
25+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\DataModel.dll</HintPath>
26+
</Reference>
27+
<Reference Include="Il2Cppmscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null">
28+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\Il2Cppmscorlib.dll</HintPath>
29+
</Reference>
30+
<Reference Include="Il2CppSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null">
31+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\Il2CppSystem.dll</HintPath>
32+
</Reference>
33+
<Reference Include="Il2CppSystem.Core">
34+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\Il2CppSystem.Core.dll</HintPath>
35+
</Reference>
36+
<Reference Include="MelonLoader, Version=0.5.4.0, Culture=neutral, PublicKeyToken=null">
37+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\MelonLoader.dll</HintPath>
38+
</Reference>
39+
<Reference Include="Microsoft.CSharp" />
40+
<Reference Include="Newtonsoft.Json">
41+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat_ML6\MelonLoader\Managed\Newtonsoft.Json.dll</HintPath>
42+
</Reference>
43+
<Reference Include="Photon-DotNet">
44+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat_ML6\MelonLoader\Managed\Photon-DotNet.dll</HintPath>
45+
</Reference>
46+
<Reference Include="UnhollowerBaseLib, Version=0.4.17.0, Culture=neutral, PublicKeyToken=null">
47+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnhollowerBaseLib.dll</HintPath>
48+
</Reference>
49+
<Reference Include="Unity.TextMeshPro, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
50+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\Unity.TextMeshPro.dll</HintPath>
51+
</Reference>
52+
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
53+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.dll</HintPath>
54+
</Reference>
55+
<Reference Include="UnityEngine.AnimationModule">
56+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat_ML6\MelonLoader\Managed\UnityEngine.AnimationModule.dll</HintPath>
57+
</Reference>
58+
<Reference Include="UnityEngine.AssetBundleModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
59+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
60+
</Reference>
61+
<Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
62+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.CoreModule.dll</HintPath>
63+
</Reference>
64+
<Reference Include="UnityEngine.ImageConversionModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
65+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.ImageConversionModule.dll</HintPath>
66+
</Reference>
67+
<Reference Include="UnityEngine.IMGUIModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
68+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.IMGUIModule.dll</HintPath>
69+
</Reference>
70+
<Reference Include="UnityEngine.InputLegacyModule">
71+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat_ML6\MelonLoader\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
72+
</Reference>
73+
<Reference Include="UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
74+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
75+
</Reference>
76+
<Reference Include="UnityEngine.UnityWebRequestModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
77+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.UnityWebRequestModule.dll</HintPath>
78+
</Reference>
79+
<Reference Include="UnityEngine.UnityWebRequestTextureModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
80+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.UnityWebRequestTextureModule.dll</HintPath>
81+
</Reference>
82+
<Reference Include="UnityEngine.UnityWebRequestWWWModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
83+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.UnityWebRequestWWWModule.dll</HintPath>
84+
</Reference>
85+
<Reference Include="VRC.UI.Core">
86+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat_ML6\MelonLoader\Managed\VRC.UI.Core.dll</HintPath>
87+
</Reference>
88+
<Reference Include="VRC.UI.Elements">
89+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat_ML6\MelonLoader\Managed\VRC.UI.Elements.dll</HintPath>
90+
</Reference>
91+
<Reference Include="VRCCore-Standalone, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
92+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\VRCCore-Standalone.dll</HintPath>
93+
</Reference>
94+
<Reference Include="VRCSDKBase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
95+
<HintPath>X:\SteamLibrary\steamapps\common\VRChat\MelonLoader\Managed\VRCSDKBase.dll</HintPath>
96+
</Reference>
97+
</ItemGroup>
98+
99+
<ItemGroup>
100+
<None Remove="2018_nameplate" />
101+
</ItemGroup>
102+
103+
<ItemGroup>
104+
<None Remove="throwbackplates" />
105+
</ItemGroup>
106+
107+
<ItemGroup>
108+
<PackageReference Include="System.Net.Http" Version="4.3.4" />
109+
</ItemGroup>
110+
111+
<ItemGroup>
112+
<None Remove="Resources\throwbackplates" />
113+
</ItemGroup>
114+
115+
<ItemGroup>
116+
<None Remove="Resources\classicplates" />
117+
<EmbeddedResource Include="Resources\classicplates" />
118+
</ItemGroup>
119+
120+
</Project>

0 commit comments

Comments
 (0)