2
2
using System . Collections . Generic ;
3
3
using UnityEngine ;
4
4
using MLAPI . NetworkingManagerComponents ;
5
+ using System . Reflection ;
6
+ using MLAPI . Attributes ;
7
+ using System . Linq ;
8
+ using System . IO ;
5
9
6
10
namespace MLAPI
7
11
{
8
12
public abstract class NetworkedBehaviour : MonoBehaviour
9
13
{
14
+ public float SyncVarSyncDelay = 0.1f ;
10
15
public bool isLocalPlayer
11
16
{
12
17
get
@@ -79,6 +84,7 @@ private void OnEnable()
79
84
{
80
85
_networkedObject = GetComponentInParent < NetworkedObject > ( ) ;
81
86
}
87
+ NetworkedObject . networkedBehaviours . Add ( this ) ;
82
88
}
83
89
84
90
internal bool networkedStartInvoked = false ;
@@ -109,6 +115,11 @@ protected void DeregisterMessageHandler(string name, int counter)
109
115
MessageManager . RemoveIncomingMessageHandler ( name , counter , networkId ) ;
110
116
}
111
117
118
+ private void OnDisable ( )
119
+ {
120
+ NetworkedObject . networkedBehaviours . Remove ( this ) ;
121
+ }
122
+
112
123
private void OnDestroy ( )
113
124
{
114
125
foreach ( KeyValuePair < string , int > pair in registeredMessageHandlers )
@@ -117,6 +128,291 @@ private void OnDestroy()
117
128
}
118
129
}
119
130
131
+ #region SYNC_VAR
132
+ private List < FieldInfo > syncedFields = new List < FieldInfo > ( ) ;
133
+ internal List < FieldType > syncedFieldTypes = new List < FieldType > ( ) ;
134
+ private List < object > syncedFieldValues = new List < object > ( ) ;
135
+ //A dirty field is a field that's not synced.
136
+ public bool [ ] dirtyFields ;
137
+ protected static ushort networkedBehaviourId ;
138
+ //This is just for the unity editor. if you turn the editor to DEBUG mode you can see what the networkedBehaviourId is.
139
+ private ushort _networkedBehaviourId = networkedBehaviourId ;
140
+ internal void SyncVarInit ( )
141
+ {
142
+ FieldInfo [ ] sortedFields = GetType ( ) . GetFields ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . FlattenHierarchy | BindingFlags . Instance ) . OrderBy ( x => x . Name ) . ToArray ( ) ;
143
+ for ( byte i = 0 ; i < sortedFields . Length ; i ++ )
144
+ {
145
+ if ( sortedFields [ i ] . IsDefined ( typeof ( SyncedVar ) , true ) )
146
+ {
147
+ if ( sortedFields [ i ] . FieldType == typeof ( bool ) )
148
+ {
149
+ syncedFields . Add ( sortedFields [ i ] ) ;
150
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
151
+ syncedFieldTypes . Add ( FieldType . Bool ) ;
152
+ }
153
+ else if ( sortedFields [ i ] . FieldType == typeof ( byte ) )
154
+ {
155
+ syncedFields . Add ( sortedFields [ i ] ) ;
156
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
157
+ syncedFieldTypes . Add ( FieldType . Byte ) ;
158
+ }
159
+ else if ( sortedFields [ i ] . FieldType == typeof ( char ) )
160
+ {
161
+ syncedFields . Add ( sortedFields [ i ] ) ;
162
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
163
+ syncedFieldTypes . Add ( FieldType . Char ) ;
164
+ }
165
+ else if ( sortedFields [ i ] . FieldType == typeof ( double ) )
166
+ {
167
+ syncedFields . Add ( sortedFields [ i ] ) ;
168
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
169
+ syncedFieldTypes . Add ( FieldType . Double ) ;
170
+ }
171
+ else if ( sortedFields [ i ] . FieldType == typeof ( float ) )
172
+ {
173
+ syncedFields . Add ( sortedFields [ i ] ) ;
174
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
175
+ syncedFieldTypes . Add ( FieldType . Single ) ;
176
+ }
177
+ else if ( sortedFields [ i ] . FieldType == typeof ( int ) )
178
+ {
179
+ syncedFields . Add ( sortedFields [ i ] ) ;
180
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
181
+ syncedFieldTypes . Add ( FieldType . Int ) ;
182
+ }
183
+ else if ( sortedFields [ i ] . FieldType == typeof ( long ) )
184
+ {
185
+ syncedFields . Add ( sortedFields [ i ] ) ;
186
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
187
+ syncedFieldTypes . Add ( FieldType . Long ) ;
188
+ }
189
+ else if ( sortedFields [ i ] . FieldType == typeof ( sbyte ) )
190
+ {
191
+ syncedFields . Add ( sortedFields [ i ] ) ;
192
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
193
+ syncedFieldTypes . Add ( FieldType . SByte ) ;
194
+ }
195
+ else if ( sortedFields [ i ] . FieldType == typeof ( short ) )
196
+ {
197
+ syncedFields . Add ( sortedFields [ i ] ) ;
198
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
199
+ syncedFieldTypes . Add ( FieldType . Short ) ;
200
+ }
201
+ else if ( sortedFields [ i ] . FieldType == typeof ( uint ) )
202
+ {
203
+ syncedFields . Add ( sortedFields [ i ] ) ;
204
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
205
+ syncedFieldTypes . Add ( FieldType . UInt ) ;
206
+ }
207
+ else if ( sortedFields [ i ] . FieldType == typeof ( ulong ) )
208
+ {
209
+ syncedFields . Add ( sortedFields [ i ] ) ;
210
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
211
+ syncedFieldTypes . Add ( FieldType . ULong ) ;
212
+ }
213
+ else if ( sortedFields [ i ] . FieldType == typeof ( ushort ) )
214
+ {
215
+ syncedFields . Add ( sortedFields [ i ] ) ;
216
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
217
+ syncedFieldTypes . Add ( FieldType . UShort ) ;
218
+ }
219
+ else if ( sortedFields [ i ] . FieldType == typeof ( string ) )
220
+ {
221
+ syncedFields . Add ( sortedFields [ i ] ) ;
222
+ syncedFieldValues . Add ( sortedFields [ i ] . GetValue ( this ) ) ;
223
+ syncedFieldTypes . Add ( FieldType . String ) ;
224
+ }
225
+ else
226
+ {
227
+ Debug . LogError ( "MLAPI: The type " + sortedFields [ i ] . FieldType . ToString ( ) + " can not be used as a syncvar" ) ;
228
+ }
229
+ }
230
+ }
231
+ if ( dirtyFields . Length > 255 )
232
+ {
233
+ Debug . LogError ( "MLAPI: You can not have more than 255 SyncVar's per NetworkedBehaviour!" ) ;
234
+ }
235
+ dirtyFields = new bool [ syncedFields . Count ] ;
236
+ }
237
+
238
+ internal void OnSyncVarUpdate ( object value , byte fieldIndex )
239
+ {
240
+ if ( isServer )
241
+ return ;
242
+ syncedFields [ fieldIndex ] . SetValue ( this , value ) ;
243
+ }
244
+
245
+ private float lastSyncTime = 0f ;
246
+ internal void SyncvarUpdate ( )
247
+ {
248
+ if ( ! isServer )
249
+ return ;
250
+ SetDirtyness ( ) ;
251
+ if ( Time . time - lastSyncTime >= SyncVarSyncDelay )
252
+ {
253
+ byte dirtyCount = ( byte ) dirtyFields . Count ( x => x == true ) ;
254
+ if ( dirtyCount == 0 )
255
+ return ; //All up to date!
256
+ //It's sync time!
257
+ using ( MemoryStream stream = new MemoryStream ( ) )
258
+ {
259
+ using ( BinaryWriter writer = new BinaryWriter ( stream ) )
260
+ {
261
+ //Write all indexes
262
+ writer . Write ( dirtyCount ) ;
263
+ for ( byte i = 0 ; i < dirtyFields . Length ; i ++ )
264
+ {
265
+ //Writes all the indexes of the dirty syncvars.
266
+ if ( dirtyFields [ i ] == true )
267
+ {
268
+ writer . Write ( networkId ) ;
269
+ writer . Write ( networkedObject . GetOrderIndex ( this ) ) ;
270
+ writer . Write ( networkedBehaviourId ) ;
271
+ writer . Write ( i ) ; //Index
272
+ switch ( syncedFieldTypes [ i ] )
273
+ {
274
+ case FieldType . Bool :
275
+ writer . Write ( ( bool ) syncedFields [ i ] . GetValue ( this ) ) ;
276
+ break ;
277
+ case FieldType . Byte :
278
+ writer . Write ( ( byte ) syncedFields [ i ] . GetValue ( this ) ) ;
279
+ break ;
280
+ case FieldType . Char :
281
+ writer . Write ( ( char ) syncedFields [ i ] . GetValue ( this ) ) ;
282
+ break ;
283
+ case FieldType . Double :
284
+ writer . Write ( ( double ) syncedFields [ i ] . GetValue ( this ) ) ;
285
+ break ;
286
+ case FieldType . Single :
287
+ writer . Write ( ( float ) syncedFields [ i ] . GetValue ( this ) ) ;
288
+ break ;
289
+ case FieldType . Int :
290
+ writer . Write ( ( int ) syncedFields [ i ] . GetValue ( this ) ) ;
291
+ break ;
292
+ case FieldType . Long :
293
+ writer . Write ( ( long ) syncedFields [ i ] . GetValue ( this ) ) ;
294
+ break ;
295
+ case FieldType . SByte :
296
+ writer . Write ( ( sbyte ) syncedFields [ i ] . GetValue ( this ) ) ;
297
+ break ;
298
+ case FieldType . Short :
299
+ writer . Write ( ( short ) syncedFields [ i ] . GetValue ( this ) ) ;
300
+ break ;
301
+ case FieldType . UInt :
302
+ writer . Write ( ( uint ) syncedFields [ i ] . GetValue ( this ) ) ;
303
+ break ;
304
+ case FieldType . ULong :
305
+ writer . Write ( ( ulong ) syncedFields [ i ] . GetValue ( this ) ) ;
306
+ break ;
307
+ case FieldType . UShort :
308
+ writer . Write ( ( ushort ) syncedFields [ i ] . GetValue ( this ) ) ;
309
+ break ;
310
+ case FieldType . String :
311
+ writer . Write ( ( string ) syncedFields [ i ] . GetValue ( this ) ) ;
312
+ break ;
313
+ }
314
+ syncedFieldValues [ i ] = syncedFields [ i ] . GetValue ( this ) ;
315
+ dirtyFields [ i ] = false ;
316
+ }
317
+ }
318
+ NetworkingManager . singleton . Send ( "MLAPI_SYNC_VAR_UPDATE" , "MLAPI_RELIABLE_FRAGMENTED_SEQUENCED" , stream . ToArray ( ) , ownerClientId ) ;
319
+ }
320
+ }
321
+ lastSyncTime = Time . time ;
322
+ }
323
+ }
324
+
325
+ private void SetDirtyness ( )
326
+ {
327
+ if ( ! isServer )
328
+ return ;
329
+ for ( int i = 0 ; i < syncedFields . Count ; i ++ )
330
+ {
331
+ switch ( syncedFieldTypes [ i ] )
332
+ {
333
+ case FieldType . Bool :
334
+ if ( ( bool ) syncedFields [ i ] . GetValue ( this ) != ( bool ) syncedFieldValues [ i ] )
335
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
336
+ else
337
+ dirtyFields [ i ] = false ; //Up to date
338
+ break ;
339
+ case FieldType . Byte :
340
+ if ( ( byte ) syncedFields [ i ] . GetValue ( this ) != ( byte ) syncedFieldValues [ i ] )
341
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
342
+ else
343
+ dirtyFields [ i ] = false ; //Up to date
344
+ break ;
345
+ case FieldType . Char :
346
+ if ( ( char ) syncedFields [ i ] . GetValue ( this ) != ( char ) syncedFieldValues [ i ] )
347
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
348
+ else
349
+ dirtyFields [ i ] = false ; //Up to date
350
+ break ;
351
+ case FieldType . Double :
352
+ if ( ( double ) syncedFields [ i ] . GetValue ( this ) != ( double ) syncedFieldValues [ i ] )
353
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
354
+ else
355
+ dirtyFields [ i ] = false ; //Up to date
356
+ break ;
357
+ case FieldType . Single :
358
+ if ( ( float ) syncedFields [ i ] . GetValue ( this ) != ( float ) syncedFieldValues [ i ] )
359
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
360
+ else
361
+ dirtyFields [ i ] = false ; //Up to date
362
+ break ;
363
+ case FieldType . Int :
364
+ if ( ( int ) syncedFields [ i ] . GetValue ( this ) != ( int ) syncedFieldValues [ i ] )
365
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
366
+ else
367
+ dirtyFields [ i ] = false ; //Up to date
368
+ break ;
369
+ case FieldType . Long :
370
+ if ( ( long ) syncedFields [ i ] . GetValue ( this ) != ( long ) syncedFieldValues [ i ] )
371
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
372
+ else
373
+ dirtyFields [ i ] = false ; //Up to date
374
+ break ;
375
+ case FieldType . SByte :
376
+ if ( ( sbyte ) syncedFields [ i ] . GetValue ( this ) != ( sbyte ) syncedFieldValues [ i ] )
377
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
378
+ else
379
+ dirtyFields [ i ] = false ; //Up to date
380
+ break ;
381
+ case FieldType . Short :
382
+ if ( ( short ) syncedFields [ i ] . GetValue ( this ) != ( short ) syncedFieldValues [ i ] )
383
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
384
+ else
385
+ dirtyFields [ i ] = false ; //Up to date
386
+ break ;
387
+ case FieldType . UInt :
388
+ if ( ( uint ) syncedFields [ i ] . GetValue ( this ) != ( uint ) syncedFieldValues [ i ] )
389
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
390
+ else
391
+ dirtyFields [ i ] = false ; //Up to date
392
+ break ;
393
+ case FieldType . ULong :
394
+ if ( ( ulong ) syncedFields [ i ] . GetValue ( this ) != ( ulong ) syncedFieldValues [ i ] )
395
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
396
+ else
397
+ dirtyFields [ i ] = false ; //Up to date
398
+ break ;
399
+ case FieldType . UShort :
400
+ if ( ( ushort ) syncedFields [ i ] . GetValue ( this ) != ( ushort ) syncedFieldValues [ i ] )
401
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
402
+ else
403
+ dirtyFields [ i ] = false ; //Up to date
404
+ break ;
405
+ case FieldType . String :
406
+ if ( ( string ) syncedFields [ i ] . GetValue ( this ) != ( string ) syncedFieldValues [ i ] )
407
+ dirtyFields [ i ] = true ; //This fields value is out of sync!
408
+ else
409
+ dirtyFields [ i ] = false ; //Up to date
410
+ break ;
411
+ }
412
+ }
413
+ }
414
+ #endregion
415
+
120
416
protected void SendToServer ( string messageType , string channelName , byte [ ] data )
121
417
{
122
418
if ( MessageManager . messageTypes [ messageType ] < 32 )
0 commit comments