/// <summary> /// Register serialization & deserialization mechanisms for transmitting the given class by ID. /// The given class does not need to implements its own serialization logic. /// </summary> public static void RegisterSerializerAndDeserializer(Type type) { int id = NetworkableId <Type> .ToId(type); Debug.Log("Using id " + id + " for tagging of class " + type.Name + " in network messages when sending/receiving NetworkableById types"); // Construct SerializerAndDeserializer<type> Type serializerAndDeserializerType = typeof(SerializerAndDeserializer <>); Type serializerAndDeserializerTypeSpecialized = serializerAndDeserializerType.MakeGenericType(type); // Find a method Serialize(StreamBuffer, object) in SerializerAndDeserializer<type> MethodInfo serializeMethodInfo = serializerAndDeserializerTypeSpecialized.GetMethod("Serialize", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, new Type[] { typeof(StreamBuffer), typeof(object) }, null); Assert.IsNotNull(serializeMethodInfo, "Unable to find virtual Serialize(StreamBuffer, object) method in " + serializerAndDeserializerTypeSpecialized.Name); SerializeStreamMethod serializer = (SerializeStreamMethod)Delegate.CreateDelegate(typeof(SerializeStreamMethod), serializeMethodInfo); // Find a method Deserialize(StreamBuffer, short) in SerializerAndDeserializer<type> MethodInfo deserializeMethodInfo = serializerAndDeserializerTypeSpecialized.GetMethod("Deserialize", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, new Type[] { typeof(StreamBuffer), typeof(short) }, null); Assert.IsNotNull(serializeMethodInfo, "Unable to find static Deserialize(StreamBuffer, short) method in " + serializerAndDeserializerTypeSpecialized.Name); DeserializeStreamMethod deserializer = (DeserializeStreamMethod)Delegate.CreateDelegate(typeof(DeserializeStreamMethod), deserializeMethodInfo); // Register serializer and deserializer methods for class bool success = PhotonPeer.RegisterType(type, (byte)id, serializer, deserializer); Assert.IsTrue(success, "Failed registering new serialization type for " + type.Name + " with code " + id); }
public void TearDown() { // Unregister Photon serializer/deserializer callbacks for the types PhotonRegisterSerializers registerSerializers = new PhotonRegisterSerializers(); registerSerializers.DeregisterSerializer(typeof(NullMembers)); registerSerializers.DeregisterSerializer(typeof(ConcreteChildById)); registerSerializers.DeregisterSerializer(typeof(AbstractBaseById)); registerSerializers.DeregisterSerializer(typeof(ConcreteChildByValue)); registerSerializers.DeregisterSerializer(typeof(AbstractBaseByValue)); // Deregister types & destroy type registries NetworkableId <Type> .Remove(typeof(NullMembers)); NetworkableId <Type> .Remove(typeof(AbstractBaseById)); NetworkableId <Type> .Remove(typeof(ConcreteChildById)); NetworkableId <AbstractBaseById> .Destroy(); NetworkableId <ConcreteChildById> .Destroy(); NetworkableIdRegistry.DestroyRootRegistry(typeof(AbstractBaseById)); NetworkableId <Type> .Remove(typeof(AbstractBaseByValue)); NetworkableId <Type> .Remove(typeof(ConcreteChildByValue)); NetworkableId <Type> .Destroy(); NetworkableIdRegistry.DestroyRootRegistry(typeof(Type)); }
public void DeregisterSerializer(Type type) { // Photon 1.80 lacks a Photon.DeregisterType() function. This undoes the actions of Photon.RegisterType() as implemented in Photon 1.80. byte typeId = (byte)NetworkableId <Type> .ToId(type); // Invoke Protocol.CodeDict.Remove(typeId) FieldInfo codeDictField = typeof(Protocol).GetField("CodeDict", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); Assert.IsNotNull(codeDictField, "Photon internals have changed; Protocol.CodeDict no longer exists"); object codeDict = codeDictField.GetValue(null); Assert.IsNotNull(codeDict, "Photon internals have changed; Protocol.CodeDict no longer exists"); MethodInfo codeDictRemoveMethodInfo = codeDict.GetType().GetMethod("Remove"); Assert.IsNotNull(codeDictRemoveMethodInfo, "Photon internals have changed; Protocol.CodeDict is no longer a Dictionary"); codeDictRemoveMethodInfo.Invoke(codeDict, new object[] { (byte)typeId }); // Invoke Protocol.TypeDict.Remove(typeId) FieldInfo typeDictField = typeof(Protocol).GetField("TypeDict", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); Assert.IsNotNull(typeDictField, "Photon internals have changed; Protocol.TypeDict no longer exists"); object typeDict = typeDictField.GetValue(null); Assert.IsNotNull(typeDict, "Photon internals have changed; Protocol.TypeDict no longer exists"); MethodInfo typeDictRemoveMethodInfo = typeDict.GetType().GetMethod("Remove"); Assert.IsNotNull(typeDictRemoveMethodInfo, "Photon internals have changed; Protocol.TypeDict is no longer a Dictionary"); typeDictRemoveMethodInfo.Invoke(typeDict, new object[] { type }); }
public void SetUp() { NetworkableId <Type> .Create(null); // Assign IDs for all networkable types NetworkableId <Type> .AddWithId(typeof(AbstractBaseByValue), 128); NetworkableId <Type> .AddWithId(typeof(ConcreteChildByValue), 129); NetworkableId <Type> .AddWithId(typeof(AbstractBaseById), 130); NetworkableId <Type> .AddWithId(typeof(ConcreteChildById), 131); NetworkableId <Type> .AddWithId(typeof(NullMembers), 132); // Items that get networked by ID need to have an ID hierarchy setup NetworkableId <AbstractBaseById> .Create(null); NetworkableId <ConcreteChildById> .Create(typeof(AbstractBaseById)); // Register Photon serializer/deserializer callbacks for the types PhotonRegisterSerializers registerSerializers = new PhotonRegisterSerializers(); registerSerializers.RegisterSerializersForDefaultObjectType(typeof(AbstractBaseByValue)); registerSerializers.RegisterSerializersForValueType(typeof(ConcreteChildByValue)); registerSerializers.RegisterSerializersForDefaultObjectType(typeof(AbstractBaseById)); registerSerializers.RegisterSerializersForIdType(typeof(ConcreteChildById)); registerSerializers.RegisterSerializersForValueType(typeof(NullMembers)); }
/// <summary> /// Register serialization & deserialization mechanisms for transmitting an abstract base class by value. /// The given class does not need to implements its own serialization logic. /// </summary> public static void RegisterSerializerAndDeserializer(Type type) { int id = NetworkableId <Type> .ToId(type); Debug.Log("Using id " + id + " for tagging of class " + type.Name + " in network messages when sending/receiving NetworkableByValue types"); bool success = PhotonPeer.RegisterType(type, (byte)id, SerializerAndDeserializer.Serialize, SerializerAndDeserializer.Deserialize); Assert.IsTrue(success, "Failed registering new serialization type for " + type.Name + " with code " + id); }
public static short Serialize(StreamBuffer outBuffer, object customObject) { int length = 0; T obj = (T)customObject; int id = NetworkableId <T> .ToId(obj); Protocol.Serialize(id, serializationBuffer, ref length); outBuffer.Write(serializationBuffer, 0, length); Debug.Log("Serializing object of type " + typeof(T).Name + " with id " + id); return((short)length); }
public static object Deserialize(StreamBuffer inBuffer, short length) { inBuffer.Read(deserializationBuffer, 0, deserializationBuffer.Length); int offset = 0; int id; Protocol.Deserialize(out id, deserializationBuffer, ref offset); Debug.Log("Deserializing object of type " + typeof(T).Name + " with id " + id); T obj = NetworkableId <T> .FromId(id); return(obj); }
public void TestSerializationByIdBaseType() { ConcreteChildById concreteObj = new ConcreteChildById(12345678, 87654321); NetworkableId <ConcreteChildById> .Add(concreteObj); byte[] buffer = Protocol.Serialize((AbstractBaseById)concreteObj); ConcreteChildById concreteObj2 = (ConcreteChildById)Protocol.Deserialize(buffer); Assert.That(concreteObj2, Is.EqualTo(concreteObj)); NetworkableId <ConcreteChildById> .Remove(concreteObj); }
static void RegisterNetworkableId(Type type, int id) { NetworkableId <Type> .AddWithId(type, id); }
public static void Initialize(NetworkableSettings networkableSettings, RegisterSerializers registerSerializers) { Assembly currAssembly = Assembly.GetExecutingAssembly(); Dictionary <Type, Type> typeToRoot = new Dictionary <Type, Type>(); List <Type> networkable = new List <Type>(); List <Type> roots = new List <Type>(); List <Type> children = new List <Type>(); List <Type> needsDefaultObjectSerializers = new List <Type>(); List <Type> needsReferenceSerializers = new List <Type>(); List <Type> needsValueSerializers = new List <Type>(); List <Type> loadResourcesAndInitializeIds = new List <Type>(); foreach (Type type in currAssembly.GetTypes()) { object[] attributesWithInheritance = type.GetCustomAttributes(true); bool isNetworkableById = Array.Exists <object>(attributesWithInheritance, attribute => attribute is NetworkableById); bool isNetworkableByValue = Array.Exists <object>(attributesWithInheritance, attribute => attribute is NetworkableByValue); bool isNetworkable = (isNetworkableById || isNetworkableByValue); Assert.IsFalse(isNetworkableById && isNetworkableByValue, "Class " + type.FullName + " is tagged both as NetworkableByValue and NetworkableById. This is not supported."); object[] baseAttributesWithInheritance = (type.BaseType != null ? type.BaseType.GetCustomAttributes(true) : new object[0]); bool isBaseNetworkableById = Array.Exists <object>(baseAttributesWithInheritance, attribute => attribute is NetworkableById); bool isBaseNetworkableByValue = Array.Exists <object>(baseAttributesWithInheritance, attribute => attribute is NetworkableByValue); bool isBaseNetworkable = (isBaseNetworkableById || isBaseNetworkableByValue); bool isNetworkableRoot = (isNetworkable && !isBaseNetworkable); if (isNetworkable) { networkable.Add(type); if (isNetworkableRoot) { roots.Add(type); } else { children.Add(type); } if (isNetworkableByValue && !type.IsAbstract) { needsValueSerializers.Add(type); } else if (isNetworkableById) { needsReferenceSerializers.Add(type); } else { needsDefaultObjectSerializers.Add(type); } if (isNetworkableById && isNetworkableRoot) { loadResourcesAndInitializeIds.Add(type); } } } foreach (Type type in networkable) { Type root = type; while (!roots.Exists(rootEntry => rootEntry == root)) { root = root.BaseType; } typeToRoot[type] = root; } NetworkableId <Type> .Create(null); Debug.Log("========= register networkable classes ====="); RegisterNetworkableTypes(networkable, networkableSettings.PersistentTypeIds); Debug.Log("========= setup NetworkableId registries for root classes ====="); foreach (Type root in roots) { RegisterNetworkableIdHierarchy(root, null); } Debug.Log("========= set Networkableid registries for child classes ====="); foreach (Type child in children) { RegisterNetworkableIdHierarchy(child, typeToRoot[child]); } Debug.Log("========= register byValue serializers ====="); foreach (Type type in needsValueSerializers) { registerSerializers.RegisterSerializersForValueType(type); } Debug.Log("========= register byId serializers ====="); foreach (Type type in needsReferenceSerializers) { registerSerializers.RegisterSerializersForIdType(type); } Debug.Log("========= register default-object serializers ====="); foreach (Type type in needsDefaultObjectSerializers) { registerSerializers.RegisterSerializersForDefaultObjectType(type); } Debug.Log("========= register assets that are by-id and present in asset database ====="); RegisterNetworkableAssets(networkableSettings.PersistentAssetIds); }