dialogic-godot / dialogic

💬 Create Dialogs, Visual Novels, RPGs, and manage Characters with Godot to create your Game!
https://dialogic.pro
MIT License
3.42k stars 206 forks source link

Extensions attempting to add custom text effects fail with an error #2218

Closed a-soulspark closed 3 weeks ago

a-soulspark commented 3 weeks ago

The problem

Attempting to add custom text effects through custom Extensions causes an error.

Describe the bug Likely due to the ordering in which different modules/extensions are loaded, the Text subsystem (which is responsible for Text Effects) gets ready before extension's subsystems gets created, which causes it to fail to create a Callable for the custom effect's method.

The error looks something like:

DialogicGameHandler.gd:346 @ get_subsystem(): Node not found: "MyExtension" (relative to "/root/Dialogic").
  <C++ Error>    Method/function failed. Returning: nullptr
  <C++ Source>   scene/main/node.cpp:1651 @ get_node()
  <Stack Trace>  DialogicGameHandler.gd:346 @ get_subsystem()
                 subsystem_text.gd:321 @ collect_text_effects()    # this is the line that causes the problem
                 subsystem_text.gd:390 @ _ready()
                 DialogicGameHandler.gd:355 @ add_subsystem()
                 DialogicGameHandler.gd:334 @ collect_subsystems()
                 DialogicGameHandler.gd:137 @ _ready()

with the troublesome line causing the error being (in the Dialogic version I am using)

text_effects[effect.command]['callable'] = Callable(dialogic.get_subsystem(effect.subsystem), effect.method)

which apparently tries to get the extension's subsystem node before it was created.

To Reproduce Steps to reproduce the behavior:

  1. Create a new extension with a Subsystem
  2. In its index.gd file, add a definition for a text effect. Something like:
    
    # index.gd

[...]

func _get_text_effects() -> Array[Dictionary]: return [ {'command':'foobar', 'subsystem':'ExtensionName', 'method':'effect_foobar'}, ]

3. Run the project
4. See error

**System (please complete the following information):**
 - OS: Windows
 - Godot Version: 4.2.2
 - Dialogic Version: 2.0 alpha-13

## Solutions

**Workaround**

I made the `collect_text_effects` method call in `subsystem_text.gd @ _ready()` be set to deferred, but there should be a better solution by just better ordering the loading steps, which I can't figure out...

```gd
# subsystem_text.gd

# [...]

func _ready():
    collect_character_names()
    # collect_text_effects()
    collect_text_effects.call_deferred()
    collect_text_modifiers()

# [...]
a-soulspark commented 3 weeks ago

Doing a little more digging, it seems like the post_install method of DialogicSubsystem is designed specifically for this purpose. I also checked the collect_text_modifiers function and it seems to have similar logic to collect_text_effects, so it is also affected by this issue! Moving the collection of text effects/modifiers to the post_install function, in my project, it seems to behave as intended.

Jowan-Spooner commented 3 weeks ago

Cool catch. Thanks for letting us know. We should certainly move it into the post_install method!