Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix custom task issues - a rare crash & a sticky name/script issue, and improve error handling #130

Merged
merged 2 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions bt/tasks/bt_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (!data.custom_name.is_empty()) {
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();
#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
}
return data.custom_name;

return _generate_name();
}

Ref<BTTask> BTTask::get_root() const {
Expand Down
28 changes: 19 additions & 9 deletions editor/limbo_ai_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading