Merge branch 'GoaLitiuM-fix_network_rpc' into 1.6

This commit is contained in:
Wojtek Figat
2023-03-14 11:50:26 +01:00
3 changed files with 43 additions and 13 deletions

View File

@@ -9,14 +9,23 @@ namespace FlaxEngine.Networking
partial class NetworkReplicator partial class NetworkReplicator
{ {
private static Dictionary<Type, KeyValuePair<SerializeFunc, SerializeFunc>> _managedSerializers; private static Dictionary<Type, KeyValuePair<SerializeFunc, SerializeFunc>> _managedSerializers;
private static List<ExecuteRPCFunc> _managedExecuteRpcFuncs;
#if FLAX_EDITOR #if FLAX_EDITOR
private static void OnScriptsReloadBegin() private static void ClearManagedReferences()
{ {
// Clear refs to managed types that will be hot-reloaded // Clear refs to managed types that will be hot-reloaded
_managedSerializers.Clear(); if (_managedSerializers != null)
_managedSerializers = null; {
FlaxEditor.ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin; _managedSerializers.Clear();
_managedSerializers = null;
}
if (_managedExecuteRpcFuncs != null)
{
_managedExecuteRpcFuncs.Clear();
_managedExecuteRpcFuncs = null;
}
FlaxEditor.ScriptsBuilder.ScriptsReloadBegin -= ClearManagedReferences;
} }
#endif #endif
@@ -55,8 +64,9 @@ namespace FlaxEngine.Networking
if (_managedSerializers == null) if (_managedSerializers == null)
{ {
_managedSerializers = new Dictionary<Type, KeyValuePair<SerializeFunc, SerializeFunc>>(); _managedSerializers = new Dictionary<Type, KeyValuePair<SerializeFunc, SerializeFunc>>();
_managedExecuteRpcFuncs = new List<ExecuteRPCFunc>();
#if FLAX_EDITOR #if FLAX_EDITOR
FlaxEditor.ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin; FlaxEditor.ScriptsBuilder.ScriptsReloadBegin += ClearManagedReferences;
#endif #endif
} }
_managedSerializers[type] = new KeyValuePair<SerializeFunc, SerializeFunc>(serialize, deserialize); _managedSerializers[type] = new KeyValuePair<SerializeFunc, SerializeFunc>(serialize, deserialize);
@@ -125,10 +135,22 @@ namespace FlaxEngine.Networking
/// <param name="isClient">Client RPC.</param> /// <param name="isClient">Client RPC.</param>
/// <param name="channel">Network channel to use for RPC transport.</param> /// <param name="channel">Network channel to use for RPC transport.</param>
[Unmanaged] [Unmanaged]
public static void AddRPC(Type type, string name, ExecuteRPCFunc execute, bool isServer = true, bool isClient = false, NetworkChannelType channel = NetworkChannelType.ReliableOrdered) public static unsafe void AddRPC(Type type, string name, ExecuteRPCFunc execute, bool isServer = true, bool isClient = false, NetworkChannelType channel = NetworkChannelType.ReliableOrdered)
{ {
if (!typeof(FlaxEngine.Object).IsAssignableFrom(type)) if (!typeof(FlaxEngine.Object).IsAssignableFrom(type))
throw new ArgumentException("Not supported type for RPC. Only FlaxEngine.Object types are valid."); throw new ArgumentException("Not supported type for RPC. Only FlaxEngine.Object types are valid.");
if (_managedExecuteRpcFuncs == null)
{
_managedSerializers = new Dictionary<Type, KeyValuePair<SerializeFunc, SerializeFunc>>();
_managedExecuteRpcFuncs = new List<ExecuteRPCFunc>();
#if FLAX_EDITOR
FlaxEditor.ScriptsBuilder.ScriptsReloadBegin += ClearManagedReferences;
#endif
}
// Store the reference to prevent garbage collection
_managedExecuteRpcFuncs.Add(execute);
Internal_AddRPC(type, name, Marshal.GetFunctionPointerForDelegate(execute), isServer, isClient, channel); Internal_AddRPC(type, name, Marshal.GetFunctionPointerForDelegate(execute), isServer, isClient, channel);
} }
} }

View File

@@ -983,7 +983,15 @@ void ManagedBinaryModule::OnLoaded(MAssembly* assembly)
{ {
if (method->GetParametersCount() == 0) if (method->GetParametersCount() == 0)
{ {
method->Invoke(nullptr, nullptr, nullptr); MObject* exception = nullptr;
method->Invoke(nullptr, nullptr, &exception);
if (exception)
{
MException ex(exception);
String methodName = String(method->GetName());
ex.Log(LogType::Error, methodName.Get());
LOG(Error, "Failed to call module initializer for class {0} from assembly {1}.", String(mclass->GetFullName()), assembly->ToString());
}
} }
} }
} }

View File

@@ -13,7 +13,7 @@ using Mono.Cecil.Cil;
namespace Flax.Build.Plugins namespace Flax.Build.Plugins
{ {
/// <summary> /// <summary>
/// Flax.Build plugin for Networking extenrions support. Generates required bindings glue code for automatic types replication and RPCs invoking. /// Flax.Build plugin for Networking extensions support. Generates required bindings glue code for automatic types replication and RPCs invoking.
/// </summary> /// </summary>
/// <seealso cref="Flax.Build.Plugin" /> /// <seealso cref="Flax.Build.Plugin" />
internal sealed class NetworkingPlugin : Plugin internal sealed class NetworkingPlugin : Plugin
@@ -476,14 +476,14 @@ namespace Flax.Build.Plugins
if (!binaryModule.Any(module => module.Tags.ContainsKey(Network))) if (!binaryModule.Any(module => module.Tags.ContainsKey(Network)))
return; return;
// Generate netoworking code inside assembly after it's being compiled // Generate networking code inside assembly after it's being compiled
var assemblyPath = buildTask.ProducedFiles[0]; var assemblyPath = buildTask.ProducedFiles[0];
var task = graph.Add<Task>(); var task = graph.Add<Task>();
task.ProducedFiles.Add(assemblyPath); task.ProducedFiles.Add(assemblyPath);
task.WorkingDirectory = buildTask.WorkingDirectory; task.WorkingDirectory = buildTask.WorkingDirectory;
task.Command = () => OnPatchDotNetAssembly(buildData, buildOptions, buildTask, assemblyPath); task.Command = () => OnPatchDotNetAssembly(buildData, buildOptions, buildTask, assemblyPath);
task.CommandPath = null; task.CommandPath = null;
task.InfoMessage = $"Generating netowrking code for {Path.GetFileName(assemblyPath)}..."; task.InfoMessage = $"Generating networking code for {Path.GetFileName(assemblyPath)}...";
task.Cost = 50; task.Cost = 50;
task.DisableCache = true; task.DisableCache = true;
task.DependentTasks = new HashSet<Task>(); task.DependentTasks = new HashSet<Task>();
@@ -580,7 +580,7 @@ namespace Flax.Build.Plugins
} }
else if (isNetworkReplicated) else if (isNetworkReplicated)
{ {
// Generate serializization methods // Generate serialization methods
GenerateSerializer(type, true, ref failed, Thunk1, voidType, networkStreamType); GenerateSerializer(type, true, ref failed, Thunk1, voidType, networkStreamType);
GenerateSerializer(type, false, ref failed, Thunk2, voidType, networkStreamType); GenerateSerializer(type, false, ref failed, Thunk2, voidType, networkStreamType);
modified = true; modified = true;
@@ -588,7 +588,7 @@ namespace Flax.Build.Plugins
} }
else if (!isINetworkSerializable && isNetworkReplicated) else if (!isINetworkSerializable && isNetworkReplicated)
{ {
// Generate serializization methods // Generate serialization methods
var addSerializer = new TypeSerializer(); var addSerializer = new TypeSerializer();
addSerializer.Type = type; addSerializer.Type = type;
addSerializer.Serialize = GenerateNativeSerializer(type, true, ref failed, Thunk1, voidType, networkStreamType); addSerializer.Serialize = GenerateNativeSerializer(type, true, ref failed, Thunk1, voidType, networkStreamType);
@@ -1274,7 +1274,7 @@ namespace Flax.Build.Plugins
// Generate static method to execute RPC locally // Generate static method to execute RPC locally
{ {
var m = new MethodDefinition(method.Name + "_Execute", MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.HideBySig, voidType); var m = new MethodDefinition(method.Name + "_Execute", MethodAttributes.Static | MethodAttributes.Assembly | MethodAttributes.HideBySig, voidType);
m.Parameters.Add(new ParameterDefinition("instancePtr", ParameterAttributes.None, intPtrType)); m.Parameters.Add(new ParameterDefinition("instancePtr", ParameterAttributes.None, intPtrType));
m.Parameters.Add(new ParameterDefinition("streamPtr", ParameterAttributes.None, module.ImportReference(intPtrType))); m.Parameters.Add(new ParameterDefinition("streamPtr", ParameterAttributes.None, module.ImportReference(intPtrType)));
ILProcessor il = m.Body.GetILProcessor(); ILProcessor il = m.Body.GetILProcessor();