예제 #1
0
        public void Handshake(byte[] bytes, int offset)
        {
            Type targetType = typeof(T);

            Type[] allTypes             = targetType.Assembly.GetTypes();
            Type[] namespaceSchemaTypes = Array.FindAll(allTypes, t => (
                                                            t.Namespace == targetType.Namespace &&
                                                            typeof(Schema.Schema).IsAssignableFrom(targetType)
                                                            ));

            Schema.Reflection reflection = new Schema.Reflection();
            Schema.Iterator   it         = new Schema.Iterator {
                Offset = offset
            };

            reflection.Decode(bytes, it);

            for (var i = 0; i < reflection.types.Count; i++)
            {
                Type schemaType = Array.Find(namespaceSchemaTypes, t => CompareTypes(t, reflection.types[i]));

                if (schemaType == null)
                {
                    throw new Exception("Local schema mismatch from server. Use \"schema-codegen\" to generate up-to-date local definitions.");
                }

                Schema.Context.GetInstance().SetTypeId(schemaType, reflection.types[i].id);
            }
        }
예제 #2
0
        protected async void ParseMessage(byte[] bytes)
        {
            byte code = bytes[0];

            if (code == Protocol.JOIN_ROOM)
            {
                var offset = 1;

                SerializerId = System.Text.Encoding.UTF8.GetString(bytes, offset + 1, bytes[offset]);
                offset      += SerializerId.Length + 1;

                if (SerializerId == "schema")
                {
                    try
                    {
                        serializer = new SchemaSerializer <T>();
                    }
                    catch (Exception e)
                    {
                        DisplaySerializerErrorHelp(e, "Consider using the \"schema-codegen\" and providing the same room state for matchmaking instead of \"" + typeof(T).Name + "\"");
                    }
                }
                else if (SerializerId == "fossil-delta")
                {
                    try
                    {
                        serializer = (ISerializer <T>) new FossilDeltaSerializer();
                    } catch (Exception e)
                    {
                        DisplaySerializerErrorHelp(e, "Consider using \"IndexedDictionary<string, object>\" instead of \"" + typeof(T).Name + "\" for matchmaking.");
                    }
                }
                else
                {
                    try
                    {
                        serializer = (ISerializer <T>) new NoneSerializer();
                    }
                    catch (Exception e)
                    {
                        DisplaySerializerErrorHelp(e, "Consider setting state in the server-side using \"this.setState(new " + typeof(T).Name + "())\"");
                    }
                }

                if (bytes.Length > offset)
                {
                    serializer.Handshake(bytes, offset);
                }

                OnJoin?.Invoke();

                // Acknowledge JOIN_ROOM
                await Connection.Send(new byte[] { Protocol.JOIN_ROOM });
            }
            else if (code == Protocol.ERROR)
            {
                Schema.Iterator it = new Schema.Iterator {
                    Offset = 1
                };
                var errorCode    = Decode.DecodeNumber(bytes, it);
                var errorMessage = Decode.DecodeString(bytes, it);
                OnError?.Invoke((int)errorCode, errorMessage);
            }
            else if (code == Protocol.ROOM_DATA_SCHEMA)
            {
                Schema.Iterator it = new Schema.Iterator {
                    Offset = 1
                };
                var typeId = Decode.DecodeNumber(bytes, it);

                Type messageType = Schema.Context.GetInstance().Get(typeId);
                var  message     = (Schema.Schema)Activator.CreateInstance(messageType);

                message.Decode(bytes, it);

                IMessageHandler handler = null;
                OnMessageHandlers.TryGetValue("s" + message.GetType(), out handler);

                if (handler != null)
                {
                    handler.Invoke(message);
                }
                else
                {
                    Debug.LogWarning("room.OnMessage not registered for Schema of type: '" + message.GetType() + "'");
                }
            }
            else if (code == Protocol.LEAVE_ROOM)
            {
                await Leave();
            }
            else if (code == Protocol.ROOM_STATE)
            {
                Debug.Log("ROOM_STATE");
                SetState(bytes, 1);
            }
            else if (code == Protocol.ROOM_STATE_PATCH)
            {
                Debug.Log("ROOM_STATE_PATCH");
                Patch(bytes, 1);
            }
            else if (code == Protocol.ROOM_DATA)
            {
                IMessageHandler handler = null;
                object          type;

                Schema.Iterator it = new Schema.Iterator {
                    Offset = 1
                };

                if (Decode.NumberCheck(bytes, it))
                {
                    type = Decode.DecodeNumber(bytes, it);
                    OnMessageHandlers.TryGetValue("i" + type, out handler);
                }
                else
                {
                    type = Decode.DecodeString(bytes, it);
                    OnMessageHandlers.TryGetValue(type.ToString(), out handler);
                }

                if (handler != null)
                {
                    //
                    // MsgPack deserialization can be optimized:
                    // https://github.com/deniszykov/msgpack-unity3d/issues/23
                    //
                    var message = (bytes.Length > it.Offset)
                                                ? MsgPack.Deserialize(handler.Type, new MemoryStream(bytes, it.Offset, bytes.Length - it.Offset, false))
                                                : null;

                    handler.Invoke(message);
                }
                else
                {
                    Debug.LogWarning("room.OnMessage not registered for: '" + type + "'");
                }
            }
        }
        protected async void ParseMessage(byte[] bytes)
        {
            byte code = bytes[0];

            Debug.Log("BYTE =>" + code);

            if (code == Protocol.JOIN_ROOM)
            {
                var offset = 1;

                SerializerId = System.Text.Encoding.UTF8.GetString(bytes, offset + 1, bytes[offset]);
                offset      += SerializerId.Length + 1;

                if (SerializerId == "schema")
                {
                    serializer = new SchemaSerializer <T>();
                }
                else if (SerializerId == "fossil-delta")
                {
                    serializer = (ISerializer <T>) new FossilDeltaSerializer();
                }

                if (bytes.Length > offset)
                {
                    serializer.Handshake(bytes, offset);
                }

                OnJoin?.Invoke();

                // Acknowledge JOIN_ROOM
                await Connection.Send(new byte[] { Protocol.JOIN_ROOM });
            }
            else if (code == Protocol.ERROR)
            {
                Schema.Iterator it = new Schema.Iterator {
                    Offset = 1
                };
                var errorCode    = Decode.DecodeNumber(bytes, it);
                var errorMessage = Decode.DecodeString(bytes, it);
                OnError?.Invoke((int)errorCode, errorMessage);
            }
            else if (code == Protocol.ROOM_DATA_SCHEMA)
            {
                Type messageType = Schema.Context.GetInstance().Get(bytes[1]);

                var message = (Schema.Schema)Activator.CreateInstance(messageType);
                message.Decode(bytes, new Schema.Iterator {
                    Offset = 2
                });

                IMessageHandler handler = null;
                OnMessageHandlers.TryGetValue("s" + message.GetType(), out handler);

                if (handler != null)
                {
                    handler.Invoke(message);
                }
                else
                {
                    Debug.LogError("room.OnMessage not registered for Schema message: " + message.GetType());
                }
            }
            else if (code == Protocol.LEAVE_ROOM)
            {
                await Leave();
            }
            else if (code == Protocol.ROOM_STATE)
            {
                Debug.Log("ROOM_STATE");
                SetState(bytes, 1);
            }
            else if (code == Protocol.ROOM_STATE_PATCH)
            {
                Debug.Log("ROOM_STATE_PATCH");
                Patch(bytes, 1);
            }
            else if (code == Protocol.ROOM_DATA)
            {
                IMessageHandler handler = null;
                object          type;

                Schema.Iterator it = new Schema.Iterator {
                    Offset = 1
                };

                if (Decode.NumberCheck(bytes, it))
                {
                    type = Decode.DecodeNumber(bytes, it);
                    OnMessageHandlers.TryGetValue("i" + type, out handler);
                }
                else
                {
                    type = Decode.DecodeString(bytes, it);
                    OnMessageHandlers.TryGetValue(type.ToString(), out handler);
                }

                if (handler != null)
                {
                    //
                    // MsgPack deserialization can be optimized:
                    // https://github.com/deniszykov/msgpack-unity3d/issues/23
                    //
                    var message = (bytes.Length > it.Offset)
                                                ? MsgPack.Deserialize(handler.Type, new MemoryStream(bytes, it.Offset, bytes.Length - it.Offset, false))
                                                : null;

                    handler.Invoke(message);
                }
                else
                {
                    Debug.LogError("room.OnMessage not registered for: " + type);
                }
            }
        }
예제 #4
0
        public bool NumberCheck(byte[] bytes, Iterator it)
        {
            byte prefix = bytes[it.Offset];

            return(prefix < 0x80 || (prefix >= 0xca && prefix <= 0xd3));
        }
예제 #5
0
        public object DecodeNumber(byte[] bytes, Iterator it)
        {
            byte prefix = bytes[it.Offset++];

            if (prefix < 0x80)
            {
                // positive fixint
                return(prefix);
            }
            else if (prefix == 0xca)
            {
                // float 32
                return(DecodeFloat32(bytes, it));
            }
            else if (prefix == 0xcb)
            {
                // float 64
                return(DecodeFloat64(bytes, it));
            }
            else if (prefix == 0xcc)
            {
                // uint 8
                return(DecodeUint8(bytes, it));
            }
            else if (prefix == 0xcd)
            {
                // uint 16
                return(DecodeUint16(bytes, it));
            }
            else if (prefix == 0xce)
            {
                // uint 32
                return(DecodeUint32(bytes, it));
            }
            else if (prefix == 0xcf)
            {
                // uint 64
                return(DecodeUint64(bytes, it));
            }
            else if (prefix == 0xd0)
            {
                // int 8
                return(DecodeInt8(bytes, it));
            }
            else if (prefix == 0xd1)
            {
                // int 16
                return(DecodeInt16(bytes, it));
            }
            else if (prefix == 0xd2)
            {
                // int 32
                return(DecodeInt32(bytes, it));
            }
            else if (prefix == 0xd3)
            {
                // int 64
                return(DecodeInt64(bytes, it));
            }
            else if (prefix > 0xdf)
            {
                // negative fixint
                return((0xff - prefix + 1) * -1);
            }

            return(double.NaN);
        }
예제 #6
0
 public bool IndexChangeCheck(byte[] bytes, Iterator it)
 {
     return(bytes[it.Offset] == (byte)SPEC.INDEX_CHANGE);
 }
예제 #7
0
 /*
  * Bool checks
  */
 public bool NilCheck(byte[] bytes, Iterator it)
 {
     return(bytes[it.Offset] == (byte)SPEC.NIL);
 }
예제 #8
0
 public bool DecodeBoolean(byte[] bytes, Iterator it)
 {
     return(DecodeUint8(bytes, it) > 0);
 }
예제 #9
0
 public uint DecodeUint8(byte[] bytes, Iterator it)
 {
     return(bytes[it.Offset++]);
 }
예제 #10
0
 public int DecodeInt8(byte[] bytes, Iterator it)
 {
     return(((int)DecodeUint8(bytes, it)) << 24 >> 24);
 }