Browse Source

Merge pull request #62805 from raulsntos/csharp-rpc

Rémi Verschelde 3 years ago
parent
commit
31974aaae2

+ 16 - 17
modules/mono/csharp_script.cpp

@@ -3069,16 +3069,11 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
 			Vector<GDMonoMethod *> methods = top->get_all_methods();
 			for (int i = 0; i < methods.size(); i++) {
 				if (!methods[i]->is_static()) {
-					Multiplayer::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
-					if (Multiplayer::RPC_MODE_DISABLED != mode) {
-						Multiplayer::RPCConfig nd;
-						nd.name = methods[i]->get_name();
-						nd.rpc_mode = mode;
-						// TODO Transfer mode, channel
-						nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
-						nd.channel = 0;
-						if (-1 == p_script->rpc_functions.find(nd)) {
-							p_script->rpc_functions.push_back(nd);
+					Multiplayer::RPCConfig rpc_config = p_script->_member_get_rpc_config(methods[i]);
+					if (rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
+						// RPC annotations can only be used once per method
+						if (p_script->rpc_functions.find(rpc_config) == -1) {
+							p_script->rpc_functions.push_back(rpc_config);
 						}
 					}
 				}
@@ -3513,15 +3508,19 @@ int CSharpScript::get_member_line(const StringName &p_member) const {
 	return -1;
 }
 
-Multiplayer::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const {
-	if (p_member->has_attribute(CACHED_CLASS(AnyPeerAttribute))) {
-		return Multiplayer::RPC_MODE_ANY_PEER;
-	}
-	if (p_member->has_attribute(CACHED_CLASS(AuthorityAttribute))) {
-		return Multiplayer::RPC_MODE_AUTHORITY;
+Multiplayer::RPCConfig CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const {
+	Multiplayer::RPCConfig rpc_config;
+
+	MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute));
+	if (rpc_attribute != nullptr) {
+		rpc_config.name = p_member->get_name();
+		rpc_config.rpc_mode = (Multiplayer::RPCMode)CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute);
+		rpc_config.call_local = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute);
+		rpc_config.transfer_mode = (Multiplayer::TransferMode)CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute);
+		rpc_config.channel = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute);
 	}
 
-	return Multiplayer::RPC_MODE_DISABLED;
+	return rpc_config;
 }
 
 const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const {

+ 1 - 1
modules/mono/csharp_script.h

@@ -179,7 +179,7 @@ private:
 	static void update_script_class_info(Ref<CSharpScript> p_script);
 	static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
 
-	Multiplayer::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;
+	Multiplayer::RPCConfig _member_get_rpc_config(IMonoClassMember *p_member) const;
 
 protected:
 	static void _bind_methods();

+ 43 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs

@@ -0,0 +1,43 @@
+using System;
+
+namespace Godot
+{
+    /// <summary>
+    /// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>,
+    /// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers).
+    /// See <see cref="RPCMode"/> and <see cref="TransferMode"/>. By default, methods are not exposed to networking
+    /// (and RPCs).
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
+    public class RPCAttribute : Attribute
+    {
+        /// <summary>
+        /// RPC mode for the annotated method.
+        /// </summary>
+        public RPCMode Mode { get; } = RPCMode.Disabled;
+
+        /// <summary>
+        /// If the method will also be called locally; otherwise, it is only called remotely.
+        /// </summary>
+        public bool CallLocal { get; set; } = false;
+
+        /// <summary>
+        /// Transfer mode for the annotated method.
+        /// </summary>
+        public TransferMode TransferMode { get; set; } = TransferMode.Reliable;
+
+        /// <summary>
+        /// Transfer channel for the annotated mode.
+        /// </summary>
+        public int TransferChannel { get; set; } = 0;
+
+        /// <summary>
+        /// Constructs a <see cref="RPCAttribute"/> instance.
+        /// </summary>
+        /// <param name="mode">The RPC mode to use.</param>
+        public RPCAttribute(RPCMode mode = RPCMode.Authority)
+        {
+            Mode = mode;
+        }
+    }
+}

+ 0 - 16
modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs

@@ -1,16 +0,0 @@
-using System;
-
-namespace Godot
-{
-    /// <summary>
-    /// Constructs a new AnyPeerAttribute instance. Members with the AnyPeerAttribute are given authority over their own player.
-    /// </summary>
-    [AttributeUsage(AttributeTargets.Method)]
-    public class AnyPeerAttribute : Attribute { }
-
-    /// <summary>
-    /// Constructs a new AuthorityAttribute instance. Members with the AuthorityAttribute are given authority over the game.
-    /// </summary>
-    [AttributeUsage(AttributeTargets.Method)]
-    public class AuthorityAttribute : Attribute { }
-}

+ 1 - 1
modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj

@@ -18,7 +18,7 @@
     <Compile Include="Core\Attributes\DisableGodotGeneratorsAttribute.cs" />
     <Compile Include="Core\Attributes\ExportAttribute.cs" />
     <Compile Include="Core\Attributes\GodotMethodAttribute.cs" />
-    <Compile Include="Core\Attributes\RPCAttributes.cs" />
+    <Compile Include="Core\Attributes\RPCAttribute.cs" />
     <Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
     <Compile Include="Core\Attributes\SignalAttribute.cs" />
     <Compile Include="Core\Attributes\ToolAttribute.cs" />

+ 10 - 4
modules/mono/mono_gd/gd_mono_cache.cpp

@@ -140,8 +140,11 @@ void CachedData::clear_godot_api_cache() {
 	field_ExportAttribute_hintString = nullptr;
 	class_SignalAttribute = nullptr;
 	class_ToolAttribute = nullptr;
-	class_AnyPeerAttribute = nullptr;
-	class_AuthorityAttribute = nullptr;
+	class_RPCAttribute = nullptr;
+	property_RPCAttribute_Mode = nullptr;
+	property_RPCAttribute_CallLocal = nullptr;
+	property_RPCAttribute_TransferMode = nullptr;
+	property_RPCAttribute_TransferChannel = nullptr;
 	class_GodotMethodAttribute = nullptr;
 	field_GodotMethodAttribute_methodName = nullptr;
 	class_ScriptPathAttribute = nullptr;
@@ -268,8 +271,11 @@ void update_godot_api_cache() {
 	CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString"));
 	CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute));
 	CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
-	CACHE_CLASS_AND_CHECK(AnyPeerAttribute, GODOT_API_CLASS(AnyPeerAttribute));
-	CACHE_CLASS_AND_CHECK(AuthorityAttribute, GODOT_API_CLASS(AuthorityAttribute));
+	CACHE_CLASS_AND_CHECK(RPCAttribute, GODOT_API_CLASS(RPCAttribute));
+	CACHE_PROPERTY_AND_CHECK(RPCAttribute, Mode, CACHED_CLASS(RPCAttribute)->get_property("Mode"));
+	CACHE_PROPERTY_AND_CHECK(RPCAttribute, CallLocal, CACHED_CLASS(RPCAttribute)->get_property("CallLocal"));
+	CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferMode, CACHED_CLASS(RPCAttribute)->get_property("TransferMode"));
+	CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferChannel, CACHED_CLASS(RPCAttribute)->get_property("TransferChannel"));
 	CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
 	CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
 	CACHE_CLASS_AND_CHECK(ScriptPathAttribute, GODOT_API_CLASS(ScriptPathAttribute));

+ 5 - 2
modules/mono/mono_gd/gd_mono_cache.h

@@ -111,8 +111,11 @@ struct CachedData {
 	GDMonoField *field_ExportAttribute_hintString = nullptr;
 	GDMonoClass *class_SignalAttribute = nullptr;
 	GDMonoClass *class_ToolAttribute = nullptr;
-	GDMonoClass *class_AnyPeerAttribute = nullptr;
-	GDMonoClass *class_AuthorityAttribute = nullptr;
+	GDMonoClass *class_RPCAttribute = nullptr;
+	GDMonoProperty *property_RPCAttribute_Mode = nullptr;
+	GDMonoProperty *property_RPCAttribute_CallLocal = nullptr;
+	GDMonoProperty *property_RPCAttribute_TransferMode = nullptr;
+	GDMonoProperty *property_RPCAttribute_TransferChannel = nullptr;
 	GDMonoClass *class_GodotMethodAttribute = nullptr;
 	GDMonoField *field_GodotMethodAttribute_methodName = nullptr;
 	GDMonoClass *class_ScriptPathAttribute = nullptr;