CORE/core.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

231 lines
10 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
# CORE modules
var logger: Node = null
var preprocessor: Node = null
var config: Node = null
# Version
const version: Dictionary = {"type":"source","releasebuild":0,"full":"source 0"}
# Protection mode
var protection_mode: bool = false
# Development mode
var development_mode: bool = false
# Loadpath (from coreinit.gd)
var loadpath: String = ""
# Errors
enum Errors {
OK,
CORE_PROTECTIONMODE,
CORE_EXCEPTION,
CORE_INVALID_MODULE,
RESOURCEMANAGER_ALREADY_EXISTS,
RESOURCEMANAGER_INVALID_FILEPATH,
RESOURCEMANAGER_RESOURCE_MISSING,
RESOURCEMANAGER_BATCH_EMPTY,
SCENEMANAGER_ALREADY_LOADED,
SCENEMANAGER_NOT_LOADED,
SCENEMANAGER_NOT_PACKEDSCENE
}
func welcome() -> void:
if protection_mode: return
logger.info("CORE/core.gd","CORE (" + version["full"] + ") welcomes you!<nl>It seems like everything is working :)")
func reload_config() -> void:
var corelog: Node = get_node("/root/CORE/CORELog")
var debugdisplay: Node = get_node("/root/CORE/DebugDisplay")
var resourcemanager: Node = get_node("/root/CORE/ResourceManager")
var splash: Node = get_node("/root/CORE/SplashScreen")
preprocessor.enabled = get_config("preprocessor_enabled",true)
preprocessor.diagnostic = get_config("preprocessor_diagnostic",false)
logger.enabled = get_config("logger_enabled",true)
logger.diagnostic = get_config("logger_diagnostic",false)
if get_config("corelog_enabled",true):
corelog.display()
else:
corelog.dissolve()
debugdisplay.config_enabled = get_config("debugdisplay_enabled",true)
debugdisplay.config_fps = get_config("debugdisplay_fps",true)
debugdisplay.config_delta = get_config("debugdisplay_delta",true)
debugdisplay.config_rendertime = get_config("debugdisplay_rendertime",true)
debugdisplay.config_memory = get_config("debugdisplay_memory",true)
resourcemanager.config_load_invalid_file_as_null = get_config("resourcemanager_load_invalid_file_as_null",false)
splash.config_enabled = get_config("splash_enabled",false)
splash.config_image = get_config("splash_image","[LOADPATH]soscore.png").replace("[LOADPATH]",loadpath)
splash.config_image_size = get_config("config.splash_image_size",256)
splash.config_color = get_config("config.splash_color","#d60532")
splash.apply_config()
func get_config(config_key:StringName,default_value:Variant) -> Variant:
if protection_mode: return null
if config.get(config_key) == null:
return default_value
else:
return config.get(config_key)
func get_module(module_name:String) -> Node:
if protection_mode: return null
if module_name == "CORELog":
var err = error("CORE",Errors.CORE_INVALID_MODULE,{"module":module_name})
logger.error("CORE/core.gd",err["error"])
return err["code"]
var module: Node = get_node_or_null("/root/CORE/" + module_name)
if module == null:
var err = error("CORE",Errors.CORE_INVALID_MODULE,{"module":module_name})
logger.error("CORE/core.gd",err["error"])
return err["code"]
return module
func devmode():
logger.warn("CORE/core.gd","Development mode is now active.<nl>Keep this disabled if you don't know what you're doing<nl>or you may encounter serious issues!<nl><nl>You have been warned!")
logger.warn("CORE/core.gd","The development mode does nothing as of now. It is just \"a thing\" implemented for the future")
development_mode = true
func exception(module:String,exception_error:String):
protection_mode = true
var submit_issue_default = "Please report this crash to the CORE Framework repository (with
the full log file). You can submit a crash report at:
https://git.staropensource.de/StarOpenSource/core/issues/new"
var submit_issue_devmode = """Please do NOT report this crash to the CORE Framework repository
as CORE is running in development mode, which is not supported."""
var exc_message: String = """
[color=red]################################
EXCEPTION! EXCEPTION! EXCEPTION!
The CORE Framework experienced a critical error in runtime.
%submit_issue%
CORE INFORMATION
version = "%version%"
development_mode = %development_mode%
preprocessor_enabled = %preprocessor_enabled%
preprocessor_diagnostic = %preprocessor_diagnostic%
logger_enabled = %logger_enabled%
logger_diagnostic = %logger_diagnostic%
OPERATING SYSTEM
timezone = %timezone%
time_utc = "%time_utc%"
time_unix = %time_unix%
date = "%date%"
locale = "%locale%"
lang = "%lang%"
name = "%name%"
distro = "%distro%"
version = "%version_os%"
memory = %memory%
memory_peak = %memory_peak%
memory_usage = %memory_usage%
processor_count = %processor_count%
processor_name = "%processor_name%"
video_adapter = %video_adapter%
rendering_api = "%rendering_api%"
APPLICATION
cmdline = %cmdline%
permissions = %permissions%
debug_build = %debug_build%
ERROR INFORMATION
module = "%module%"
error = "%error%"
STACKTRACE
%stacktrace%
EXCEPTION! EXCEPTION! EXCEPTION!
################################
"""
if development_mode:
exc_message = exc_message.replace("%submit_issue%",submit_issue_devmode)
else:
exc_message = exc_message.replace("%submit_issue%",submit_issue_default)
exc_message = exc_message.replace("%version%",version["full"])
exc_message = exc_message.replace("%development_mode%",str(development_mode))
exc_message = exc_message.replace("%preprocessor_enabled%",str(preprocessor.enabled))
exc_message = exc_message.replace("%preprocessor_diagnostic%",str(preprocessor.diagnostic))
exc_message = exc_message.replace("%logger_enabled%",str(logger.enabled))
exc_message = exc_message.replace("%logger_diagnostic%",str(logger.diagnostic))
exc_message = exc_message.replace("%timezone%",str(Time.get_time_zone_from_system()))
exc_message = exc_message.replace("%time_utc%",Time.get_time_string_from_system(true))
exc_message = exc_message.replace("%time_unix%",str(Time.get_unix_time_from_datetime_string(Time.get_time_string_from_system(true))))
exc_message = exc_message.replace("%date%",Time.get_date_string_from_system(true))
exc_message = exc_message.replace("%locale%",OS.get_locale())
exc_message = exc_message.replace("%lang%",OS.get_locale_language())
exc_message = exc_message.replace("%name%",OS.get_name())
exc_message = exc_message.replace("%distro%",OS.get_distribution_name())
exc_message = exc_message.replace("%version_os%",OS.get_version())
exc_message = exc_message.replace("%memory%",str(OS.get_memory_info()))
exc_message = exc_message.replace("%memory_peak%",str(OS.get_static_memory_peak_usage()))
exc_message = exc_message.replace("%memory_usage%",str(OS.get_static_memory_usage()))
exc_message = exc_message.replace("%processor_count%",str(OS.get_processor_count()))
exc_message = exc_message.replace("%processor_name%",OS.get_processor_name())
exc_message = exc_message.replace("%video_adapter%",str(OS.get_video_adapter_driver_info()))
exc_message = exc_message.replace("%rendering_api%",RenderingServer.get_video_adapter_api_version())
exc_message = exc_message.replace("%cmdline%",str(OS.get_cmdline_args()))
exc_message = exc_message.replace("%permissions%",str(OS.get_granted_permissions()))
exc_message = exc_message.replace("%debug_build%",str(OS.is_debug_build()))
exc_message = exc_message.replace("%module%",module)
exc_message = exc_message.replace("%error%",exception_error)
exc_message = exc_message.replace("%stacktrace%",str(get_stack()))
print_rich(exc_message)
await get_tree().create_timer(0.25).timeout
get_tree().quit(255)
func error(module:String,error_enum:Errors,error_info:Dictionary = {}) -> Dictionary:
match(error_enum):
Errors.OK:
exception("core","Module \"" + module + "\" tried recieving information about error OK (are you ok?)")
Errors.CORE_PROTECTIONMODE:
return {"code":9223372036854775807,"error":"CORE is in protection mode and is unavailable"}
Errors.CORE_EXCEPTION:
return {"code":9223372036854775806,"error":"Launching nuke in 3... 2... 1..."}
Errors.CORE_INVALID_MODULE:
return {"code":Errors.CORE_INVALID_MODULE,"error":"The CORE module \"" + error_info["module"] + "\" does not exist"}
Errors.RESOURCEMANAGER_ALREADY_EXISTS:
return {"code":Errors.RESOURCEMANAGER_ALREADY_EXISTS,"error":"Failed loading resource: The resource \"" + error_info["name"] + "\" is already loaded"}
Errors.RESOURCEMANAGER_INVALID_FILEPATH:
return {"code":Errors.RESOURCEMANAGER_INVALID_FILEPATH,"error":"Failed loading resource: The filepath \"" + error_info["filepath"] + "\" is invalid"}
Errors.RESOURCEMANAGER_RESOURCE_MISSING:
return {"code":Errors.RESOURCEMANAGER_RESOURCE_MISSING,"error":"Failed unloading resource: The resource \"" + error_info["name"] + "\" is not loaded"}
Errors.RESOURCEMANAGER_BATCH_EMPTY:
return {"code":Errors.RESOURCEMANAGER_BATCH_EMPTY,"error":"Failed processing batch: The batch is empty"}
Errors.SCENEMANAGER_ALREADY_LOADED:
if error_info["one_scene_overlay"]:
return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed adding scene \"" + error_info["scene"] + "\" to overlay \"" + error_info["overlay"] + "\": The overlay is full"}
else:
return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed adding scene \"" + error_info["scene"] + "\" to overlay \"" + error_info["overlay"] + "\": A resource with the same name is already present in that overlay"}
Errors.SCENEMANAGER_NOT_LOADED:
if error_info["one_scene_overlay"]:
return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed removing scene \"" + error_info["scene"] + "\" from overlay \"" + error_info["overlay"] + "\": The overlay is empty"}
else:
return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed removing scene \"" + error_info["scene"] + "\" from overlay \"" + error_info["overlay"] + "\": A resource with that name could not be found within the overlay"}
Errors.SCENEMANAGER_NOT_PACKEDSCENE:
return {"code":Errors.SCENEMANAGER_NOT_PACKEDSCENE,"error":"Failed adding scene \"" + error_info["scene"] + "\" to overlay \"" + error_info["overlay"] + "\": The specified resource is not a PackedScene"}
_:
exception("core","Failed generating error: Invalid error \"" + str(error) + "\"")
return error("CORE",Errors.CORE_EXCEPTION)
func exit_safely(exitcode:int = 0) -> void:
if protection_mode: return
logger.info("CORE/core.gd","Shutting down...")
protection_mode = true
await get_tree().create_timer(0.5).timeout
get_tree().quit(exitcode)