Exemplo n.º 1
0
        /// <inheritdoc />
        public void Handshake(byte[] bytes, int offset)
        {
            System.Type targetType = typeof(T);

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

            ColyseusReflection reflection = new ColyseusReflection();
            Iterator           it         = new Iterator {
                Offset = offset
            };

            reflection.Decode(bytes, it);

            for (int i = 0; i < reflection.types.Count; i++)
            {
                System.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.");
                }

                ColyseusContext.GetInstance().SetTypeId(schemaType, reflection.types[i].id);
            }
        }
        /// <summary>
        ///     The function that will be called when the <see cref="colyseusConnection" /> receives a message
        /// </summary>
        /// <param name="bytes">The message as provided from the <see cref="colyseusConnection" /></param>
        protected async void ParseMessage(byte[] bytes)
        {
            byte code = bytes[0];

            if (code == ColyseusProtocol.JOIN_ROOM)
            {
                int offset = 1;

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

                if (SerializerId == "schema")
                {
                    try
                    {
                        serializer = new ColyseusSchemaSerializer <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")
                {
                    Debug.LogError(
                        "FossilDelta Serialization has been deprecated. It is highly recommended that you update your code to use the Schema Serializer. Otherwise, you must use an earlier version of the Colyseus plugin");
                }
                else
                {
                    try
                    {
                        serializer = (IColyseusSerializer <T>) new ColyseusNoneSerializer();
                    }
                    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 colyseusConnection.Send(new[] { ColyseusProtocol.JOIN_ROOM });
            }
            else if (code == ColyseusProtocol.ERROR)
            {
                Iterator it = new Iterator {
                    Offset = 1
                };
                float  errorCode    = Decode.DecodeNumber(bytes, it);
                string errorMessage = Decode.DecodeString(bytes, it);
                OnError?.Invoke((int)errorCode, errorMessage);
            }
            else if (code == ColyseusProtocol.ROOM_DATA_SCHEMA)
            {
                Iterator it = new Iterator {
                    Offset = 1
                };
                float typeId = Decode.DecodeNumber(bytes, it);

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

                message.Decode(bytes, it);

                IColyseusMessageHandler 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 == ColyseusProtocol.LEAVE_ROOM)
            {
                await Leave();
            }
            else if (code == ColyseusProtocol.ROOM_STATE)
            {
                Debug.Log("ROOM_STATE");
                SetState(bytes, 1);
            }
            else if (code == ColyseusProtocol.ROOM_STATE_PATCH)
            {
                Patch(bytes, 1);
            }
            else if (code == ColyseusProtocol.ROOM_DATA)
            {
                IColyseusMessageHandler handler = null;
                object type;

                Iterator it = new 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
                    //
                    object 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 + "'");
                }
            }
        }