2024-02-12 19:47:28 +01:00
# CORE FRAMEWORK SOURCE FILE
# Copyright (c) 2024 The StarOpenSource Project & Contributors
2024-03-03 18:53:09 +01:00
# Licensed under the GNU Affero General Public License v3
2024-02-12 19:47:28 +01:00
#
# This program is free software: you can redistribute it and/or modify
2024-03-03 18:53:09 +01:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2024-02-12 19:47:28 +01:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2024-03-03 18:53:09 +01:00
# GNU Affero General Public License for more details.
2024-02-12 19:47:28 +01:00
#
2024-03-03 18:53:09 +01:00
# You should have received a copy of the GNU Affero General Public License
2024-02-12 19:47:28 +01:00
# along with this program. If not, see <https://www.gnu.org/licenses/>.
## Initializes and manages the framework.
##
## The [b]CORE Object[/b] is responsible for initializing, managing and
2024-04-08 02:43:31 +02:00
## serving the CORE Framework.
2024-02-04 21:36:30 +01:00
extends Node
class_name Core
2024-04-08 02:43:31 +02:00
# Versioning
2024-03-28 12:54:12 +01:00
## The version number
const version_version : int = 1
2024-04-08 02:43:31 +02:00
## The version type. See [enum CoreTypes.VersionType] for more information.
2024-04-14 14:52:19 +02:00
const version_type : CoreTypes . VersionType = CoreTypes . VersionType . RELEASE
2024-03-28 12:54:12 +01:00
## The version type number. Resets on every new version and version type.
2024-04-14 15:18:21 +02:00
const version_typerelease : int = 1
2024-02-04 21:36:30 +01:00
# Modules
2024-04-08 02:43:31 +02:00
## Used internally for loading, managing and unloading modules.
2024-03-31 17:35:09 +02:00
const modules : Array [ String ] = [ " logger " , " misc " , " sms " , " logui " , " erm " , " storage " ]
2024-04-08 02:43:31 +02:00
## CORE's configuration object.[br]
## [b]NEVER access this yourself! To change the configuration use [method reload_configuration] instead.[/b]
var config : CoreConfiguration
2024-04-09 20:13:49 +02:00
## The framework scheduler.[br]
## Performs various maintenance tasks every minute.
## [b]Danger: [i]Don't modify this.[/i][/b]
var scheduler : Timer
2024-04-08 02:43:31 +02:00
## The 'Logger' module
2024-02-04 21:36:30 +01:00
var logger : CoreBaseModule
2024-04-08 02:43:31 +02:00
## The 'Miscellaneous' module
2024-02-04 21:36:30 +01:00
var misc : CoreBaseModule
2024-04-08 02:43:31 +02:00
## The 'Scene Management System' module
2024-02-09 21:18:14 +01:00
var sms : CoreBaseModule
2024-04-08 02:43:31 +02:00
## The 'Log UI' module. Not important for you, it just displays the log graphically :3
2024-02-04 21:36:30 +01:00
var logui : CoreBaseModule
2024-04-08 02:43:31 +02:00
## The 'Easy Request Maker' module (formerly 'Easy DownLoader')
2024-03-31 17:35:09 +02:00
var erm : CoreBaseModule
2024-04-08 02:43:31 +02:00
## The 'Storage' module
2024-03-18 03:23:27 +01:00
var storage : CoreBaseModule
2024-02-04 21:36:30 +01:00
2024-04-08 02:43:31 +02:00
# /etc/
## Stores the path to CORE's installation directory.[br]
2024-04-08 21:19:24 +02:00
## [b]Danger: [i]Don't modify this.[/i][/b]
2024-02-04 21:36:30 +01:00
var basepath : String
2024-04-15 00:07:25 +02:00
# Contains a list of all registered cleanup hooks.
2024-04-14 23:48:53 +02:00
var cleanup_hooks : Dictionary = { }
2024-04-23 21:02:38 +02:00
## Internal, don't modify.
2024-04-15 00:07:25 +02:00
# Contains a list of all loaded custom modules.
2024-02-05 18:03:16 +01:00
var custom_modules : Dictionary = { }
2024-04-23 21:02:38 +02:00
## Internal, don't modify.
2024-04-15 00:07:25 +02:00
# Contains the node holding all custom modules as children.
2024-02-09 15:30:20 +01:00
var custom_modules_node : Node
2024-04-23 21:02:38 +02:00
## Internal, don't modify.
2024-04-15 00:07:25 +02:00
# The CORE Object's logger instance.
2024-04-08 21:30:24 +02:00
var loggeri : CoreLoggerInstance
2024-04-23 21:02:38 +02:00
## Internal, don't modify.
# Makes CORE inaccessible if true.
var disabled : bool = false
2024-02-04 21:36:30 +01:00
2024-04-08 02:43:31 +02:00
# +++ initialization +++
2024-02-04 21:36:30 +01:00
func _init ( new_config : CoreConfiguration = CoreConfiguration . new ( ) ) - > void :
name = " CORE "
2024-03-03 19:08:20 +01:00
if ! check_godot_version ( ) : return
2024-02-04 21:36:30 +01:00
if ! determine_basepath ( ) : queue_free ( )
2024-02-09 15:30:20 +01:00
custom_modules_node = Node . new ( )
2024-02-04 21:36:30 +01:00
reload_configuration ( new_config )
initialize_modules ( )
apply_configuration ( )
2024-04-09 20:13:49 +02:00
initialize_scheduler ( )
2024-02-04 21:36:30 +01:00
func _ready ( ) - > void :
inject_modules ( )
2024-02-09 22:59:43 +01:00
custom_modules_node . name = " Custom Modules "
2024-02-09 15:30:20 +01:00
add_child ( custom_modules_node )
2024-04-09 20:13:49 +02:00
loggeri = logger . get_instance ( basepath . replace ( " res:// " , " " ) + " src/core.gd " , self )
add_child ( scheduler )
2024-04-14 14:23:05 +02:00
get_tree ( ) . auto_accept_quit = false
2024-02-04 21:36:30 +01:00
2024-04-15 00:07:25 +02:00
# Initializes all built-in modules during the preinitialization phase.
2024-04-23 21:02:38 +02:00
## Internal, don't call.
2024-02-04 21:36:30 +01:00
func initialize_modules ( ) - > void :
2024-03-29 02:40:56 +01:00
for module in modules :
set ( module , CoreBaseModule . new ( ) )
get ( module ) . name = module
get ( module ) . set_script ( load ( basepath + " src/ " + module + " .gd " ) )
get ( module ) . core = self
2024-04-09 20:13:49 +02:00
get ( module ) . loggeri = logger . get_instance ( basepath . replace ( " res:// " , " " ) + " src/ " + module + " .gd " , get ( module ) )
2024-03-29 02:40:56 +01:00
get ( module ) . _initialize ( )
2024-02-04 21:36:30 +01:00
2024-04-15 00:07:25 +02:00
# Injects CORE's builtin modules into the SceneTree.
2024-04-23 21:02:38 +02:00
## Internal, don't call.
2024-03-29 02:40:56 +01:00
func inject_modules ( ) - > void : for module in modules : add_child ( get ( module ) )
2024-02-04 21:36:30 +01:00
2024-04-15 00:07:25 +02:00
# Initializes the framework scheduler.
2024-04-23 21:02:38 +02:00
## Internal, don't call.
2024-04-09 20:13:49 +02:00
func initialize_scheduler ( ) - > void :
scheduler = Timer . new ( )
scheduler . name = " Scheduler "
scheduler . autostart = true
scheduler . one_shot = false
scheduler . paused = false
scheduler . wait_time = 60
scheduler . process_mode = Node . PROCESS_MODE_ALWAYS
scheduler . connect ( " timeout " , func ( ) - > void :
loggeri . verb ( " Running scheduler tasks " )
for module in modules : await get ( module ) . _schedule ( )
for module in custom_modules_node . get_children ( ) : await module . _schedule ( )
)
2024-04-08 02:43:31 +02:00
## Waits for all modules to fully initialize.[br]
2024-03-22 21:12:11 +01:00
## [br]
2024-04-08 02:43:31 +02:00
## This ensures that all modules are fully initialized and ready for usage.[br]
## [i][b]Not calling this function during startup may lead to runtime issues.[/b][/i]
func complete_init ( no_success_message : bool = false ) - > void :
2024-03-22 21:12:11 +01:00
var modsinit_builtin : Array [ String ] = [ " workaround " ]
var modsinit_custom : Array [ String ] = [ " workaround " ]
while modsinit_builtin . size ( ) != 0 and modsinit_custom . size ( ) != 0 :
# Clear arrays
modsinit_builtin = [ ]
modsinit_custom = [ ]
# Check builtin modules
2024-03-29 02:40:56 +01:00
for module in modules : if ! get ( module ) . initialized : modsinit_builtin . append ( module )
2024-03-22 21:12:11 +01:00
# Check custom modules
for module_name in custom_modules :
if ! custom_modules [ module_name ] . initialized : modsinit_custom . append ( module_name )
# Print and sleep
if modsinit_builtin . size ( ) != 0 or modsinit_custom . size ( ) != 0 :
print ( " Waiting for modules to finish initialization: " )
2024-04-14 14:42:46 +02:00
if modsinit_builtin . size ( ) != 0 : print ( " Built-in: " + str ( modsinit_builtin ) )
2024-03-29 02:40:56 +01:00
if modsinit_custom . size ( ) != 0 : print ( " Custom: " + str ( modsinit_custom ) )
2024-03-22 21:12:11 +01:00
await get_tree ( ) . create_timer ( 1 ) . timeout
# Initialization complete
await get_tree ( ) . process_frame
2024-04-08 21:30:24 +02:00
if ! no_success_message : loggeri . info ( " Initialized CORE successfully " )
2024-03-22 21:12:11 +01:00
2024-04-09 20:13:49 +02:00
# +++ configuration +++
## Loads a (new) configuration object and applies it to all modules.
func reload_configuration ( new_config : CoreConfiguration = CoreConfiguration . new ( ) ) - > void :
var initialized = config != null
if initialized : loggeri . verb ( " Reloading CORE ' s configuration " )
if config != null : config . queue_free ( )
2024-04-12 16:59:29 +02:00
config = new_config . duplicate ( )
2024-04-09 20:13:49 +02:00
if is_devmode ( ) : # Override configuration in development mode
config . logger_level = CoreTypes . LoggerLevel . DIAG
if initialized : loggeri . verb ( " Overrode configuration (development mode) " )
if initialized : apply_configuration ( )
2024-04-15 00:07:25 +02:00
# Applies a new configuration.
2024-04-23 21:02:38 +02:00
## Internal, don't call.
2024-04-09 20:13:49 +02:00
func apply_configuration ( ) - > void :
if loggeri != null : loggeri . verb ( " Applying configuration " )
2024-04-10 21:34:12 +02:00
if is_devmode ( ) and loggeri != null : loggeri . warn ( " The CORE Framework is in development mode. Here be dragons! " )
2024-04-09 20:13:49 +02:00
if ! config . custom_modules :
2024-04-12 15:48:17 +02:00
if loggeri != null : loggeri . diag ( " Removing all custom modules (custom modules support is disabled) " )
2024-04-09 20:13:49 +02:00
for module in custom_modules : unregister_custom_module ( module )
for module in modules : get ( module ) . _pull_config ( )
if config . custom_modules :
for module in custom_modules :
2024-04-12 15:48:17 +02:00
custom_modules [ module ] . _pull_config ( )
2024-04-14 15:17:55 +02:00
# Workaround
logger . verbose_mode = OS . is_stdout_verbose ( )
2024-04-09 20:13:49 +02:00
2024-04-08 02:43:31 +02:00
# +++ custom module support +++
2024-02-12 19:47:28 +01:00
## Registers a new custom module.
2024-03-31 11:22:57 +02:00
func register_custom_module ( module_name : String , module_origin : String , module_class : CoreBaseModule ) - > bool :
2024-04-08 21:30:24 +02:00
loggeri . verb ( " Registering new custom module \" " + module_name + " \" " )
2024-02-10 18:49:25 +01:00
if ! config . custom_modules :
2024-04-08 21:30:24 +02:00
loggeri . error ( " Registering module failed: Custom module support is disabled. " )
2024-02-10 18:49:25 +01:00
return false
2024-02-05 18:03:16 +01:00
if custom_modules . has ( module_name ) :
2024-04-08 21:30:24 +02:00
loggeri . error ( " Registering module failed: A custom module with the name \" " + module_name + " \" already exists. " )
2024-02-10 18:49:25 +01:00
return false
2024-04-08 21:30:24 +02:00
loggeri . diag ( " Updating variables " )
2024-03-31 11:22:57 +02:00
module_class . name = module_name
2024-03-22 21:41:27 +01:00
module_class . core = self
2024-04-09 20:13:49 +02:00
module_class . loggeri = logger . get_instance ( module_origin , module_class )
2024-04-08 21:37:39 +02:00
module_class . loggeri . framework = true
2024-04-08 21:30:24 +02:00
loggeri . diag ( " Adding module to SceneTree " )
2024-02-09 15:30:20 +01:00
custom_modules_node . add_child ( module_class )
2024-04-08 21:30:24 +02:00
loggeri . diag ( " Merging module with custom_modules " )
2024-02-05 18:03:16 +01:00
custom_modules . merge ( { module_name : module_class } )
2024-04-08 21:30:24 +02:00
loggeri . diag ( " Initializing custom module " )
2024-02-05 18:03:16 +01:00
module_class . _initialize ( )
2024-04-08 21:30:24 +02:00
loggeri . diag ( " Updating custom module configuration " )
2024-02-05 18:03:16 +01:00
module_class . _pull_config ( )
2024-02-10 18:49:25 +01:00
return true
2024-02-05 18:03:16 +01:00
2024-04-08 02:43:31 +02:00
## Unregisters a custom module, making it no longer available.
2024-02-05 18:03:16 +01:00
func unregister_custom_module ( module_name : String ) - > void :
2024-04-08 21:30:24 +02:00
loggeri . verb ( " Unregistering custom module \" " + module_name + " \" " )
2024-02-05 18:03:16 +01:00
if ! custom_modules . has ( module_name ) :
2024-04-08 21:30:24 +02:00
loggeri . error ( " Unregistering module failed: A custom module with the name \" " + module_name + " \" does not exist. " )
2024-02-05 18:03:16 +01:00
return
2024-04-14 19:58:48 +02:00
var module : Node = custom_modules [ module_name ]
2024-03-29 02:40:56 +01:00
await module . _cleanup ( )
2024-03-31 11:22:57 +02:00
module . loggeri . queue_free ( )
2024-03-29 02:40:56 +01:00
custom_modules_node . remove_child ( module )
2024-02-05 18:03:16 +01:00
custom_modules . erase ( module_name )
2024-03-29 02:40:56 +01:00
module . queue_free ( )
2024-02-05 18:03:16 +01:00
2024-04-08 02:43:31 +02:00
## Returns a registered custom module.[br]
## Please note that you can't get CORE's built-in modules with this function.
2024-02-05 18:03:16 +01:00
func get_custom_module ( module_name : String ) - > CoreBaseModule :
2024-04-08 21:30:24 +02:00
loggeri . diag ( " Getting custom module \" " + module_name + " \" " )
2024-02-05 18:03:16 +01:00
if ! custom_modules . has ( module_name ) :
2024-04-08 21:30:24 +02:00
loggeri . error ( " Getting module failed: A custom module with the name \" " + module_name + " \" does not exist. " )
2024-03-22 21:41:27 +01:00
return null
2024-02-05 18:03:16 +01:00
return custom_modules [ module_name ]
2024-04-14 23:48:53 +02:00
# +++ cleanup ++
2024-04-08 02:43:31 +02:00
## Makes sure that CORE does not leak memory on shutdown/unload.[br]
2024-04-14 23:48:53 +02:00
## Unloads all custom modules, built-in modules, frees any of CORE's classes and lastly itself.[br]
## Only call this function if you're sure that your application or game no longer uses the CORE Framework.
2024-04-08 02:43:31 +02:00
func cleanup ( ) - > void :
2024-04-08 21:30:24 +02:00
loggeri . info ( " Cleaning up " )
2024-04-14 23:48:53 +02:00
loggeri . verb ( " Calling cleanup hooks " )
for hook in cleanup_hooks :
if ! cleanup_hooks [ hook ] . is_valid ( ) :
loggeri . error ( " Cleanup hook # " + str ( hook ) + " is invalid " )
else :
loggeri . diag ( " Calling cleanup hook # " + str ( hook ) )
await cleanup_hooks [ hook ] . call ( )
loggeri . verb ( " Unregistering custom modules " )
2024-04-14 19:58:48 +02:00
for module in custom_modules_node . get_children ( ) : await unregister_custom_module ( module . name )
2024-04-14 23:48:53 +02:00
loggeri . verb ( " Removing custom module support " )
2024-04-12 17:03:37 +02:00
remove_child ( custom_modules_node )
custom_modules_node . queue_free ( )
2024-04-14 23:48:53 +02:00
loggeri . verb ( " Unloading built-in modules " )
2024-04-08 02:43:31 +02:00
var modules_reverse : Array [ String ] = modules . duplicate ( )
modules_reverse . reverse ( )
for module in modules_reverse :
await get ( module ) . _cleanup ( )
get ( module ) . queue_free ( )
2024-04-14 23:48:53 +02:00
print ( " Freeing configuration " )
2024-04-12 17:03:37 +02:00
config . queue_free ( )
2024-04-14 19:58:48 +02:00
await get_tree ( ) . process_frame
2024-04-14 23:48:53 +02:00
print ( " Freeing " )
2024-04-08 02:43:31 +02:00
queue_free ( )
2024-04-14 23:48:53 +02:00
# Generates a new cleanup hook id
2024-04-23 21:02:38 +02:00
## Internal, don't call.
2024-04-14 23:48:53 +02:00
func _generate_hook_id ( ) - > int :
var id = randi ( )
if cleanup_hooks . has ( id ) :
loggeri . warn ( " New cleanup hook id # " + str ( id ) + " is already taken " )
return _generate_hook_id ( )
elif id == - 1 :
loggeri . warn ( " Invalid cleanup hook id ' -1 ' " )
return _generate_hook_id ( )
return id
## Registers a new cleanup hook.[br]
## Returns the hook id.
func register_cleanup_hook ( callable : Callable ) - > int :
if ! callable . is_valid ( ) :
loggeri . error ( " Could not add cleanup hook: Callable is not valid " )
return - 1
var id : int = _generate_hook_id ( )
loggeri . verb ( " Adding new cleanup hook # " + str ( id ) )
cleanup_hooks . merge ( { id : callable } )
return id
## Unregisters a cleanup hook by it's id.
func unregister_cleanup_hook_by_id ( id : int ) - > bool :
if ! cleanup_hooks . has ( id ) :
loggeri . error ( " Could not remove cleanup hook (id): Hook # " + str ( id ) + " does not exist " )
return false
loggeri . verb ( " Removed cleanup hook # " + str ( id ) + " (id) " )
cleanup_hooks . erase ( id )
return true
## Unregisters a cleanup hook by it's reference.
func unregister_cleanup_hook_by_ref ( callable : Callable ) - > bool :
var id : Variant = cleanup_hooks . find_key ( callable )
if id == null :
loggeri . error ( " Could not remove cleanup hook (ref): Could not find a matching hook " )
return false
if typeof ( id ) != TYPE_INT : await loggeri . crash ( " Could not remove cleanup hook (ref): find_key did not return an integer (returned ' " + str ( id ) + " ' ) " )
loggeri . verb ( " Removed cleanup hook # " + str ( id ) + " (ref) " )
cleanup_hooks . erase ( id )
return true
# +++ etc +++
2024-04-09 00:53:43 +02:00
## Returns if the framework is in development mode.
2024-02-04 21:36:30 +01:00
func is_devmode ( ) - > bool :
2024-04-09 00:53:43 +02:00
return config . development
2024-02-04 21:36:30 +01:00
2024-04-08 02:43:31 +02:00
## Replaces placeholders with human-friendly strings.[br]
## You can use the following placeholders:[br]
## - [code]%version%[/code]: Returns the version number.[br]
## - [code]%version_type%[/code]: Returns the version type number[br]
## - [code]%version_semantic%[/code]: Returns the result of [method Core.get_version_semantic], example [i]5.2.3[/i][br]
## - [code]%version_type%[/code]: Returns the version type as a word, for example [i]Release Candidate[/i][br]
## - [code]%version_type_technical%[/code]: Returns the version type as one or two lowercase letters, for example [i]rc[/i][br]
2024-03-03 19:08:40 +01:00
## - [code]%devmode%[/code]: Returns the development mode status[br]
2024-04-08 02:43:31 +02:00
## - [code]%headless%[/code]: Returns the headless mode status[br]
## - [code]%custommodules%[/code]: Returns if custom module support is enabled
2024-02-04 21:36:30 +01:00
func get_formatted_string ( string : String ) - > String :
# Version strings
2024-03-28 12:54:12 +01:00
string = string . replace ( " % version % " , str ( version_version ) )
2024-04-08 20:18:49 +02:00
string = string . replace ( " % version_typerelease % " , str ( version_typerelease ) )
2024-02-04 21:36:30 +01:00
var semantic_version : Array [ int ] = get_version_semantic ( )
2024-03-28 12:54:12 +01:00
string = string . replace ( " % version_semantic % " , str ( semantic_version [ 0 ] ) + " . " + str ( semantic_version [ 1 ] ) + " . " + str ( semantic_version [ 2 ] ) )
2024-02-04 21:36:30 +01:00
match ( version_type ) :
CoreTypes . VersionType . RELEASE :
2024-04-08 02:43:31 +02:00
string = string . replace ( " % version_type % " , " Release " )
string = string . replace ( " % version_type_technical % " , " r " )
2024-02-04 21:36:30 +01:00
CoreTypes . VersionType . RELEASECANDIDATE :
2024-04-08 02:43:31 +02:00
string = string . replace ( " % version_type % " , " Release Candidate " )
string = string . replace ( " % version_type_technical % " , " rc " )
2024-02-04 21:36:30 +01:00
CoreTypes . VersionType . BETA :
2024-04-08 02:43:31 +02:00
string = string . replace ( " % version_type % " , " Beta " )
string = string . replace ( " % version_type_technical % " , " b " )
2024-02-04 21:36:30 +01:00
CoreTypes . VersionType . ALPHA :
2024-04-08 02:43:31 +02:00
string = string . replace ( " % version_type % " , " Alpha " )
string = string . replace ( " % version_type_technical % " , " a " )
2024-04-08 21:30:24 +02:00
_ : await loggeri . crash ( " Invalid version type " + str ( version_type ) )
2024-02-04 21:36:30 +01:00
# Development mode
if is_devmode ( ) : string = string . replace ( " %d evmode % " , " Enabled " )
else : string = string . replace ( " %d evmode % " , " Disabled " )
# Headless mode
if config . headless : string = string . replace ( " %he adless % " , " Enabled " )
else : string = string . replace ( " %he adless % " , " Disabled " )
2024-02-10 18:49:25 +01:00
# Custom module support
if config . custom_modules : string = string . replace ( " %c ustommodules % " , " Enabled " )
else : string = string . replace ( " %c ustommodules % " , " Disabled " )
2024-02-04 21:36:30 +01:00
return string
2024-02-12 19:47:28 +01:00
## Returns CORE's versioning scheme into the semantic versioning scheme.[br]
2024-04-08 02:43:31 +02:00
## The first integer contains the version number, the second integer contains the version type ([code]0[/code] for alpha, [code]1[/code] for beta, [code]2[/code] for rc and [code]3[/code] for release and the last integer contains the version type number.
2024-02-04 21:36:30 +01:00
func get_version_semantic ( ) - > Array [ int ] :
var version_type_int : int
match ( version_type ) :
CoreTypes . VersionType . RELEASE : version_type_int = 3
CoreTypes . VersionType . RELEASECANDIDATE : version_type_int = 2
CoreTypes . VersionType . BETA : version_type_int = 1
CoreTypes . VersionType . ALPHA : version_type_int = 0
2024-03-28 12:54:12 +01:00
return [ version_version , version_type_int , version_typerelease ]
2024-02-12 19:56:17 +01:00
2024-04-15 00:07:25 +02:00
# Determines CORE's installation/base path.
2024-02-12 19:56:17 +01:00
func determine_basepath ( ) - > bool :
if FileAccess . file_exists ( " res://.corebasepath " ) :
basepath = " res:// "
elif FileAccess . file_exists ( " res://CORE/.corebasepath " ) :
basepath = " res://CORE/ "
elif FileAccess . file_exists ( " res://addons/CORE/.corebasepath " ) :
basepath = " res://addons/CORE/ "
else :
assert ( false , " CORE is not located at ' res://CORE/ ' , aborting initialization " )
return false
return true
## Checks compatibility with the running version.
func check_godot_version ( ) - > bool :
var version : Dictionary = Engine . get_version_info ( )
match ( version [ " major " ] ) :
4 : pass
_ :
2024-03-03 19:08:20 +01:00
printerr ( " The CORE Framework does not support Godot versions older or newer than 4.x.x " )
return false
2024-02-12 19:56:17 +01:00
match ( version [ " minor " ] ) :
2024-03-03 19:08:20 +01:00
0 : printerr ( " The CORE Framework does not support Godot versions older than 4.2.x. Please update to Godot 4.2.x to ensure full compatibility. " )
1 : printerr ( " The CORE Framework does not support Godot versions older than 4.2.x. Please update to Godot 4.2.x to ensure full compatibility. " )
2024-02-12 19:56:17 +01:00
2 : pass
2024-03-03 19:08:20 +01:00
_ :
printerr ( " The CORE Framework does not support Godot versions newer than 4.2.x. Please downgrade to Godot 4.2.x. " )
return false
if version [ " status " ] != " stable " :
printerr ( " The CORE Framework does not support unstable Godot versions. Please switch to Godot stable 4.2.x. " )
return false
2024-02-12 19:56:17 +01:00
return true
2024-04-08 21:42:03 +02:00
## Makes sure for all log messages to be flushed and that CORE is correctly cleaned up.[br]
## Using [method SceneTree.quit] directly may cause various issues.[br]
## [b]Note: [i]Using the [code]await[/code] keyword is required for this function.[/i][/b]
func quit_safely ( exitcode : int = 0 ) - > void :
loggeri . info ( " Shutting down (code " + str ( exitcode ) + " ) " )
await get_tree ( ) . create_timer ( 0.25 ) . timeout
await cleanup ( )
get_tree ( ) . quit ( exitcode )
2024-04-14 14:23:05 +02:00
2024-04-15 00:07:25 +02:00
# Just ignore this.
2024-04-23 21:02:38 +02:00
## Internal, don't call.
2024-04-14 14:23:05 +02:00
func _notification ( what ) - > void :
match ( what ) :
NOTIFICATION_WM_CLOSE_REQUEST :
if config . automatic_shutdown :
await quit_safely ( 0 )