Skip to content

Commit a8ead8b

Browse files
committed
validate local schema during Handshake(). colyseus/schema#11
1 parent f22431b commit a8ead8b

File tree

7 files changed

+220
-60
lines changed

7 files changed

+220
-60
lines changed

Assets/ColyseusClient.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class ColyseusClient : MonoBehaviour {
2121
protected Client client;
2222
protected Room<State> room;
2323

24-
protected IndexedDictionary<Player, GameObject> players = new IndexedDictionary<Player, GameObject>();
24+
protected IndexedDictionary<Entity, GameObject> entities = new IndexedDictionary<Entity, GameObject>();
2525

2626
// Use this for initialization
2727
IEnumerator Start () {
@@ -85,9 +85,9 @@ void JoinRoom ()
8585
Debug.Log("Joined room successfully.");
8686
m_SessionIdText.text = "sessionId: " + room.SessionId;
8787

88-
room.State.players.OnAdd += OnPlayerAdd;
89-
room.State.players.OnRemove += OnPlayerRemove;
90-
room.State.players.OnChange += OnPlayerMove;
88+
room.State.entities.OnAdd += OnEntityAdd;
89+
room.State.entities.OnRemove += OnEntityRemove;
90+
room.State.entities.OnChange += OnEntityMove;
9191

9292
PlayerPrefs.SetString("sessionId", room.SessionId);
9393
PlayerPrefs.Save();
@@ -117,9 +117,9 @@ void ReJoinRoom ()
117117
Debug.Log("Joined room successfully.");
118118
m_SessionIdText.text = "sessionId: " + room.SessionId;
119119

120-
room.State.players.OnAdd += OnPlayerAdd;
121-
room.State.players.OnRemove += OnPlayerRemove;
122-
room.State.players.OnChange += OnPlayerMove;
120+
room.State.entities.OnAdd += OnEntityAdd;
121+
room.State.entities.OnRemove += OnEntityRemove;
122+
room.State.entities.OnChange += OnEntityMove;
123123
};
124124

125125
room.OnStateChange += OnStateChangeHandler;
@@ -131,12 +131,12 @@ void LeaveRoom()
131131
room.Leave(false);
132132

133133
// Destroy player entities
134-
foreach (KeyValuePair<Player, GameObject> entry in players)
134+
foreach (KeyValuePair<Entity, GameObject> entry in entities)
135135
{
136136
Destroy(entry.Value);
137137
}
138138

139-
players.Clear();
139+
entities.Clear();
140140
}
141141

142142
void SendMessage()
@@ -163,7 +163,7 @@ void OnStateChangeHandler (object sender, StateChangeEventArgs<State> e)
163163
Debug.Log("State has been updated!");
164164
}
165165

166-
void OnPlayerAdd(object sender, KeyValueEventArgs<Player, string> item)
166+
void OnEntityAdd(object sender, KeyValueEventArgs<Entity, string> item)
167167
{
168168
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
169169

@@ -172,23 +172,23 @@ void OnPlayerAdd(object sender, KeyValueEventArgs<Player, string> item)
172172
cube.transform.position = new Vector3(item.Value.x, item.Value.y, 0);
173173

174174
// add "player" to map of players
175-
players.Add(item.Value, cube);
175+
entities.Add(item.Value, cube);
176176
}
177177

178-
void OnPlayerRemove(object sender, KeyValueEventArgs<Player, string> item)
178+
void OnEntityRemove(object sender, KeyValueEventArgs<Entity, string> item)
179179
{
180180
GameObject cube;
181-
players.TryGetValue(item.Value, out cube);
181+
entities.TryGetValue(item.Value, out cube);
182182
Destroy(cube);
183183

184-
players.Remove(item.Value);
184+
entities.Remove(item.Value);
185185
}
186186

187187

188-
void OnPlayerMove (object sender, KeyValueEventArgs<Player, string> item)
188+
void OnEntityMove (object sender, KeyValueEventArgs<Entity, string> item)
189189
{
190190
GameObject cube;
191-
players.TryGetValue (item.Value, out cube);
191+
entities.TryGetValue (item.Value, out cube);
192192

193193
Debug.Log(item.Value.x);
194194

Assets/Player.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@
22
// THIS FILE HAS BEEN GENERATED AUTOMATICALLY
33
// DO NOT CHANGE IT MANUALLY UNLESS YOU KNOW WHAT YOU'RE DOING
44
//
5+
// GENERATED USING @colyseus/schema 0.4.25-alpha.0
6+
//
57

68
using Colyseus.Schema;
79

8-
public class Player : Schema {
9-
[Type("number")]
10-
public float x = 0;
11-
12-
[Type("number")]
13-
public float y = 0;
14-
15-
[Type("boolean")]
10+
public class Player : Entity {
11+
[Type(2, "boolean")]
1612
public bool connected = false;
1713
}
1814

Assets/Plugins/Colyseus/Serializer/Schema/Schema.cs

Lines changed: 98 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
using System.Collections.Specialized;
44
using System.Collections.Generic;
55
using System.Reflection;
6+
using System.Linq;
7+
8+
using UnityEngine;
69

710
/***
811
Allowed primitive types:
@@ -28,15 +31,39 @@
2831

2932
namespace Colyseus.Schema
3033
{
31-
[AttributeUsage(AttributeTargets.Field)]
32-
public class Type : Attribute
34+
class Context
3335
{
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+
}
3456

57+
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
58+
public class Type : Attribute
59+
{
60+
public int Index;
3561
public string FieldType;
3662
public System.Type ChildType;
3763

38-
public Type(string type, System.Type childType = null)
64+
public Type(int index, string type, System.Type childType = null)
3965
{
66+
Index = index; // GetType().GetFields() doesn't guarantee order of fields, need to manually track them here!
4067
FieldType = type;
4168
ChildType = childType;
4269
}
@@ -51,6 +78,7 @@ public enum SPEC: byte
5178
END_OF_STRUCTURE = 0xc1, // (msgpack spec: never used)
5279
NIL = 0xc0,
5380
INDEX_CHANGE = 0xd4,
81+
TYPE_ID = 0xd5
5482
}
5583

5684
public class DataChange
@@ -86,12 +114,13 @@ public interface ISchemaCollection
86114
void InvokeOnAdd(object item, object index);
87115
void InvokeOnChange(object item, object index);
88116
void InvokeOnRemove(object item, object index);
89-
90-
object CreateItemInstance();
117+
91118
object GetItems();
92119
void SetItems(object items);
93120
void TriggerAll();
94121

122+
System.Type GetChildType();
123+
95124
bool HasSchemaChild { get; }
96125
int Count { get; }
97126
object this[object key] { get; set; }
@@ -127,9 +156,9 @@ public ISchemaCollection Clone()
127156
return clone;
128157
}
129158

130-
public object CreateItemInstance()
159+
public System.Type GetChildType()
131160
{
132-
return (T) Activator.CreateInstance(typeof(T));
161+
return typeof(T);
133162
}
134163

135164
public bool HasSchemaChild
@@ -221,9 +250,9 @@ public ISchemaCollection Clone()
221250
return clone;
222251
}
223252

224-
public object CreateItemInstance()
253+
public System.Type GetChildType()
225254
{
226-
return (T) Activator.CreateInstance(typeof(T));
255+
return typeof(T);
227256
}
228257

229258
public bool HasSchemaChild
@@ -371,16 +400,14 @@ public class Schema
371400

372401
public Schema()
373402
{
374-
int index = 0;
375-
376403
FieldInfo[] fields = GetType().GetFields();
377404
foreach (FieldInfo field in fields)
378405
{
379406
object[] typeAttributes = field.GetCustomAttributes(typeof(Type), true);
380407
for (var i=0; i<typeAttributes.Length; i++)
381408
{
382409
Type t = (Type)typeAttributes[i];
383-
fieldsByIndex.Add(index++, field.Name);
410+
fieldsByIndex.Add(t.Index, field.Name);
384411
fieldTypes.Add(field.Name, t.FieldType);
385412
if (t.FieldType == "ref" || t.FieldType == "array" || t.FieldType == "map")
386413
{
@@ -411,6 +438,12 @@ public void Decode(byte[] bytes, Iterator it = null)
411438
var changes = new List<DataChange>();
412439
var totalBytes = bytes.Length;
413440

441+
// skip TYPE_ID of existing instances
442+
if (bytes[it.Offset] == (byte) SPEC.TYPE_ID)
443+
{
444+
it.Offset += 2;
445+
}
446+
414447
while (it.Offset < totalBytes)
415448
{
416449
var index = bytes[it.Offset++];
@@ -440,7 +473,7 @@ public void Decode(byte[] bytes, Iterator it = null)
440473
}
441474
else
442475
{
443-
value = this[field] ?? Activator.CreateInstance(childType);
476+
value = this[field] ?? CreateTypeInstance(bytes, it, childType);
444477
(value as Schema).Decode(bytes, it);
445478
}
446479

@@ -500,7 +533,7 @@ public void Decode(byte[] bytes, Iterator it = null)
500533

501534
if (isNew)
502535
{
503-
item = (Schema)currentValue.CreateItemInstance();
536+
item = (Schema)CreateTypeInstance(bytes, it, currentValue.GetChildType());
504537

505538
}
506539
else if (indexChangedFrom != -1)
@@ -514,7 +547,7 @@ public void Decode(byte[] bytes, Iterator it = null)
514547

515548
if (item == null)
516549
{
517-
item = (Schema)currentValue.CreateItemInstance();
550+
item = (Schema)CreateTypeInstance(bytes, it, currentValue.GetChildType());
518551
isNew = true;
519552
}
520553

@@ -592,7 +625,7 @@ public void Decode(byte[] bytes, Iterator it = null)
592625

593626
if (isNew && isSchemaType)
594627
{
595-
item = (Schema)currentValue.CreateItemInstance();
628+
item = (Schema)CreateTypeInstance(bytes, it, currentValue.GetChildType());
596629

597630
} else if (previousKey != null)
598631
{
@@ -686,5 +719,54 @@ public void TriggerAll()
686719

687720
OnChange.Invoke(this, new OnChangeEventArgs(changes));
688721
}
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>();
689761
}
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+
690772
}

0 commit comments

Comments
 (0)