JeremyStarTM
ab5b3ade52
- Rewrote mkdevprj/rmdevprj in Makefile - Add MOAM modloader - Add core.exception() - Add protection mode - Rewrote module initialization - Add experimental markdown parser - Many more very small changes
123 lines
6.6 KiB
GDScript
123 lines
6.6 KiB
GDScript
# 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
|
|
extends Node
|
|
|
|
@onready
|
|
var core = get_node("/root/core")
|
|
|
|
var config_loadpath = null
|
|
var config_wanted_name = null
|
|
var config_wanted_version = null
|
|
var config_wanted_api = null
|
|
|
|
var modlist = []
|
|
var hooks = {}
|
|
|
|
func load_mods() -> Array:
|
|
if core.protection_mode: return []
|
|
var errors = []
|
|
for directory in DirAccess.get_directories_at(config_loadpath):
|
|
var return_value = 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 + "\"")
|
|
if modlist.has(mod_name):
|
|
Logger.error("moam","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")
|
|
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()
|
|
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)
|
|
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")
|
|
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.")
|
|
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.")
|
|
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))
|
|
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))
|
|
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")
|
|
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()
|
|
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()
|
|
if mod_err == "":
|
|
modlist.append(mod_name)
|
|
return ""
|
|
else:
|
|
get_tree().root.remove_child(entrypoint)
|
|
return "Modification \"" + mod_name + "\" could not be loaded as it returned this error: " + mod_err
|
|
|
|
func unload_mods() -> void:
|
|
for mod in modlist:
|
|
await unload_mod(mod)
|
|
|
|
func unload_mod(mod_name:String) -> void:
|
|
Logger.info("moam","Unloading modification \"" + mod_name + "\"")
|
|
if !modlist.has(mod_name):
|
|
Logger.error("moam","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")
|
|
return
|
|
await get_node("/root/" + mod_name)._stop()
|
|
get_tree().root.remove_child(get_node("/root/" + mod_name))
|
|
modlist.erase(mod_name)
|
|
|
|
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")
|
|
return false
|
|
if hooks.has(hook_name):
|
|
Logger.error("moam","Failed registering hook \"" + hook_name + "\" for mod \"" + mod_Name + "\" as the hook already exists")
|
|
return true
|
|
|
|
func get_list() -> Array:
|
|
return modlist
|
|
|
|
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())
|
|
modinfo_raw.close()
|
|
if modinfo == null:
|
|
return {"error":"Failed parsing modinfo for modification \"" + modinfo + "\""}
|
|
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_wanted_api = config_wanted_version
|
|
else:
|
|
config_wanted_api = core.config.moam_wanted_api
|
|
|
|
func initialize() -> void:
|
|
if core.protection_mode: return
|
|
core.setready()
|