Fix code duplication in CSharpScript

Removes code duplication between `CSharpScript::reload()` and `CSharpScript::initialize_for_managed_type()`.

Removes a redundant `CSharpScript::update_exports()` call in `CSharpLanguage::reload_assemblies()` as `CSharpScript::reload()` already calls it when appropriate.

Fixes missing update of RPC information in `CSharpScript::initialize_for_managed_type()`.
This commit is contained in:
opl- 2020-10-12 09:48:29 +02:00
parent bf37ab52b3
commit e4d20ae373
2 changed files with 75 additions and 116 deletions

View file

@ -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();
update_script_class_info(this);
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.
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;
}

View file

@ -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;