hooks.gd 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. @tool
  2. class_name _ModLoaderHooks
  3. extends Object
  4. # This Class provides utility functions for working with Mod Hooks.
  5. # Currently all of the included functions are internal and should only be used by the mod loader itself.
  6. # Functions with external use are exposed through the ModLoaderMod class.
  7. const LOG_NAME := "ModLoader:Hooks"
  8. static var any_mod_hooked := false
  9. ## Internal ModLoader method. [br]
  10. ## To add hooks from a mod use [method ModLoaderMod.add_hook].
  11. static func add_hook(mod_callable: Callable, script_path: String, method_name: String) -> void:
  12. any_mod_hooked = true
  13. var hash := get_hook_hash(script_path, method_name)
  14. if not ModLoaderStore.modding_hooks.has(hash):
  15. ModLoaderStore.modding_hooks[hash] = []
  16. ModLoaderStore.modding_hooks[hash].push_back(mod_callable)
  17. ModLoaderLog.debug('Added hook "%s" to method: "%s" in script: "%s"'
  18. % [mod_callable.get_method(), method_name, script_path], LOG_NAME
  19. )
  20. if not ModLoaderStore.hooked_script_paths.has(script_path):
  21. ModLoaderStore.hooked_script_paths[script_path] = [method_name]
  22. elif not ModLoaderStore.hooked_script_paths[script_path].has(method_name):
  23. ModLoaderStore.hooked_script_paths[script_path].append(method_name)
  24. static func call_hooks(vanilla_method: Callable, args: Array, hook_hash: int) -> Variant:
  25. var hooks: Array = ModLoaderStore.modding_hooks.get(hook_hash, [])
  26. if hooks.is_empty():
  27. return vanilla_method.callv(args)
  28. var chain := ModLoaderHookChain.new(vanilla_method.get_object(), [vanilla_method] + hooks)
  29. return chain.execute_next(args)
  30. static func call_hooks_async(vanilla_method: Callable, args: Array, hook_hash: int) -> Variant:
  31. var hooks: Array = ModLoaderStore.modding_hooks.get(hook_hash, [])
  32. if hooks.is_empty():
  33. return await vanilla_method.callv(args)
  34. var chain := ModLoaderHookChain.new(vanilla_method.get_object(), [vanilla_method] + hooks)
  35. return await chain.execute_next_async(args)
  36. static func get_hook_hash(path: String, method: String) -> int:
  37. return hash(path + method)
  38. static func on_new_hooks_created() -> void:
  39. if ModLoaderStore.ml_options.disable_restart:
  40. ModLoaderLog.debug("Mod Loader handled restart is disabled.", LOG_NAME)
  41. return
  42. ModLoaderLog.debug("Instancing restart notification scene from path: %s" % [ModLoaderStore.ml_options.restart_notification_scene_path], LOG_NAME)
  43. var restart_notification_scene = load(ModLoaderStore.ml_options.restart_notification_scene_path).instantiate()
  44. ModLoader.add_child(restart_notification_scene)