11using LabExtended . Core ;
2- using LabExtended . Utilities ;
3- using LabExtended . Attributes ;
42using LabExtended . Extensions ;
53
64using Mirror ;
75
6+ using System . Reflection ;
87using System . Reflection . Emit ;
98
109using UnityEngine ;
@@ -22,8 +21,17 @@ namespace LabExtended.API;
2221/// </summary>
2322public static class MirrorMethods
2423{
24+ private static bool hasInitialized ;
25+
26+ private static Dictionary < string , string > rpcNames = new ( ) ;
27+ private static Dictionary < string , int > rpcHashes = new ( ) ;
28+ private static Dictionary < string , ulong > dirtyBits = new ( ) ;
29+ private static Dictionary < Type , MethodInfo > writers = new ( ) ;
30+
31+ private static Action < NetworkIdentity , NetworkConnection > sendSpawnMessage ;
32+
2533 /// <summary>
26- /// Gets the maximum length of a string.
34+ /// Gets the maximum length of a string (amount of UTF-8 bytes) that can be sent over the network .
2735 /// </summary>
2836 public const int MaxStringLength = 65534 ;
2937
@@ -32,31 +40,76 @@ public static class MirrorMethods
3240 /// <remarks>Keys are formatted as the declaring type of the property and then the name of the property
3341 /// (MyType.MyProperty)</remarks>
3442 /// </summary>
35- public static Dictionary < string , string > RpcNames { get ; } = new ( ) ;
43+ public static Dictionary < string , string > RpcNames
44+ {
45+ get
46+ {
47+ if ( ! hasInitialized )
48+ Init ( ) ;
49+
50+ return rpcNames ;
51+ }
52+ }
3653
3754 /// <summary>
3855 /// Gets hashes of all RPCs.
3956 /// <remarks>Keys are formatted as the declaring type of the property and then the name of the property
4057 /// (MyType.MyProperty)</remarks>
4158 /// </summary>
42- public static Dictionary < string , int > RpcHashes { get ; } = new ( ) ;
59+ public static Dictionary < string , int > RpcHashes
60+ {
61+ get
62+ {
63+ if ( ! hasInitialized )
64+ Init ( ) ;
65+
66+ return rpcHashes ;
67+ }
68+ }
4369
4470 /// <summary>
4571 /// Gets dirty bits of all network properties
4672 /// <remarks>Keys are formatted as the declaring type of the property and then the name of the property
4773 /// (MyType.MyProperty)</remarks>
4874 /// </summary>
49- public static Dictionary < string , ulong > DirtyBits { get ; } = new ( ) ;
75+ public static Dictionary < string , ulong > DirtyBits
76+ {
77+ get
78+ {
79+ if ( ! hasInitialized )
80+ Init ( ) ;
81+
82+ return dirtyBits ;
83+ }
84+ }
5085
5186 /// <summary>
5287 /// Gets Mirror-generated network writer extensions.
5388 /// </summary>
54- public static Dictionary < Type , Func < object , object [ ] , object > > Writers { get ; } = new ( ) ;
89+ public static Dictionary < Type , MethodInfo > Writers
90+ {
91+ get
92+ {
93+ if ( ! hasInitialized )
94+ Init ( ) ;
95+
96+ return writers ;
97+ }
98+ }
5599
56100 /// <summary>
57101 /// Gets the <see cref="NetworkServer.SendSpawnMessage"/> delegate.
58102 /// </summary>
59- public static Action < NetworkIdentity , NetworkConnection > SendSpawnMessage { get ; private set ; }
103+ public static Action < NetworkIdentity , NetworkConnection > SendSpawnMessage
104+ {
105+ get
106+ {
107+ if ( ! hasInitialized )
108+ Init ( ) ;
109+
110+ return sendSpawnMessage ;
111+ }
112+ }
60113
61114 /// <summary>
62115 /// Attempts to get a specific behaviour component of a network identity.
@@ -848,7 +901,7 @@ public static void WriteCustomSyncVar(this NetworkWriter writer, NetworkBehaviou
848901 if ( ! Writers . TryGetValue ( customValue . GetType ( ) , out var definedValueWriter ) )
849902 throw new Exception ( $ "Type { customValue . GetType ( ) . FullName } does not have a defined writer") ;
850903
851- valueWriter = ( x , y ) => definedValueWriter ( null , [ x , y ] ) ;
904+ valueWriter = ( x , y ) => definedValueWriter . Invoke ( x , [ y ] ) ;
852905 }
853906
854907 WriteCustomSyncVar ( writer , behaviour . netId , dirtyBit , behaviour . ComponentIndex , customValue , valueWriter ) ;
@@ -880,7 +933,7 @@ public static void WriteCustomSyncVar<T>(this NetworkWriter writer, NetworkBehav
880933 if ( ! Writers . TryGetValue ( customValue . GetType ( ) , out var definedValueWriter ) )
881934 throw new Exception ( $ "Type { customValue . GetType ( ) . FullName } does not have a defined writer") ;
882935
883- valueWriter = ( x , y ) => definedValueWriter ( null , [ x , y ] ) ;
936+ valueWriter = ( x , y ) => definedValueWriter . Invoke ( x , [ y ] ) ;
884937 }
885938
886939 WriteCustomSyncVar ( writer , behaviour . netId , dirtyBit , behaviour . ComponentIndex , customValue ,
@@ -1077,12 +1130,12 @@ private static void InitIdentityServerSide(NetworkIdentity identity, NetworkConn
10771130 }
10781131
10791132 // TODO: There's a weird bug that causes the Mono runtime to randomly crash at random points in this method.
1080- [ LoaderInitialize ( 1 ) ]
1081- private static void OnInit ( )
1133+ // Seems to be caused by the Mono runtimn as no exceptions are thrown (and it doesn't happen on Windows).
1134+ private static void Init ( )
10821135 {
10831136 try
10841137 {
1085- SendSpawnMessage =
1138+ sendSpawnMessage =
10861139 typeof ( NetworkServer ) . FindMethod ( x => x . Name == "SendSpawnMessage" )
10871140 . CreateDelegate ( typeof ( Action < NetworkIdentity , NetworkConnection > ) ) as
10881141 Action < NetworkIdentity , NetworkConnection > ;
@@ -1108,18 +1161,21 @@ private static void OnInit()
11081161 if ( isSerializer && method . ReturnType == typeof ( void ) && method . Name . StartsWith ( "Write" ) )
11091162 {
11101163 var parameters = method . GetAllParameters ( ) ;
1111- if ( parameters . Length != 2 ) continue ;
1164+
1165+ if ( parameters . Length != 2 )
1166+ continue ;
11121167
11131168 var serializedType = parameters
11141169 . FirstOrDefault ( y => y . ParameterType != typeof ( NetworkWriter ) )
11151170 ? . ParameterType ;
11161171
1117- if ( serializedType is null ) continue ;
1118- if ( Writers . ContainsKey ( serializedType ) ) continue ;
1119-
1120- var invoker = FastReflection . ForMethod ( method ) ;
1172+ if ( serializedType is null )
1173+ continue ;
1174+
1175+ if ( Writers . ContainsKey ( serializedType ) )
1176+ continue ;
11211177
1122- Writers . Add ( serializedType , invoker ) ;
1178+ Writers . Add ( serializedType , method ) ;
11231179 }
11241180 else if ( method . HasAttribute < ClientRpcAttribute > ( ) || method . HasAttribute < TargetRpcAttribute > ( ) )
11251181 {
@@ -1129,10 +1185,14 @@ private static void OnInit()
11291185 continue ;
11301186
11311187 var body = method . GetMethodBody ( ) ;
1132- if ( body is null ) continue ;
1188+
1189+ if ( body is null )
1190+ continue ;
11331191
11341192 var codes = body . GetILAsByteArray ( ) ;
1135- if ( codes ? . Length < 1 ) continue ;
1193+
1194+ if ( codes ? . Length < 1 )
1195+ continue ;
11361196
11371197 var full = method . Module . ResolveString ( BitConverter . ToInt32 ( codes ,
11381198 codes . IndexOf ( ( byte ) OpCodes . Ldstr . Value ) + 1 ) ) ;
@@ -1148,19 +1208,29 @@ private static void OnInit()
11481208 for ( var y = 0 ; y < properties . Length ; y ++ )
11491209 {
11501210 var prop = properties [ y ] ;
1151- if ( ! prop . Name . StartsWith ( "Network" ) ) continue ;
1211+
1212+ if ( ! prop . Name . StartsWith ( "Network" ) )
1213+ continue ;
11521214
11531215 var name = $ "{ prop . ReflectedType . Name } .{ prop . Name } ";
1154- if ( DirtyBits . ContainsKey ( name ) ) continue ;
1216+
1217+ if ( DirtyBits . ContainsKey ( name ) )
1218+ continue ;
11551219
11561220 var setter = prop . GetSetMethod ( true ) ;
1157- if ( setter is null ) continue ;
1221+
1222+ if ( setter is null )
1223+ continue ;
11581224
11591225 var body = setter . GetMethodBody ( ) ;
1160- if ( body is null ) continue ;
1226+
1227+ if ( body is null )
1228+ continue ;
11611229
11621230 var il = body . GetILAsByteArray ( ) ;
1163- if ( il ? . Length < 1 ) continue ;
1231+
1232+ if ( il ? . Length < 1 )
1233+ continue ;
11641234
11651235 var bit = il [ il . LastIndexOf ( ( byte ) OpCodes . Ldc_I8 . Value ) + 1 ] ;
11661236
@@ -1181,18 +1251,23 @@ private static void OnInit()
11811251 {
11821252 var method = writerExtensions [ i ] ;
11831253
1184- if ( method . IsGenericMethod ) continue ;
1185- if ( method . HasAttribute < ObsoleteAttribute > ( ) ) continue ;
1254+ if ( method . IsGenericMethod )
1255+ continue ;
1256+
1257+ if ( method . HasAttribute < ObsoleteAttribute > ( ) )
1258+ continue ;
11861259
11871260 var parameters = method . GetAllParameters ( ) ;
1188- if ( parameters . Length != 2 ) continue ;
1261+
1262+ if ( parameters . Length != 2 )
1263+ continue ;
11891264
11901265 var type = parameters . FirstOrDefault ( x => x . ParameterType != typeof ( NetworkWriter ) ) ? . ParameterType ;
1191- if ( type is null ) continue ;
1192-
1193- var invoker = FastReflection . ForMethod ( method ) ;
11941266
1195- Writers . Add ( type , invoker ) ;
1267+ if ( type is null )
1268+ continue ;
1269+
1270+ Writers . Add ( type , method ) ;
11961271 }
11971272 catch ( Exception ex )
11981273 {
@@ -1209,20 +1284,26 @@ private static void OnInit()
12091284 {
12101285 var method = generatedMethods [ i ] ;
12111286
1212- if ( method . IsGenericMethod ) continue ;
1213- if ( method . ReturnType != typeof ( void ) ) continue ;
1287+ if ( method . IsGenericMethod )
1288+ continue ;
1289+
1290+ if ( method . ReturnType != typeof ( void ) )
1291+ continue ;
12141292
12151293 var parameters = method . GetAllParameters ( ) ;
1216- if ( parameters . Length != 2 ) continue ;
1294+
1295+ if ( parameters . Length != 2 )
1296+ continue ;
12171297
12181298 var type = parameters . FirstOrDefault ( x => x . ParameterType != typeof ( NetworkWriter ) ) ? . ParameterType ;
12191299
1220- if ( type is null ) continue ;
1221- if ( Writers . ContainsKey ( type ) ) continue ;
1300+ if ( type is null )
1301+ continue ;
12221302
1223- var invoker = FastReflection . ForMethod ( method ) ;
1303+ if ( Writers . ContainsKey ( type ) )
1304+ continue ;
12241305
1225- Writers . Add ( type , invoker ) ;
1306+ Writers . Add ( type , method ) ;
12261307 }
12271308 catch ( Exception ex )
12281309 {
@@ -1234,5 +1315,7 @@ private static void OnInit()
12341315 {
12351316 ApiLog . Error ( "Mirror Methods" , ex ) ;
12361317 }
1318+
1319+ hasInitialized = true ;
12371320 }
12381321}
0 commit comments