22using System . Collections . Generic ;
33using UnityEngine ;
44using MLAPI . NetworkingManagerComponents ;
5+ using System . Reflection ;
6+ using MLAPI . Attributes ;
7+ using System . Linq ;
8+ using System . IO ;
59
610namespace MLAPI
711{
812 public abstract class NetworkedBehaviour : MonoBehaviour
913 {
14+ public float SyncVarSyncDelay = 0.1f ;
1015 public bool isLocalPlayer
1116 {
1217 get
@@ -79,6 +84,7 @@ private void OnEnable()
7984 {
8085 _networkedObject = GetComponentInParent < NetworkedObject > ( ) ;
8186 }
87+ NetworkedObject . networkedBehaviours . Add ( this ) ;
8288 }
8389
8490 internal bool networkedStartInvoked = false ;
@@ -109,6 +115,11 @@ protected void DeregisterMessageHandler(string name, int counter)
109115 MessageManager . RemoveIncomingMessageHandler ( name , counter , networkId ) ;
110116 }
111117
118+ private void OnDisable ( )
119+ {
120+ NetworkedObject . networkedBehaviours . Remove ( this ) ;
121+ }
122+
112123 private void OnDestroy ( )
113124 {
114125 foreach ( KeyValuePair < string , int > pair in registeredMessageHandlers )
@@ -117,6 +128,291 @@ private void OnDestroy()
117128 }
118129 }
119130
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+
120416 protected void SendToServer ( string messageType , string channelName , byte [ ] data )
121417 {
122418 if ( MessageManager . messageTypes [ messageType ] < 32 )
0 commit comments