godot.gd 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. @tool
  2. class_name _ModLoaderGodot
  3. extends Object
  4. # This Class provides methods for interacting with Godot.
  5. # Currently all of the included methods are internal and should only be used by the mod loader itself.
  6. const LOG_NAME := "ModLoader:Godot"
  7. const AUTOLOAD_CONFIG_HELP_MSG := "To configure your autoloads, go to Project > Project Settings > Autoload."
  8. const ENGINE_VERSION_HEX_4_2_2 := 0x040202
  9. const ENGINE_VERSION_HEX_4_2_0 := 0x040200
  10. static var engine_version_hex: int = Engine.get_version_info().hex
  11. # Check autoload positions:
  12. # Ensure 1st autoload is `ModLoaderStore`, and 2nd is `ModLoader`.
  13. static func check_autoload_positions() -> void:
  14. var override_cfg_path := _ModLoaderPath.get_override_path()
  15. var is_override_cfg_setup := _ModLoaderFile.file_exists(override_cfg_path)
  16. # If the override file exists we assume the ModLoader was setup with the --setup-create-override-cfg cli arg
  17. # In that case the ModLoader will be the last entry in the autoload array
  18. if is_override_cfg_setup:
  19. ModLoaderLog.info("override.cfg setup detected, ModLoader will be the last autoload loaded.", LOG_NAME)
  20. return
  21. # If there are Autoloads that need to be before the ModLoader
  22. # "allow_modloader_autoloads_anywhere" in the ModLoader Options can be enabled.
  23. # With that only the correct order of, ModLoaderStore first and ModLoader second, is checked.
  24. if ModLoaderStore.ml_options.allow_modloader_autoloads_anywhere:
  25. is_autoload_before("ModLoaderStore", "ModLoader", true)
  26. else:
  27. var _pos_ml_store := check_autoload_position("ModLoaderStore", 0, true)
  28. var _pos_ml_core := check_autoload_position("ModLoader", 1, true)
  29. # Check if autoload_name_before is before autoload_name_after
  30. # Returns a bool if the position does not match.
  31. # Optionally triggers a fatal error
  32. static func is_autoload_before(autoload_name_before: String, autoload_name_after: String, trigger_error := false) -> bool:
  33. var autoload_name_before_index := get_autoload_index(autoload_name_before)
  34. var autoload_name_after_index := get_autoload_index(autoload_name_after)
  35. # Check if the Store is before the ModLoader
  36. if not autoload_name_before_index < autoload_name_after_index:
  37. var error_msg := (
  38. "Expected %s ( position: %s ) to be loaded before %s ( position: %s ). "
  39. % [autoload_name_before, autoload_name_before_index, autoload_name_after, autoload_name_after_index]
  40. )
  41. var help_msg := AUTOLOAD_CONFIG_HELP_MSG if OS.has_feature("editor") else ""
  42. if trigger_error:
  43. var final_message = error_msg + help_msg
  44. push_error(final_message)
  45. ModLoaderLog._write_to_log_file(final_message)
  46. ModLoaderLog._write_to_log_file(JSON.stringify(get_stack(), " "))
  47. assert(false, final_message)
  48. return false
  49. return true
  50. # Check the index position of the provided autoload (0 = 1st, 1 = 2nd, etc).
  51. # Returns a bool if the position does not match.
  52. # Optionally triggers a fatal error
  53. static func check_autoload_position(autoload_name: String, position_index: int, trigger_error := false) -> bool:
  54. var autoload_array := get_autoload_array()
  55. var autoload_index := autoload_array.find(autoload_name)
  56. var position_matches := autoload_index == position_index
  57. if not position_matches and trigger_error:
  58. var error_msg := (
  59. "Expected %s to be the autoload in position %s, but this is currently %s. "
  60. % [autoload_name, str(position_index + 1), autoload_array[position_index]]
  61. )
  62. var help_msg := AUTOLOAD_CONFIG_HELP_MSG if OS.has_feature("editor") else ""
  63. var final_message = error_msg + help_msg
  64. push_error(final_message)
  65. ModLoaderLog._write_to_log_file(final_message)
  66. ModLoaderLog._write_to_log_file(JSON.stringify(get_stack(), " "))
  67. assert(false, final_message)
  68. return position_matches
  69. # Get an array of all autoloads -> ["autoload/AutoloadName", ...]
  70. static func get_autoload_array() -> Array:
  71. var autoloads := []
  72. # Get all autoload settings
  73. for prop in ProjectSettings.get_property_list():
  74. var name: String = prop.name
  75. if name.begins_with("autoload/"):
  76. autoloads.append(name.trim_prefix("autoload/"))
  77. return autoloads
  78. # Get the index of a specific autoload
  79. static func get_autoload_index(autoload_name: String) -> int:
  80. var autoloads := get_autoload_array()
  81. var autoload_index := autoloads.find(autoload_name)
  82. return autoload_index
  83. static func is_version_below(version_hex: int) -> bool:
  84. return engine_version_hex < version_hex
  85. static func is_version_above(version_hex: int) -> bool:
  86. return engine_version_hex > version_hex