diff options
-rw-r--r-- | modules/mono/csharp_script.cpp | 33 | ||||
-rw-r--r-- | modules/mono/csharp_script.h | 2 | ||||
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs | 43 | ||||
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs | 16 | ||||
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj | 2 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_cache.cpp | 14 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_cache.h | 7 |
7 files changed, 76 insertions, 41 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 622838b308..4c2d103aa6 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -3063,16 +3063,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); } } } @@ -3507,15 +3502,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 { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 69bd8703aa..32cc6ad6c4 100644 --- a/modules/mono/csharp_script.h +++ b/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(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs new file mode 100644 index 0000000000..0a1c8322d7 --- /dev/null +++ b/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; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs deleted file mode 100644 index f0d37c344d..0000000000 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs +++ /dev/null @@ -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 { } -} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 1fcfe74c86..e59f45bbf6 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/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" /> diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index 44a8e26b8f..fd78fae4ad 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/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)); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 92136e1f41..b3b0865608 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/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; |