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>
This commit is contained in:
JeremyStar™ 2023-08-25 14:34:57 +02:00 committed by JeremyStar™
parent ab5b3ade52
commit 99703cf03e
55 changed files with 2035 additions and 1985 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
*.import
config.gd
devprj

View file

@ -1,8 +1,9 @@
#!/bin/make
CORE=$(shell pwd)
ASSETS=$(CORE)/assets
DOCSCONF=$(CORE)/mkdocs.yml
DOCSOUT=$(CORE)/docs_out
TESTPROJECT=/tmp/core_devproject
TESTPROJECT=$(CORE)/devprj
dist: help
help:
@ -23,7 +24,6 @@ docs-deps-paru:
@paru -Sy --needed python-pyyaml-env-tag python-mergedeep python-six python-smmap python-gitdb python-urllib3 python-idna python-dateutil python-pytz python-babel python-requests python-regex python-pygments python-colorama python-watchdog python-packaging python-ghp-import python-click python-jinja python-yaml python-gitpython python-markupsafe pymdown-extensions mkdocs-material-pymdownx-extras mkdocs-git-revision-date-localized-plugin mkdocs-material mkdocs
docs-serve:
@echo ":: Serving documentation, press CTRL+C to exit"
# prevent make from terminating
@bash -c "mkdocs serve --dirtyreload --config-file "$(DOCSCONF)";exit 0"
docs-build:
@make docs-clean
@ -34,16 +34,12 @@ docs-clean:
@rm -rf "$(DOCSOUT)"
mkdevprj:
@echo ":: Creating development project"
@mkdir -p $(TESTPROJECT)/mods/testmod/
@echo -e "config_version=5\n[application]\nconfig/name=\"CORE development project\"\nrun/main_scene=\"res://CORE/coreinit.tscn\"\nconfig/use_custom_user_dir=true\nconfig/custom_user_dir_name=\"core_devproject\"\nconfig/features=PackedStringArray(\"4.1\", \"GL Compatibility\")\nboot_splash/bg_color=Color(0, 0, 0, 1)\nboot_splash/show_image=false\nconfig/icon=\"res://CORE/soscore.png\"\n[autoload]\nLogger=\"*res://CORE/logger.gd\"\nPreprocessor=\"*res://CORE/preprocessor.gd\"\n[display]\nwindow/size/viewport_width=960\nwindow/size/viewport_height=540\n[rendering]\nrenderer/rendering_method=\"gl_compatibility\"\nrenderer/rendering_method.mobile=\"gl_compatibility\"" > "$(TESTPROJECT)/project.godot"
@echo -e "extends Node\n\n@onready\nvar core: Node = get_node(\"/root/core\")\n\nfunc _ready() -> void:\n core.welcome()" > "$(TESTPROJECT)/init.gd"
@echo -e "extends Node\nvar core_startscript = \"res://init.gd\"\nvar wmgr_size_x = 960\nvar wmgr_size_y = 540\nvar wmgr_title = \"CORE development project\"\nvar wmgr_mode = 0\nvar splash_enabled = false\nvar splash_image = \"res://CORE/soscore.png\"\nvar splash_image_size = 256\nvar splash_color = \"000000\"\nvar moam_loadpath = \"res://mods/\"\nvar moam_wanted_name = \"coredevprj\"\nvar moam_wanted_version = 1\nvar moam_wanted_api = 1" > config.gd
@echo -e "{\n\"wanted\": {\n\"min_version\": 1,\n\"max_version\": 1,\n\"min_api\": 1,\n\"max_api\": 1\n},\n\"mod\": {\n\"name\": \"CORE Test Mod\",\n\"version\": 1,\n\"version_friendly\": "1.0",\n\"authors\": [\n\"The CORE Team\"\n],\n\"license\": \"GNU General Public License v3\",\n\"entrypoint\": \"testmod.gd\"\n}\n}" > "$(TESTPROJECT)/mods/testmod/coredevprj.coremod"
@echo -e "extends Node\n@onready\nvar core: Node = get_node(\"/root/core\")\nfunc _start() -> String:\n await get_tree().create_timer(0).timeout\n Logger.info(\"testmod\",\"_start() has been called.\")\n return \"\"\nfunc _stop() -> void:\n await get_tree().create_timer(0).timeout\n Logger.info(\"testmod\",\"_stop() has been called.\")" > "$(TESTPROJECT)/mods/testmod/testmod.gd"
@cp -r $(ASSETS)/testproject $(TESTPROJECT)
@ln -s $(CORE) $(TESTPROJECT)/CORE
@mv $(TESTPROJECT)/config.gd $(TESTPROJECT)/CORE/config.gd
@echo ":: Development project created."
@echo " You can now launch Godot and open '$(TESTPROJECT)'."
@echo " Don't forget to save and execute 'make rmdevprj' when you're finished."
@echo " If you want to submit your changes, remember to execute 'make rmdevprj' first!"
rmdevprj:
@echo ":: Removing development project"
@echo ":: !!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View file

@ -11,15 +11,15 @@ CORE is under heavy development and can be very unstable. Please do not use CORE
- Notification API
- Basic debugging tool (CTRL+C to crash, F3 to toggle statistics)
- ~~Better documentation (docs4everything)~~
- Everything commented and explained
- ~~Everything commented and explained~~
- Documentation page explaining what does what (for CORE noobies)
- ~~Autoload singleton check removal~~
- More wmgr functions
- ~~More wmgr functions~~ (the window manager got removed in the rewrite)
- ~~Website~~
- ~~Silencing startup messages (info -> diag)~~
- ~~Remove autoload component~~
- ~~Fix syntax (set return types missing)~~
- Much more configuration options
- ~~Much more configuration options~~ (CORE's already pretty configurable)
- Implement preprocessor placeholders
- Clipboard content
- CORE version
@ -69,13 +69,12 @@ CORE is under heavy development and can be very unstable. Please do not use CORE
Yes, in theory you can refactor your entire codebase and make a giant mess, but we don't recommend doing that.
# Requirements
- Godot 4.0/4.1 (stable releases only)
- Godot 4.1 (stable releases only)
- Good experience with Godot 4 and GDScript
# Recommendations
- Use smgr instead of manually managing scenes or CORE will break apart. If you don't want headaches, use smgr.
- Use the CORE logger for logging. It supports rich formatting (using tags, handled by our Preprocessor™) and is generally better than using print() for everything.
- Use wmgr for managing the main window title, size, position, etc.
- Use the Scene Manager instead of manually managing scenes or CORE will break apart. If you don't want headaches, use the Scene Manager.
- Use the CORE's logger implementation instead of print(). It supports rich formatting (using tags, handled by our Preprocessor™) and is generally better than using print() for everything.
# How to install
- Download the [CORE manager](https://git.staropensource.de/StarOpenSource/core-manager#download) and open it

View file

@ -0,0 +1,9 @@
extends Node
@onready
var core: Node = get_node("/root/CORE")
@onready
var logger: Node = core.get_module("Logger")
func _ready() -> void:
logger.info("init.gd","init.gd loaded.")

View file

@ -0,0 +1,18 @@
{
"wanted": {
"min_version": 1,
"max_version": 1,
"min_api": 1,
"max_api": 1
},
"mod": {
"name": "CORE Test Mod",
"version": 1,
"version_friendly": 1.0,
"authors": [
"The CORE Team"
],
"license": "GNU General Public License v3",
"entrypoint": "testmod.gd"
}
}

View file

@ -0,0 +1,15 @@
extends Node
@onready
var core: Node = get_node("/root/core")
@onready
var logger: Node = core.get_module("Logger")
func _start() -> String:
await get_tree().create_timer(0).timeout
logger.info("testmod","_start() has been called.")
return ""
func _stop() -> void:
await get_tree().create_timer(0).timeout
logger.info("testmod","_stop() has been called.")

View file

@ -0,0 +1,29 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="CORE development project"
run/main_scene="res://CORE/coreinit.tscn"
config/use_custom_user_dir=true
config/custom_user_dir_name="core_devproject"
config/features=PackedStringArray("4.1", "GL Compatibility")
boot_splash/bg_color=Color(0, 0, 0, 1)
boot_splash/show_image=false
[display]
window/size/viewport_width=960
window/size/viewport_height=540
[rendering]
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"

View file

@ -1,38 +0,0 @@
[gd_scene load_steps=3 format=3]
[ext_resource type="FontFile" path="res://CORE/hack.ttf" id="1_lr4q1"]
[ext_resource type="Script" path="res://CORE/corelog.gd" id="2_6qdog"]
[node name="COREBackground" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Background" type="ColorRect" parent="."]
layout_mode = 0
offset_right = 960.0
offset_bottom = 540.0
color = Color(0, 0, 0, 1)
[node name="Log" type="RichTextLabel" parent="Background"]
layout_mode = 0
offset_right = 960.0
offset_bottom = 540.0
theme_override_colors/default_color = Color(1, 1, 1, 1)
theme_override_fonts/normal_font = ExtResource("1_lr4q1")
theme_override_fonts/bold_font = ExtResource("1_lr4q1")
theme_override_fonts/italics_font = ExtResource("1_lr4q1")
theme_override_fonts/bold_italics_font = ExtResource("1_lr4q1")
theme_override_fonts/mono_font = ExtResource("1_lr4q1")
theme_override_font_sizes/normal_font_size = 12
theme_override_font_sizes/bold_font_size = 12
theme_override_font_sizes/italics_font_size = 12
theme_override_font_sizes/bold_italics_font_size = 12
theme_override_font_sizes/mono_font_size = 12
bbcode_enabled = true
text = "(coreinit) [INFO] Initializing CORE"
scroll_following = true
script = ExtResource("2_6qdog")

View file

@ -1,70 +1,78 @@
# moam.gd
# Mother Of All Mods (the CORE modloader)
#
# This file is part of StarOpenSource CORE (SOSCORE)
# Made by the StarOpenSource Project and Contributers
# Licensed under GNU GPLv3
######################################
# 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
@onready
var core = get_node("/root/core")
# CORE modules
var core: Node = null
var logger: Node = null
# Configuration
var config_loadpath = null
var config_wanted_name = null
var config_wanted_version = null
var config_wanted_api = null
# Modification list
var modlist = []
# Hook list
var hooks = {}
func load_mods() -> Array:
if core.protection_mode: return []
var errors = []
var errors: Array = []
for directory in DirAccess.get_directories_at(config_loadpath):
var return_value = await load_mod(directory)
var return_value: String = await load_mod(directory)
if return_value != "":
errors.append(return_value)
return errors
func load_mod(mod_name:String) -> String:
Logger.info("moam","Loading modification \"" + mod_name + "\"")
logger.info("CORE/cml.gd","Loading modification \"" + mod_name + "\"")
if modlist.has(mod_name):
Logger.error("moam","Modification \"" + mod_name + "\" is already loaded")
logger.error("CORE/cml.gd","Modification \"" + mod_name + "\" is already loaded")
if !FileAccess.file_exists(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod"):
Logger.error("moam","Modification located at " + config_loadpath + "/" + mod_name + " does not contain a " + config_wanted_name + ".coremod file")
logger.error("CORE/cml.gd","Modification located at " + config_loadpath + "/" + mod_name + " does not contain a " + config_wanted_name + ".coremod file")
return "Modification located at " + config_loadpath + "/" + mod_name + " does not contain a " + config_wanted_name + ".coremod file"
var modinfo_raw = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ)
var modinfo = modinfo_raw.get_as_text()
var modinfo_raw: FileAccess = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ)
var modinfo: Dictionary = JSON.parse_string(modinfo_raw.get_as_text())
modinfo_raw.close()
modinfo = JSON.parse_string(modinfo)
if modinfo == null:
Logger.error("moam","Failed modinfo parsing for modification located at " + config_loadpath + "/" + mod_name)
logger.error("CORE/cml.gd","Failed modinfo parsing for modification located at " + config_loadpath + "/" + mod_name)
return "Failed modinfo parsing for modification located at " + config_loadpath + "/" + mod_name
if !modinfo.has_all(["wanted","mod"]):
Logger.error("moam","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted, mod or both")
logger.error("CORE/cml.gd","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted, mod or both")
return "The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted, mod or both"
if !modinfo["wanted"].has_all(["min_version","max_version","min_api","max_api"]):
Logger.error("moam","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted.min_version, wanted.max_version, wanted.min_api or wanted.max_api or some combination of them.")
logger.error("CORE/cml.gd","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted.min_version, wanted.max_version, wanted.min_api or wanted.max_api or some combination of them.")
return "The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted.min_version, wanted.max_version, wanted.min_api or wanted.max_api or some combination of them."
if !modinfo["mod"].has_all(["name","version","authors","license","entrypoint"]):
Logger.error("moam","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain mod.name, mod.version, mod.authors, mod.license or mod.entrypoint or some combination of them.")
logger.error("CORE/cml.gd","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain mod.name, mod.version, mod.authors, mod.license or mod.entrypoint or some combination of them.")
return "The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain mod.name, mod.version, mod.authors, mod.license or mod.entrypoint or some combination of them."
if not modinfo["wanted"]["min_version"] <= config_wanted_version or not modinfo["wanted"]["max_version"] >= config_wanted_version:
Logger.error("moam","The modification \"" + modinfo["mod"]["name"] + " does not match wanted version " + str(config_wanted_version))
logger.error("CORE/cml.gd","The modification \"" + modinfo["mod"]["name"] + " does not match wanted version " + str(config_wanted_version))
return "The modification \"" + modinfo["mod"]["name"] + " does not match wanted version " + str(config_wanted_version)
if not modinfo["wanted"]["min_api"] <= config_wanted_api or not modinfo["wanted"]["max_api"] >= config_wanted_api:
Logger.error("moam","The modification \"" + modinfo["mod"]["name"] + " does not match wanted api " + str(config_wanted_api))
logger.error("CORE/cml.gd","The modification \"" + modinfo["mod"]["name"] + " does not match wanted api " + str(config_wanted_api))
return "The modification \"" + modinfo["mod"]["name"] + " does not match wanted api " + str(config_wanted_api)
if !FileAccess.file_exists(config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"]):
Logger.error("moam","The entrypoint for the modification \"" + modinfo["mod"]["name"] + "\" located at \"" + config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"] + "\" does not exist")
logger.error("CORE/cml.gd","The entrypoint for the modification \"" + modinfo["mod"]["name"] + "\" located at \"" + config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"] + "\" does not exist")
return "The entrypoint for the modification \"" + modinfo["mod"]["name"] + "\" located at \"" + config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"] + "\" does not exist"
var entrypoint_script = ResourceLoader.load(config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"])
var entrypoint = Control.new()
var entrypoint_script: Script = ResourceLoader.load(config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"])
var entrypoint: Node = Node.new()
entrypoint.name = mod_name
entrypoint.set_script(entrypoint_script)
get_tree().root.add_child(entrypoint)
var mod_err = await get_node("/root/" + mod_name)._start()
var mod_err: String = await get_node("/root/" + mod_name)._start()
if mod_err == "":
modlist.append(mod_name)
return ""
@ -77,11 +85,11 @@ func unload_mods() -> void:
await unload_mod(mod)
func unload_mod(mod_name:String) -> void:
Logger.info("moam","Unloading modification \"" + mod_name + "\"")
logger.info("CORE/cml.gd","Unloading modification \"" + mod_name + "\"")
if !modlist.has(mod_name):
Logger.error("moam","Modification \"" + mod_name + "\" is not loaded")
logger.error("CORE/cml.gd","Modification \"" + mod_name + "\" is not loaded")
if get_tree().root.get_node_or_null(mod_name) == null:
core.exception("moam","Could not locate mod entrypoint script for mod \"" + mod_name + "\" during unload")
core.exception("CORE/cml.gd","Could not locate mod entrypoint script for mod \"" + mod_name + "\" during unload")
return
await get_node("/root/" + mod_name)._stop()
get_tree().root.remove_child(get_node("/root/" + mod_name))
@ -89,10 +97,9 @@ func unload_mod(mod_name:String) -> void:
func register_hook(mod_name:String,hook_name:String,hook_action:int,method:Callable) -> bool:
if !modlist.has(mod_name):
core.exception("moam","Failed registering hook \"" + hook_name + "\" for mod \"" + mod_name + "\" as it does not exist or is not loaded")
core.exception("CORE/cml.gd","Failed registering hook \"" + hook_name + "\" for mod \"" + mod_name + "\" as it does not exist or is not loaded")
return false
if hooks.has(hook_name):
Logger.error("moam","Failed registering hook \"" + hook_name + "\" for mod \"" + mod_Name + "\" as the hook already exists")
core.exception("CORE/cml.gd","Function not implemented")
return true
func get_list() -> Array:
@ -101,23 +108,19 @@ func get_list() -> Array:
func get_info(mod_name:String) -> Dictionary:
if !modlist.has(mod_name):
return {"error":"Modification \"" + mod_name + "\" is not loaded"}
var modinfo_raw = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ)
var modinfo = JSON.parse_string(modinfo_raw.get_as_text())
var modinfo_raw: FileAccess = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ)
var modinfo: Dictionary = JSON.parse_string(modinfo_raw.get_as_text())
modinfo_raw.close()
if modinfo == null:
return {"error":"Failed parsing modinfo for modification \"" + modinfo + "\""}
return {"error":"Failed parsing modinfo for modification \"" + mod_name + "\""}
return modinfo
func load_configuration() -> void:
if core.protection_mode: return
config_loadpath = core.config.moam_loadpath
config_wanted_name = core.config.moam_wanted_name
config_wanted_version = core.config.moam_wanted_version
if core.config.get("moam_wanted_api") == null:
config_loadpath = core.config.cml_loadpath
config_wanted_name = core.config.cml_wanted_name
config_wanted_version = core.config.cml_wanted_version
if core.config.get("cml_wanted_api") == null:
config_wanted_api = config_wanted_version
else:
config_wanted_api = core.config.moam_wanted_api
func initialize() -> void:
if core.protection_mode: return
core.setready()
config_wanted_api = core.config.cml_wanted_api

242
core.gd
View file

@ -1,90 +1,120 @@
# core.gd
# CORE Holder
#
# This file is part of StarOpenSource CORE (SOSCORE)
# Made by the StarOpenSource Project and Contributers
# Licensed under GNU GPLv3
######################################
# 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
const version = "source 0"
var protection_mode = false
var locked = false
var readycount = 0
var readylized = false # Fun Fact: "ready" is a signal from "Node" and I (JeremyStarTM) just added "lized" from "initialized" to it to avoid a error thrown by Godot
var config = null
var wmgr = null
var smgr = null
var resmgr = null
var events = null
var splash = null
var moam = null
var mkdown = null
enum Errors {UNKNOWN}
enum Responsibilities {UNKNOWN}
# CORE modules
var logger: Node = null
var preprocessor: Node = null
var config: Node = null
func attach(type:String,module,do_setup:bool = true) -> void:
if protection_mode: return
if locked:
return
Logger.diag("core","Attaching " + type + " to CORE")
var mod = module
if do_setup:
mod = Control.new()
mod.name = type
mod.set_script(module)
match(type):
"config": config = mod
"wmgr": wmgr = mod
"smgr": smgr = mod
"resmgr": resmgr = mod
"events": events = mod
"splash": splash = mod
"moam": moam = mod
"mkdown": mkdown = mod
_:
exception("core","Attaching \"" + type + "\" failed as it is not a valid module")
mod.free()
return
add_child(mod)
Logger.diag("core","Attached " + type + " successfully")
# 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 = ""
func setready() -> void:
if protection_mode: return
readycount = readycount+1
if readycount == 7:
readylized = true
func lock() -> void:
if protection_mode: return
locked = true
Logger.diag("core","CORE is now locked. No new attachments can be added.")
# 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 (" + version + ") welcomes you!<nl>It seems like everything is working :)")
logger.info("CORE/core.gd","CORE (" + version["full"] + ") welcomes you!<nl>It seems like everything is working :)")
func exception(script:String,error:String):
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 exc_message = """
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.
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
%submit_issue%
CORE INFORMATION
version = "%version%"
readylized = %readylized%
readycount = %readycount%
locked = %locked%
development_mode = %development_mode%
preprocessor_enabled = %preprocessor_enabled%
preprocessor_tests = %preprocessor_tests%
preprocessor_tests_executed = %preprocessor_tests_executed%
preprocessor_tests_success = %preprocessor_tests_success%
preprocessor_diagnostic = %preprocessor_diagnostic%
logger_enabled = %logger_enabled%
logger_diag = %logger_diag%
logger_diagnostic = %logger_diagnostic%
OPERATING SYSTEM
timezone = %timezone%
@ -110,7 +140,7 @@ permissions = %permissions%
debug_build = %debug_build%
ERROR INFORMATION
script = "%script%"
module = "%module%"
error = "%error%"
STACKTRACE
@ -119,17 +149,16 @@ STACKTRACE
EXCEPTION! EXCEPTION! EXCEPTION!
################################
"""
exc_message = exc_message.replace("%version%",version)
exc_message = exc_message.replace("%readylized%",str(readylized))
exc_message = exc_message.replace("%readycount%",str(readycount))
exc_message = exc_message.replace("%locked%",str(locked))
exc_message = exc_message.replace("%preprocessor_enabled%",str(Preprocessor.enabled))
exc_message = exc_message.replace("%preprocessor_tests%",str(Preprocessor.tests_enabled))
exc_message = exc_message.replace("%preprocessor_tests_executed%",str(Preprocessor.tests_executed))
exc_message = exc_message.replace("%preprocessor_tests_success%",str(Preprocessor.tests_success))
exc_message = exc_message.replace("%logger_enabled%",str(Logger.enable))
exc_message = exc_message.replace("%logger_diag%",str(Logger.enable_diag))
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))
@ -152,22 +181,51 @@ EXCEPTION! EXCEPTION! EXCEPTION!
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("%script%",script)
exc_message = exc_message.replace("%error%",error)
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,respo:Responsibilities,error:Errors,error_info:Dictionary = {}) -> Dictionary:
var error_text = ""
match(respo):
Responsibilities["UNKNOWN"]:
pass
match(error):
Errors["UNKNOWN"]:
error_text = ""
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 {}
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)

View file

@ -1,51 +1,209 @@
# coreinit.gd
# CORE Initializer
#
# This file is part of StarOpenSource CORE (SOSCORE)
# Made by the StarOpenSource Project and Contributers
# Licensed under GNU GPLv3
######################################
# 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
@onready
var engine_version = Engine.get_version_info()
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 -> CORE only supports Godot 4. Please upgrade/downgrade your Godot Project to Godot 4.")
await get_tree().create_timer(0.1).timeout
get_tree().quit(141)
return
if engine_version["minor"] != 0 and engine_version["minor"] != 1:
print("coreinit -> CORE only supports Godot 4.0 and 4.1. Please upgrade/downgrade your Godot Project to Godot 4.0 or 4.1.")
await get_tree().create_timer(0.1).timeout
get_tree().quit(142)
return
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 -> CORE only supports stable Godot 4 releases. Please upgrade/downgrade your Godot Project to a stable version.")
await get_tree().create_timer(0.1).timeout
get_tree().quit(143)
return
if get_node_or_null(NodePath("/root/Logger")) == null:
print("coreinit -> The CORE logger is missing in your autoload project settings!")
await get_tree().create_timer(0.1).timeout
get_tree().quit(144)
return
if get_node_or_null(NodePath("/root/Preprocessor")) == null:
print("coreinit -> The CORE preprocessor is missing in your autoload project settings!")
await get_tree().create_timer(0.1).timeout
get_tree().quit(145)
return
if !FileAccess.file_exists("res://CORE/config.gd"):
print("coreinit -> The CORE configuration file (config.gd) is missing! Please copy the config.gd.example file and rename it to config.gd!")
await get_tree().create_timer(0.1).timeout
get_tree().quit(146)
return
print("coreinit -> Constructing coreloader")
var coreloader = Control.new()
coreloader.name = "coreloader"
coreloader.set_script(ResourceLoader.load("res://CORE/coreloader.gd"))
print("coreinit -> Injecting coreloader")
get_tree().root.add_child.call_deferred(coreloader)
print("coreinit -> Switching to COREBackground")
get_tree().change_scene_to_packed(ResourceLoader.load("res://CORE/background.tscn"))
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

View file

@ -2,13 +2,10 @@
[ext_resource type="Script" path="res://CORE/coreinit.gd" id="1_ubktt"]
[node name="coreinit" type="Control"]
layout_mode = 3
anchors_preset = 0
[node name="coreinit" type="Node"]
script = ExtResource("1_ubktt")
[node name="ColorRect" type="ColorRect" parent="."]
layout_mode = 0
offset_left = -5e+08
offset_top = -5e+08
offset_right = 5e+08

View file

@ -1,66 +0,0 @@
# coreloader.gd
# CORE Loader
#
# This file is part of StarOpenSource CORE (SOSCORE)
# Made by the StarOpenSource Project and Contributers
# Licensed under GNU GPLv3
extends Node
func _ready() -> void:
await get_tree().create_timer(1.5).timeout
Logger.diag("coreloader","Starting initialization")
Logger.diag("coreloader","Loading configuration file")
var scr_config = ResourceLoader.load("res://CORE/config.gd")
Logger.diag("coreloader","Preloading core scripts")
var scr_core = ResourceLoader.load("res://CORE/core.gd")
var scr_wmgr = ResourceLoader.load("res://CORE/wmgr.gd")
var scr_smgr = ResourceLoader.load("res://CORE/smgr.gd")
var scr_resmgr = ResourceLoader.load("res://CORE/resmgr.gd")
var scr_events = ResourceLoader.load("res://CORE/events.gd")
var scr_splash = ResourceLoader.load("res://CORE/splash.tscn").instantiate()
var scr_moam = ResourceLoader.load("res://CORE/moam.gd")
var scr_mkdown = ResourceLoader.load("res://CORE/mkdown.gd")
Logger.diag("coreloader","Constructing CORE")
var core = Control.new()
core.name = "core"
core.script = scr_core
Logger.diag("coreloader","Attaching CORE to /root/")
get_tree().root.add_child(core)
Logger.diag("coreloader","Attaching modules")
core.attach("config",scr_config)
core.attach("wmgr",scr_wmgr)
core.attach("smgr",scr_smgr)
core.attach("resmgr",scr_resmgr)
core.attach("events",scr_events)
core.attach("splash",scr_splash,false)
core.attach("moam",scr_moam)
core.attach("mkdown",scr_mkdown)
if core.protection_mode: return
Logger.diag("coreloader","Loading module configurations")
core.wmgr.load_configuration()
core.splash.load_configuration()
core.moam.load_configuration()
Logger.diag("coreloader","Initializing modules")
core.wmgr.initialize()
core.smgr.initialize()
core.resmgr.initialize()
core.events.initialize()
core.splash.initialize()
core.moam.initialize()
core.mkdown.initialize()
Logger.diag("coreloader","Locking CORE")
core.lock()
Logger.diag("coreloader","Waiting for CORE to fully initialize")
while !core.readylized:
await get_tree().create_timer(1).timeout
Logger.diag("coreloader","CORE has been initialized and is ready.")
Logger.diag("coreloader","Preloading project init script")
var initscr = ResourceLoader.load(core.config.core_startscript)
Logger.diag("coreloader","Constructing project init script")
var initscr_obj = Control.new()
initscr_obj.name = "ProjectInitScript"
initscr_obj.set_script(initscr)
Logger.diag("coreloader","Adding project init script to /root/")
get_tree().root.add_child(initscr_obj)
Logger.diag("coreloader","Removing coreloader")
queue_free()

View file

@ -1,38 +1,50 @@
# corelog.gd
# CORE Log
#
# This file is part of StarOpenSource CORE (SOSCORE)
# Made by the StarOpenSource Project and Contributers
# Licensed under GNU GPLv3
extends RichTextLabel
######################################
# 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 log_prefix = ""
var log_suffix = ""
# CORE modules
var core: Node = null
var logger: Node = null
func _ready() -> void:
# Enable recieving of log messages
Logger.connect("logevent",Callable(self,"logevent"))
# Disable VScrollBar functionality & visibility
get_child(0,true).add_theme_stylebox_override("grabber",StyleBoxEmpty.new())
get_child(0,true).add_theme_stylebox_override("grabber_highlight",StyleBoxEmpty.new())
get_child(0,true).add_theme_stylebox_override("grabber_pressed",StyleBoxEmpty.new())
get_child(0,true).add_theme_stylebox_override("scroll",StyleBoxEmpty.new())
get_child(0,true).add_theme_stylebox_override("scroll_focus",StyleBoxEmpty.new())
get_child(0,true).set_deferred("size",Vector2i(0,0))
get_child(0,true).mouse_filter = Control.MOUSE_FILTER_IGNORE
# Make RichTextLabel ignore all mouse events (to disable scrolling)
mouse_filter = Control.MOUSE_FILTER_IGNORE
# Initializes CORELog
func initialize() -> void:
if core.protection_mode: return
# logevent (signal) -> logupdate()
logger.connect("logevent",Callable(self,"logupdate"))
# Activate auto scrolling
$Background/Log.scroll_active = true
$Background/Log.scroll_following = true
# Disable mouse influence
$Background/Log.mouse_filter = Control.MOUSE_FILTER_IGNORE
$Background/Log.get_child(0,true).mouse_filter = Control.MOUSE_FILTER_IGNORE
# Remove every VScrollBar style
$Background/Log.get_child(0,true).add_theme_stylebox_override("grabber",StyleBoxEmpty.new())
$Background/Log.get_child(0,true).add_theme_stylebox_override("grabber_highlight",StyleBoxEmpty.new())
$Background/Log.get_child(0,true).add_theme_stylebox_override("grabber_pressed",StyleBoxEmpty.new())
$Background/Log.get_child(0,true).add_theme_stylebox_override("scroll",StyleBoxEmpty.new())
$Background/Log.get_child(0,true).add_theme_stylebox_override("scroll_focus",StyleBoxEmpty.new())
# Set VScollBar size to zero
$Background/Log.get_child(0,true).set_deferred("size",Vector2i(0,0))
func _process(_delta) -> void:
var windowsize = DisplayServer.window_get_size()
$".".size = windowsize
get_parent().size = windowsize
get_parent().get_parent().size = windowsize
# Updates log text
func logupdate(_type:String,_script:String,_method:String,logmessage:String) -> void:
$Background/Log.text = $Background/Log.text + "\n" + logmessage
func logevent(_type:String,_script:String,_message:String,logcomp:String) -> void:
# Appends log to RichTextLabel
text = text + "\n" + log_prefix + logcomp + log_suffix
# These two functions are very self explanitory
func display() -> void:
if core.protection_mode: return
$Background.visible = true
func rmconnect() -> void:
# Disables recieving of log messages
Logger.disconnect("logevent",Callable(self,"logevent"))
func dissolve() -> void:
if core.protection_mode: return
$Background.visible = false

52
corelog.tscn Normal file
View file

@ -0,0 +1,52 @@
[gd_scene load_steps=5 format=3]
[ext_resource type="Script" path="res://CORE/corelog.gd" id="1_8l1qi"]
[ext_resource type="FontFile" path="res://CORE/hack.ttf" id="1_m5led"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_adeh8"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_koe3t"]
[node name="CORELog" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_8l1qi")
[node name="Background" type="ColorRect" parent="."]
layout_mode = 0
offset_right = 960.0
offset_bottom = 540.0
color = Color(0, 0, 0, 1)
[node name="Log" type="RichTextLabel" parent="Background"]
layout_mode = 0
offset_right = 960.0
offset_bottom = 540.0
theme_override_colors/default_color = Color(1, 1, 1, 1)
theme_override_fonts/normal_font = ExtResource("1_m5led")
theme_override_fonts/bold_font = ExtResource("1_m5led")
theme_override_fonts/italics_font = ExtResource("1_m5led")
theme_override_fonts/bold_italics_font = ExtResource("1_m5led")
theme_override_fonts/mono_font = ExtResource("1_m5led")
theme_override_font_sizes/normal_font_size = 12
theme_override_font_sizes/bold_font_size = 12
theme_override_font_sizes/italics_font_size = 12
theme_override_font_sizes/bold_italics_font_size = 12
theme_override_font_sizes/mono_font_size = 12
theme_override_styles/focus = SubResource("StyleBoxEmpty_adeh8")
theme_override_styles/normal = SubResource("StyleBoxEmpty_koe3t")
bbcode_enabled = true
text = "coreinit -> \"Fixing\" busy setting up children issue
coreinit -> Bootstrapping CORE
coreinit -> Checking CORE requirements
coreinit -> Loading modules
coreinit -> Constructing modules
coreinit -> Injecting modules
coreinit -> Updating dependency references
coreinit -> Applying configuration to base modules
coreinit -> Initializing base modules"
scroll_following = true

View file

@ -1,11 +1,27 @@
#!/bin/bash
if [ "$1" == "--help" ]; then
echo "Environment variables: VERBOSE (false)"
echo " FILEEXTENSION (*)"
echo " IGNORE_SCRIPT (false)"
echo " IGNORE_DOCUMENTATION (false)"
echo " NUMBER_ONLY (false)"
exit 0
fi
function dircount() {
if [ "$VERBOSE" == "true" ]; then echo ":: Checking directory \"$*\"..."; fi
cd "$*" || exit 54
for file in $FILEEXTENSION; do
export "file_full=$*/$file"
if [ -d "$file" ]; then
dircount "$file_full"
if [ "$file" == "devprj" ]; then
if [ "$VERBOSE" == "true" ]; then echo ":: Skipping directory \"devprj\"";fi
else
if [ "$IGNORE_DOCUMENTATION" == "true" ] && [ "$file" == "docs" ]; then
if [ "$VERBOSE" == "true" ]; then echo ":: Skipping directory \"docs\"";fi
else
dircount "$file_full"
fi
fi
elif [ -f "$file" ]; then
if [ "$IGNORE_SCRIPT" == "true" ] && [ "$file" == "count_characters.sh" ]; then
if [ "$VERBOSE" == "true" ]; then echo ":: Skipping this script"; fi

71
debugdisplay.gd Normal file
View file

@ -0,0 +1,71 @@
######################################
# 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 core: Node = null
var misc: Node = null
# Important nodes
@onready
var display: RichTextLabel = get_node("Display")
# Config
var config_enabled: bool = false
var config_fps: bool = false
var config_delta: bool = false
var config_rendertime: bool = false
var config_memory: bool = false
# Check if enabled
func _process(_delta) -> void:
if config_enabled:
update_display()
display.visible = true
else:
display.visible = false
# Updates the display with useful information
func update_display():
var displaytext: String = ""
var displaysize: int = 17
# Get memory information
var info_memory: Dictionary = OS.get_memory_info()
if config_memory:
info_memory.merge({"peak":OS.get_static_memory_peak_usage(),"percent":float(OS.get_static_memory_usage())/info_memory["physical"]*100,"used":OS.get_static_memory_usage()})
# If fps is enabled, add the fps counter
if config_fps:
displaysize = displaysize+17*1
displaytext = displaytext + "\nFPS: " + str(snappedf(misc.get_fps(false),0.01))
# If delta is enabled, add the delta counter
if config_delta:
displaysize = displaysize+17*1
displaytext = displaytext + "\nDelta: " + str(misc.get_delta())
# If rendertime is enabled, add the rendertime counter
if config_rendertime:
displaysize = displaysize+17*1
displaytext = displaytext + "\nRendertime: " + str(misc.get_rendertime())
# If memory is enabled, display memory information
if config_memory:
displaysize = displaysize+17*2
displaytext = displaytext + "\nMemory (Available|Used|Stack): " + str(misc.byte_to_mib(info_memory["available"],true)) + " MiB|" + str(misc.byte_to_mib(info_memory["used"],true)) + " MiB|" + str(misc.byte_to_mib(info_memory["stack"],true)) + " MiB"
displaytext = displaytext + "\nMemory (Physical|Peak|%): " + str(misc.byte_to_mib(info_memory["physical"],true)) + " MiB|" + str(misc.byte_to_mib(info_memory["peak"],true)) + " MiB|" + str(snappedf(info_memory["percent"],0.001)) + "%"
# Add CORE version and (if enabled) a dev mode notice
if core.development_mode:
displaytext = "CORE " + core.version["full"] + " [color=yellow](development mode)[/color]" + displaytext
else:
displaytext = "CORE " + core.version["full"] + displaytext
# Update display
display.text = displaytext
display.size = Vector2i(540,displaysize)

34
debugdisplay.tscn Normal file
View file

@ -0,0 +1,34 @@
[gd_scene load_steps=5 format=3]
[ext_resource type="Script" path="res://CORE/debugdisplay.gd" id="1_hcfi0"]
[ext_resource type="FontFile" path="res://CORE/hack.ttf" id="1_nhdg1"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_3c08d"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5ghow"]
bg_color = Color(0.839216, 0.0196078, 0.196078, 0.862745)
corner_radius_bottom_right = 16
shadow_color = Color(0, 0, 0, 0)
[node name="DebugDisplay" type="Node"]
script = ExtResource("1_hcfi0")
[node name="Display" type="RichTextLabel" parent="."]
offset_right = 540.0
offset_bottom = 102.0
theme_override_colors/default_color = Color(1, 1, 1, 1)
theme_override_fonts/normal_font = ExtResource("1_nhdg1")
theme_override_font_sizes/normal_font_size = 14
theme_override_font_sizes/bold_font_size = 14
theme_override_font_sizes/italics_font_size = 14
theme_override_font_sizes/bold_italics_font_size = 14
theme_override_font_sizes/mono_font_size = 14
theme_override_styles/focus = SubResource("StyleBoxEmpty_3c08d")
theme_override_styles/normal = SubResource("StyleBoxFlat_5ghow")
bbcode_enabled = true
text = "CORE source-N (development mode) (THIS IS A PLACEHOLDER!)
FPS:
Delta:
Rendertime:
Memory (1):
Memory (2):"

9
docs/breaking-commits.md Normal file
View file

@ -0,0 +1,9 @@
---
hide:
- navigation
---
# Breaking commits
We sometimes push a commit that may break something for some project. Here's where we list critical changes.
## 404 Documentation not found
There are no breaking commits as of now.

View file

@ -6,16 +6,16 @@ hide:
Welcome to the StarOpenSource documentation! Look below for more information about CORE and code references.
## What, why, wtf?
The **StarOpenSource CORE Framework** (also known as **CORE** or **SOSCORE**) is a framework that makes the development of games and applications written in **Godot 4.0 and 4.1** easier. CORE implements useful & common functions *(such as calculating the current FPS)* and provides a logging system that even supports formatting, a scene manager and so much more.
The **StarOpenSource CORE Framework** (also known as **CORE** or **SOSCORE**) is a framework that makes the development of games and applications written in **Godot 4.1** easier. CORE implements useful & common functions *(such as calculating the current FPS)* and provides a logging system that even supports formatting, a scene manager and so much more.
## Can I use CORE in my existing project?
In theory, yes. But if you don't want to refactor a large part of your codebase, don't install CORE.
Yes, unless you want to refactor your entire project. Remember: CORE is a framework, NOT a library and NOT a regular addon!