CORE/coreinit.gd
JeremyStarTM 99703cf03e CORE rewrite (#1)
Reviewed-on: StarOpenSource/core#1

Rewrote CORE and improved the startup process and startup time significantly. The documentation has been beefed up too and is now much better. Existing projects may need major refactoring however.
Co-authored-by: JeremyStarTM <jeremystartm@staropensource.de>
Co-committed-by: JeremyStarTM <jeremystartm@staropensource.de>
2023-08-25 14:34:57 +02:00

209 lines
8.3 KiB
GDScript

######################################
# THE CORE FRAMEWORK #
# MADE BY THE STAROPENSOURCE PROJECT #
# AND CONTRIBUTERS (THANK YOU!) #
# #
# COPYRIGHT 2023 THE STAROPENSOURCE #
# PROJECT AND CONTRIBUTERS #
# #
# LICENSED UNDER THE GNU GENERAL #
# PUBLIC LICENSE VERSION 3 (ONLY) #
######################################
extends Node
var loadpath: String = "res://CORE/"
# To workaround the "busy setting up children" issue coreinit.gd
# "reloads" itself. I don't know why it works, but it works.
func _ready() -> void:
if name == "COREINIT":
initialize()
else:
print("coreinit -> \"Fixing\" busy setting up children issue")
var coreinit_raw: Script = ResourceLoader.load(loadpath + "coreinit.gd")
var coreinit: Node = Node.new()
coreinit.name = "COREINIT"
coreinit.set_script(coreinit_raw)
get_tree().root.add_child.call_deferred(coreinit)
if loadpath == "":
coreinit.set_deferred("loathpath","res://CORE/")
else:
coreinit.set_deferred("loadpath",loadpath)
queue_free()
# Bootstraps CORE
func initialize() -> void:
print("coreinit -> Bootstrapping CORE")
# Check requirements and quit if not met
if !check_requirements():
await get_tree().create_timer(0.25).timeout
get_tree().quit(255)
return
# Load module scripts and scenes
print("coreinit -> Loading modules")
var mod_config_raw: Script = ResourceLoader.load(loadpath + "config.gd")
var mod_corelog_raw: PackedScene = ResourceLoader.load(loadpath + "corelog.tscn")
var mod_logger_raw: Script = ResourceLoader.load(loadpath + "logger.gd")
var mod_preprocessor_raw: Script = ResourceLoader.load(loadpath + "preprocessor.gd")
var mod_core_raw: Script = ResourceLoader.load(loadpath + "core.gd")
var mod_misc_raw: Script = ResourceLoader.load(loadpath + "misc.gd")
var mod_debugdisplay_raw: PackedScene = ResourceLoader.load(loadpath + "debugdisplay.tscn")
var mod_splash_raw: PackedScene = ResourceLoader.load(loadpath + "splash.tscn")
var mod_resmgr_raw: Script = ResourceLoader.load(loadpath + "resmgr.gd")
var mod_smgr_raw: Script = ResourceLoader.load(loadpath + "smgr.gd")
var mod_events_raw: Script = ResourceLoader.load(loadpath + "events.gd")
#var mod_cml_raw: Script = ResourceLoader.load(loadpath + "cml.gd")
var mod_mkdown_raw: Script = ResourceLoader.load(loadpath + "mkdown.gd")
# Create nodes and add the raw scripts + give them names
print("coreinit -> Constructing modules")
var mod_config: Node = Node.new()
mod_config.name = "Config"
mod_config.set_script(mod_config_raw)
var mod_preprocessor: Node = Node.new()
mod_preprocessor.name = "Preprocessor"
mod_preprocessor.set_script(mod_preprocessor_raw)
var mod_logger: Node = Node.new()
mod_logger.name = "Logger"
mod_logger.set_script(mod_logger_raw)
var mod_corelog: Node = mod_corelog_raw.instantiate()
mod_corelog.name = "CORELog"
var mod_core: Node = Node.new()
mod_core.name = "CORE"
mod_core.set_script(mod_core_raw)
mod_core.loadpath = loadpath
var mod_misc: Node = Node.new()
mod_misc.name = "Miscellaneous"
mod_misc.set_script(mod_misc_raw)
var mod_debugdisplay: Node = mod_debugdisplay_raw.instantiate()
mod_debugdisplay.name = "DebugDisplay"
var mod_splash: Node = mod_splash_raw.instantiate()
mod_splash.name = "SplashScreen"
var mod_resmgr: Node = Node.new()
mod_resmgr.name = "ResourceManager"
mod_resmgr.set_script(mod_resmgr_raw)
var mod_smgr: Node = Node.new()
mod_smgr.name = "SceneManager"
mod_smgr.set_script(mod_smgr_raw)
var mod_events: Node = Node.new()
mod_events.name = "Events"
mod_events.set_script(mod_events_raw)
#var mod_cml: Node = Node.new()
#mod_cml.name = "ModLoader"
#mod_cml.set_script(mod_cml_raw)
var mod_mkdown: Node = Node.new()
mod_mkdown.name = "Markdown"
mod_mkdown.set_script(mod_mkdown_raw)
# Add all modules to /root/
print("coreinit -> Injecting modules")
get_tree().root.add_child(mod_core)
mod_core.add_child(mod_config)
mod_core.add_child(mod_preprocessor)
mod_core.add_child(mod_logger)
mod_core.add_child(mod_misc)
mod_core.add_child(mod_corelog)
mod_core.add_child(mod_debugdisplay)
mod_core.add_child(mod_splash)
mod_core.add_child(mod_resmgr)
mod_core.add_child(mod_smgr)
#mod_core.add_child(mod_cml)
mod_core.add_child(mod_events)
mod_core.add_child(mod_mkdown)
# Updates references to other modules
print("coreinit -> Updating dependency references")
mod_corelog.core = mod_core
mod_corelog.logger = mod_logger
mod_preprocessor.core = mod_core
mod_preprocessor.logger = mod_logger
mod_logger.core = mod_core
mod_logger.preprocessor = mod_preprocessor
mod_core.logger = mod_logger
mod_core.preprocessor = mod_preprocessor
mod_core.config = mod_config
mod_misc.core = mod_core
mod_debugdisplay.core = mod_core
mod_debugdisplay.misc = mod_misc
mod_splash.core = mod_core
mod_splash.logger = mod_logger
mod_resmgr.core = mod_core
mod_resmgr.logger = mod_logger
mod_smgr.logger = mod_logger
mod_smgr.core = mod_core
mod_smgr.resourcemanager = mod_resmgr
mod_events.core = mod_core
#mod_cml.core = mod_core
#mod_cml.logger = mod_logger
mod_events.logger = mod_logger
mod_mkdown.core = mod_core
mod_mkdown.logger = mod_logger
# Apply config to base modules
print("coreinit -> Applying configuration to base modules")
mod_preprocessor.enabled = get_config(mod_config,"preprocessor_enabled",true)
mod_preprocessor.diagnostic = get_config(mod_config,"preprocessor_diagnostic",false)
mod_logger.enabled = get_config(mod_config,"logger_enabled",true)
mod_logger.diagnostic = get_config(mod_config,"logger_diagnostic",false)
if get_config(mod_config,"corelog_enable",true):
mod_corelog.display()
else:
mod_corelog.dissolve()
# Call initialize() on base modules
print("coreinit -> Initializing base modules")
mod_corelog.initialize()
mod_logger.initialize()
mod_preprocessor.initialize()
# Apply config to all modules
mod_logger.diag("CORE/coreinit.gd","Reloading configuration")
mod_core.reload_config()
# Call initialize() method on all modules
mod_logger.diag("CORE/coreinit.gd","Initializing modules")
#mod_splash.initialize() ## Has no initialize() method
#mod_resmgr.initialize() ## Has no initialize() method
mod_smgr.initialize()
#mod_cml.initialize()
mod_events.initialize()
# Inject init script
mod_logger.diag("CORE/coreinit.gd","Loading init script")
if !FileAccess.file_exists(get_config(mod_config,"startup_script","res://init.gd")):
mod_core.exception("CORE/coreinit.gd","Startup script located at \"" + get_config(mod_config,"startup_script","res://init.gd") + "\" does not exist")
return
var initscr_raw: Script = ResourceLoader.load(get_config(mod_config,"core_initscript","res://init.gd"))
mod_logger.diag("CORE/coreinit.gd","Constructing init script")
var initscr: Node = Node.new()
initscr.name = "InitializationScript"
initscr.set_script(initscr_raw)
mod_logger.diag("CORE/coreinit.gd","Injecting init script")
get_tree().root.add_child(initscr)
mod_logger.diag("CORE/coreinit.gd","Bootstrapped CORE, exiting.")
queue_free()
# Retrieves a key's value from the configuration file
func get_config(config:Node,config_key:StringName,default_value:Variant) -> Variant:
if config.get(config_key) == null:
return default_value
else:
return config.get(config_key)
# Check CORE's requirements
func check_requirements() -> bool:
var engine_version: Dictionary = Engine.get_version_info()
print("coreinit -> Checking CORE requirements")
# Check if Godot major version is exactly 4
if engine_version["major"] != 4:
print("coreinit -> Error: CORE only supports Godot 4.1.stable releases.")
return false
# Check if Godot minor version is exactly 1
if engine_version["minor"] != 1:
print("coreinit -> Error: CORE only supports Godot 4.1.stable releases.")
return false
# Check if Godot release channel is "stable"
if engine_version["status"] != "stable":
print("coreinit -> Error: CORE only supports Godot 4.1.stable releases.")
return false
# Display warning if autoloads are used
if get_tree().root.get_child_count(true) != 2:
print("coreinit -> Warning: We do not recommend using autoloads in your project as bugs may occur.")
# Check if configuration file exists
if !FileAccess.file_exists(loadpath + "config.gd"):
print("coreinit -> Error: The CORE configuration file is missing. Use CORE Manager to repair your project.")
return false
# Success!
return true