10
10
using UIExpansionKit ;
11
11
using UnhollowerBaseLib ;
12
12
using UnhollowerBaseLib . Runtime ;
13
- using UnhollowerRuntimeLib . XrefScans ;
14
13
using UnityEngine ;
15
14
using UnityEngine . Animations ;
16
15
using VRC . Core ;
17
16
using AMEnumA = VRCAvatarManager . ObjectNPrivateSealedIEnumerator1ObjectIEnumeratorIDisposableInObVRAc1GaApAcObBoUnique ;
18
17
using AMEnumB = VRCAvatarManager . ObjectNPrivateSealedIEnumerator1ObjectIEnumeratorIDisposableInObGaVRApBoBoObBoObUnique ;
18
+ using AMEnumC = VRCAvatarManager . ObjectNPrivateSealedIEnumerator1ObjectIEnumeratorIDisposableInObVRAc1GaApAcObObUnique ;
19
19
using Object = UnityEngine . Object ;
20
20
21
21
[ 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" ) ]
23
23
[ assembly: MelonOptionalDependencies ( "UIExpansionKit" ) ]
24
24
25
25
namespace AdvancedSafety
26
26
{
27
27
public class AdvancedSafetyMod : MelonMod
28
28
{
29
+ private static List < object > ourPinnedDelegates = new List < object > ( ) ;
30
+
29
31
public override void OnApplicationStart ( )
30
32
{
31
33
AdvancedSafetySettings . RegisterSettings ( ) ;
@@ -34,41 +36,24 @@ public override void OnApplicationStart()
34
36
. GetMethods ( BindingFlags . Public | BindingFlags . Static | BindingFlags . DeclaredOnly ) . Where ( it =>
35
37
it . Name . StartsWith ( "Method_Public_Static_Object_Object_Vector3_Quaternion_Boolean_Boolean_Boolean_" ) && it . GetParameters ( ) . Length == 6 ) . ToList ( ) ;
36
38
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 )
55
40
{
56
41
unsafe
57
42
{
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 ) ;
59
49
60
- Imports. Hook ( ( IntPtr ) ( & originalMethodPointer ) ,
61
- typeof ( AdvancedSafetyMod ) . GetMethod ( nameof ( ObjectInstantiatePatch ) ,
62
- BindingFlags . Static | BindingFlags . NonPublic ) ! . MethodHandle . GetFunctionPointer ( ) ) ;
50
+ ourPinnedDelegates . Add ( replacement ) ;
63
51
64
- ourOriginalInstantiate =
65
- Marshal . GetDelegateForFunctionPointer < ObjectInstantiateDelegate > ( originalMethodPointer ) ;
52
+ Imports . Hook ( ( IntPtr ) ( & originalMethodPointer ) , Marshal . GetFunctionPointerForDelegate ( replacement ) ) ;
53
+
54
+ originalInstantiateDelegate = Marshal . GetDelegateForFunctionPointer < ObjectInstantiateDelegate > ( originalMethodPointer ) ;
66
55
}
67
56
}
68
- else
69
- {
70
- MelonLogger . LogError ( "Patch target for object instantiation not found, avatar filtering will not work" ) ;
71
- }
72
57
73
58
unsafe
74
59
{
@@ -93,6 +78,18 @@ public override void OnApplicationStart()
93
78
94
79
ourMoveNextB = originalMethodPointer ;
95
80
}
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
+ }
96
93
97
94
unsafe
98
95
{
@@ -124,9 +121,9 @@ public override void OnModSettingsApplied()
124
121
[ UnmanagedFunctionPointer ( CallingConvention . Cdecl ) ]
125
122
private delegate IntPtr ObjectInstantiateDelegate ( IntPtr assetPtr , Vector3 pos , Quaternion rot , byte allowCustomShaders , byte isUI , byte validate ) ;
126
123
127
- private static ObjectInstantiateDelegate ourOriginalInstantiate ;
128
124
private static IntPtr ourMoveNextA ;
129
125
private static IntPtr ourMoveNextB ;
126
+ private static IntPtr ourMoveNextC ;
130
127
131
128
private static IntPtr ourInvokeMethodInfo ;
132
129
@@ -287,25 +284,40 @@ private static bool MoveNextPatchB(IntPtr thisPtr)
287
284
}
288
285
}
289
286
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 )
291
303
{
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 ) ;
294
306
295
307
var avatarManager = AvatarManagerCookie . CurrentManager ;
296
308
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 ) ;
298
310
299
311
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 ) ;
301
313
302
314
var go = new Object ( assetPtr ) . TryCast < GameObject > ( ) ;
303
315
if ( go == null )
304
- return ourOriginalInstantiate ( assetPtr , pos , rot , allowCustomShaders , isUI , validate ) ;
316
+ return originalInstantiateDelegate ( assetPtr , pos , rot , allowCustomShaders , isUI , validate ) ;
305
317
306
318
var wasActive = go . activeSelf ;
307
319
go . SetActive ( false ) ;
308
- var result = ourOriginalInstantiate ( assetPtr , pos , rot , allowCustomShaders , isUI , validate ) ;
320
+ var result = originalInstantiateDelegate ( assetPtr , pos , rot , allowCustomShaders , isUI , validate ) ;
309
321
go . SetActive ( wasActive ) ;
310
322
if ( result == IntPtr . Zero ) return result ;
311
323
var instantiated = new GameObject ( result ) ;
0 commit comments