static NetworkingService() { #if UNITY_EDITOR if (!EditorApplication.isPlaying) { return; } #endif settings = Resources.Load <NetworkingSettings>("NetworkingSettings"); matchmakingHandler = new MatchmakingHandler(); serialization = new SerializableTypes(); eventHandler = new MultiplayerEventHandler(serialization); clientHandler = new ClientHandler(); roomHandler = new RoomHandler(); callbackHandler = new CallbackHandler(clientHandler, roomHandler); resourceHandler = new ResourceHandler(settings, eventHandler); serialization.RegisterCustomTypesInternal(); PhotonNetwork.SerializationRate = settings.SerializationRate; PhotonNetwork.SendRate = settings.SendRate; PhotonNetwork.AutomaticallySyncScene = settings.SynchronizeClientScenes; PhotonNetwork.AddCallbackTarget(callbackHandler); PhotonNetwork.AddCallbackTarget(eventHandler); }
public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = "Default") { SerializableTypeInfo currentValue; // Check if declaring type is generics var resolvedType = dataType.Resolve(); if (resolvedType != null && resolvedType.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters)) { throw new NotSupportedException(String.Format("Serialization of nested types referencing parent's generic parameters is not currently supported. " + "[Nested type={0} Parent={1}]", resolvedType.FullName, resolvedType.DeclaringType)); } var profileInfo = GetSerializableTypes(profile); if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out currentValue)) { // TODO: Doesn't work in some generic case if (//currentValue.SerializerType.ConvertCSharp() != serializableTypeInfo.SerializerType.ConvertCSharp() || currentValue.Mode != serializableTypeInfo.Mode) { throw new InvalidOperationException(string.Format("Incompatible serializer found for same type in different assemblies for {0}", dataType.ConvertCSharp())); } return; } // Check that we don't simply try to add the same serializer than Default profile (optimized) SerializableTypeInfo defaultValue; if (profile != "Default" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out defaultValue)) { if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName) { // Already added in default profile, early exit return; } } profileInfo.AddSerializableTypeInfo(dataType, serializableTypeInfo); // Scan and add dependencies (stored in EnumerateGenericInstantiations() functions). if (serializableTypeInfo.Local && serializableTypeInfo.SerializerType != null) { var resolvedSerializerType = serializableTypeInfo.SerializerType.Resolve(); if (resolvedSerializerType != null) { var enumerateGenericInstantiationsMethod = resolvedSerializerType.Methods.FirstOrDefault(x => x.Name == "EnumerateGenericInstantiations"); if (enumerateGenericInstantiationsMethod != null) { // Detect all ldtoken (attributes would have been better, but unfortunately C# doesn't allow generics in attributes) foreach (var inst in enumerateGenericInstantiationsMethod.Body.Instructions) { if (inst.OpCode.Code == Code.Ldtoken) { var type = (TypeReference)inst.Operand; // Try to "close" generics type with serializer type as a context var dependentType = ResolveGenericsVisitor.Process(serializableTypeInfo.SerializerType, type); if (!dependentType.ContainsGenericParameter()) { // Import type so that it becomes local to the assembly // (otherwise SerializableTypeInfo.Local will be false and it won't be instantiated) var importedType = Assembly.MainModule.ImportReference(dependentType); if (GenerateSerializer(importedType) == null) { throw new InvalidOperationException(string.Format("Could not find serializer for generic dependent type {0} when processing {1}", dependentType, dataType)); } } } } } } } }