Skip to content
This repository was archived by the owner on May 15, 2023. It is now read-only.

Commit 663eb1c

Browse files
committed
AS: fix compatibility with VRChat build 992
1 parent 556e56e commit 663eb1c

File tree

2 files changed

+51
-39
lines changed

2 files changed

+51
-39
lines changed

AdvancedSafety/AdvancedSafety.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<VrcReferences>true</VrcReferences>
66
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
77
<LangVersion>latest</LangVersion>
8-
<Version>1.2.0.0</Version>
8+
<Version>1.2.1.0</Version>
99
</PropertyGroup>
1010

1111
<ItemGroup>

AdvancedSafety/AdvancedSafetyMod.cs

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,24 @@
1010
using UIExpansionKit;
1111
using UnhollowerBaseLib;
1212
using UnhollowerBaseLib.Runtime;
13-
using UnhollowerRuntimeLib.XrefScans;
1413
using UnityEngine;
1514
using UnityEngine.Animations;
1615
using VRC.Core;
1716
using AMEnumA = VRCAvatarManager.ObjectNPrivateSealedIEnumerator1ObjectIEnumeratorIDisposableInObVRAc1GaApAcObBoUnique;
1817
using AMEnumB = VRCAvatarManager.ObjectNPrivateSealedIEnumerator1ObjectIEnumeratorIDisposableInObGaVRApBoBoObBoObUnique;
18+
using AMEnumC = VRCAvatarManager.ObjectNPrivateSealedIEnumerator1ObjectIEnumeratorIDisposableInObVRAc1GaApAcObObUnique;
1919
using Object = UnityEngine.Object;
2020

2121
[assembly:MelonGame("VRChat", "VRChat")]
22-
[assembly:MelonInfo(typeof(AdvancedSafetyMod), "Advanced Safety", "1.2.0", "knah", "https://github.com/knah/VRCMods")]
22+
[assembly:MelonInfo(typeof(AdvancedSafetyMod), "Advanced Safety", "1.2.1", "knah", "https://github.com/knah/VRCMods")]
2323
[assembly:MelonOptionalDependencies("UIExpansionKit")]
2424

2525
namespace AdvancedSafety
2626
{
2727
public class AdvancedSafetyMod : MelonMod
2828
{
29+
private static List<object> ourPinnedDelegates = new List<object>();
30+
2931
public override void OnApplicationStart()
3032
{
3133
AdvancedSafetySettings.RegisterSettings();
@@ -34,41 +36,24 @@ public override void OnApplicationStart()
3436
.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).Where(it =>
3537
it.Name.StartsWith("Method_Public_Static_Object_Object_Vector3_Quaternion_Boolean_Boolean_Boolean_") && it.GetParameters().Length == 6).ToList();
3638

37-
MethodBase patchTarget = null;
38-
foreach (var methodInfo in typeof(AssetManagement).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly))
39-
{
40-
foreach (var it in XrefScanner.XrefScan(methodInfo))
41-
{
42-
if (it.Type != XrefType.Method) continue;
43-
var methodBase = it.TryResolve();
44-
if (methodBase == null) continue;
45-
if (matchingMethods.Contains(methodBase))
46-
{
47-
patchTarget = methodBase;
48-
goto haveTarget;
49-
}
50-
}
51-
}
52-
53-
haveTarget:
54-
if (patchTarget != null)
39+
foreach (var matchingMethod in matchingMethods)
5540
{
5641
unsafe
5742
{
58-
var originalMethodPointer = *(IntPtr*) (IntPtr) UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(patchTarget).GetValue(null);
43+
var originalMethodPointer = *(IntPtr*) (IntPtr) UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(matchingMethod).GetValue(null);
44+
45+
ObjectInstantiateDelegate originalInstantiateDelegate = null;
46+
47+
ObjectInstantiateDelegate replacement = (assetPtr, pos, rot, allowCustomShaders, isUI, validate) =>
48+
ObjectInstantiatePatch(assetPtr, pos, rot, allowCustomShaders, isUI, validate, originalInstantiateDelegate);
5949

60-
Imports.Hook((IntPtr) (&originalMethodPointer),
61-
typeof(AdvancedSafetyMod).GetMethod(nameof(ObjectInstantiatePatch),
62-
BindingFlags.Static | BindingFlags.NonPublic)!.MethodHandle.GetFunctionPointer());
50+
ourPinnedDelegates.Add(replacement);
6351

64-
ourOriginalInstantiate =
65-
Marshal.GetDelegateForFunctionPointer<ObjectInstantiateDelegate>(originalMethodPointer);
52+
Imports.Hook((IntPtr) (&originalMethodPointer), Marshal.GetFunctionPointerForDelegate(replacement));
53+
54+
originalInstantiateDelegate = Marshal.GetDelegateForFunctionPointer<ObjectInstantiateDelegate>(originalMethodPointer);
6655
}
6756
}
68-
else
69-
{
70-
MelonLogger.LogError("Patch target for object instantiation not found, avatar filtering will not work");
71-
}
7257

7358
unsafe
7459
{
@@ -93,6 +78,18 @@ public override void OnApplicationStart()
9378

9479
ourMoveNextB = originalMethodPointer;
9580
}
81+
82+
unsafe
83+
{
84+
var originalMethodPointer = *(IntPtr*) (IntPtr) UnhollowerUtils
85+
.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumC).GetMethod(
86+
nameof(AMEnumC.MoveNext)))
87+
.GetValue(null);
88+
89+
Imports.Hook((IntPtr)(&originalMethodPointer), typeof(AdvancedSafetyMod).GetMethod(nameof(MoveNextPatchC), BindingFlags.Static | BindingFlags.NonPublic)!.MethodHandle.GetFunctionPointer());
90+
91+
ourMoveNextC = originalMethodPointer;
92+
}
9693

9794
unsafe
9895
{
@@ -124,9 +121,9 @@ public override void OnModSettingsApplied()
124121
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
125122
private delegate IntPtr ObjectInstantiateDelegate(IntPtr assetPtr, Vector3 pos, Quaternion rot, byte allowCustomShaders, byte isUI, byte validate);
126123

127-
private static ObjectInstantiateDelegate ourOriginalInstantiate;
128124
private static IntPtr ourMoveNextA;
129125
private static IntPtr ourMoveNextB;
126+
private static IntPtr ourMoveNextC;
130127

131128
private static IntPtr ourInvokeMethodInfo;
132129

@@ -287,25 +284,40 @@ private static bool MoveNextPatchB(IntPtr thisPtr)
287284
}
288285
}
289286

290-
private static IntPtr ObjectInstantiatePatch(IntPtr assetPtr, Vector3 pos, Quaternion rot, byte allowCustomShaders, byte isUI, byte validate)
287+
private static bool MoveNextPatchC(IntPtr thisPtr)
288+
{
289+
try
290+
{
291+
using (new AvatarManagerCookie(new AMEnumC(thisPtr).field_Public_VRCAvatarManager_0))
292+
return SafeInvokeMoveNext(ourMoveNextC, thisPtr);
293+
}
294+
catch (Exception ex)
295+
{
296+
MelonLogger.LogError($"Error when wrapping avatar creation: {ex}");
297+
return false;
298+
}
299+
}
300+
301+
private static IntPtr ObjectInstantiatePatch(IntPtr assetPtr, Vector3 pos, Quaternion rot,
302+
byte allowCustomShaders, byte isUI, byte validate, ObjectInstantiateDelegate originalInstantiateDelegate)
291303
{
292-
if (AvatarManagerCookie.CurrentManager == null || assetPtr == IntPtr.Zero)
293-
return ourOriginalInstantiate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
304+
if (AvatarManagerCookie.CurrentManager == null || assetPtr == IntPtr.Zero)
305+
return originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
294306

295307
var avatarManager = AvatarManagerCookie.CurrentManager;
296308
var vrcPlayer = avatarManager.field_Private_VRCPlayer_0;
297-
if (vrcPlayer == null) return ourOriginalInstantiate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
309+
if (vrcPlayer == null) return originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
298310

299311
if (vrcPlayer == VRCPlayer.field_Internal_Static_VRCPlayer_0) // never apply to self
300-
return ourOriginalInstantiate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
312+
return originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
301313

302314
var go = new Object(assetPtr).TryCast<GameObject>();
303315
if (go == null)
304-
return ourOriginalInstantiate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
316+
return originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
305317

306318
var wasActive = go.activeSelf;
307319
go.SetActive(false);
308-
var result = ourOriginalInstantiate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
320+
var result = originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate);
309321
go.SetActive(wasActive);
310322
if (result == IntPtr.Zero) return result;
311323
var instantiated = new GameObject(result);

0 commit comments

Comments
 (0)