Merge pull request #130 from limbonaut/fix-custom-task-issues

Fix custom task issues - a rare crash & a sticky name/script issue, and improve error handling
This commit is contained in:
Serhii Snitsaruk 2024-06-03 11:08:21 +02:00 committed by GitHub
commit 2c8e0d2da0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 33 deletions

View File

@ -118,31 +118,31 @@ bool BTTask::is_displayed_collapsed() const {
}
String BTTask::get_task_name() {
if (data.custom_name.is_empty()) {
#ifdef LIMBOAI_MODULE
if (get_script_instance() && get_script_instance()->has_method(LW_NAME(_generate_name))) {
if (unlikely(!get_script_instance()->get_script()->is_tool())) {
ERR_PRINT(vformat("BTTask: Task script should be a \"tool\" script!"));
} else {
return get_script_instance()->call(LimboStringNames::get_singleton()->_generate_name);
}
}
return _generate_name();
#elif LIMBOAI_GDEXTENSION
Ref<Script> task_script = get_script();
if (task_script.is_valid() && task_script->is_tool()) {
Variant call_result;
VCALL_OR_NATIVE_V(_generate_name, Variant, call_result);
ERR_FAIL_COND_V(call_result.get_type() == Variant::NIL, _generate_name());
String task_name = call_result;
ERR_FAIL_COND_V(task_name.is_empty(), _generate_name());
return task_name;
} else {
return _generate_name();
}
#endif
if (!data.custom_name.is_empty()) {
return data.custom_name;
}
return data.custom_name;
Ref<Script> task_script = get_script();
if (task_script.is_valid()) {
bool has_generate_method = has_method(LW_NAME(_generate_name));
ERR_FAIL_COND_V_MSG(has_generate_method && !task_script->is_tool(), _generate_name(), vformat("BTTask: @tool annotation is required if _generate_name is defined: %s", task_script->get_path()));
if (task_script->is_tool() && has_generate_method) {
String call_result;
VCALL_V(_generate_name, call_result);
if (call_result.is_empty() || call_result == "<null>") {
// Force reset script instance.
set_script(Variant());
set_script(task_script);
// Retry.
VCALL_V(_generate_name, call_result);
}
ERR_FAIL_COND_V_MSG(call_result.is_empty() || call_result == "<null>", _generate_name(), vformat("BTTask: _generate_name() failed to return a proper name string (%s)", task_script->get_path()));
return call_result;
}
}
return _generate_name();
}
Ref<BTTask> BTTask::get_root() const {

View File

@ -124,25 +124,35 @@ void LimboAIEditor::_add_task_with_prototype(const Ref<BTTask> &p_prototype) {
}
Ref<BTTask> LimboAIEditor::_create_task_by_class_or_path(const String &p_class_or_path) const {
ERR_FAIL_COND_V(p_class_or_path.is_empty(), nullptr);
Ref<BTTask> ret;
if (p_class_or_path.begins_with("res:")) {
Ref<Script> s = RESOURCE_LOAD(p_class_or_path, "Script");
ERR_FAIL_COND_V_MSG(s.is_null(), nullptr, vformat("LimboAI: Failed to instantiate task. Bad script: %s", p_class_or_path));
Variant inst = ClassDB::instantiate(s->get_instance_base_type());
ERR_FAIL_COND_V_MSG(inst == Variant(), nullptr, vformat("LimboAI: Failed to instantiate base type \"%s\".", s->get_instance_base_type()));
ERR_FAIL_COND_V_MSG(s.is_null(), nullptr, vformat("LimboAI: Can't add task. Bad script: %s", p_class_or_path));
StringName base_type = s->get_instance_base_type();
if (base_type == StringName()) {
// Try reloading script.
s->reload(true);
base_type = s->get_instance_base_type();
}
ERR_FAIL_COND_V_MSG(base_type == StringName(), nullptr, vformat("LimboAI: Can't add task. Bad script: %s", p_class_or_path));
if (unlikely(!((Object *)inst)->is_class("BTTask"))) {
Variant inst = ClassDB::instantiate(base_type);
Object *obj = inst;
ERR_FAIL_NULL_V_MSG(obj, nullptr, vformat("LimboAI: Can't add task. Failed to create base type \"%s\".", base_type));
if (unlikely(!IS_CLASS(obj, BTTask))) {
ERR_PRINT_ED(vformat("LimboAI: Can't add task. Script is not a BTTask: %s", p_class_or_path));
VARIANT_DELETE_IF_OBJECT(inst);
ERR_PRINT(vformat("LimboAI: Failed to instantiate task. Script is not a BTTask: %s", p_class_or_path));
return nullptr;
}
if (inst && s.is_valid()) {
((Object *)inst)->set_script(s);
ret = inst;
}
ret.reference_ptr(Object::cast_to<BTTask>(obj));
ret->set_script(s);
} else {
ERR_FAIL_COND_V(!ClassDB::is_parent_class(p_class_or_path, "BTTask"), nullptr);
ret = ClassDB::instantiate(p_class_or_path);
}
return ret;