GodotModding / GodotModding/godot-mod-loader

Using both Extension and Hook to modify the same function causes the game to crash

Open
#571 0 comments 1 reaction 0 assignees View on GitHub
4.x bug documentation
Dominant language
GDScript
Stars
675
Forks
54
Avg merge
2m
Merged PRs (30d)
2

Description

## Description

- This issue commonly occurs when different mods modify the same function using **Extension** and **Hook** simultaneously.
- Unrelated to the modified code itself, even if both sides only change it to simply call the original function.
- It is not a typical function-level code conflict caused by two mods modifying the same function. Instead, it is specifically a **conflict between the two modification methods (Extension vs Hook)**.
- If Extension and Hook are used on **different functions within the same file**, the issue does not occur.

The official documentation provides the following recommendation:
`Hooks are slightly more complex to use and little less powerful than Script Extensions, so prefer using those if possible.`

And about Mod Hooks:
`The main feature of mod hooks is that they can mod global classes - scripts which use class_name to be globally accessible. Global classes have a bug which prevents us from using extensions.`

If all mod developers strictly followed this recommendation, the situation of using mixed modification methods (Extension and Hook) on the same `.gd` file (or even the same function) would not happen, and the issue could be avoided.
However, it should be noted that this recommendation is not specifically aimed at this issue. It is a gentle guideline rather than a strict rule or warning, and it does not describe the potential severe consequences of not following it, so some developers may have overlooked it.

## Error Log

Excerpt from the log:

```
SUCCESS ModLoader: DONE: Completely finished loading mods
USER SCRIPT ERROR: Parse Error: Could not resolve super class inheritance from "res://content/caves/mushroomcave/MushroomCave.gd".
at: GDScript::reload (res://mods-unpacked/Abevol-OffScreenResourceIndicators/extensions/content/caves/mushroomcave/MushroomCave.gd:0)
ERROR: Failed to load script "res://mods-unpacked/Abevol-OffScreenResourceIndicators/extensions/content/caves/mushroomcave/MushroomCave.gd" with error "Parse error".
at: ResourceFormatLoaderGDScript::load (modules\gdscript\gdscript.cpp:2726)
USER SCRIPT ERROR: Parse Error: Could not resolve super class inheritance from "res://content/caves/mushroomcave/MushroomCave.gd".
at: GDScript::reload (res://mods-unpacked/Abevol-OffScreenResourceIndicators/extensions/content/caves/mushroomcave/MushroomCave.gd:0)
```

Full log: [godot.log](https://github.com/user-attachments/files/21835169/godot.log)

## Test Code

- The test code was minimized to reduce interference from unrelated factors.
- Before each test, the `mod-hooks.zip` file was deleted to avoid issues from cached code.
- The results for both `ModLoaderMod.add_hook` and `ModLoaderMod.install_script_hooks` were identical, so only one is shown here.

### Using Extension

```gdscript
func install_script_extensions() -> void:
var scripts = [
"res://content/caves/mushroomcave/MushroomCave.gd",
]

for script_path in scripts:
var relative_path = script_path.trim_prefix("res://")
var extension_path = extensions_dir_path.path_join(relative_path)
ModLoaderLog.info("Install script extension: " + script_path + " -> " + extension_path, LOG_NAME)
ModLoaderMod.install_script_extension(extension_path)
```

Extension code for `MushroomCave.gd`:

```gdscript
extends "res://content/caves/mushroomcave/MushroomCave.gd"

# Test modifying the same function
func _process(delta):
super(delta)

# Test modifying a different function
# func useHit(keeper: Keeper) -> bool:
# return super(keeper)
```

### Using Hook

```gdscript
func install_script_hook_test() -> void:
ModLoaderMod.add_hook(_processForMushroomCave, "res://content/caves/mushroomcave/MushroomCave.gd", "_process")

func _processForMushroomCave(chain: ModLoaderHookChain, delta):
chain.execute_next([delta])
```

## Environment

* OS: Windows 11
* Game: Dome Keeper
* Game Engine: godotsteam v4.2.2

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.