Format code

This commit is contained in:
Wojtek Figat
2023-03-13 20:20:10 +01:00
parent d2a0438b71
commit 6f304040b0

View File

@@ -53,6 +53,7 @@ namespace Flax.Build.Plugins
internal const string NetworkRpc = "NetworkRpc"; internal const string NetworkRpc = "NetworkRpc";
private const string Thunk1 = "INetworkSerializable_Serialize"; private const string Thunk1 = "INetworkSerializable_Serialize";
private const string Thunk2 = "INetworkSerializable_Deserialize"; private const string Thunk2 = "INetworkSerializable_Deserialize";
private static readonly Dictionary<string, InBuildSerializer> _inBuildSerializers = new Dictionary<string, InBuildSerializer>() private static readonly Dictionary<string, InBuildSerializer> _inBuildSerializers = new Dictionary<string, InBuildSerializer>()
{ {
{ "System.Boolean", new InBuildSerializer("WriteBoolean", "ReadBoolean") }, { "System.Boolean", new InBuildSerializer("WriteBoolean", "ReadBoolean") },
@@ -127,6 +128,7 @@ namespace Flax.Build.Plugins
{ {
fields = structInfo.Fields; fields = structInfo.Fields;
} }
bool useReplication = false, useRpc = false; bool useReplication = false, useRpc = false;
if (fields != null) if (fields != null)
{ {
@@ -139,6 +141,7 @@ namespace Flax.Build.Plugins
} }
} }
} }
if (properties != null) if (properties != null)
{ {
foreach (var propertyInfo in properties) foreach (var propertyInfo in properties)
@@ -150,6 +153,7 @@ namespace Flax.Build.Plugins
} }
} }
} }
if (functions != null) if (functions != null)
{ {
foreach (var functionInfo in functions) foreach (var functionInfo in functions)
@@ -161,20 +165,22 @@ namespace Flax.Build.Plugins
} }
} }
} }
if (useReplication) if (useReplication)
{ {
typeInfo.SetTag(NetworkReplicated, string.Empty); typeInfo.SetTag(NetworkReplicated, string.Empty);
// Generate C++ wrapper functions to serialize/deserialize type // Generate C++ wrapper functions to serialize/deserialize type
BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkReplicator.h"); BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkReplicator.h");
BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkStream.h"); BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkStream.h");
OnGenerateCppTypeSerialize(buildData, typeInfo, contents, fields, properties, true); OnGenerateCppTypeSerialize(buildData, typeInfo, contents, fields, properties, true);
OnGenerateCppTypeSerialize(buildData, typeInfo, contents, fields, properties, false); OnGenerateCppTypeSerialize(buildData, typeInfo, contents, fields, properties, false);
} }
if (useRpc) if (useRpc)
{ {
typeInfo.SetTag(NetworkRpc, string.Empty); typeInfo.SetTag(NetworkRpc, string.Empty);
// Generate C++ wrapper functions to invoke/execute RPC // Generate C++ wrapper functions to invoke/execute RPC
BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkStream.h"); BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkStream.h");
BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkReplicator.h"); BindingsGenerator.CppIncludeFiles.Add("Engine/Networking/NetworkReplicator.h");
@@ -282,7 +288,7 @@ namespace Flax.Build.Plugins
// Replicate base type // Replicate base type
OnGenerateCppWriteSerializer(contents, classStructInfo.BaseType.NativeName, "obj", serialize); OnGenerateCppWriteSerializer(contents, classStructInfo.BaseType.NativeName, "obj", serialize);
} }
// Replicate all marked fields and properties // Replicate all marked fields and properties
if (fields != null) if (fields != null)
{ {
@@ -293,6 +299,7 @@ namespace Flax.Build.Plugins
OnGenerateCppTypeSerializeData(buildData, typeInfo, contents, fieldInfo.Type, $"obj.{fieldInfo.Name}", serialize); OnGenerateCppTypeSerializeData(buildData, typeInfo, contents, fieldInfo.Type, $"obj.{fieldInfo.Name}", serialize);
} }
} }
if (properties != null) if (properties != null)
{ {
foreach (var propertyInfo in properties) foreach (var propertyInfo in properties)
@@ -308,6 +315,7 @@ namespace Flax.Build.Plugins
} }
} }
} }
contents.AppendLine(" }"); contents.AppendLine(" }");
contents.AppendLine(); contents.AppendLine();
} }
@@ -326,9 +334,10 @@ namespace Flax.Build.Plugins
if (apiType != null) if (apiType != null)
return IsRawPOD(buildData, apiType); return IsRawPOD(buildData, apiType);
} }
return false; return false;
} }
private void OnGenerateCppTypeSerializeData(Builder.BuildData buildData, ApiTypeInfo caller, StringBuilder contents, TypeInfo type, string name, bool serialize) private void OnGenerateCppTypeSerializeData(Builder.BuildData buildData, ApiTypeInfo caller, StringBuilder contents, TypeInfo type, string name, bool serialize)
{ {
var apiType = BindingsGenerator.FindApiTypeInfo(buildData, type, caller); var apiType = BindingsGenerator.FindApiTypeInfo(buildData, type, caller);
@@ -365,7 +374,7 @@ namespace Flax.Build.Plugins
throw new Exception($"Invalid pointer type '{type}' that cannot be serialized for replication of {caller.Name}."); throw new Exception($"Invalid pointer type '{type}' that cannot be serialized for replication of {caller.Name}.");
if (type.IsRef) if (type.IsRef)
throw new Exception($"Invalid reference type '{type}' that cannot be serialized for replication of {caller.Name}."); throw new Exception($"Invalid reference type '{type}' that cannot be serialized for replication of {caller.Name}.");
// Structure serializer // Structure serializer
OnGenerateCppWriteSerializer(contents, apiType.NativeName, name, serialize); OnGenerateCppWriteSerializer(contents, apiType.NativeName, name, serialize);
} }
@@ -375,13 +384,13 @@ namespace Flax.Build.Plugins
OnGenerateCppWriteRaw(contents, name, serialize); OnGenerateCppWriteRaw(contents, name, serialize);
} }
} }
private void OnGenerateCppWriteRaw(StringBuilder contents, string data, bool serialize) private void OnGenerateCppWriteRaw(StringBuilder contents, string data, bool serialize)
{ {
var method = serialize ? "Write" : "Read"; var method = serialize ? "Write" : "Read";
contents.AppendLine($" stream->{method}({data});"); contents.AppendLine($" stream->{method}({data});");
} }
private void OnGenerateCppWriteSerializer(StringBuilder contents, string type, string data, bool serialize) private void OnGenerateCppWriteSerializer(StringBuilder contents, string type, string data, bool serialize)
{ {
if (type == "ScriptingObject" || type == "Script" || type == "Actor") if (type == "ScriptingObject" || type == "Script" || type == "Actor")
@@ -405,6 +414,7 @@ namespace Flax.Build.Plugins
// Register generated serializer functions // Register generated serializer functions
contents.AppendLine($" NetworkReplicator::AddSerializer(ScriptingTypeHandle({typeNameNative}::TypeInitializer), {typeNameInternal}Internal::INetworkSerializable_Serialize, {typeNameInternal}Internal::INetworkSerializable_Deserialize);"); contents.AppendLine($" NetworkReplicator::AddSerializer(ScriptingTypeHandle({typeNameNative}::TypeInitializer), {typeNameInternal}Internal::INetworkSerializable_Serialize, {typeNameInternal}Internal::INetworkSerializable_Deserialize);");
} }
if (rpcTag != null) if (rpcTag != null)
{ {
// Register generated RPCs // Register generated RPCs
@@ -413,6 +423,7 @@ namespace Flax.Build.Plugins
{ {
functions = classInfo.Functions; functions = classInfo.Functions;
} }
if (functions != null) if (functions != null)
{ {
foreach (var functionInfo in functions) foreach (var functionInfo in functions)
@@ -430,16 +441,15 @@ namespace Flax.Build.Plugins
// Skip types that don't use networking // Skip types that don't use networking
if (typeInfo.GetTag(NetworkReplicated) == null) if (typeInfo.GetTag(NetworkReplicated) == null)
return; return;
if (typeInfo is ClassInfo) if (typeInfo is ClassInfo)
return; return;
// Generate C# wrapper functions to serialize/deserialize type directly from managed code // Generate C# wrapper functions to serialize/deserialize type directly from managed code
OnGenerateCSharpTypeSerialize(buildData, typeInfo, contents, indent, true); OnGenerateCSharpTypeSerialize(buildData, typeInfo, contents, indent, true);
OnGenerateCSharpTypeSerialize(buildData, typeInfo, contents, indent, false); OnGenerateCSharpTypeSerialize(buildData, typeInfo, contents, indent, false);
} }
private void OnGenerateCSharpTypeSerialize(Builder.BuildData buildData, ApiTypeInfo typeInfo, StringBuilder contents, string indent, bool serialize) private void OnGenerateCSharpTypeSerialize(Builder.BuildData buildData, ApiTypeInfo typeInfo, StringBuilder contents, string indent, bool serialize)
{ {
var mode = serialize ? "true" : "false"; var mode = serialize ? "true" : "false";
@@ -463,6 +473,7 @@ namespace Flax.Build.Plugins
contents.Append(indent).AppendLine($" throw new NotImplementedException(\"Not supported native structure with references used in managed code for replication.\");"); contents.Append(indent).AppendLine($" throw new NotImplementedException(\"Not supported native structure with references used in managed code for replication.\");");
} }
} }
contents.Append(indent).AppendLine("}"); contents.Append(indent).AppendLine("}");
} }
@@ -493,7 +504,7 @@ namespace Flax.Build.Plugins
private void OnPatchDotNetAssembly(Builder.BuildData buildData, NativeCpp.BuildOptions buildOptions, Task buildTask, string assemblyPath) private void OnPatchDotNetAssembly(Builder.BuildData buildData, NativeCpp.BuildOptions buildOptions, Task buildTask, string assemblyPath)
{ {
using (DefaultAssemblyResolver assemblyResolver = new DefaultAssemblyResolver()) using (DefaultAssemblyResolver assemblyResolver = new DefaultAssemblyResolver())
using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters{ ReadWrite = true, ReadSymbols = true, AssemblyResolver = assemblyResolver })) using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters { ReadWrite = true, ReadSymbols = true, AssemblyResolver = assemblyResolver }))
{ {
// Setup module search locations // Setup module search locations
var searchDirectories = new HashSet<string>(); var searchDirectories = new HashSet<string>();
@@ -503,6 +514,7 @@ namespace Flax.Build.Plugins
if (file.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) if (file.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
searchDirectories.Add(Path.GetDirectoryName(file)); searchDirectories.Add(Path.GetDirectoryName(file));
} }
foreach (var e in searchDirectories) foreach (var e in searchDirectories)
assemblyResolver.AddSearchDirectory(e); assemblyResolver.AddSearchDirectory(e);
@@ -554,6 +566,7 @@ namespace Flax.Build.Plugins
} }
} }
} }
var isNetworkReplicated = false; var isNetworkReplicated = false;
foreach (FieldDefinition f in type.Fields) foreach (FieldDefinition f in type.Fields)
{ {
@@ -562,6 +575,7 @@ namespace Flax.Build.Plugins
isNetworkReplicated = true; isNetworkReplicated = true;
break; break;
} }
foreach (PropertyDefinition p in type.Properties) foreach (PropertyDefinition p in type.Properties)
{ {
if (!p.HasAttribute(NetworkReplicatedAttribute)) if (!p.HasAttribute(NetworkReplicatedAttribute))
@@ -569,6 +583,7 @@ namespace Flax.Build.Plugins
isNetworkReplicated = true; isNetworkReplicated = true;
break; break;
} }
if (type.IsValueType) if (type.IsValueType)
{ {
if (isINetworkSerializable) if (isINetworkSerializable)
@@ -597,6 +612,7 @@ namespace Flax.Build.Plugins
modified = true; modified = true;
} }
} }
if (failed) if (failed)
throw new Exception($"Failed to generate network replication for assembly {assemblyPath}"); throw new Exception($"Failed to generate network replication for assembly {assemblyPath}");
if (!modified) if (!modified)
@@ -650,6 +666,7 @@ namespace Flax.Build.Plugins
il.Emit(OpCodes.Newobj, module.ImportReference(serializeFuncCtor)); il.Emit(OpCodes.Newobj, module.ImportReference(serializeFuncCtor));
il.Emit(OpCodes.Call, module.ImportReference(addSerializer)); il.Emit(OpCodes.Call, module.ImportReference(addSerializer));
} }
foreach (var e in methodRPCs) foreach (var e in methodRPCs)
{ {
// NetworkReplicator.AddRPC(typeof(<type>), "<name>", <name>_Execute, <isServer>, <isClient>, <channel>); // NetworkReplicator.AddRPC(typeof(<type>), "<name>", <name>_Execute, <isServer>, <isClient>, <channel>);
@@ -664,13 +681,14 @@ namespace Flax.Build.Plugins
il.Emit(OpCodes.Ldc_I4, e.Channel); il.Emit(OpCodes.Ldc_I4, e.Channel);
il.Emit(OpCodes.Call, module.ImportReference(addRPC)); il.Emit(OpCodes.Call, module.ImportReference(addRPC));
} }
il.Emit(OpCodes.Nop); il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
c.Methods.Add(m); c.Methods.Add(m);
} }
// Serialize assembly back to the file // Serialize assembly back to the file
assembly.Write(new WriterParameters { WriteSymbols = true } ); assembly.Write(new WriterParameters { WriteSymbols = true });
} }
} }
@@ -696,7 +714,7 @@ namespace Flax.Build.Plugins
TypeDefinition networkStream = networkStreamType.Resolve(); TypeDefinition networkStream = networkStreamType.Resolve();
ILProcessor il = m.Body.GetILProcessor(); ILProcessor il = m.Body.GetILProcessor();
il.Emit(OpCodes.Nop); il.Emit(OpCodes.Nop);
// Serialize base type // Serialize base type
if (type.BaseType != null && type.BaseType.FullName != "System.ValueType" && type.BaseType.FullName != "FlaxEngine.Object" && type.BaseType.CanBeResolved()) if (type.BaseType != null && type.BaseType.FullName != "System.ValueType" && type.BaseType.FullName != "FlaxEngine.Object" && type.BaseType.CanBeResolved())
{ {
@@ -747,14 +765,14 @@ namespace Flax.Build.Plugins
il.Emit(OpCodes.Call, module.ImportReference(fromUnmanagedPtr)); il.Emit(OpCodes.Call, module.ImportReference(fromUnmanagedPtr));
il.Emit(OpCodes.Castclass, type); il.Emit(OpCodes.Castclass, type);
il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Stloc_0);
// NetworkStream stream = (NetworkStream)FlaxEngine.Object.FromUnmanagedPtr(streamPtr) // NetworkStream stream = (NetworkStream)FlaxEngine.Object.FromUnmanagedPtr(streamPtr)
il.Body.Variables.Add(new VariableDefinition(networkStream)); il.Body.Variables.Add(new VariableDefinition(networkStream));
il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, module.ImportReference(fromUnmanagedPtr)); il.Emit(OpCodes.Call, module.ImportReference(fromUnmanagedPtr));
il.Emit(OpCodes.Castclass, module.ImportReference(networkStream)); il.Emit(OpCodes.Castclass, module.ImportReference(networkStream));
il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Stloc_1);
// Generate normal serializer // Generate normal serializer
var serializer = GenerateSerializer(type, serialize, ref failed, name, voidType, networkStreamType); var serializer = GenerateSerializer(type, serialize, ref failed, name, voidType, networkStreamType);
@@ -810,17 +828,20 @@ namespace Flax.Build.Plugins
failed = true; failed = true;
return; return;
} }
if (property.SetMethod == null) if (property.SetMethod == null)
{ {
MonoCecil.CompilationError($"Missing setter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication.", property); MonoCecil.CompilationError($"Missing setter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication.", property);
failed = true; failed = true;
return; return;
} }
if (property.GetMethod.IsVirtual) if (property.GetMethod.IsVirtual)
propertyGetOpCode = OpCodes.Callvirt; propertyGetOpCode = OpCodes.Callvirt;
if (property.SetMethod.IsVirtual) if (property.SetMethod.IsVirtual)
propertySetOpCode = OpCodes.Callvirt; propertySetOpCode = OpCodes.Callvirt;
} }
ModuleDefinition module = type.Module; ModuleDefinition module = type.Module;
TypeDefinition valueTypeDef = valueType.Resolve(); TypeDefinition valueTypeDef = valueType.Resolve();
if (_inBuildSerializers.TryGetValue(valueType.FullName, out var serializer)) if (_inBuildSerializers.TryGetValue(valueType.FullName, out var serializer))
@@ -843,6 +864,7 @@ namespace Flax.Build.Plugins
il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_1);
m = networkStreamType.GetMethod(serializer.ReadMethod); m = networkStreamType.GetMethod(serializer.ReadMethod);
} }
il.Emit(OpCodes.Callvirt, module.ImportReference(m)); il.Emit(OpCodes.Callvirt, module.ImportReference(m));
if (!serialize) if (!serialize)
{ {
@@ -966,7 +988,7 @@ namespace Flax.Build.Plugins
else else
il.Emit(propertyGetOpCode, property.GetMethod); il.Emit(propertyGetOpCode, property.GetMethod);
// int num2 = ((array2 != null) ? array2.Length : 0); // int num2 = ((array2 != null) ? array2.Length : 0);
il.Emit(OpCodes.Dup); il.Emit(OpCodes.Dup);
Instruction jmp1 = il.Create(OpCodes.Nop); Instruction jmp1 = il.Create(OpCodes.Nop);
il.Emit(OpCodes.Brtrue_S, jmp1); il.Emit(OpCodes.Brtrue_S, jmp1);
@@ -979,8 +1001,8 @@ namespace Flax.Build.Plugins
il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Conv_I4);
il.Append(jmp2); il.Append(jmp2);
il.Emit(OpCodes.Stloc, varStart + 0); il.Emit(OpCodes.Stloc, varStart + 0);
// stream.WriteInt32(num2); // stream.WriteInt32(num2);
il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldloc, varStart + 0); il.Emit(OpCodes.Ldloc, varStart + 0);
var m = networkStreamType.GetMethod("WriteInt32"); var m = networkStreamType.GetMethod("WriteInt32");
@@ -1039,16 +1061,16 @@ namespace Flax.Build.Plugins
var m = networkStreamType.GetMethod("ReadInt32"); var m = networkStreamType.GetMethod("ReadInt32");
il.Emit(OpCodes.Callvirt, module.ImportReference(m)); il.Emit(OpCodes.Callvirt, module.ImportReference(m));
il.Emit(OpCodes.Stloc, varStart + 0); il.Emit(OpCodes.Stloc, varStart + 0);
// System.Array.Resize(ref Array1, num); // System.Array.Resize(ref Array1, num);
il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldflda, field); il.Emit(OpCodes.Ldflda, field);
il.Emit(OpCodes.Ldloc, varStart + 0); il.Emit(OpCodes.Ldloc, varStart + 0);
module.TryGetTypeReference("System.Array", out var arrayType); module.TryGetTypeReference("System.Array", out var arrayType);
m = arrayType.Resolve().GetMethod("Resize", 2); m = arrayType.Resolve().GetMethod("Resize", 2);
il.Emit(OpCodes.Call, module.ImportReference(m.InflateGeneric(elementType))); il.Emit(OpCodes.Call, module.ImportReference(m.InflateGeneric(elementType)));
// fixed (int* buffer = Array1) // fixed (int* buffer = Array1)
il.Emit(OpCodes.Nop); il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, field); il.Emit(OpCodes.Ldfld, field);
@@ -1067,8 +1089,8 @@ namespace Flax.Build.Plugins
il.Emit(OpCodes.Stloc, varStart + 1); il.Emit(OpCodes.Stloc, varStart + 1);
Instruction jmp3 = il.Create(OpCodes.Nop); Instruction jmp3 = il.Create(OpCodes.Nop);
il.Emit(OpCodes.Br_S, jmp3); il.Emit(OpCodes.Br_S, jmp3);
// stream.ReadBytes((byte*)buffer, num * sizeof(<elementType>)); // stream.ReadBytes((byte*)buffer, num * sizeof(<elementType>));
il.Append(jmp2); il.Append(jmp2);
il.Emit(OpCodes.Ldloc, varStart + 2); il.Emit(OpCodes.Ldloc, varStart + 2);
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
@@ -1127,7 +1149,7 @@ namespace Flax.Build.Plugins
module.GetType("System.Guid", out var guidType); module.GetType("System.Guid", out var guidType);
module.GetType("FlaxEngine.Object", out var scriptingObjectType); module.GetType("FlaxEngine.Object", out var scriptingObjectType);
if (serialize) if (serialize)
{ {
il.InsertBefore(ilStart, il.Create(OpCodes.Nop)); il.InsertBefore(ilStart, il.Create(OpCodes.Nop));
il.InsertBefore(ilStart, il.Create(OpCodes.Ldloc, streamLocalIndex)); il.InsertBefore(ilStart, il.Create(OpCodes.Ldloc, streamLocalIndex));
il.InsertBefore(ilStart, il.Create(OpCodes.Ldarg, localIndex)); il.InsertBefore(ilStart, il.Create(OpCodes.Ldarg, localIndex));
@@ -1222,12 +1244,14 @@ namespace Flax.Build.Plugins
failed = true; failed = true;
return; return;
} }
if (method.IsVirtual) if (method.IsVirtual)
{ {
MonoCecil.CompilationError($"Not supported virtual RPC method '{method.FullName}'.", method); MonoCecil.CompilationError($"Not supported virtual RPC method '{method.FullName}'.", method);
failed = true; failed = true;
return; return;
} }
ModuleDefinition module = type.Module; ModuleDefinition module = type.Module;
var voidType = module.TypeSystem.Void; var voidType = module.TypeSystem.Void;
if (method.ReturnType != voidType) if (method.ReturnType != voidType)
@@ -1236,12 +1260,14 @@ namespace Flax.Build.Plugins
failed = true; failed = true;
return; return;
} }
if (method.IsStatic) if (method.IsStatic)
{ {
MonoCecil.CompilationError($"Not supported static RPC method '{method.FullName}'.", method); MonoCecil.CompilationError($"Not supported static RPC method '{method.FullName}'.", method);
failed = true; failed = true;
return; return;
} }
var methodRPC = new MethodRPC(); var methodRPC = new MethodRPC();
methodRPC.Type = type; methodRPC.Type = type;
methodRPC.Method = method; methodRPC.Method = method;
@@ -1252,6 +1278,7 @@ namespace Flax.Build.Plugins
methodRPC.IsClient = (bool)attribute.ConstructorArguments[1].Value; methodRPC.IsClient = (bool)attribute.ConstructorArguments[1].Value;
methodRPC.Channel = (int)attribute.ConstructorArguments[2].Value; methodRPC.Channel = (int)attribute.ConstructorArguments[2].Value;
} }
methodRPC.IsServer = (bool)attribute.GetFieldValue("Server", methodRPC.IsServer); methodRPC.IsServer = (bool)attribute.GetFieldValue("Server", methodRPC.IsServer);
methodRPC.IsClient = (bool)attribute.GetFieldValue("Client", methodRPC.IsClient); methodRPC.IsClient = (bool)attribute.GetFieldValue("Client", methodRPC.IsClient);
methodRPC.Channel = (int)attribute.GetFieldValue("Channel", methodRPC.Channel); methodRPC.Channel = (int)attribute.GetFieldValue("Channel", methodRPC.Channel);
@@ -1261,12 +1288,14 @@ namespace Flax.Build.Plugins
failed = true; failed = true;
return; return;
} }
if (!methodRPC.IsServer && !methodRPC.IsClient) if (!methodRPC.IsServer && !methodRPC.IsClient)
{ {
MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier.", method); MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier.", method);
failed = true; failed = true;
return; return;
} }
module.GetType("System.IntPtr", out var intPtrType); module.GetType("System.IntPtr", out var intPtrType);
module.GetType("FlaxEngine.Object", out var scriptingObjectType); module.GetType("FlaxEngine.Object", out var scriptingObjectType);
var fromUnmanagedPtr = scriptingObjectType.Resolve().GetMethod("FromUnmanagedPtr"); var fromUnmanagedPtr = scriptingObjectType.Resolve().GetMethod("FromUnmanagedPtr");
@@ -1294,7 +1323,7 @@ namespace Flax.Build.Plugins
il.Emit(OpCodes.Call, module.ImportReference(fromUnmanagedPtr)); il.Emit(OpCodes.Call, module.ImportReference(fromUnmanagedPtr));
il.Emit(OpCodes.Castclass, networkStream); il.Emit(OpCodes.Castclass, networkStream);
il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Stloc_1);
// Add locals for each RPC parameter // Add locals for each RPC parameter
var argsStart = il.Body.Variables.Count; var argsStart = il.Body.Variables.Count;
for (int i = 0; i < method.Parameters.Count; i++) for (int i = 0; i < method.Parameters.Count; i++)
@@ -1306,6 +1335,7 @@ namespace Flax.Build.Plugins
failed = true; failed = true;
return; return;
} }
var parameterType = parameter.ParameterType; var parameterType = parameter.ParameterType;
il.Body.Variables.Add(new VariableDefinition(parameterType)); il.Body.Variables.Add(new VariableDefinition(parameterType));
} }
@@ -1324,8 +1354,9 @@ namespace Flax.Build.Plugins
{ {
il.Emit(OpCodes.Ldloc, argsStart + i); il.Emit(OpCodes.Ldloc, argsStart + i);
} }
il.Emit(OpCodes.Callvirt, method); il.Emit(OpCodes.Callvirt, method);
il.Emit(OpCodes.Nop); il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
type.Methods.Add(m); type.Methods.Add(m);
@@ -1418,7 +1449,6 @@ namespace Flax.Build.Plugins
il.InsertBefore(ilStart, tmp); il.InsertBefore(ilStart, tmp);
//il.InsertBefore(ilStart, il.Create(OpCodes.Ret)); //il.InsertBefore(ilStart, il.Create(OpCodes.Ret));
il.InsertBefore(ilStart, il.Create(OpCodes.Br, jumpBodyEnd)); il.InsertBefore(ilStart, il.Create(OpCodes.Br, jumpBodyEnd));
} }
// if (client && networkMode == NetworkManagerMode.Server) return; // if (client && networkMode == NetworkManagerMode.Server) return;