(hopefully) implemented media paths

This commit is contained in:
FatalErr42O 2023-08-29 11:56:32 -07:00
parent 2dfaff26f3
commit 4356f54e1c
3 changed files with 180 additions and 1 deletions

View File

@ -13,4 +13,15 @@ end
mtul.path = minetest.get_modpath("MTUL-core")
dofile(mtul.path.."/libs/modlib/binary.lua")
dofile(mtul.path.."/libs/modlib/table.lua")
dofile(mtul.path.."/libs/modlib/math.lua")
dofile(mtul.path.."/libs/modlib/math.lua")
--utilities
--[[
exports:
mtul.
media_paths
overriden_media_paths
modname_by_media
overriden_modnames_by_media
]]
dofile(mtul.path.."/libs/modlib/mod_utils.lua")
dofile(mtul.path.."/libs/modlib/mod_utils_media.lua")

104
libs/modlib/mod_utils.lua Normal file
View File

@ -0,0 +1,104 @@
function mtul.utils.get_resource(modname, resource, ...)
if not resource then
resource = modname
modname = minetest.get_current_modname()
end
return table.concat({minetest.get_modpath(modname), resource, ...}, "/")
end
local function trim_spacing(text)
return text:match"^%s*(.-)%s*$"
end
--I will add a file reading lib eventually...
local read_file = mtul.file.read or function(mod, filename)
local filepath = mtul.utils.get_resource(mod, filename)
local file, err = io.open(filename, "r")
if file == nil then return nil, err end
local content = file:read"*a"
file:close()
end
local mod_info
function mtul.utils.get_mod_info()
if mod_info then return mod_info end
mod_info = {}
-- TODO validate modnames
local modnames = minetest.get_modnames()
for _, mod in pairs(modnames) do
local info
local mod_conf = Settings(mtul.utils.get_resource(mod, "mod.conf"))
if mod_conf then
info = {}
mod_conf = mod_conf:to_table()
local function read_depends(field)
local depends = {}
for depend in (mod_conf[field] or ""):gmatch"[^,]+" do
depends[trim_spacing(depend)] = true
end
info[field] = depends
end
read_depends"depends"
read_depends"optional_depends"
else
info = {
description = read_file(mod, "description.txt"),
depends = {},
optional_depends = {}
}
local depends_txt = read_file(mod, "depends.txt")
if depends_txt then
local trimmed = {}
for key, value in pairs(string.split(depends_txt or "", "\n")) do
trimmed[key] = trim_spacing(value)
end
for _, dependency in ipairs(trimmed) do
local modname, is_optional = dependency:match"(.+)(%??)"
table.insert(is_optional == "" and info.depends or info.optional_depends, modname)
end
end
end
if info.name == nil then
info.name = mod
end
mod_info[mod] = info
end
return mod_info
end
local mod_load_order
function mtul.utils.get_mod_load_order()
if mod_load_order then return mod_load_order end
mod_load_order = {}
local mod_info = mtul.utils.get_mod_info()
-- If there are circular soft dependencies, it is possible that a mod is loaded, but not in the right order
-- TODO somehow maximize the number of soft dependencies fulfilled in case of circular soft dependencies
local function load(mod)
if mod.status == "loaded" then
return true
end
if mod.status == "loading" then
return false
end
-- TODO soft/vs hard loading status, reset?
mod.status = "loading"
-- Try hard dependencies first. These must be fulfilled.
for depend in pairs(mod.depends) do
if not load(mod_info[depend]) then
return false
end
end
-- Now, try soft dependencies.
for depend in pairs(mod.optional_depends) do
-- Mod may not exist
if mod_info[depend] then
load(mod_info[depend])
end
end
mod.status = "loaded"
table.insert(mod_load_order, mod)
return true
end
for _, mod in pairs(mod_info) do
assert(load(mod))
end
return mod_load_order
end

View File

@ -0,0 +1,64 @@
--felt this was big enough that it practically deserved it's own file.
-- TODO support for server texture packs (and possibly client TPs in singleplayer?)
local media_foldernames = {"textures", "sounds", "media", "models", "locale"}
local media_extensions = {
-- Textures
"png", "jpg", "bmp", "tga", "pcx", "ppm", "psd", "wal", "rgb";
-- Sounds
"ogg";
-- Models
"x", "b3d", "md2", "obj";
-- Translations
"tr";
}
--mmmm yes, according to modlib we should make this loop it's own global function apart of modlib. Foolish me thinking we can just make case specific
for i, v in pairs(media_extensions) do
media_extensions[v] = true
end
local function collect_media(modname)
local media = {}
local function traverse(folderpath)
-- Traverse files (collect media)
local filenames = minetest.get_dir_list(folderpath, false)
for _, filename in pairs(filenames) do
local _, ext = modlib.file.get_extension(filename)
if media_extensions[ext] then
media[filename] = table.concat({folderpath, filename}, "/")
end
end
-- Traverse subfolders
local foldernames = minetest.get_dir_list(folderpath, true)
for _, foldername in pairs(foldernames) do
if not foldername:match"^[_%.]" then -- ignore hidden subfolders / subfolders starting with `_`
traverse(table.concat({folderpath, foldername}, "/"))
end
end
end
for _, foldername in ipairs(media_foldernames) do -- order matters!
traverse(mtul.utils.get_resource(modname, foldername))
end
return media
end
-- TODO clean this up eventually
local paths = {}
local mods = {}
local overridden_paths = {}
local overridden_mods = {}
for _, mod in ipairs(mtul.utils.get_mod_load_order()) do
local mod_media = collect_media(mod.name)
for medianame, path in pairs(mod_media) do
if paths[medianame] then
overridden_paths[medianame] = overridden_paths[medianame] or {}
table.insert(overridden_paths[medianame], paths[medianame])
overridden_mods[medianame] = overridden_mods[medianame] or {}
table.insert(overridden_mods[medianame], mods[medianame])
end
paths[medianame] = path
mods[medianame] = mod.name
end
end
mtul.media_paths = paths
mtul.overriden_media_paths = paths
mtul.modname_by_media = paths
mtul.overriden_modnames_by_media = paths