3
3
using System . Collections . Specialized ;
4
4
using System . Collections . Generic ;
5
5
using System . Reflection ;
6
+ using System . Linq ;
7
+
8
+ using UnityEngine ;
6
9
7
10
/***
8
11
Allowed primitive types:
28
31
29
32
namespace Colyseus . Schema
30
33
{
31
- [ AttributeUsage ( AttributeTargets . Field ) ]
32
- public class Type : Attribute
34
+ class Context
33
35
{
36
+ protected static Context instance = new Context ( ) ;
37
+ protected List < System . Type > types = new List < System . Type > ( ) ;
38
+ protected Dictionary < uint , System . Type > typeIds = new Dictionary < uint , System . Type > ( ) ;
39
+
40
+ public static Context GetInstance ( )
41
+ {
42
+ return instance ;
43
+ }
44
+
45
+ public void SetTypeId ( System . Type type , uint typeid )
46
+ {
47
+ Debug . Log ( ">>>>>>> SET TYPE ID: " + typeid + ", Type => " + type . Name ) ;
48
+ typeIds [ typeid ] = type ;
49
+ }
50
+
51
+ public System . Type Get ( uint typeid )
52
+ {
53
+ return typeIds [ typeid ] ;
54
+ }
55
+ }
34
56
57
+ [ AttributeUsage ( AttributeTargets . Field , AllowMultiple = false ) ]
58
+ public class Type : Attribute
59
+ {
60
+ public int Index ;
35
61
public string FieldType ;
36
62
public System . Type ChildType ;
37
63
38
- public Type ( string type , System . Type childType = null )
64
+ public Type ( int index , string type , System . Type childType = null )
39
65
{
66
+ Index = index ; // GetType().GetFields() doesn't guarantee order of fields, need to manually track them here!
40
67
FieldType = type ;
41
68
ChildType = childType ;
42
69
}
@@ -51,6 +78,7 @@ public enum SPEC: byte
51
78
END_OF_STRUCTURE = 0xc1 , // (msgpack spec: never used)
52
79
NIL = 0xc0 ,
53
80
INDEX_CHANGE = 0xd4 ,
81
+ TYPE_ID = 0xd5
54
82
}
55
83
56
84
public class DataChange
@@ -86,12 +114,13 @@ public interface ISchemaCollection
86
114
void InvokeOnAdd ( object item , object index ) ;
87
115
void InvokeOnChange ( object item , object index ) ;
88
116
void InvokeOnRemove ( object item , object index ) ;
89
-
90
- object CreateItemInstance ( ) ;
117
+
91
118
object GetItems ( ) ;
92
119
void SetItems ( object items ) ;
93
120
void TriggerAll ( ) ;
94
121
122
+ System . Type GetChildType ( ) ;
123
+
95
124
bool HasSchemaChild { get ; }
96
125
int Count { get ; }
97
126
object this [ object key ] { get ; set ; }
@@ -127,9 +156,9 @@ public ISchemaCollection Clone()
127
156
return clone ;
128
157
}
129
158
130
- public object CreateItemInstance ( )
159
+ public System . Type GetChildType ( )
131
160
{
132
- return ( T ) Activator . CreateInstance ( typeof ( T ) ) ;
161
+ return typeof ( T ) ;
133
162
}
134
163
135
164
public bool HasSchemaChild
@@ -221,9 +250,9 @@ public ISchemaCollection Clone()
221
250
return clone ;
222
251
}
223
252
224
- public object CreateItemInstance ( )
253
+ public System . Type GetChildType ( )
225
254
{
226
- return ( T ) Activator . CreateInstance ( typeof ( T ) ) ;
255
+ return typeof ( T ) ;
227
256
}
228
257
229
258
public bool HasSchemaChild
@@ -371,16 +400,14 @@ public class Schema
371
400
372
401
public Schema ( )
373
402
{
374
- int index = 0 ;
375
-
376
403
FieldInfo [ ] fields = GetType ( ) . GetFields ( ) ;
377
404
foreach ( FieldInfo field in fields )
378
405
{
379
406
object [ ] typeAttributes = field . GetCustomAttributes ( typeof ( Type ) , true ) ;
380
407
for ( var i = 0 ; i < typeAttributes . Length ; i ++ )
381
408
{
382
409
Type t = ( Type ) typeAttributes [ i ] ;
383
- fieldsByIndex . Add ( index ++ , field . Name ) ;
410
+ fieldsByIndex . Add ( t . Index , field . Name ) ;
384
411
fieldTypes . Add ( field . Name , t . FieldType ) ;
385
412
if ( t . FieldType == "ref" || t . FieldType == "array" || t . FieldType == "map" )
386
413
{
@@ -411,6 +438,12 @@ public void Decode(byte[] bytes, Iterator it = null)
411
438
var changes = new List < DataChange > ( ) ;
412
439
var totalBytes = bytes . Length ;
413
440
441
+ // skip TYPE_ID of existing instances
442
+ if ( bytes [ it . Offset ] == ( byte ) SPEC . TYPE_ID )
443
+ {
444
+ it . Offset += 2 ;
445
+ }
446
+
414
447
while ( it . Offset < totalBytes )
415
448
{
416
449
var index = bytes [ it . Offset ++ ] ;
@@ -440,7 +473,7 @@ public void Decode(byte[] bytes, Iterator it = null)
440
473
}
441
474
else
442
475
{
443
- value = this [ field ] ?? Activator . CreateInstance ( childType ) ;
476
+ value = this [ field ] ?? CreateTypeInstance ( bytes , it , childType ) ;
444
477
( value as Schema ) . Decode ( bytes , it ) ;
445
478
}
446
479
@@ -500,7 +533,7 @@ public void Decode(byte[] bytes, Iterator it = null)
500
533
501
534
if ( isNew )
502
535
{
503
- item = ( Schema ) currentValue . CreateItemInstance ( ) ;
536
+ item = ( Schema ) CreateTypeInstance ( bytes , it , currentValue . GetChildType ( ) ) ;
504
537
505
538
}
506
539
else if ( indexChangedFrom != - 1 )
@@ -514,7 +547,7 @@ public void Decode(byte[] bytes, Iterator it = null)
514
547
515
548
if ( item == null )
516
549
{
517
- item = ( Schema ) currentValue . CreateItemInstance ( ) ;
550
+ item = ( Schema ) CreateTypeInstance ( bytes , it , currentValue . GetChildType ( ) ) ;
518
551
isNew = true ;
519
552
}
520
553
@@ -592,7 +625,7 @@ public void Decode(byte[] bytes, Iterator it = null)
592
625
593
626
if ( isNew && isSchemaType )
594
627
{
595
- item = ( Schema ) currentValue . CreateItemInstance ( ) ;
628
+ item = ( Schema ) CreateTypeInstance ( bytes , it , currentValue . GetChildType ( ) ) ;
596
629
597
630
} else if ( previousKey != null )
598
631
{
@@ -686,5 +719,54 @@ public void TriggerAll()
686
719
687
720
OnChange . Invoke ( this , new OnChangeEventArgs ( changes ) ) ;
688
721
}
722
+
723
+ protected object CreateTypeInstance ( byte [ ] bytes , Iterator it , System . Type type )
724
+ {
725
+ if ( bytes [ it . Offset ] == ( byte ) SPEC . TYPE_ID )
726
+ {
727
+ it . Offset ++ ;
728
+ uint typeId = Decoder . GetInstance ( ) . DecodeUint8 ( bytes , it ) ;
729
+ System . Type anotherType = Context . GetInstance ( ) . Get ( typeId ) ;
730
+ Debug . Log ( "CreateTypeInstance: (inherited) " + anotherType . Name ) ;
731
+ return Activator . CreateInstance ( anotherType ) ;
732
+
733
+ }
734
+ else
735
+ {
736
+ Debug . Log ( "CreateTypeInstance: (default) " + type . Name ) ;
737
+ return Activator . CreateInstance ( type ) ;
738
+ }
739
+ }
740
+ }
741
+
742
+ public class ReflectionField : Schema
743
+ {
744
+ [ Type ( 0 , "string" ) ]
745
+ public string name ;
746
+
747
+ [ Type ( 1 , "string" ) ]
748
+ public string type ;
749
+
750
+ [ Type ( 2 , "uint8" ) ]
751
+ public uint referencedType ;
752
+ }
753
+
754
+ public class ReflectionType : Schema
755
+ {
756
+ [ Type ( 0 , "uint8" ) ]
757
+ public uint id ;
758
+
759
+ [ Type ( 1 , "array" , typeof ( ArraySchema < ReflectionField > ) ) ]
760
+ public ArraySchema < ReflectionField > fields = new ArraySchema < ReflectionField > ( ) ;
689
761
}
762
+
763
+ public class Reflection : Schema
764
+ {
765
+ [ Type ( 0 , "array" , typeof ( ArraySchema < ReflectionType > ) ) ]
766
+ public ArraySchema < ReflectionType > types = new ArraySchema < ReflectionType > ( ) ;
767
+
768
+ [ Type ( 1 , "uint8" ) ]
769
+ public uint rootType ;
770
+ }
771
+
690
772
}
0 commit comments