Browse Source

Merge pull request #42731 from opl-/fix/csharpscript-load-code-duplication

Fix code duplication in CSharpScript
Rémi Verschelde 4 years ago
parent
commit
f2002afae7
2 changed files with 75 additions and 116 deletions
  1. 74 116
      modules/mono/csharp_script.cpp
  2. 1 0
      modules/mono/csharp_script.h

+ 74 - 116
modules/mono/csharp_script.cpp

@@ -975,7 +975,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
 			script->signals_invalidated = true;
 
 			script->reload(p_soft_reload);
-			script->update_exports();
 
 			if (!script->valid) {
 				script->pending_reload_instances.clear();
@@ -2955,13 +2954,24 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon
 
 	CRASH_COND(p_script->native == nullptr);
 
+	p_script->valid = true;
+
+	update_script_class_info(p_script);
+
+#ifdef TOOLS_ENABLED
+	p_script->_update_member_info_no_exports();
+#endif
+}
+
+// Extract information about the script using the mono class.
+void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
 	GDMonoClass *base = p_script->script_class->get_parent_class();
 
+	// `base` should only be set if the script is a user defined type.
 	if (base != p_script->native) {
 		p_script->base = base;
 	}
 
-	p_script->valid = true;
 	p_script->tool = p_script->script_class->has_attribute(CACHED_CLASS(ToolAttribute));
 
 	if (!p_script->tool) {
@@ -2996,17 +3006,74 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon
 
 	p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
 
-	// Need to fetch method from base classes as well
+	p_script->rpc_functions.clear();
+	p_script->rpc_variables.clear();
+
 	GDMonoClass *top = p_script->script_class;
 	while (top && top != p_script->native) {
+		// Fetch methods from base classes as well
 		top->fetch_methods_with_godot_api_checks(p_script->native);
+
+		// Update RPC info
+		{
+			Vector<GDMonoMethod *> methods = top->get_all_methods();
+			for (int i = 0; i < methods.size(); i++) {
+				if (!methods[i]->is_static()) {
+					MultiplayerAPI::RPCMode mode = p_script->_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 == p_script->rpc_functions.find(nd)) {
+							p_script->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 = p_script->_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 == p_script->rpc_variables.find(nd)) {
+							p_script->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 = p_script->_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 == p_script->rpc_variables.find(nd)) {
+							p_script->rpc_variables.push_back(nd);
+						}
+					}
+				}
+			}
+		}
+
 		top = top->get_parent_class();
 	}
 
+	// Sort so we are 100% that they are always the same.
+	p_script->rpc_functions.sort_custom<SortNetData>();
+	p_script->rpc_variables.sort_custom<SortNetData>();
+
 	p_script->load_script_signals(p_script->script_class, p_script->native);
-#ifdef TOOLS_ENABLED
-	p_script->_update_member_info_no_exports();
-#endif
 }
 
 bool CSharpScript::can_instance() const {
@@ -3305,124 +3372,15 @@ Error CSharpScript::reload(bool p_keep_state) {
 			print_verbose("Found class " + script_class->get_full_name() + " for script " + get_path());
 #endif
 
-			tool = script_class->has_attribute(CACHED_CLASS(ToolAttribute));
-
-			if (!tool) {
-				GDMonoClass *nesting_class = script_class->get_nesting_class();
-				tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute));
-			}
-
-#if TOOLS_ENABLED
-			if (!tool) {
-				tool = script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly();
-			}
-#endif
-
 			native = GDMonoUtils::get_class_native_base(script_class);
 
 			CRASH_COND(native == nullptr);
 
-			GDMonoClass *base_class = script_class->get_parent_class();
-
-			if (base_class != native) {
-				base = base_class;
-			}
-
-#ifdef DEBUG_ENABLED
-			// For debug builds, we must fetch from all native base methods as well.
-			// Native base methods must be fetched before the current class.
-			// Not needed if the script class itself is a native class.
+			update_script_class_info(this);
 
-			if (script_class != native) {
-				GDMonoClass *native_top = native;
-				while (native_top) {
-					native_top->fetch_methods_with_godot_api_checks(native);
-
-					if (native_top == CACHED_CLASS(GodotObject)) {
-						break;
-					}
-
-					native_top = native_top->get_parent_class();
-				}
-			}
-#endif
-
-			script_class->fetch_methods_with_godot_api_checks(native);
-
-			// Need to fetch method from base classes as well
-			GDMonoClass *top = script_class;
-			while (top && top != native) {
-				top->fetch_methods_with_godot_api_checks(native);
-				top = top->get_parent_class();
-			}
-
-			load_script_signals(script_class, native);
 			_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;
 	}
 

+ 1 - 0
modules/mono/csharp_script.h

@@ -164,6 +164,7 @@ private:
 	// Do not use unless you know what you are doing
 	friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
 	static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native);
+	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);
 
 	MultiplayerAPI::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;