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

Custom Resources that worked in 4.2.2 do not in 4.3 (does not recognize as resource?) #95789

Open
monk125 opened this issue Aug 19, 2024 · 5 comments · May be fixed by #97302
Open

Custom Resources that worked in 4.2.2 do not in 4.3 (does not recognize as resource?) #95789

monk125 opened this issue Aug 19, 2024 · 5 comments · May be fixed by #97302

Comments

@monk125
Copy link

monk125 commented Aug 19, 2024

Tested versions

No issue in v4.2.2.stable.official [15073af] and previous
First visual(?) errors in v4.3.rc1.official [e343dbb]
First game-ending exception occurs in v4.3.rc2.official [3978628] and later (rc3 and 4.3 tested)

System information

Godot v4.3.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1080 (NVIDIA; 32.0.15.6081) - Intel(R) Core(TM) i5-7600 CPU @ 3.50GHz (4 Threads)

Issue description

Short version, something's wacky with my custom resources since I updated to 4.3 from 4.2.2

I have a very simple resource which looks like this:

class_name Infusion
extends Resource

@export var air: int = 0
@export var earth: int = 0
@export var fire: int = 0
@export var ice: int = 0

Which is used by another custom resource (CombatCard) as an export variable, like so:
@export var infusion:= Infusion.new()

In 4.2.2, this worked as I expected, with CombatCards that did not have a custom Infusion set defaulting to a new Infusion instance with 0s across the board. Additionally, the autocomplete had that custom resource icon (the cube thing) for the resources, as shown.
image

This is not the case when I load that same project in 4.3.rc1 or later:
image

You'll notice that the Infusion resource (which extends Resource) has no symbol. Additionally, QuestInfoScreen now shows the icon for ColorRect, which is what that class extends, whereas previously it also had the cube icon. I don't know if that's intentional.

The project still seems to run fine despite this in 4.3.rc1. In 4.3.rc2, rc3, or 4.3, however, it causes the project to crash when run with the following error.

image
image

Invalid call. Nonexistent function 'new' in base 'GDScript'
at function: @implicit_new

Steps to reproduce

I've been able to reproduce the visual portion of this issue in a brand new project (here, MyCustomResource is another dead simple class that extends Resource and has a single member variable of type int, not even exported)
image

I've not been able to reproduce the crash yet. I suspect it has something to do with loading or preloading of the parent CombatCard resource, or scenes which use that resource? I don't really know, feel free to ask if you want more info.

My next plan is to try removing the Infusion class and just storing those variables in the parent resource, and see whether anything else is broken. I should also have access to Linux Mint in the short term to check if it's OS related.

If you think an MRP would help, I can try to pare down my main project a bit and upload that. I'm open to suggestions, if there's anything I can do to help let me know, in the meantime I'll carry on development in 4.2.2

Minimal reproduction project (MRP)

95789MRP.zip

EDIT: Did some hacking and slashing on the project, and got an MRP. It probably won't run well, but the important thing is that it results in the issue for me (before any other issue, anyway)

Step 1: Open Project
Step 2: Run Project

Project will throw the error before showing the main menu

@matheusmdx
Copy link
Contributor

The icon not appearing in autocompletion is a regression from #91923:

image


The invalid call error i wasn't able to reproduce in stable version. Just for record, i remember we had a similar bug but was already solved in dev/beta versions: #92610

@monk125
Copy link
Author

monk125 commented Aug 20, 2024

Added MRP to OP. This project makes it to the main menu in 4.2.2, but throws the error in 4.3

@matheusmdx
Copy link
Contributor

With the mrp i was able to reproduce the error, bisected to #94871

image


A detail is if i copy the infusion.gd to another project and use new() will work without problem so seems something else in the scene/project is messing up the function call

@akien-mga
Copy link
Member

CC @rune-scape

@rune-scape
Copy link
Contributor

stacktrace of where the call error flag is set,

GDScript::_new(GDScript * const this, const Variant ** p_args, int p_argcount, Callable::CallError & r_error) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:207)
MethodBindVarArgTR<GDScript, Variant>::call(const MethodBindVarArgTR<GDScript, Variant> * const this, Object * p_object, const Variant ** p_args, int p_arg_count, Callable::CallError & r_error) (/home/rune/git/godot/core/object/method_bind.h:271)
GDScriptFunction::call(GDScriptFunction * const this, GDScriptInstance * p_instance, const Variant ** p_args, int p_argcount, Callable::CallError & r_err, GDScriptFunction::CallState * p_state) (/home/rune/git/godot/modules/gdscript/gdscript_vm.cpp:1874)
GDScript::_super_implicit_constructor(GDScript * const this, GDScript * p_script, GDScriptInstance * p_instance, Callable::CallError & r_error) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:140)
GDScript::_super_implicit_constructor(GDScript * const this, GDScript * p_script, GDScriptInstance * p_instance, Callable::CallError & r_error) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:133)
GDScript::_create_instance(GDScript * const this, const Variant ** p_args, int p_argcount, Object * p_owner, bool p_is_ref_counted, Callable::CallError & r_error) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:169)
GDScript::instance_create(GDScript * const this, Object * p_this) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:420)
Object::set_script(Object * const this, const Variant & p_script) (/home/rune/git/godot/core/object/object.cpp:941)
Object::set(Object * const this, const StringName & p_name, const Variant & p_value, bool * r_valid) (/home/rune/git/godot/core/object/object.cpp:255)
ResourceLoaderText::load(ResourceLoaderText * const this) (/home/rune/git/godot/scene/resources/resource_format_text.cpp:760)
ResourceFormatLoaderText::load(ResourceFormatLoaderText * const this, const String & p_path, const String & p_original_path, Error * r_error, bool p_use_sub_threads, float * r_progress, ResourceFormatLoader::CacheMode p_cache_mode) (/home/rune/git/godot/scene/resources/resource_format_text.cpp:1392)
ResourceLoader::_load(const String & p_path, const String & p_original_path, const String & p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error * r_error, bool p_use_sub_threads, float * r_progress) (/home/rune/git/godot/core/io/resource_loader.cpp:269)
ResourceLoader::_thread_load_function(void * p_userdata) (/home/rune/git/godot/core/io/resource_loader.cpp:326)
ResourceLoader::_load_start(const String & p_path, const String & p_type_hint, ResourceLoader::LoadThreadMode p_thread_mode, ResourceFormatLoader::CacheMode p_cache_mode) (/home/rune/git/godot/core/io/resource_loader.cpp:542)
ResourceLoaderText::load(ResourceLoaderText * const this) (/home/rune/git/godot/scene/resources/resource_format_text.cpp:472)
ResourceFormatLoaderText::load(ResourceFormatLoaderText * const this, const String & p_path, const String & p_original_path, Error * r_error, bool p_use_sub_threads, float * r_progress, ResourceFormatLoader::CacheMode p_cache_mode) (/home/rune/git/godot/scene/resources/resource_format_text.cpp:1392)
ResourceLoader::_load(const String & p_path, const String & p_original_path, const String & p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error * r_error, bool p_use_sub_threads, float * r_progress) (/home/rune/git/godot/core/io/resource_loader.cpp:269)
ResourceLoader::_thread_load_function(void * p_userdata) (/home/rune/git/godot/core/io/resource_loader.cpp:326)
ResourceLoader::_load_start(const String & p_path, const String & p_type_hint, ResourceLoader::LoadThreadMode p_thread_mode, ResourceFormatLoader::CacheMode p_cache_mode) (/home/rune/git/godot/core/io/resource_loader.cpp:542)
ResourceLoader::load(const String & p_path, const String & p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error * r_error) (/home/rune/git/godot/core/io/resource_loader.cpp:458)
GDScriptAnalyzer::reduce_preload(GDScriptAnalyzer * const this, GDScriptParser::PreloadNode * p_preload) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:4465)
GDScriptAnalyzer::reduce_expression(GDScriptAnalyzer * const this, GDScriptParser::ExpressionNode * p_expression, bool p_is_root) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:2499)
GDScriptAnalyzer::resolve_assignable(GDScriptAnalyzer * const this, GDScriptParser::AssignableNode * p_assignable, const char * p_kind) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:1902)
GDScriptAnalyzer::resolve_constant(GDScriptAnalyzer * const this, GDScriptParser::ConstantNode * p_constant, bool p_is_local) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:2030)
GDScriptAnalyzer::resolve_class_member(GDScriptAnalyzer * const this, GDScriptParser::ClassNode * p_class, int p_index, const GDScriptParser::Node * p_source) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:1025)
GDScriptAnalyzer::resolve_class_interface(GDScriptAnalyzer * const this, GDScriptParser::ClassNode * p_class, const GDScriptParser::Node * p_source) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:1231)
GDScriptAnalyzer::resolve_class_interface(GDScriptAnalyzer * const this, GDScriptParser::ClassNode * p_class, bool p_recursive) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:1259)
GDScriptAnalyzer::resolve_interface(GDScriptAnalyzer * const this) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:5884)
GDScriptAnalyzer::analyze(GDScriptAnalyzer * const this) (/home/rune/git/godot/modules/gdscript/gdscript_analyzer.cpp:5918)
GDScript::reload(GDScript * const this, bool p_keep_state) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:820)
GDScriptCache::get_full_script(const String & p_path, Error & r_error, const String & p_owner, bool p_update_from_disk) (/home/rune/git/godot/modules/gdscript/gdscript_cache.cpp:373)
GDScriptCache::finish_compiling(const String & p_owner) (/home/rune/git/godot/modules/gdscript/gdscript_cache.cpp:413)
GDScriptCompiler::compile(GDScriptCompiler * const this, const GDScriptParser * p_parser, GDScript * p_script, bool p_keep_state) (/home/rune/git/godot/modules/gdscript/gdscript_compiler.cpp:3281)
GDScript::reload(GDScript * const this, bool p_keep_state) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:839)
GDScriptCache::get_full_script(const String & p_path, Error & r_error, const String & p_owner, bool p_update_from_disk) (/home/rune/git/godot/modules/gdscript/gdscript_cache.cpp:373)
GDScriptCache::finish_compiling(const String & p_owner) (/home/rune/git/godot/modules/gdscript/gdscript_cache.cpp:413)
GDScriptCompiler::compile(GDScriptCompiler * const this, const GDScriptParser * p_parser, GDScript * p_script, bool p_keep_state) (/home/rune/git/godot/modules/gdscript/gdscript_compiler.cpp:3281)
GDScript::reload(GDScript * const this, bool p_keep_state) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:839)
GDScriptCache::get_full_script(const String & p_path, Error & r_error, const String & p_owner, bool p_update_from_disk) (/home/rune/git/godot/modules/gdscript/gdscript_cache.cpp:373)
GDScriptCache::finish_compiling(const String & p_owner) (/home/rune/git/godot/modules/gdscript/gdscript_cache.cpp:413)
GDScriptCompiler::compile(GDScriptCompiler * const this, const GDScriptParser * p_parser, GDScript * p_script, bool p_keep_state) (/home/rune/git/godot/modules/gdscript/gdscript_compiler.cpp:3281)
GDScript::reload(GDScript * const this, bool p_keep_state) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:839)
GDScriptCache::get_full_script(const String & p_path, Error & r_error, const String & p_owner, bool p_update_from_disk) (/home/rune/git/godot/modules/gdscript/gdscript_cache.cpp:373)
ResourceFormatLoaderGDScript::load(ResourceFormatLoaderGDScript * const this, const String & p_path, const String & p_original_path, Error * r_error, bool p_use_sub_threads, float * r_progress, ResourceFormatLoader::CacheMode p_cache_mode) (/home/rune/git/godot/modules/gdscript/gdscript.cpp:2947)
ResourceLoader::_load(const String & p_path, const String & p_original_path, const String & p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error * r_error, bool p_use_sub_threads, float * r_progress) (/home/rune/git/godot/core/io/resource_loader.cpp:269)
ResourceLoader::_thread_load_function(void * p_userdata) (/home/rune/git/godot/core/io/resource_loader.cpp:326)
ResourceLoader::_load_start(const String & p_path, const String & p_type_hint, ResourceLoader::LoadThreadMode p_thread_mode, ResourceFormatLoader::CacheMode p_cache_mode) (/home/rune/git/godot/core/io/resource_loader.cpp:542)
ResourceLoader::load(const String & p_path, const String & p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error * r_error) (/home/rune/git/godot/core/io/resource_loader.cpp:458)
Main::start() (/home/rune/git/godot/main/main.cpp:3791)
main(int argc, char ** argv) (/home/rune/git/godot/platform/linuxbsd/godot_linuxbsd.cpp:84)

it goes like this:
load "res://globals/events.gd"
-> finish compiling "res://cards/combat cards/card.gd"
-> finish compiling "res://cards/combat cards/combat_card.gd"
-> analyze "res://heroes/hero_stats.gd"
-> preload "res://cards/combat cards/Cryomancer/cryomancer_card_pool.tres"
-> load "res://cards/combat cards/Cryomancer/frostbite.tres"
-> instantiate "res://cards/combat cards/Cryomancer/frostbite.gd"
-> instantiate "res://cards/combat cards/combat_card.gd"
-> instantiate "res://cards/infusion.gd" (invalid)

seems like a dependancy issue with resources, where 'combat_card.gd' is valid and in the full_gdscript_cache so when 'frostbite.tres' tries to instantiate it, it thinks everything is good, but 'infusion.gd' is still shallow (even tho it could be loaded ok) bc its later on in the dependencies to compile (it was next to compile, i checked)

scripts could maybe have a shallow flag and call reload on themselves if instantiated when shallow, but the system is kinda complicated and that seems like patchwork solution that could create more problems

an error print when trying to instantiate a partially loaded script would be helpful for users

@github-project-automation github-project-automation bot moved this to For team assessment in GDScript Issue Triage Sep 10, 2024
@dalexeev dalexeev moved this from For team assessment to Fix pending review in GDScript Issue Triage Sep 22, 2024
@dalexeev dalexeev added this to the 4.4 milestone Sep 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Fix pending review
Development

Successfully merging a pull request may close this issue.

6 participants