diff options
Diffstat (limited to 'modules/mono/csharp_script.cpp')
| -rw-r--r-- | modules/mono/csharp_script.cpp | 244 |
1 files changed, 178 insertions, 66 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 9e19e5f8c4..c722076fe2 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -31,6 +31,7 @@ #include "csharp_script.h" #include <mono/metadata/threads.h> +#include <stdint.h> #include "core/io/json.h" #include "core/os/file_access.h" @@ -161,13 +162,13 @@ void CSharpLanguage::finish() { #ifdef DEBUG_ENABLED for (Map<ObjectID, int>::Element *E = unsafe_object_references.front(); E; E = E->next()) { - const ObjectID &id = E->get(); + const ObjectID &id = E->key(); Object *obj = ObjectDB::get_instance(id); if (obj) { - ERR_PRINTS("Leaked unsafe reference to object: " + obj->get_class() + ":" + itos(id)); + ERR_PRINT("Leaked unsafe reference to object: " + obj->to_string()); } else { - ERR_PRINTS("Leaked unsafe reference to deleted object: " + itos(id)); + ERR_PRINT("Leaked unsafe reference to deleted object: " + itos(id)); } } #endif @@ -853,7 +854,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { while (script->instances.front()) { Object *obj = script->instances.front()->get(); - obj->set_script(RefPtr()); // Remove script and existing script instances (placeholder are not removed before domain reload) + obj->set_script(REF()); // Remove script and existing script instances (placeholder are not removed before domain reload) } script->_clear(); @@ -876,7 +877,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // Use a placeholder for now to avoid losing the state when saving a scene - obj->set_script(scr.get_ref_ptr()); + obj->set_script(scr); PlaceHolderScriptInstance *placeholder = scr->placeholder_instance_create(obj); obj->set_script_instance(placeholder); @@ -1002,7 +1003,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { CRASH_COND(si != NULL); #endif // Re-create script instance - obj->set_script(script.get_ref_ptr()); // will create the script instance as well + obj->set_script(script); // will create the script instance as well } } @@ -1080,7 +1081,7 @@ void CSharpLanguage::_load_scripts_metadata() { int err_line; Error json_err = JSON::parse(old_json, old_dict_var, err_str, err_line); if (json_err != OK) { - ERR_PRINTS("Failed to parse metadata file: '" + err_str + "' (" + String::num_int64(err_line) + ")."); + ERR_PRINT("Failed to parse metadata file: '" + err_str + "' (" + String::num_int64(err_line) + ")."); return; } @@ -1721,8 +1722,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const { Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - if (!script.is_valid()) - ERR_FAIL_V(Variant()); + ERR_FAIL_COND_V(!script.is_valid(), Variant()); GD_MONO_SCOPE_THREAD_ATTACH; @@ -1980,67 +1980,44 @@ bool CSharpInstance::refcount_decremented() { return ref_dying; } -MultiplayerAPI::RPCMode CSharpInstance::_member_get_rpc_mode(IMonoClassMember *p_member) const { - - if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) - return MultiplayerAPI::RPC_MODE_REMOTE; - if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) - return MultiplayerAPI::RPC_MODE_MASTER; - if (p_member->has_attribute(CACHED_CLASS(PuppetAttribute))) - return MultiplayerAPI::RPC_MODE_PUPPET; - if (p_member->has_attribute(CACHED_CLASS(SlaveAttribute))) - return MultiplayerAPI::RPC_MODE_PUPPET; - if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute))) - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - if (p_member->has_attribute(CACHED_CLASS(SyncAttribute))) - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute))) - return MultiplayerAPI::RPC_MODE_MASTERSYNC; - if (p_member->has_attribute(CACHED_CLASS(PuppetSyncAttribute))) - return MultiplayerAPI::RPC_MODE_PUPPETSYNC; +Vector<ScriptNetData> CSharpInstance::get_rpc_methods() const { + return script->get_rpc_methods(); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +uint16_t CSharpInstance::get_rpc_method_id(const StringName &p_method) const { + return script->get_rpc_method_id(p_method); } -MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const { +StringName CSharpInstance::get_rpc_method(const uint16_t p_rpc_method_id) const { + return script->get_rpc_method(p_rpc_method_id); +} - GD_MONO_SCOPE_THREAD_ATTACH; +MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + return script->get_rpc_mode_by_id(p_rpc_method_id); +} - GDMonoClass *top = script->script_class; +MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const { + return script->get_rpc_mode(p_method); +} - while (top && top != script->native) { - GDMonoMethod *method = top->get_fetched_method_unknown_params(p_method); +Vector<ScriptNetData> CSharpInstance::get_rset_properties() const { + return script->get_rset_properties(); +} - if (method && !method->is_static()) - return _member_get_rpc_mode(method); +uint16_t CSharpInstance::get_rset_property_id(const StringName &p_variable) const { + return script->get_rset_property_id(p_variable); +} - top = top->get_parent_class(); - } +StringName CSharpInstance::get_rset_property(const uint16_t p_rset_member_id) const { + return script->get_rset_property(p_rset_member_id); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const { + return script->get_rset_mode_by_id(p_rset_member_id); } MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const { - - GD_MONO_SCOPE_THREAD_ATTACH; - - GDMonoClass *top = script->script_class; - - while (top && top != script->native) { - GDMonoField *field = top->get_field(p_variable); - - if (field && !field->is_static()) - return _member_get_rpc_mode(field); - - GDMonoProperty *property = top->get_property(p_variable); - - if (property && !property->is_static()) - return _member_get_rpc_mode(property); - - top = top->get_parent_class(); - } - - return MultiplayerAPI::RPC_MODE_DISABLED; + return script->get_rset_mode(p_variable); } void CSharpInstance::notification(int p_notification) { @@ -2444,7 +2421,7 @@ bool CSharpScript::_update_exports() { if (tmp_native && !base_ref) { Node *node = Object::cast_to<Node>(tmp_native); if (node && node->is_inside_tree()) { - ERR_PRINTS("Temporary instance was added to the scene tree."); + ERR_PRINT("Temporary instance was added to the scene tree."); } else { memdelete(tmp_native); } @@ -2522,7 +2499,7 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Ve arg.type = GDMonoMarshal::managed_to_variant_type(types[i]); if (arg.type == Variant::NIL) { - ERR_PRINTS("Unknown type of signal parameter: '" + arg.name + "' in '" + p_class->get_full_name() + "'."); + ERR_PRINT("Unknown type of signal parameter: '" + arg.name + "' in '" + p_class->get_full_name() + "'."); return false; } @@ -2552,7 +2529,7 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect if (p_member->is_static()) { if (p_member->has_attribute(CACHED_CLASS(ExportAttribute))) - ERR_PRINTS("Cannot export member because it is static: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); + ERR_PRINT("Cannot export member because it is static: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } @@ -2575,12 +2552,12 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect GDMonoProperty *property = static_cast<GDMonoProperty *>(p_member); if (!property->has_getter()) { if (exported) - ERR_PRINTS("Read-only property cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); + ERR_PRINT("Read-only property cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } if (!property->has_setter()) { if (exported) - ERR_PRINTS("Write-only property (without getter) cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); + ERR_PRINT("Write-only property (without getter) cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } } @@ -2599,7 +2576,7 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect String hint_string; if (variant_type == Variant::NIL) { - ERR_PRINTS("Unknown exported member type: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); + ERR_PRINT("Unknown exported member type: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } @@ -2891,7 +2868,7 @@ bool CSharpScript::can_instance() const { "Compile", ProjectSettings::get_singleton()->globalize_path(get_path())); } else { - ERR_PRINTS("C# project could not be created; cannot add file: '" + get_path() + "'."); + ERR_PRINT("C# project could not be created; cannot add file: '" + get_path() + "'."); } } } @@ -3252,6 +3229,69 @@ Error CSharpScript::reload(bool p_keep_state) { _update_exports(); } + rpc_functions.clear(); + rpc_variables.clear(); + + GDMonoClass *top = script_class; + while (top && top != native) { + { + Vector<GDMonoMethod *> methods = top->get_all_methods(); + for (int i = 0; i < methods.size(); i++) { + if (!methods[i]->is_static()) { + MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(methods[i]); + if (MultiplayerAPI::RPC_MODE_DISABLED != mode) { + ScriptNetData nd; + nd.name = methods[i]->get_name(); + nd.mode = mode; + if (-1 == rpc_functions.find(nd)) { + rpc_functions.push_back(nd); + } + } + } + } + } + + { + Vector<GDMonoField *> fields = top->get_all_fields(); + for (int i = 0; i < fields.size(); i++) { + if (!fields[i]->is_static()) { + MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(fields[i]); + if (MultiplayerAPI::RPC_MODE_DISABLED != mode) { + ScriptNetData nd; + nd.name = fields[i]->get_name(); + nd.mode = mode; + if (-1 == rpc_variables.find(nd)) { + rpc_variables.push_back(nd); + } + } + } + } + } + + { + Vector<GDMonoProperty *> properties = top->get_all_properties(); + for (int i = 0; i < properties.size(); i++) { + if (!properties[i]->is_static()) { + MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(properties[i]); + if (MultiplayerAPI::RPC_MODE_DISABLED != mode) { + ScriptNetData nd; + nd.name = properties[i]->get_name(); + nd.mode = mode; + if (-1 == rpc_variables.find(nd)) { + rpc_variables.push_back(nd); + } + } + } + } + } + + top = top->get_parent_class(); + } + + // Sort so we are 100% that they are always the same. + rpc_functions.sort_custom<SortNetData>(); + rpc_variables.sort_custom<SortNetData>(); + return OK; } @@ -3325,6 +3365,78 @@ int CSharpScript::get_member_line(const StringName &p_member) const { return -1; } +MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const { + + if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) + return MultiplayerAPI::RPC_MODE_REMOTE; + if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) + return MultiplayerAPI::RPC_MODE_MASTER; + if (p_member->has_attribute(CACHED_CLASS(PuppetAttribute))) + return MultiplayerAPI::RPC_MODE_PUPPET; + if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute))) + return MultiplayerAPI::RPC_MODE_REMOTESYNC; + if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute))) + return MultiplayerAPI::RPC_MODE_MASTERSYNC; + if (p_member->has_attribute(CACHED_CLASS(PuppetSyncAttribute))) + return MultiplayerAPI::RPC_MODE_PUPPETSYNC; + + return MultiplayerAPI::RPC_MODE_DISABLED; +} + +Vector<ScriptNetData> CSharpScript::get_rpc_methods() const { + return rpc_functions; +} + +uint16_t CSharpScript::get_rpc_method_id(const StringName &p_method) const { + for (int i = 0; i < rpc_functions.size(); i++) { + if (rpc_functions[i].name == p_method) { + return i; + } + } + return UINT16_MAX; +} + +StringName CSharpScript::get_rpc_method(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName()); + return rpc_functions[p_rpc_method_id].name; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rpc_method_id].mode; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode(const StringName &p_method) const { + return get_rpc_mode_by_id(get_rpc_method_id(p_method)); +} + +Vector<ScriptNetData> CSharpScript::get_rset_properties() const { + return rpc_variables; +} + +uint16_t CSharpScript::get_rset_property_id(const StringName &p_variable) const { + for (int i = 0; i < rpc_variables.size(); i++) { + if (rpc_variables[i].name == p_variable) { + return i; + } + } + return UINT16_MAX; +} + +StringName CSharpScript::get_rset_property(const uint16_t p_rset_member_id) const { + ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName()); + return rpc_variables[p_rset_member_id].name; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const { + ERR_FAIL_COND_V(p_rset_member_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rset_member_id].mode; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rset_mode(const StringName &p_variable) const { + return get_rset_mode_by_id(get_rset_property_id(p_variable)); +} + Error CSharpScript::load_source_code(const String &p_path) { Error ferr = read_all_file_utf8(p_path, source); @@ -3437,7 +3549,7 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r "Compile", ProjectSettings::get_singleton()->globalize_path(p_path)); } else { - ERR_PRINTS("C# project could not be created; cannot add file: '" + p_path + "'."); + ERR_PRINT("C# project could not be created; cannot add file: '" + p_path + "'."); } } #endif |
