// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. using System; using System.Runtime.InteropServices; using System.Collections.Generic; namespace FlaxEngine.Networking { partial class NetworkReplicator { private static Dictionary> _managedSerializers; #if FLAX_EDITOR private static void OnScriptsReloadBegin() { // Clear refs to managed types that will be hot-reloaded _managedSerializers.Clear(); _managedSerializers = null; FlaxEditor.ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin; } #endif /// /// Network object replication serialization/deserialization delegate. /// /// /// Use Object.FromUnmanagedPtr(instancePtr/streamPtr) to get object or NetworkStream from raw native pointers. /// /// var instance = Object.FromUnmanagedPtr(instancePtr) /// var stream = (NetworkStream)Object.FromUnmanagedPtr(streamPtr) public delegate void SerializeFunc(IntPtr instancePtr, IntPtr streamPtr); /// /// Registers a new serialization methods for a given C# type. /// /// /// Use Object.FromUnmanagedPtr(instancePtr/streamPtr) to get object or NetworkStream from raw native pointers. /// /// The C# type (class or structure). /// Function to call for value serialization. /// Function to call for value deserialization. [Unmanaged] public static void AddSerializer(Type type, SerializeFunc serialize, SerializeFunc deserialize) { // C#-only types (eg. custom C# structures) cannot use native serializers due to missing ScriptingType if (typeof(FlaxEngine.Object).IsAssignableFrom(type)) { Internal_AddSerializer(type, Marshal.GetFunctionPointerForDelegate(serialize), Marshal.GetFunctionPointerForDelegate(deserialize)); } else { if (_managedSerializers == null) { _managedSerializers = new Dictionary>(); #if FLAX_EDITOR FlaxEditor.ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin; #endif } _managedSerializers[type] = new KeyValuePair(serialize, deserialize); } } /// /// Invokes the network replication serializer for a given type. /// /// The scripting type to serialize. /// The value instance to serialize. /// The input/output stream to use for serialization. /// True if serialize, otherwise deserialize mode. /// True if failed, otherwise false. [Unmanaged] public static bool InvokeSerializer(Type type, FlaxEngine.Object instance, NetworkStream stream, bool serialize) { return Internal_InvokeSerializer(type, FlaxEngine.Object.GetUnmanagedPtr(instance), FlaxEngine.Object.GetUnmanagedPtr(stream), serialize); } /// /// Invokes the network replication serializer for a given type. /// /// The scripting type to serialize. /// The value instance to serialize. /// The input/output stream to use for serialization. /// True if serialize, otherwise deserialize mode. /// True if failed, otherwise false. [Unmanaged] public static bool InvokeSerializer(System.Type type, IntPtr instance, NetworkStream stream, bool serialize) { if (_managedSerializers != null && _managedSerializers.TryGetValue(type, out var e)) { var serializer = serialize ? e.Key : e.Value; serializer(instance, FlaxEngine.Object.GetUnmanagedPtr(stream)); return false; } return Internal_InvokeSerializer(type, instance, FlaxEngine.Object.GetUnmanagedPtr(stream), serialize); } } }