2024-02-04 21:36:30 +01:00
|
|
|
##############################################################################
|
|
|
|
### CORE FRAMEWORK SOURCE FILE ###
|
|
|
|
### Copyright (c) 2024 The StarOpenSource Project & Contributors ###
|
|
|
|
### Licensed under the GNU General Public License v3 ###
|
|
|
|
### ###
|
|
|
|
### This program is free software: you can redistribute it and/or modify ###
|
|
|
|
### it under the terms of the GNU General Public License as published by ###
|
|
|
|
### the Free Software Foundation, either version 3 of the License, or ###
|
|
|
|
### (at your option) any later version. ###
|
|
|
|
### ###
|
|
|
|
### 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 ###
|
|
|
|
### GNU General Public License for more details. ###
|
|
|
|
### ###
|
|
|
|
### You should have received a copy of the GNU General Public License ###
|
|
|
|
### along with this program. If not, see <https://www.gnu.org/licenses/>. ###
|
|
|
|
##############################################################################
|
|
|
|
### src/core.gd (CORE Object) ###
|
|
|
|
### ###
|
|
|
|
### This source file is responsible for initializing CORE's modules, ###
|
|
|
|
### handling communication between them and much more. ###
|
|
|
|
##############################################################################
|
|
|
|
extends Node
|
|
|
|
class_name Core
|
|
|
|
|
|
|
|
# Constants
|
|
|
|
const version_release: int = 1
|
|
|
|
const version_type: CoreTypes.VersionType = CoreTypes.VersionType.ALPHA
|
|
|
|
const version_typerelease: int = 0
|
|
|
|
|
|
|
|
# Modules
|
|
|
|
var logger: CoreBaseModule
|
|
|
|
var misc: CoreBaseModule
|
2024-02-09 21:18:14 +01:00
|
|
|
var sms: CoreBaseModule
|
2024-02-04 21:36:30 +01:00
|
|
|
var logui: CoreBaseModule
|
|
|
|
|
|
|
|
# Variables
|
|
|
|
var basepath: String
|
2024-02-05 18:03:16 +01:00
|
|
|
var config: CoreConfiguration
|
|
|
|
var custom_modules: Dictionary = {}
|
2024-02-09 15:30:20 +01:00
|
|
|
var custom_modules_node: Node
|
2024-02-04 21:36:30 +01:00
|
|
|
|
|
|
|
# Preinitialization
|
|
|
|
func _init(new_config: CoreConfiguration = CoreConfiguration.new()) -> void:
|
|
|
|
name = "CORE"
|
|
|
|
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()
|
|
|
|
|
|
|
|
# Initialization
|
|
|
|
func _ready() -> void:
|
|
|
|
inject_modules()
|
2024-02-09 15:30:20 +01:00
|
|
|
add_child(custom_modules_node)
|
2024-02-04 21:36:30 +01:00
|
|
|
logger.info("Initialized CORE successfully")
|
|
|
|
if is_devmode(): logger.warn("The CORE Framework is in development mode. Here be dragons!")
|
|
|
|
if config.headless: logger.warn("CORE is in headless mode. Certain modules will not work as expected.")
|
|
|
|
|
|
|
|
# Initialize modules
|
|
|
|
func initialize_modules() -> void:
|
|
|
|
# Create Nodes
|
|
|
|
logger = CoreBaseModule.new()
|
|
|
|
misc = CoreBaseModule.new()
|
2024-02-09 21:18:14 +01:00
|
|
|
sms = CoreBaseModule.new()
|
2024-02-04 21:36:30 +01:00
|
|
|
logui = CoreBaseModule.new()
|
|
|
|
# Set names
|
|
|
|
logger.name = "Logger"
|
|
|
|
misc.name = "Misc"
|
2024-02-09 21:18:14 +01:00
|
|
|
sms.name = "SceneManagementSystem"
|
2024-02-04 21:36:30 +01:00
|
|
|
logui.name = "LogUI"
|
|
|
|
# Set scripts
|
|
|
|
logger.set_script(ResourceLoader.load(basepath + "src/logger.gd"))
|
|
|
|
misc.set_script(ResourceLoader.load(basepath + "src/misc.gd"))
|
2024-02-09 21:18:14 +01:00
|
|
|
sms.set_script(ResourceLoader.load(basepath + "src/sms.gd"))
|
2024-02-04 21:36:30 +01:00
|
|
|
logui.set_script(ResourceLoader.load(basepath + "src/logui.gd"))
|
|
|
|
# Set reference to self
|
|
|
|
logger.core = self
|
|
|
|
misc.core = self
|
2024-02-09 21:18:14 +01:00
|
|
|
sms.core = self
|
2024-02-04 21:36:30 +01:00
|
|
|
logui.core = self
|
|
|
|
# Call _initialize() (workaround as modules cannot access "core" during _init())
|
|
|
|
logger._initialize()
|
|
|
|
misc._initialize()
|
2024-02-09 21:18:14 +01:00
|
|
|
sms._initialize()
|
2024-02-04 21:36:30 +01:00
|
|
|
logui._initialize()
|
|
|
|
|
|
|
|
# Inject modules into the SceneTree
|
|
|
|
func inject_modules() -> void:
|
|
|
|
add_child(logger)
|
|
|
|
add_child(misc)
|
2024-02-09 21:18:14 +01:00
|
|
|
add_child(sms)
|
2024-02-04 21:36:30 +01:00
|
|
|
add_child(logui)
|
|
|
|
|
2024-02-05 18:03:16 +01:00
|
|
|
# Registers a custom module
|
|
|
|
func register_custom_module(module_name: String, module_class: CoreBaseModule) -> void:
|
|
|
|
logger.verb("Registering new custom module \"" + module_name + "\"")
|
|
|
|
if custom_modules.has(module_name):
|
|
|
|
logger.error("Registering module failed: A custom module with the name \"" + module_name + "\" already exists.")
|
|
|
|
return
|
2024-02-09 15:30:20 +01:00
|
|
|
module_class.name = module_name
|
|
|
|
logger.diag("Adding module to SceneTree")
|
|
|
|
custom_modules_node.add_child(module_class)
|
|
|
|
logger.diag("Merging module with custom_modules")
|
2024-02-05 18:03:16 +01:00
|
|
|
custom_modules.merge({ module_name: module_class })
|
2024-02-09 15:30:20 +01:00
|
|
|
logger.diag("Initializing custom module")
|
2024-02-05 18:03:16 +01:00
|
|
|
module_class._initialize()
|
2024-02-09 15:30:20 +01:00
|
|
|
logger.diag("Updating custom module configuration")
|
2024-02-05 18:03:16 +01:00
|
|
|
module_class._pull_config()
|
|
|
|
|
|
|
|
# Unregisters a custom module
|
|
|
|
func unregister_custom_module(module_name: String) -> void:
|
|
|
|
logger.verb("Unregistering custom module \"" + module_name + "\"")
|
|
|
|
if !custom_modules.has(module_name):
|
|
|
|
logger.error("Unregistering module failed: A custom module with the name \"" + module_name + "\" does not exist.")
|
|
|
|
return
|
2024-02-09 15:30:20 +01:00
|
|
|
custom_modules_node.remove_child(get_custom_module(module_name))
|
2024-02-05 18:03:16 +01:00
|
|
|
custom_modules.erase(module_name)
|
|
|
|
|
|
|
|
# Returns a custom module
|
|
|
|
func get_custom_module(module_name: String) -> CoreBaseModule:
|
|
|
|
logger.diag("Getting custom module \"" + module_name + "\"")
|
|
|
|
if !custom_modules.has(module_name):
|
|
|
|
logger.error("Getting module failed: A custom module with the name \"" + module_name + "\" does not exist.")
|
|
|
|
return
|
|
|
|
return custom_modules[module_name]
|
|
|
|
|
2024-02-04 21:36:30 +01:00
|
|
|
# (Re-)Load configuration
|
|
|
|
func reload_configuration(new_config: CoreConfiguration = CoreConfiguration.new()) -> void:
|
|
|
|
var initialized = config != null
|
2024-02-09 15:30:20 +01:00
|
|
|
if initialized: logger.verb("Reloading CORE's configuration")
|
2024-02-04 21:36:30 +01:00
|
|
|
config = new_config
|
|
|
|
if is_devmode(): # Override configuration in development mode
|
|
|
|
config.logger_level = CoreTypes.LoggerLevel.VERB
|
2024-02-09 15:30:20 +01:00
|
|
|
if initialized: logger.verb("Overrode configuration (development mode)")
|
2024-02-04 21:36:30 +01:00
|
|
|
if initialized: apply_configuration()
|
|
|
|
|
|
|
|
# Call _pull_config() functions
|
|
|
|
func apply_configuration() -> void:
|
2024-02-09 15:30:20 +01:00
|
|
|
logger.verb("Applying configuration")
|
2024-02-04 21:36:30 +01:00
|
|
|
logger._pull_config()
|
|
|
|
misc._pull_config()
|
2024-02-09 21:18:14 +01:00
|
|
|
sms._pull_config()
|
2024-02-04 21:36:30 +01:00
|
|
|
logui._pull_config()
|
2024-02-09 15:30:20 +01:00
|
|
|
for module in custom_modules:
|
|
|
|
logger.diag("Updating configuration for custom module \"" + module.name + "\"")
|
|
|
|
module._pull_config()
|
2024-02-04 21:36:30 +01:00
|
|
|
|
|
|
|
# Determines CORE's installation/base path
|
|
|
|
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
|
|
|
|
|
|
|
|
# Return development mode status
|
|
|
|
func is_devmode() -> bool:
|
|
|
|
return config.debug_allow and basepath == "res://" and OS.is_debug_build()
|
|
|
|
|
|
|
|
# Replaces variables with human-friendly strings
|
|
|
|
func get_formatted_string(string: String) -> String:
|
|
|
|
# Version strings
|
|
|
|
string = string.replace("%release%", str(version_release))
|
|
|
|
string = string.replace("%release_type%", str(version_typerelease))
|
|
|
|
var semantic_version: Array[int] = get_version_semantic()
|
|
|
|
string = string.replace("%release_semantic%", str(semantic_version[0]) + "." + str(semantic_version[1]) + "." + str(semantic_version[2]))
|
|
|
|
match(version_type):
|
|
|
|
CoreTypes.VersionType.RELEASE:
|
|
|
|
string = string.replace("%type%", "Release")
|
|
|
|
string = string.replace("%type_technical%", "r")
|
|
|
|
CoreTypes.VersionType.RELEASECANDIDATE:
|
|
|
|
string = string.replace("%type%", "Release Candidate")
|
|
|
|
string = string.replace("%type_technical%", "rc")
|
|
|
|
CoreTypes.VersionType.BETA:
|
|
|
|
string = string.replace("%type%", "Beta")
|
|
|
|
string = string.replace("%type_technical%", "b")
|
|
|
|
CoreTypes.VersionType.ALPHA:
|
|
|
|
string = string.replace("%type%", "Alpha")
|
|
|
|
string = string.replace("%type_technical%", "a")
|
2024-02-09 15:28:42 +01:00
|
|
|
_: await logger.crash("Invalid version type " + str(version_type), true)
|
2024-02-04 21:36:30 +01:00
|
|
|
# Development mode
|
|
|
|
if is_devmode(): string = string.replace("%devmode%", "Enabled")
|
|
|
|
else: string = string.replace("%devmode%", "Disabled")
|
|
|
|
# Headless mode
|
|
|
|
if config.headless: string = string.replace("%headless%", "Enabled")
|
|
|
|
else: string = string.replace("%headless%", "Disabled")
|
|
|
|
return string
|
|
|
|
|
|
|
|
# Return CORE's version in the semantic versioning scheme
|
|
|
|
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
|
|
|
|
return [version_release, version_type_int, version_typerelease]
|